* Revert "Refactor to use new git client (#6447)"
This reverts commit 57fbe4f317.
* Fix pr create regression
399 lines
10 KiB
Go
399 lines
10 KiB
Go
package git
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/cli/cli/v2/internal/run"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestClientCommand(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
repoDir string
|
|
gitPath string
|
|
wantExe string
|
|
wantArgs []string
|
|
}{
|
|
{
|
|
name: "creates command",
|
|
gitPath: "path/to/git",
|
|
wantExe: "path/to/git",
|
|
wantArgs: []string{"path/to/git", "ref-log"},
|
|
},
|
|
{
|
|
name: "adds repo directory configuration",
|
|
repoDir: "path/to/repo",
|
|
gitPath: "path/to/git",
|
|
wantExe: "path/to/git",
|
|
wantArgs: []string{"path/to/git", "-C", "path/to/repo", "ref-log"},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
in, out, errOut := &bytes.Buffer{}, &bytes.Buffer{}, &bytes.Buffer{}
|
|
client := Client{
|
|
Stdin: in,
|
|
Stdout: out,
|
|
Stderr: errOut,
|
|
RepoDir: tt.repoDir,
|
|
GitPath: tt.gitPath,
|
|
}
|
|
cmd, err := client.Command(context.Background(), "ref-log")
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, tt.wantExe, cmd.Path)
|
|
assert.Equal(t, tt.wantArgs, cmd.Args)
|
|
assert.Equal(t, in, cmd.Stdin)
|
|
assert.Equal(t, out, cmd.Stdout)
|
|
assert.Equal(t, errOut, cmd.Stderr)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestClientAuthenticatedCommand(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
path string
|
|
wantArgs []string
|
|
}{
|
|
{
|
|
name: "adds credential helper config options",
|
|
path: "path/to/gh",
|
|
wantArgs: []string{"git", "-c", "credential.helper=", "-c", "credential.helper=!\"path/to/gh\" auth git-credential", "fetch"},
|
|
},
|
|
{
|
|
name: "fallback when GhPath is not set",
|
|
wantArgs: []string{"git", "-c", "credential.helper=", "-c", "credential.helper=!\"gh\" auth git-credential", "fetch"},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
client := Client{
|
|
GhPath: tt.path,
|
|
GitPath: "git",
|
|
}
|
|
cmd, err := client.AuthenticatedCommand(context.Background(), "fetch")
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, tt.wantArgs, cmd.Args)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestClientRemotes(t *testing.T) {
|
|
tempDir := t.TempDir()
|
|
initRepo(t, tempDir)
|
|
gitDir := filepath.Join(tempDir, ".git")
|
|
remoteFile := filepath.Join(gitDir, "config")
|
|
remotes := `
|
|
[remote "origin"]
|
|
url = git@example.com:monalisa/origin.git
|
|
[remote "test"]
|
|
url = git://github.com/hubot/test.git
|
|
gh-resolved = other
|
|
[remote "upstream"]
|
|
url = https://github.com/monalisa/upstream.git
|
|
gh-resolved = base
|
|
[remote "github"]
|
|
url = git@github.com:hubot/github.git
|
|
`
|
|
f, err := os.OpenFile(remoteFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0755)
|
|
assert.NoError(t, err)
|
|
_, err = f.Write([]byte(remotes))
|
|
assert.NoError(t, err)
|
|
err = f.Close()
|
|
assert.NoError(t, err)
|
|
client := Client{
|
|
RepoDir: tempDir,
|
|
}
|
|
rs, err := client.Remotes(context.Background())
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 4, len(rs))
|
|
assert.Equal(t, "upstream", rs[0].Name)
|
|
assert.Equal(t, "base", rs[0].Resolved)
|
|
assert.Equal(t, "github", rs[1].Name)
|
|
assert.Equal(t, "", rs[1].Resolved)
|
|
assert.Equal(t, "origin", rs[2].Name)
|
|
assert.Equal(t, "", rs[2].Resolved)
|
|
assert.Equal(t, "test", rs[3].Name)
|
|
assert.Equal(t, "other", rs[3].Resolved)
|
|
}
|
|
|
|
func TestClientRemotesNoResolvedRemote(t *testing.T) {
|
|
tempDir := t.TempDir()
|
|
initRepo(t, tempDir)
|
|
gitDir := filepath.Join(tempDir, ".git")
|
|
remoteFile := filepath.Join(gitDir, "config")
|
|
remotes := `
|
|
[remote "origin"]
|
|
url = git@example.com:monalisa/origin.git
|
|
[remote "test"]
|
|
url = git://github.com/hubot/test.git
|
|
[remote "upstream"]
|
|
url = https://github.com/monalisa/upstream.git
|
|
[remote "github"]
|
|
url = git@github.com:hubot/github.git
|
|
`
|
|
f, err := os.OpenFile(remoteFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0755)
|
|
assert.NoError(t, err)
|
|
_, err = f.Write([]byte(remotes))
|
|
assert.NoError(t, err)
|
|
err = f.Close()
|
|
assert.NoError(t, err)
|
|
client := Client{
|
|
RepoDir: tempDir,
|
|
}
|
|
rs, err := client.Remotes(context.Background())
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 4, len(rs))
|
|
assert.Equal(t, "upstream", rs[0].Name)
|
|
assert.Equal(t, "github", rs[1].Name)
|
|
assert.Equal(t, "origin", rs[2].Name)
|
|
assert.Equal(t, "", rs[2].Resolved)
|
|
assert.Equal(t, "test", rs[3].Name)
|
|
}
|
|
|
|
func TestParseRemotes(t *testing.T) {
|
|
remoteList := []string{
|
|
"mona\tgit@github.com:monalisa/myfork.git (fetch)",
|
|
"origin\thttps://github.com/monalisa/octo-cat.git (fetch)",
|
|
"origin\thttps://github.com/monalisa/octo-cat-push.git (push)",
|
|
"upstream\thttps://example.com/nowhere.git (fetch)",
|
|
"upstream\thttps://github.com/hubot/tools (push)",
|
|
"zardoz\thttps://example.com/zed.git (push)",
|
|
"koke\tgit://github.com/koke/grit.git (fetch)",
|
|
"koke\tgit://github.com/koke/grit.git (push)",
|
|
}
|
|
|
|
r := parseRemotes(remoteList)
|
|
assert.Equal(t, 5, len(r))
|
|
|
|
assert.Equal(t, "mona", r[0].Name)
|
|
assert.Equal(t, "ssh://git@github.com/monalisa/myfork.git", r[0].FetchURL.String())
|
|
assert.Nil(t, r[0].PushURL)
|
|
|
|
assert.Equal(t, "origin", r[1].Name)
|
|
assert.Equal(t, "/monalisa/octo-cat.git", r[1].FetchURL.Path)
|
|
assert.Equal(t, "/monalisa/octo-cat-push.git", r[1].PushURL.Path)
|
|
|
|
assert.Equal(t, "upstream", r[2].Name)
|
|
assert.Equal(t, "example.com", r[2].FetchURL.Host)
|
|
assert.Equal(t, "github.com", r[2].PushURL.Host)
|
|
|
|
assert.Equal(t, "zardoz", r[3].Name)
|
|
assert.Nil(t, r[3].FetchURL)
|
|
assert.Equal(t, "https://example.com/zed.git", r[3].PushURL.String())
|
|
|
|
assert.Equal(t, "koke", r[4].Name)
|
|
assert.Equal(t, "/koke/grit.git", r[4].FetchURL.Path)
|
|
assert.Equal(t, "/koke/grit.git", r[4].PushURL.Path)
|
|
}
|
|
|
|
func TestClientLastCommit(t *testing.T) {
|
|
client := Client{
|
|
RepoDir: "./fixtures/simple.git",
|
|
}
|
|
c, err := client.LastCommit(context.Background())
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "6f1a2405cace1633d89a79c74c65f22fe78f9659", c.Sha)
|
|
assert.Equal(t, "Second commit", c.Title)
|
|
}
|
|
|
|
func TestClientCommitBody(t *testing.T) {
|
|
client := Client{
|
|
RepoDir: "./fixtures/simple.git",
|
|
}
|
|
body, err := client.CommitBody(context.Background(), "6f1a2405cace1633d89a79c74c65f22fe78f9659")
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "I'm starting to get the hang of things\n", body)
|
|
}
|
|
|
|
func TestClientUncommittedChangeCount(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
expected int
|
|
output string
|
|
}{
|
|
{
|
|
name: "no changes",
|
|
expected: 0,
|
|
output: "",
|
|
},
|
|
{
|
|
name: "one change",
|
|
expected: 1,
|
|
output: " M poem.txt",
|
|
},
|
|
{
|
|
name: "untracked file",
|
|
expected: 2,
|
|
output: " M poem.txt\n?? new.txt",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
cs, restore := run.Stub()
|
|
defer restore(t)
|
|
cs.Register(`git status --porcelain`, 0, tt.output)
|
|
client := Client{}
|
|
ucc, err := client.UncommittedChangeCount(context.Background())
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, tt.expected, ucc)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestClientCurrentBranch(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
stub string
|
|
expected string
|
|
}{
|
|
{
|
|
name: "branch name",
|
|
stub: "branch-name\n",
|
|
expected: "branch-name",
|
|
},
|
|
{
|
|
name: "ref",
|
|
stub: "refs/heads/branch-name\n",
|
|
expected: "branch-name",
|
|
},
|
|
{
|
|
name: "escaped ref",
|
|
stub: "refs/heads/branch\u00A0with\u00A0non\u00A0breaking\u00A0space\n",
|
|
expected: "branch\u00A0with\u00A0non\u00A0breaking\u00A0space",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
cs, teardown := run.Stub()
|
|
defer teardown(t)
|
|
cs.Register(`git symbolic-ref --quiet HEAD`, 0, tt.stub)
|
|
client := Client{}
|
|
branch, err := client.CurrentBranch(context.Background())
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, tt.expected, branch)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestClientCurrentBranch_detached_head(t *testing.T) {
|
|
cs, teardown := run.Stub()
|
|
defer teardown(t)
|
|
cs.Register(`git symbolic-ref --quiet HEAD`, 1, "")
|
|
client := Client{}
|
|
_, err := client.CurrentBranch(context.Background())
|
|
assert.EqualError(t, err, "failed to run git: not on any branch")
|
|
}
|
|
|
|
func TestParseCloneArgs(t *testing.T) {
|
|
type wanted struct {
|
|
args []string
|
|
dir string
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args []string
|
|
want wanted
|
|
}{
|
|
{
|
|
name: "args and target",
|
|
args: []string{"target_directory", "-o", "upstream", "--depth", "1"},
|
|
want: wanted{
|
|
args: []string{"-o", "upstream", "--depth", "1"},
|
|
dir: "target_directory",
|
|
},
|
|
},
|
|
{
|
|
name: "only args",
|
|
args: []string{"-o", "upstream", "--depth", "1"},
|
|
want: wanted{
|
|
args: []string{"-o", "upstream", "--depth", "1"},
|
|
dir: "",
|
|
},
|
|
},
|
|
{
|
|
name: "only target",
|
|
args: []string{"target_directory"},
|
|
want: wanted{
|
|
args: []string{},
|
|
dir: "target_directory",
|
|
},
|
|
},
|
|
{
|
|
name: "no args",
|
|
args: []string{},
|
|
want: wanted{
|
|
args: []string{},
|
|
dir: "",
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
args, dir := parseCloneArgs(tt.args)
|
|
got := wanted{args: args, dir: dir}
|
|
assert.Equal(t, got, tt.want)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestClientAddRemote(t *testing.T) {
|
|
tests := []struct {
|
|
title string
|
|
name string
|
|
url string
|
|
dir string
|
|
branches []string
|
|
want string
|
|
}{
|
|
{
|
|
title: "fetch all",
|
|
name: "test",
|
|
url: "URL",
|
|
dir: "DIRECTORY",
|
|
branches: []string{},
|
|
want: "git -C DIRECTORY remote add -f test URL",
|
|
},
|
|
{
|
|
title: "fetch specific branches only",
|
|
name: "test",
|
|
url: "URL",
|
|
dir: "DIRECTORY",
|
|
branches: []string{"trunk", "dev"},
|
|
want: "git -C DIRECTORY remote add -t trunk -t dev -f test URL",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.title, func(t *testing.T) {
|
|
cs, cmdTeardown := run.Stub()
|
|
defer cmdTeardown(t)
|
|
cs.Register(tt.want, 0, "")
|
|
client := Client{
|
|
RepoDir: tt.dir,
|
|
}
|
|
_, err := client.AddRemote(context.Background(), tt.name, tt.url, tt.branches)
|
|
assert.NoError(t, err)
|
|
})
|
|
}
|
|
}
|
|
|
|
func initRepo(t *testing.T, dir string) {
|
|
errBuf := &bytes.Buffer{}
|
|
inBuf := &bytes.Buffer{}
|
|
outBuf := &bytes.Buffer{}
|
|
client := Client{
|
|
RepoDir: dir,
|
|
Stderr: errBuf,
|
|
Stdin: inBuf,
|
|
Stdout: outBuf,
|
|
}
|
|
cmd, err := client.Command(context.Background(), []string{"init", "--quiet"}...)
|
|
assert.NoError(t, err)
|
|
err = cmd.Run()
|
|
assert.NoError(t, err)
|
|
}
|