mirror of
https://github.com/x-motemen/ghq.git
synced 2026-09-10 07:26:27 -04:00
508 lines
13 KiB
Go
508 lines
13 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"reflect"
|
|
"testing"
|
|
|
|
"github.com/x-motemen/ghq/cmdutil"
|
|
)
|
|
|
|
var (
|
|
remoteDummyURL = mustParseURL("https://example.com/git/repo")
|
|
dummySvnInfo = []byte(`Path: trunk
|
|
URL: https://svn.apache.org/repos/asf/subversion/trunk
|
|
Relative URL: ^/subversion/trunk
|
|
Repository Root: https://svn.apache.org/repos/asf
|
|
Repository UUID: 13f79535-47bb-0310-9956-ffa450edef68
|
|
Revision: 1872085
|
|
Node Kind: directory
|
|
Last Changed Author: julianfoad
|
|
Last Changed Rev: 1872031
|
|
Last Changed Date: 2019-08-16 15:16:45 +0900 (Fri, 16 Aug 2019)
|
|
`)
|
|
)
|
|
|
|
func TestVCSBackend(t *testing.T) {
|
|
tempDir := newTempDir(t)
|
|
localDir := filepath.Join(tempDir, "repo")
|
|
var _commands []*exec.Cmd
|
|
lastCommand := func() *exec.Cmd { return _commands[len(_commands)-1] }
|
|
defer func(orig func(cmd *exec.Cmd) error) {
|
|
cmdutil.CommandRunner = orig
|
|
}(cmdutil.CommandRunner)
|
|
cmdutil.CommandRunner = func(cmd *exec.Cmd) error {
|
|
_commands = append(_commands, cmd)
|
|
if reflect.DeepEqual(cmd.Args, []string{"svn", "info", "https://example.com/git/repo/trunk"}) {
|
|
return fmt.Errorf("[test] failed to svn info")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
testCases := []struct {
|
|
name string
|
|
f func() error
|
|
expect []string
|
|
dir string
|
|
}{{
|
|
name: "[git] clone",
|
|
f: func() error {
|
|
return GitBackend.Clone(&vcsGetOption{
|
|
url: remoteDummyURL,
|
|
dir: localDir,
|
|
})
|
|
},
|
|
expect: []string{"git", "clone", remoteDummyURL.String(), localDir},
|
|
}, {
|
|
name: "[git] shallow clone",
|
|
f: func() error {
|
|
return GitBackend.Clone(&vcsGetOption{
|
|
url: remoteDummyURL,
|
|
dir: localDir,
|
|
shallow: true,
|
|
silent: true,
|
|
})
|
|
},
|
|
expect: []string{"git", "clone", "--depth", "1", remoteDummyURL.String(), localDir},
|
|
}, {
|
|
name: "[git] clone specific branch",
|
|
f: func() error {
|
|
return GitBackend.Clone(&vcsGetOption{
|
|
url: remoteDummyURL,
|
|
dir: localDir,
|
|
branch: "hello",
|
|
})
|
|
},
|
|
expect: []string{"git", "clone", "--branch", "hello", "--single-branch", remoteDummyURL.String(), localDir},
|
|
}, {
|
|
name: "[git] update",
|
|
f: func() error {
|
|
return GitBackend.Update(&vcsGetOption{
|
|
dir: localDir,
|
|
})
|
|
},
|
|
expect: []string{"git", "pull", "--ff-only"},
|
|
dir: localDir,
|
|
}, {
|
|
name: "[git] fetch",
|
|
f: func() error {
|
|
defer func(orig func(cmd *exec.Cmd) error) {
|
|
cmdutil.CommandRunner = orig
|
|
}(cmdutil.CommandRunner)
|
|
cmdutil.CommandRunner = func(cmd *exec.Cmd) error {
|
|
_commands = append(_commands, cmd)
|
|
if reflect.DeepEqual(cmd.Args, []string{"git", "rev-parse", "@{upstream}"}) {
|
|
return fmt.Errorf("[test] failed to git rev-parse @{upstream}")
|
|
}
|
|
return nil
|
|
}
|
|
return GitBackend.Update(&vcsGetOption{
|
|
dir: localDir,
|
|
})
|
|
},
|
|
expect: []string{"git", "fetch"},
|
|
dir: localDir,
|
|
}, {
|
|
name: "[git] recursive",
|
|
f: func() error {
|
|
return GitBackend.Clone(&vcsGetOption{
|
|
url: remoteDummyURL,
|
|
dir: localDir,
|
|
recursive: true,
|
|
})
|
|
},
|
|
expect: []string{"git", "clone", "--recursive", remoteDummyURL.String(), localDir},
|
|
}, {
|
|
name: "[git] update recursive",
|
|
f: func() error {
|
|
return GitBackend.Update(&vcsGetOption{
|
|
dir: localDir,
|
|
recursive: true,
|
|
})
|
|
},
|
|
expect: []string{"git", "submodule", "update", "--init", "--recursive"},
|
|
dir: localDir,
|
|
}, {
|
|
name: "[git] bare clone",
|
|
f: func() error {
|
|
return GitBackend.Clone(&vcsGetOption{
|
|
url: remoteDummyURL,
|
|
dir: localDir,
|
|
bare: true,
|
|
silent: true,
|
|
})
|
|
},
|
|
expect: []string{"git", "clone", "--bare", remoteDummyURL.String(), localDir},
|
|
}, {
|
|
name: "[git] (partial) blobless clone",
|
|
f: func() error {
|
|
return GitBackend.Clone(&vcsGetOption{
|
|
url: remoteDummyURL,
|
|
dir: localDir,
|
|
partial: "blobless",
|
|
})
|
|
},
|
|
expect: []string{"git", "clone", "--filter=blob:none", remoteDummyURL.String(), localDir},
|
|
}, {
|
|
name: "[git] (partial) treeless clone",
|
|
f: func() error {
|
|
return GitBackend.Clone(&vcsGetOption{
|
|
url: remoteDummyURL,
|
|
dir: localDir,
|
|
partial: "treeless",
|
|
})
|
|
},
|
|
expect: []string{"git", "clone", "--filter=tree:0", remoteDummyURL.String(), localDir},
|
|
}, {
|
|
name: "[git] switch git-svn on update",
|
|
f: func() error {
|
|
err := os.MkdirAll(filepath.Join(localDir, ".git", "svn"), 0755)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer os.RemoveAll(filepath.Join(localDir, ".git"))
|
|
return GitBackend.Update(&vcsGetOption{
|
|
dir: localDir,
|
|
})
|
|
},
|
|
expect: []string{"git", "svn", "rebase"},
|
|
dir: localDir,
|
|
}, {
|
|
name: "[svn] checkout",
|
|
f: func() error {
|
|
return SubversionBackend.Clone(&vcsGetOption{
|
|
url: remoteDummyURL,
|
|
dir: localDir,
|
|
})
|
|
},
|
|
expect: []string{"svn", "checkout", remoteDummyURL.String(), localDir},
|
|
}, {
|
|
name: "[svn] checkout shallow",
|
|
f: func() error {
|
|
return SubversionBackend.Clone(&vcsGetOption{
|
|
url: remoteDummyURL,
|
|
dir: localDir,
|
|
shallow: true,
|
|
})
|
|
},
|
|
expect: []string{"svn", "checkout", "--depth", "immediates", remoteDummyURL.String(), localDir},
|
|
}, {
|
|
name: "[svn] checkout specific branch",
|
|
f: func() error {
|
|
return SubversionBackend.Clone(&vcsGetOption{
|
|
url: remoteDummyURL,
|
|
dir: localDir,
|
|
branch: "hello",
|
|
})
|
|
},
|
|
expect: []string{"svn", "checkout", remoteDummyURL.String() + "/branches/hello", localDir},
|
|
}, {
|
|
name: "[svn] checkout with filling trunk",
|
|
f: func() error {
|
|
defer func(orig func(cmd *exec.Cmd) error) {
|
|
cmdutil.CommandRunner = orig
|
|
}(cmdutil.CommandRunner)
|
|
cmdutil.CommandRunner = func(cmd *exec.Cmd) error {
|
|
_commands = append(_commands, cmd)
|
|
if reflect.DeepEqual(cmd.Args, []string{"svn", "info", "https://example.com/git/repo/trunk"}) {
|
|
cmd.Stdout.Write(dummySvnInfo)
|
|
}
|
|
return nil
|
|
}
|
|
return SubversionBackend.Clone(&vcsGetOption{
|
|
url: remoteDummyURL,
|
|
dir: localDir,
|
|
})
|
|
},
|
|
expect: []string{"svn", "checkout", remoteDummyURL.String() + "/trunk", localDir},
|
|
}, {
|
|
name: "[svn] update",
|
|
f: func() error {
|
|
return SubversionBackend.Update(&vcsGetOption{
|
|
dir: localDir,
|
|
silent: true,
|
|
})
|
|
},
|
|
expect: []string{"svn", "update"},
|
|
dir: localDir,
|
|
}, {
|
|
name: "[git-svn] clone",
|
|
f: func() error {
|
|
return GitsvnBackend.Clone(&vcsGetOption{
|
|
url: remoteDummyURL,
|
|
dir: localDir,
|
|
})
|
|
},
|
|
expect: []string{"git", "svn", "clone", remoteDummyURL.String(), localDir},
|
|
}, {
|
|
name: "[git-svn] update",
|
|
f: func() error {
|
|
return GitsvnBackend.Update(&vcsGetOption{
|
|
dir: localDir,
|
|
})
|
|
},
|
|
expect: []string{"git", "svn", "rebase"},
|
|
dir: localDir,
|
|
}, {
|
|
name: "[git-svn] clone shallow",
|
|
f: func() error {
|
|
defer func(orig func(cmd *exec.Cmd) error) {
|
|
cmdutil.CommandRunner = orig
|
|
}(cmdutil.CommandRunner)
|
|
cmdutil.CommandRunner = func(cmd *exec.Cmd) error {
|
|
_commands = append(_commands, cmd)
|
|
if reflect.DeepEqual(cmd.Args, []string{"svn", "info", "https://example.com/git/repo/trunk"}) {
|
|
cmd.Stdout.Write(dummySvnInfo)
|
|
}
|
|
return nil
|
|
}
|
|
return GitsvnBackend.Clone(&vcsGetOption{
|
|
url: remoteDummyURL,
|
|
dir: localDir,
|
|
shallow: true,
|
|
})
|
|
},
|
|
expect: []string{"git", "svn", "clone", "-s", "-r1872031:HEAD", remoteDummyURL.String(), localDir},
|
|
}, {
|
|
name: "[git-svn] clone specific branch",
|
|
f: func() error {
|
|
return GitsvnBackend.Clone(&vcsGetOption{
|
|
url: remoteDummyURL,
|
|
dir: localDir,
|
|
branch: "hello",
|
|
})
|
|
},
|
|
expect: []string{"git", "svn", "clone", remoteDummyURL.String() + "/branches/hello", localDir},
|
|
}, {
|
|
name: "[git-svn] clone specific branch from tagged URL with shallow",
|
|
f: func() error {
|
|
defer func(orig func(cmd *exec.Cmd) error) {
|
|
cmdutil.CommandRunner = orig
|
|
}(cmdutil.CommandRunner)
|
|
cmdutil.CommandRunner = func(cmd *exec.Cmd) error {
|
|
_commands = append(_commands, cmd)
|
|
if reflect.DeepEqual(
|
|
cmd.Args, []string{"svn", "info", "https://example.com/git/repo/branches/develop"},
|
|
) {
|
|
cmd.Stdout.Write(dummySvnInfo)
|
|
}
|
|
return nil
|
|
}
|
|
copied := *remoteDummyURL
|
|
copied.Path += "/tags/v9.9.9"
|
|
return GitsvnBackend.Clone(&vcsGetOption{
|
|
url: &copied,
|
|
dir: localDir,
|
|
branch: "develop",
|
|
shallow: true,
|
|
})
|
|
},
|
|
expect: []string{
|
|
"git", "svn", "clone", "-r1872031:HEAD", remoteDummyURL.String() + "/branches/develop", localDir},
|
|
}, {
|
|
name: "[hg] clone",
|
|
f: func() error {
|
|
return MercurialBackend.Clone(&vcsGetOption{
|
|
url: remoteDummyURL,
|
|
dir: localDir,
|
|
})
|
|
},
|
|
expect: []string{"hg", "clone", remoteDummyURL.String(), localDir},
|
|
}, {
|
|
name: "[hg] update",
|
|
f: func() error {
|
|
return MercurialBackend.Update(&vcsGetOption{
|
|
dir: localDir,
|
|
})
|
|
},
|
|
expect: []string{"hg", "pull", "--update"},
|
|
dir: localDir,
|
|
}, {
|
|
name: "[hg] clone shallow",
|
|
f: func() error {
|
|
return MercurialBackend.Clone(&vcsGetOption{
|
|
url: remoteDummyURL,
|
|
dir: localDir,
|
|
shallow: true,
|
|
})
|
|
},
|
|
expect: []string{"hg", "clone", remoteDummyURL.String(), localDir},
|
|
}, {
|
|
name: "[hg] clone specific branch",
|
|
f: func() error {
|
|
return MercurialBackend.Clone(&vcsGetOption{
|
|
url: remoteDummyURL,
|
|
dir: localDir,
|
|
branch: "hello",
|
|
})
|
|
},
|
|
expect: []string{"hg", "clone", "--branch", "hello", remoteDummyURL.String(), localDir},
|
|
}, {
|
|
name: "[darcs] clone",
|
|
f: func() error {
|
|
return DarcsBackend.Clone(&vcsGetOption{
|
|
url: remoteDummyURL,
|
|
dir: localDir,
|
|
})
|
|
},
|
|
expect: []string{"darcs", "get", remoteDummyURL.String(), localDir},
|
|
}, {
|
|
name: "[darcs] clone shallow",
|
|
f: func() error {
|
|
return DarcsBackend.Clone(&vcsGetOption{
|
|
url: remoteDummyURL,
|
|
dir: localDir,
|
|
shallow: true,
|
|
})
|
|
},
|
|
expect: []string{"darcs", "get", "--lazy", remoteDummyURL.String(), localDir},
|
|
}, {
|
|
name: "[darcs] update",
|
|
f: func() error {
|
|
return DarcsBackend.Update(&vcsGetOption{
|
|
dir: localDir,
|
|
})
|
|
},
|
|
expect: []string{"darcs", "pull"},
|
|
dir: localDir,
|
|
}, {
|
|
name: "[pijul] clone",
|
|
f: func() error {
|
|
return PijulBackend.Clone(&vcsGetOption{
|
|
url: remoteDummyURL,
|
|
dir: localDir,
|
|
})
|
|
},
|
|
expect: []string{"pijul", "clone", remoteDummyURL.String(), localDir},
|
|
}, {
|
|
name: "[pijul] update",
|
|
f: func() error {
|
|
return PijulBackend.Update(&vcsGetOption{
|
|
dir: localDir,
|
|
})
|
|
},
|
|
expect: []string{"pijul", "pull"},
|
|
dir: localDir,
|
|
}, {
|
|
name: "[bzr] clone",
|
|
f: func() error {
|
|
return BazaarBackend.Clone(&vcsGetOption{
|
|
url: remoteDummyURL,
|
|
dir: localDir,
|
|
})
|
|
},
|
|
expect: []string{"bzr", "branch", remoteDummyURL.String(), localDir},
|
|
}, {
|
|
name: "[bzr] update",
|
|
f: func() error {
|
|
return BazaarBackend.Update(&vcsGetOption{
|
|
dir: localDir,
|
|
})
|
|
},
|
|
expect: []string{"bzr", "pull", "--overwrite"},
|
|
dir: localDir,
|
|
}, {
|
|
name: "[bzr] clone shallow",
|
|
f: func() error {
|
|
return BazaarBackend.Clone(&vcsGetOption{
|
|
url: remoteDummyURL,
|
|
dir: localDir,
|
|
shallow: true,
|
|
})
|
|
},
|
|
expect: []string{"bzr", "branch", remoteDummyURL.String(), localDir},
|
|
}, {
|
|
name: "[fossil] clone",
|
|
f: func() error {
|
|
return FossilBackend.Clone(&vcsGetOption{
|
|
url: remoteDummyURL,
|
|
dir: localDir,
|
|
})
|
|
},
|
|
expect: []string{"fossil", "open", fossilRepoName},
|
|
dir: localDir,
|
|
}, {
|
|
name: "[fossil] update",
|
|
f: func() error {
|
|
return FossilBackend.Update(&vcsGetOption{
|
|
dir: localDir,
|
|
})
|
|
},
|
|
expect: []string{"fossil", "update"},
|
|
dir: localDir,
|
|
}}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
if err := tc.f(); err != nil {
|
|
t.Errorf("error should be nil, but: %s", err)
|
|
}
|
|
c := lastCommand()
|
|
if !reflect.DeepEqual(c.Args, tc.expect) {
|
|
t.Errorf("\ngot: %+v\nexpect: %+v", c.Args, tc.expect)
|
|
}
|
|
if c.Dir != tc.dir {
|
|
t.Errorf("got: %s, expect: %s", c.Dir, tc.dir)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCvsDummyBackend(t *testing.T) {
|
|
tempDir := newTempDir(t)
|
|
localDir := filepath.Join(tempDir, "repo")
|
|
|
|
if err := cvsDummyBackend.Clone(&vcsGetOption{
|
|
url: remoteDummyURL,
|
|
dir: localDir,
|
|
}); err == nil {
|
|
t.Error("error should be occurred, but nil")
|
|
}
|
|
|
|
if err := cvsDummyBackend.Clone(&vcsGetOption{
|
|
url: remoteDummyURL,
|
|
dir: localDir,
|
|
shallow: true,
|
|
}); err == nil {
|
|
t.Error("error should be occurred, but nil")
|
|
}
|
|
|
|
if err := cvsDummyBackend.Update(&vcsGetOption{
|
|
dir: localDir,
|
|
}); err == nil {
|
|
t.Error("error should be occurred, but nil")
|
|
}
|
|
}
|
|
|
|
func TestBranchOptionIgnoredErrors(t *testing.T) {
|
|
tempDir := newTempDir(t)
|
|
localDir := filepath.Join(tempDir, "repo")
|
|
|
|
if err := DarcsBackend.Clone(&vcsGetOption{
|
|
url: remoteDummyURL,
|
|
dir: localDir,
|
|
branch: "hello",
|
|
}); err == nil {
|
|
t.Error("error should be occurred, but nil")
|
|
}
|
|
|
|
if err := FossilBackend.Clone(&vcsGetOption{
|
|
url: remoteDummyURL,
|
|
dir: localDir,
|
|
branch: "hello",
|
|
}); err == nil {
|
|
t.Error("error should be occurred, but nil")
|
|
}
|
|
|
|
if err := BazaarBackend.Clone(&vcsGetOption{
|
|
url: remoteDummyURL,
|
|
dir: localDir,
|
|
branch: "hello",
|
|
}); err == nil {
|
|
t.Error("error should be occurred, but nil")
|
|
}
|
|
}
|