diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c25c46f..1ab35a2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: steps: - uses: actions/checkout@v4 - - run: git config --global url.https://github.com/.insteadOf ssh://git@github.com/ + - run: git config url.https://github.com/.insteadOf ssh://git@github.com/ - uses: actions/setup-go@v5 with: diff --git a/README.md b/README.md index aa78735..9d3a6d2 100644 --- a/README.md +++ b/README.md @@ -4,19 +4,7 @@ ## Usage -Set a `GETPATH` with `git config` or use the default of `~/src` - -```console -$ git config --global get.path "~/src" -``` - -The environmental variable `$GETPATH` may also be set: - -```shell -export GETPATH=~/src -``` - -Get a repository. +Get a repository to `~/src` ```console $ git get github.com/arbourd/git-get @@ -29,6 +17,18 @@ $ git get git@github.com:arbourd/git-get.git ~/src/github.com/arbourd/git-get ``` +Set a custom `GETPATH` with `git config`. + +```console +$ git config --global get.path "~/dev" +``` + +Set a custom `GETPATH` with the environmental variable `$GETPATH`. + +```shell +export GETPATH=~/dev +``` + ### Using SSH as the default By default, when getting a repository without specifying a protocol (eg: github.com/arbourd/git-get) HTTPS will be used. diff --git a/get/get.go b/get/get.go index 51bb5a0..ac882de 100644 --- a/get/get.go +++ b/get/get.go @@ -12,47 +12,50 @@ import ( "github.com/ldez/go-git-cmd-wrapper/v2/config" "github.com/ldez/go-git-cmd-wrapper/v2/git" "github.com/ldez/go-git-cmd-wrapper/v2/types" - "github.com/mitchellh/go-homedir" ) -// DefaultGetPath is the default path where repositories will be cloned if not configured -const defaultGetPath = "~/src" +const ( + // defaultGetpath is the default path where repositories will be cloned if not configured + defaultGetpath = "~/src" -// DefaultScheme is the scheme used when a URL is provided without one -const defaultScheme = "https" + // defaultScheme is the scheme used when a URL is provided without one + defaultScheme = "https" + + // GitConfigKey is the key that is used to store GETPATH information in the global Git config + GitConfigKey = "get.path" + + // EnvKey is the name of the environmental variable that is used to store GETPATH information + EnvKey = "GETPATH" +) // Path returns the absolute GETPATH func Path() (string, error) { - path := configPath() + p := configPath() - path, err := homedir.Expand(path) - if err != nil { - return "", err + if strings.HasPrefix(p, "~") { + dir, err := os.UserHomeDir() + if err != nil { + return "", err + } + + p = filepath.Join(dir, p[1:]) } - if !filepath.IsAbs(path) { - return "", fmt.Errorf("GETPATH entry is relative; must be an absolute path: \"%s\"", path) + if !filepath.IsAbs(p) { + return "", fmt.Errorf("GETPATH is not an absolute path: \"%s\"", p) } // Make GETPATH directory if it does not exist - if _, err := os.Stat(path); os.IsNotExist(err) { - err := os.MkdirAll(path, os.ModePerm) + if _, err := os.Stat(p); os.IsNotExist(err) { + err := os.MkdirAll(p, os.ModePerm) if err != nil { return "", err } } - return path, nil + return p, nil } -const ( - // GitConfigKey is the key that is used to store GETPATH information in the global Git config - GitConfigKey = "get.path" - - // EnvVar is the name of the environmental variable that is used to store GETPATH information - EnvVar = "GETPATH" -) - // configPath returns the GETPATH from the config, environment or default func configPath() string { out, _ := git.Config(config.Global, config.Get(GitConfigKey, "")) @@ -60,11 +63,11 @@ func configPath() string { return getpath } - if getpath := os.Getenv(EnvVar); getpath != "" { + if getpath := os.Getenv(EnvKey); getpath != "" { return getpath } - return defaultGetPath + return defaultGetpath } var scpSyntaxRe = regexp.MustCompile(`^(\w+)@([\w.-]+):(.*)$`) @@ -128,7 +131,7 @@ func Clone(u *url.URL, dir string) (string, error) { _, err = git.Clone(clone.Repository(u.String()), clone.Directory(dir)) if err != nil { - return "", err + return "", fmt.Errorf("git clone: %s", err) } } diff --git a/get/get_test.go b/get/get_test.go index dff974b..84bc587 100644 --- a/get/get_test.go +++ b/get/get_test.go @@ -1,74 +1,69 @@ package get import ( + "fmt" "net/url" "os" "path/filepath" - "strings" + "runtime" "testing" "github.com/ldez/go-git-cmd-wrapper/v2/config" "github.com/ldez/go-git-cmd-wrapper/v2/git" - "github.com/mitchellh/go-homedir" ) func TestPath(t *testing.T) { - home, _ := homedir.Dir() - - configDir, _ := os.MkdirTemp("", "git-get-gitconfig-") - envDir, _ := os.MkdirTemp("", "git-get-envvar-") - defer os.RemoveAll(configDir) - defer os.RemoveAll(envDir) - - out, _ := git.Config(config.Global, config.Get(GitConfigKey, "")) - if before := strings.TrimSpace(out); before != "" { - // Set git-get global gitconfig at the end of tests if previously set - defer git.Config(config.Global, config.Entry(GitConfigKey, before)) - } else { - // Unset git-get global gitconfig at the end of tests if previously unset - defer git.Config(config.Global, config.Unset(GitConfigKey, "")) + home, err := os.UserHomeDir() + if err != nil { + t.Fatalf("unable to detect homedir: %s", err) } + defaultGetpath := filepath.Join(home, "src") + configGetpath := t.TempDir() + envGetpath := t.TempDir() + cases := map[string]struct { - gitConfigGetPath string - envVarGetPath string + gitConfigGetpath string + envGetpath string expectedPath string wantErr bool }{ "default": { - expectedPath: filepath.Join(home, "src"), + expectedPath: defaultGetpath, }, "git config getpath": { - envVarGetPath: filepath.Join(configDir), - expectedPath: filepath.Join(configDir), + gitConfigGetpath: configGetpath, + expectedPath: configGetpath, }, "env var getpath": { - envVarGetPath: filepath.Join(envDir), - expectedPath: filepath.Join(envDir), + envGetpath: envGetpath, + expectedPath: envGetpath, }, - "git config getpath over env var getpath": { - gitConfigGetPath: filepath.Join(configDir), - envVarGetPath: filepath.Join(envDir), - expectedPath: filepath.Join(configDir), + "git config getpath overrides env var getpath": { + gitConfigGetpath: configGetpath, + envGetpath: envGetpath, + expectedPath: configGetpath, }, "relative GETPATH": { - envVarGetPath: "../test", - wantErr: true, + envGetpath: "../test", + wantErr: true, }, } for name, c := range cases { t.Run(name, func(t *testing.T) { - // Empty GETPATH for tests - git.Config(config.Global, config.Unset(GitConfigKey, "")) - os.Setenv("GETPATH", "") + err := gitConfigGlobalFixture(t) + if err != nil { + t.Fatalf("unable to setup test fixture: %s", err) + } - if c.gitConfigGetPath != "" { - git.Config(config.Global, config.Entry(GitConfigKey, c.gitConfigGetPath)) + if c.gitConfigGetpath != "" { + git.Config(config.Global, config.Entry(GitConfigKey, c.gitConfigGetpath)) } - if c.envVarGetPath != "" { - os.Setenv("GETPATH", c.envVarGetPath) + os.Setenv("GETPATH", "") + if c.envGetpath != "" { + os.Setenv("GETPATH", c.envGetpath) } path, err := Path() @@ -84,55 +79,46 @@ func TestPath(t *testing.T) { } func TestConfigPath(t *testing.T) { - configDir, _ := os.MkdirTemp("", "git-get-gitconfig-") - envDir, _ := os.MkdirTemp("", "git-get-envvar-") - defer os.RemoveAll(configDir) - defer os.RemoveAll(envDir) - - out, _ := git.Config(config.Global, config.Get(GitConfigKey, "")) - if before := strings.TrimSpace(out); before != "" { - // Set git-get global gitconfig at the end of tests if previously set - defer git.Config(config.Global, config.Entry(GitConfigKey, before)) - } else { - // Unset git-get global gitconfig at the end of tests if previously unset - defer git.Config(config.Global, config.Unset(GitConfigKey, "")) - } + configGetpath := t.TempDir() + envGetpath := t.TempDir() cases := map[string]struct { - gitConfigGetPath string - envVarGetPath string + gitConfigGetpath string + envGetpath string expectedPath string }{ "default": { expectedPath: "~/src", }, "git config getpath": { - envVarGetPath: filepath.Join(configDir), - expectedPath: filepath.Join(configDir), + envGetpath: configGetpath, + expectedPath: configGetpath, }, "env var getpath": { - envVarGetPath: filepath.Join(envDir), - expectedPath: filepath.Join(envDir), + envGetpath: envGetpath, + expectedPath: envGetpath, }, "git config getpath over env var getpath": { - gitConfigGetPath: filepath.Join(configDir), - envVarGetPath: filepath.Join(envDir), - expectedPath: filepath.Join(configDir), + gitConfigGetpath: configGetpath, + envGetpath: envGetpath, + expectedPath: configGetpath, }, } for name, c := range cases { t.Run(name, func(t *testing.T) { - // Empty GETPATH for tests - git.Config(config.Global, config.Unset(GitConfigKey, "")) - os.Setenv("GETPATH", "") + err := gitConfigGlobalFixture(t) + if err != nil { + t.Fatalf("unable to setup test fixture: %s", err) + } - if c.gitConfigGetPath != "" { - git.Config(config.Global, config.Entry(GitConfigKey, c.gitConfigGetPath)) + if c.gitConfigGetpath != "" { + git.Config(config.Global, config.Entry(GitConfigKey, c.gitConfigGetpath)) } - if c.envVarGetPath != "" { - os.Setenv("GETPATH", c.envVarGetPath) + os.Setenv("GETPATH", "") + if c.envGetpath != "" { + os.Setenv("GETPATH", c.envGetpath) } path := configPath() @@ -237,8 +223,7 @@ func TestDirectory(t *testing.T) { } func TestClone(t *testing.T) { - dir, _ := os.MkdirTemp("", "git-get-") - defer os.RemoveAll(dir) + dir := t.TempDir() cases := map[string]struct { url *url.URL @@ -302,3 +287,27 @@ func TestClone(t *testing.T) { }) } } + +// gitConfigGlobalFixture creates a temporary folder and .gitconfig to be used as the global +// Git config for tests. +func gitConfigGlobalFixture(t *testing.T) error { + // Skip fixture on Windows in CI + if os.Getenv("CI") == "true" && runtime.GOOS == "windows" { + git.Config(config.Global, config.Entry(GitConfigKey, "")) + return nil + } + + gitconfig := filepath.Join(t.TempDir(), ".gitconfig") + + _, err := os.Create(gitconfig) + if err != nil { + return fmt.Errorf("unable create .gitconfig: %s", err) + } + + err = os.Setenv("GIT_CONFIG_GLOBAL", gitconfig) + if err != nil { + return fmt.Errorf("unable to set GIT_CONFIG_GLOBAL: %s", err) + } + + return nil +} diff --git a/go.mod b/go.mod index 40f5a12..994c4fc 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,4 @@ module github.com/arbourd/git-get go 1.22 -require ( - github.com/ldez/go-git-cmd-wrapper/v2 v2.6.0 - github.com/mitchellh/go-homedir v1.1.0 -) +require github.com/ldez/go-git-cmd-wrapper/v2 v2.6.0 diff --git a/go.sum b/go.sum index cfd0163..23cdc88 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,2 @@ github.com/ldez/go-git-cmd-wrapper/v2 v2.6.0 h1:o5QIusOiH9phm1gY2UGO6JQjYSPFYbgFCcntOigBvMg= github.com/ldez/go-git-cmd-wrapper/v2 v2.6.0/go.mod h1:whnaSah+AmezZS8vwp8FyFzEBHZCLKywWILUj5D8Jq0= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=