diff --git a/backup.go b/backup.go index 7144ab3..f1c7007 100644 --- a/backup.go +++ b/backup.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "log" "net/url" "os/exec" @@ -16,6 +17,16 @@ var execCommand = exec.Command var appFS = afero.NewOsFs() var gitCommand = "git" var gethomeDir = homedir.Dir +var lookPath = exec.LookPath + +// checkGitAvailability verifies that the git command is available in the system PATH +func checkGitAvailability() error { + _, err := lookPath(gitCommand) + if err != nil { + return fmt.Errorf("git command not found in PATH. Please install git to use gitbackup. Visit https://git-scm.com/downloads for installation instructions") + } + return nil +} // Check if we have a copy of the repo already, if // we do, we update the repo, else we do a fresh clone diff --git a/backup_test.go b/backup_test.go index e0d737a..6ee639b 100644 --- a/backup_test.go +++ b/backup_test.go @@ -5,6 +5,7 @@ import ( "os" "os/exec" "path" + "strings" "sync" "testing" @@ -243,3 +244,38 @@ func TestSetupBackupDir(t *testing.T) { } } } + +func TestCheckGitAvailability(t *testing.T) { + // Save original lookPath + originalLookPath := lookPath + defer func() { + lookPath = originalLookPath + }() + + t.Run("git is available", func(t *testing.T) { + lookPath = func(file string) (string, error) { + if file == "git" { + return "/usr/bin/git", nil + } + return "", fmt.Errorf("not found") + } + err := checkGitAvailability() + if err != nil { + t.Errorf("Expected no error, got %v", err) + } + }) + + t.Run("git is not available", func(t *testing.T) { + lookPath = func(file string) (string, error) { + return "", fmt.Errorf("executable file not found in $PATH") + } + err := checkGitAvailability() + if err == nil { + t.Error("Expected error when git is not available, got nil") + } + expectedMsg := "git command not found in PATH" + if err != nil && !strings.HasPrefix(err.Error(), expectedMsg) { + t.Errorf("Expected error message to start with '%s', got '%s'", expectedMsg, err.Error()) + } + }) +} diff --git a/git_repository_clone.go b/git_repository_clone.go index 8af2912..6265c02 100644 --- a/git_repository_clone.go +++ b/git_repository_clone.go @@ -9,6 +9,11 @@ import ( // handleGitRepositoryClone clones or updates all repositories for the configured service func handleGitRepositoryClone(client interface{}, c *appConfig) error { + // Check if git is available before proceeding + if err := checkGitAvailability(); err != nil { + return err + } + // Used for waiting for all the goroutines to finish before exiting var wg sync.WaitGroup defer wg.Wait()