diff --git a/commands/execenv/env.go b/commands/execenv/env.go index dca417a38e3c6139ed7c52bf717993e1de1af646..bee5ff487a59166c1913f6173880196eca691e0d 100644 --- a/commands/execenv/env.go +++ b/commands/execenv/env.go @@ -19,12 +19,12 @@ const gitBugNamespace = "git-bug" // Env is the environment of a command type Env struct { - Repo repository.ClockedRepo - Backend *cache.RepoCache - In In - Out Out - Err Out - RepoPath []string + Repo repository.ClockedRepo + Backend *cache.RepoCache + In In + Out Out + Err Out + GitDir string } func NewEnv() *Env { diff --git a/commands/execenv/loading.go b/commands/execenv/loading.go index 82b8904b5871ffac2c6409c66b514e7ee02d5f64..6e496ebcd54104296e939e4beb6a14658c9e4e7e 100644 --- a/commands/execenv/loading.go +++ b/commands/execenv/loading.go @@ -1,9 +1,9 @@ package execenv import ( + "errors" "fmt" "os" - "path/filepath" "github.com/spf13/cobra" "github.com/vbauerster/mpb/v8" @@ -173,14 +173,36 @@ func CacheBuildProgressBar(env *Env, events chan cache.BuildEvent) error { return nil } +var errNotDirectory = errors.New("path must be a directory for --git-dir or GIT_DIR") + func getRepoPath(env *Env) (string, error) { - if len(env.RepoPath) > 0 { - return filepath.Join(env.RepoPath...), nil + var path string + + if gitDir := os.Getenv("GIT_DIR"); gitDir != "" { + path = gitDir + } + + if path == "" && env.GitDir != "" { + path = env.GitDir + } + + if path == "" { + wd, err := os.Getwd() + if err != nil { + return "", fmt.Errorf("unable to get the current working directory: %q", err) + } + + path = wd } - cwd, err := os.Getwd() + fi, err := os.Stat(path) if err != nil { - return "", fmt.Errorf("unable to get the current working directory: %q", err) + return "", err } - return cwd, nil + + if !fi.IsDir() { + return "", errNotDirectory + } + + return path, nil } diff --git a/commands/execenv/loading_test.go b/commands/execenv/loading_test.go new file mode 100644 index 0000000000000000000000000000000000000000..6b803395b6fe20259b445a4c0d2ff6969f5f6919 --- /dev/null +++ b/commands/execenv/loading_test.go @@ -0,0 +1,78 @@ +package execenv + +import ( + "os" + "path/filepath" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// ***** WARNING ***** - due to the use of testing with an environment +// +// variable, do NOT use t.Parallel() with these +// test cases. +func TestGetRepoPath(t *testing.T) { + t.Run("no Git path provided (use WD)", func(t *testing.T) { + // WD during tests is the directory containing the test file + path, err := getRepoPath(&Env{}) + require.NoError(t, err) + assert.True(t, strings.HasSuffix(path, filepath.Join("commands", "execenv"))) + }) + + t.Run("flag provided", func(t *testing.T) { + gitDir := filepath.Join(string(filepath.Separator), "tmp") + + path, err := getRepoPath(&Env{ + GitDir: gitDir, + }) + require.NoError(t, err) + assert.Equal(t, gitDir, path) + }) + + t.Run("environment variable provided", func(t *testing.T) { + gitDir := filepath.Join(string(filepath.Separator), "tmp") + t.Setenv("GIT_DIR", gitDir) + + path, err := getRepoPath(&Env{}) + require.NoError(t, err) + assert.Equal(t, gitDir, path) + }) + + t.Run("GIT_DIR supercedes --git-dir", func(t *testing.T) { + homeDir, err := os.UserHomeDir() + require.NoError(t, err) + + tmpDir := filepath.Join(string(filepath.Separator), "tmp") + t.Setenv("GIT_DIR", tmpDir) + + path, err := getRepoPath(&Env{ + GitDir: homeDir, + }) + require.NoError(t, err) + assert.Equal(t, tmpDir, path) + + }) + + t.Run("path does not exist", func(t *testing.T) { + _, err := getRepoPath(&Env{ + GitDir: filepath.Join("/", "tmp", "does-not-exist"), + }) + require.ErrorIs(t, err, os.ErrNotExist) + }) + + t.Run("path is not a directory", func(t *testing.T) { + gitDir := filepath.Join(os.TempDir(), "plain-file") + + f, err := os.Create(gitDir) + require.NoError(t, err) + require.NoError(t, f.Close()) + + _, err = getRepoPath(&Env{ + GitDir: gitDir, + }) + require.ErrorIs(t, err, errNotDirectory) + }) +} diff --git a/commands/root.go b/commands/root.go index 38db157768339ccb87eaf1ecb73f789f428b381c..11e34d74ffc4aceaa868606e5bea3c9f2b05cd98 100644 --- a/commands/root.go +++ b/commands/root.go @@ -21,6 +21,10 @@ git-bug use git objects to store the bug tracking separated from the files history. As bugs are regular git objects, they can be pushed and pulled from/to the same git remote you are already using to collaborate with other people. +By default, git-bug manages bugs and users in the Git repository containing +the current working directory. This behavior can be changed using the --git-dir +flag described below, or by setting the GIT-DIR environment variable, which +takes precedence over the CLI flag. `, PersistentPreRun: func(cmd *cobra.Command, args []string) { @@ -55,7 +59,7 @@ the same git remote you are already using to collaborate with other people. } env := execenv.NewEnv() - cmd.PersistentFlags().StringArrayVarP(&env.RepoPath, "repo-path", "C", []string{}, `Run as if git-bug was started in instead of the current working directory.`) + cmd.PersistentFlags().StringVar(&env.GitDir, "git-dir", "", `run as if git-bug was started in `) addCmdWithGroup(bugcmd.NewBugCommand(env), entityGroup) addCmdWithGroup(usercmd.NewUserCommand(env), entityGroup)