From e0f87d7ef9c459ad2ce42527e5b5bd502072dc41 Mon Sep 17 00:00:00 2001 From: Simon Cornet Date: Wed, 5 Mar 2025 08:45:55 +0100 Subject: [PATCH] feat: improve logging and added verbose output --- cmd/gogitlabber/git.go | 40 +++++++++++++------------ cmd/gogitlabber/gitlab.go | 10 +++---- cmd/gogitlabber/input.go | 50 +++++++++++++++++++++++--------- cmd/gogitlabber/main.go | 24 +++++++++++---- cmd/gogitlabber/output.go | 20 ++++++++++++- cmd/gogitlabber/prerequisites.go | 6 ++-- 6 files changed, 104 insertions(+), 46 deletions(-) diff --git a/cmd/gogitlabber/git.go b/cmd/gogitlabber/git.go index e351fe6..0eafb02 100644 --- a/cmd/gogitlabber/git.go +++ b/cmd/gogitlabber/git.go @@ -2,7 +2,6 @@ package main import ( "fmt" - "log" "os/exec" "strings" "sync" @@ -54,10 +53,6 @@ func checkoutRepositories(repositories []Repository, concurrency int) { switch { case strings.Contains(string(repoStatus), "No such file or directory"): - // update the progress bar - descriptionPrefixPre := "Cloning repository " - descriptionPrefix := descriptionPrefixPre + repoName + " ..." - // clone the repo cloneRepository := func(repoDestination string, url string) (string, error) { cloneCmd := exec.Command("git", "clone", url, repoDestination) @@ -67,29 +62,41 @@ func checkoutRepositories(repositories []Repository, concurrency int) { } _, err := cloneRepository(repoDestination, url) if err != nil { - log.Printf("ERROR: %v\n", err) + logPrint("ERROR: %v\n", err) } - // set a lock, increment counters and unlock + // set a lock, increment counters, update progressbar and unlock mu.Lock() clonedCount++ - bar.Describe(descriptionPrefix) - progressBarAdd(1) + if !verbose { + // update the progress bar + descriptionPrefixPre := "Cloning repository " + descriptionPrefix := descriptionPrefixPre + repoName + " ..." + bar.Describe(descriptionPrefix) + progressBarAdd(1) + } mu.Unlock() // pull the latest case strings.Contains(string(repoStatus), url): pullRepository(repoName, repoDestination) - progressBarAdd(1) + if !verbose { + descriptionPrefixPre := "Pulling repository " + descriptionPrefix := descriptionPrefixPre + repoName + " ..." + bar.Describe(descriptionPrefix) + progressBarAdd(1) + } default: - log.Printf("ERROR: decided not to clone or pull repository %v\n", repoName) - log.Printf("ERROR: this is why: %v\n", repoStatus) + logPrint("ERROR: decided not to clone or pull repository" + repoName, nil) + logPrint("ERROR: this is why: " + repoStatus, nil) // set a lock, increment counters and unlock mu.Lock() errorCount++ - progressBarAdd(1) + if !verbose { + progressBarAdd(1) + } mu.Unlock() } }(repo) @@ -101,10 +108,6 @@ func checkoutRepositories(repositories []Repository, concurrency int) { func pullRepository(repoName string, repoDestination string) { - // update the progress bar - descriptionPrefixPre := "Pulling repository " - descriptionPrefix := descriptionPrefixPre + repoName + " ..." - // find remote findRemote := func(repoDestination string) (string, error) { remoteCmd := exec.Command("git", "-C", repoDestination, "remote", "show") @@ -124,7 +127,6 @@ func pullRepository(repoName string, repoDestination string) { // set a lock, increment counters and unlock mu.Lock() - bar.Describe(descriptionPrefix) pulledCount++ mu.Unlock() @@ -141,7 +143,7 @@ func pullRepository(repoName string, repoDestination string) { pullErrorMsg = append(pullErrorMsg, repoDestination) default: - log.Printf("ERROR: pulling %v\n", err) + logPrint("ERROR: pulling " + repoName, nil) } } } diff --git a/cmd/gogitlabber/gitlab.go b/cmd/gogitlabber/gitlab.go index 821124a..05efa74 100644 --- a/cmd/gogitlabber/gitlab.go +++ b/cmd/gogitlabber/gitlab.go @@ -29,7 +29,7 @@ func fetchRepositoriesGitlab() ([]Repository, error) { req, err := http.NewRequest("GET", url, nil) if err != nil { - return nil, fmt.Errorf("creating request: %v\n", err) + return nil, fmt.Errorf("ERROR: creating request: %v\n", err) } req.Header.Set("PRIVATE-TOKEN", gitlabToken) @@ -37,21 +37,21 @@ func fetchRepositoriesGitlab() ([]Repository, error) { client := &http.Client{} resp, err := client.Do(req) if err != nil { - return nil, fmt.Errorf("making request: %v\n", err) + return nil, fmt.Errorf("ERROR: making request: %v\n", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("API request failed with status: %d\n", resp.StatusCode) + return nil, fmt.Errorf("ERROR: API request failed with status: %d\n", resp.StatusCode) } var repositories []Repository if err := json.NewDecoder(resp.Body).Decode(&repositories); err != nil { - return nil, fmt.Errorf("decoding response: %v\n", err) + return nil, fmt.Errorf("ERROR: decoding response: %v\n", err) } if len(repositories) < 1 { - return repositories, fmt.Errorf("no repositories found\n") + return repositories, fmt.Errorf("ERROR: no repositories found\n") } return repositories, nil diff --git a/cmd/gogitlabber/input.go b/cmd/gogitlabber/input.go index b37ec78..981c1cf 100644 --- a/cmd/gogitlabber/input.go +++ b/cmd/gogitlabber/input.go @@ -16,6 +16,7 @@ func manageArguments() { var destinationFlag = flag.String("destination", "$HOME/Documents", "Specify where to check the repositories out\n example: -destination=$HOME/repos\nenv = GOGITLABBER_DESTINATION\n") var hostFlag = flag.String("gitlab-url", "gitlab.com", "Specify GitLab host\n example: -gitlab-url=gitlab.com\nenv = GITLAB_URL\n") var tokenFlag = flag.String("gitlab-api-token", "", "Specify GitLab API token\n example: -gitlab-api=glpat-xxxx\nenv = GITLAB_API_TOKEN\n") + var verboseFlag = flag.Bool("verbose", false, "Specify verbosity\n example: -verbose=true\nenv = GOGITLABBER_VERBOSE\n") flag.Parse() @@ -25,32 +26,50 @@ func manageArguments() { gitlabToken = *tokenFlag includeArchived = *archivedFlag repoDestinationPre = *destinationFlag + verbose = *verboseFlag + + // manage verbosity option + switch envVerbose := os.Getenv("GOGITLABBER_VERBOSE"); { + case envVerbose != "": + var err error + verbose, err = strconv.ParseBool(envVerbose) + logPrint("CONFIG: verbose option found", nil) + if err != nil { + logFatal("FATAL: config; not a valid bool", nil) + } + default: + flag.Usage() + logFatal("FATAL: config; no verbose option found", nil) + } // manage gitlab api option switch envToken := os.Getenv("GITLAB_API_TOKEN"); { case envToken != "": gitlabToken = envToken + logPrint("CONFIG: Gitlab API Token found", nil) default: flag.Usage() - log.Printf("FATAL: config; gitlab api token not found\n") + logFatal("CONFIG: Giltab API Token not found", nil) } // manage gitlab url option switch envHost := os.Getenv("GITLAB_URL"); { case envHost != "": gitlabHost = envHost + logPrint("CONFIG: Gitlab host found", nil) default: flag.Usage() - log.Fatalf("FATAL: config; gitlab host not found\n") + logFatal("CONFIG: Gitlab host not found", nil) } // manage destination option switch envRepoDest := os.Getenv("GOGITLABBER_DESTINATION"); { case envRepoDest != "": repoDestinationPre = envRepoDest + logPrint("CONFIG: destination found", nil) default: flag.Usage() - log.Fatalf("FATAL: config; destination not found\n") + logFatal("CONFIG: destination not found", nil) } // add slash 🎩🎸 if not provided @@ -60,36 +79,41 @@ func manageArguments() { } // manage concurrency option - switch envConcurrency := os.Getenv("GOGITLABBER_CONCURRENCY"); { - case envConcurrency == "": - concurrency = 15 - case envConcurrency != "": + switch envConcurrency := os.Getenv("GOGITLABBER_CONCURRENCY"); { + case envConcurrency == "": + concurrency = 15 + case envConcurrency != "": concurrencyValue, err := strconv.Atoi(envConcurrency) if err != nil { - log.Fatalf("FATAL: invalid concurrency value in environment: %v", err) + logFatal("invalid concurrency value in environment: %v", err) } concurrency = concurrencyValue - default: - flag.Usage() - log.Fatalf("FATAL: config; concurrency not found\n") - } + logPrint("CONFIG: concurrency option found", nil) + default: + flag.Usage() + log.Fatalln("FATAL: config; concurrency not found") + } // manage archived option switch envArchived := os.Getenv("GOGITLABBER_ARCHIVED"); { case envArchived == "": includeArchived = "excluded" + logPrint("CONFIG: archive option found", nil) case envArchived == "any": includeArchived = envArchived + logPrint("CONFIG: archive option found", nil) case envArchived == "exclusive": includeArchived = envArchived + logPrint("CONFIG: archive option found", nil) case envArchived == "excluded": includeArchived = envArchived + logPrint("CONFIG: archive option found", nil) default: flag.Usage() - log.Fatalf("FATAL: config; no or wrong archive option found\n") + logFatal("FATAL: config; no or wrong archive option found", nil) } } diff --git a/cmd/gogitlabber/main.go b/cmd/gogitlabber/main.go index 4c21cee..c8c59c1 100644 --- a/cmd/gogitlabber/main.go +++ b/cmd/gogitlabber/main.go @@ -1,6 +1,9 @@ package main -import "log" +import ( + "io" + "log" +) // userdata var concurrency int @@ -8,6 +11,7 @@ var gitlabHost string var gitlabToken string var includeArchived string var repoDestinationPre string +var verbose bool // keep count 🧛 var clonedCount int @@ -27,16 +31,26 @@ func main() { manageArguments() // check for git - verifyGitAvailable() + err := verifyGitAvailable() + if err != nil { + logFatal("FATAL: git not found in path: %v", err) + } + logPrint("Git is available. Proceeding with the program.", nil) // fetch repository information from gitlab repositories, err := fetchRepositoriesGitlab() - if err != nil { - log.Fatalf("FATAL: %v", err) + if err != nil { + logFatal("FATAL: %v", err) + } + logPrint("Logged into GitLab, Repositories found. Proceeding with the program.", nil) + + // print progressbar ony if not in verbose mode + if !verbose { + progressBar(repositories) + log.SetOutput(io.Discard) } // manage found repositories - progressBar(repositories) checkoutRepositories(repositories, concurrency) printSummary() printPullError(pullErrorMsg) diff --git a/cmd/gogitlabber/output.go b/cmd/gogitlabber/output.go index 4585ec0..8715ed3 100644 --- a/cmd/gogitlabber/output.go +++ b/cmd/gogitlabber/output.go @@ -41,7 +41,7 @@ func progressBar(repositories []Repository) { func progressBarAdd(amount int) { if err := bar.Add(amount); err != nil { - log.Printf("ERROR: Progress bar update error: %v\n", err) + logPrint("ERROR: Progress bar update error: %v\n", err) } } @@ -66,3 +66,21 @@ func printPullError(pullErrorMsg []string) { } } } + +func logPrint(message string, err error) { + if verbose == true { + if err != nil { + log.Printf("gogitlabber | %v error: %v\n", message, err) + } + if err == nil { + log.Printf("gogitlabber | %v\n", message) + } + } +} + +func logFatal(message string, err error) { + if err != nil { + log.Fatalf("gogitlabber | FATAL: %v error: %v\n", message, err) + } + log.Fatalf("gogitlabber | FATAL: %v\n", message) +} diff --git a/cmd/gogitlabber/prerequisites.go b/cmd/gogitlabber/prerequisites.go index c420b2c..d6125b5 100644 --- a/cmd/gogitlabber/prerequisites.go +++ b/cmd/gogitlabber/prerequisites.go @@ -1,13 +1,13 @@ package main import ( - "log" "os/exec" ) -func verifyGitAvailable() { +func verifyGitAvailable() error { _, err := exec.LookPath("git") if err != nil { - log.Fatal("could not find git in path") + return err } + return nil }