Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve tests by using temporary Git config #22

Merged
merged 1 commit into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:

steps:
- uses: actions/checkout@v4
- run: git config --global url.https://github.com/.insteadOf ssh://[email protected]/
- run: git config url.https://github.com/.insteadOf ssh://[email protected]/

- uses: actions/setup-go@v5
with:
Expand Down
26 changes: 13 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -29,6 +17,18 @@ $ git get [email protected]: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.
Expand Down
53 changes: 28 additions & 25 deletions get/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,59 +12,62 @@ 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, ""))
if getpath := strings.TrimSpace(out); getpath != "" {
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.-]+):(.*)$`)
Expand Down Expand Up @@ -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)
}
}

Expand Down
152 changes: 79 additions & 73 deletions get/get_test.go
Original file line number Diff line number Diff line change
@@ -1,75 +1,62 @@
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)
home, err := os.UserHomeDir()
if err != nil {
t.Fatalf("unable to detect homedir: %s", err)
}

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, ""))
defaultGetpath := filepath.Join(home, "src")
configGetpath := t.TempDir()
envGetpath := t.TempDir()
err = gitConfigGlobalFixture(t)
if err != nil {
t.Fatalf("unable to setup test fixture: %s", err)
}

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", "")

if c.gitConfigGetPath != "" {
git.Config(config.Global, config.Entry(GitConfigKey, c.gitConfigGetPath))
}

if c.envVarGetPath != "" {
os.Setenv("GETPATH", c.envVarGetPath)
}
setupEnv(c.gitConfigGetpath, c.envGetpath)

path, err := Path()
if err != nil && !c.wantErr {
Expand All @@ -84,56 +71,39 @@ 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()
err := gitConfigGlobalFixture(t)
if err != nil {
t.Fatalf("unable to setup test fixture: %s", err)
}

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", "")

if c.gitConfigGetPath != "" {
git.Config(config.Global, config.Entry(GitConfigKey, c.gitConfigGetPath))
}

if c.envVarGetPath != "" {
os.Setenv("GETPATH", c.envVarGetPath)
}
setupEnv(c.gitConfigGetpath, c.envGetpath)

path := configPath()
if path != c.expectedPath {
Expand Down Expand Up @@ -237,8 +207,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
Expand Down Expand Up @@ -302,3 +271,40 @@ 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" {
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
}

// setupEnv unsets both global Git config and environmental GETPATHs, before setting them
// again if provided to ensure that the test environement is clean.
func setupEnv(gitConfigGetpath, envGetpath string) {
os.Setenv("GETPATH", "")
if envGetpath != "" {
os.Setenv("GETPATH", envGetpath)
}

git.Config(config.Global, config.Entry(GitConfigKey, ""))
if gitConfigGetpath != "" {
git.Config(config.Global, config.Entry(GitConfigKey, gitConfigGetpath))
}
}
5 changes: 1 addition & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -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=