mirror of
https://github.com/x-motemen/ghq.git
synced 2026-09-10 07:26:27 -04:00
Append ".git" to directory name for bare git repositories
This commit is contained in:
parent
67a22bf1f7
commit
e883e7d4d6
|
|
@ -13,6 +13,7 @@ func doCreate(c *cli.Context) error {
|
|||
name = c.Args().First()
|
||||
vcs = c.String("vcs")
|
||||
w = c.App.Writer
|
||||
bare = c.Bool("bare")
|
||||
)
|
||||
|
||||
if name == "" {
|
||||
|
|
@ -24,7 +25,7 @@ func doCreate(c *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
localRepo, err := LocalRepositoryFromURL(u)
|
||||
localRepo, err := LocalRepositoryFromURL(u, bare)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ func doGet(c *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
if andLook && firstArg != "" {
|
||||
return look(firstArg)
|
||||
return look(firstArg, g.bare)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -121,7 +121,7 @@ func detectShell() string {
|
|||
return "/bin/sh"
|
||||
}
|
||||
|
||||
func look(name string) error {
|
||||
func look(name string, bare bool) error {
|
||||
var (
|
||||
reposFound []*LocalRepository
|
||||
mu sync.Mutex
|
||||
|
|
@ -138,7 +138,7 @@ func look(name string) error {
|
|||
|
||||
if len(reposFound) == 0 {
|
||||
if url, err := newURL(name, false, false); err == nil {
|
||||
repo, err := LocalRepositoryFromURL(url)
|
||||
repo, err := LocalRepositoryFromURL(url, bare)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ func TestCommandGet(t *testing.T) {
|
|||
}, {
|
||||
name: "bare",
|
||||
scenario: func(t *testing.T, tmpRoot string, cloneArgs *_cloneArgs, updateArgs *_updateArgs) {
|
||||
localDir := filepath.Join(tmpRoot, "github.com", "motemen", "ghq-test-repo")
|
||||
localDir := filepath.Join(tmpRoot, "github.com", "motemen", "ghq-test-repo.git")
|
||||
|
||||
app.Run([]string{"", "get", "--bare", "motemen/ghq-test-repo"})
|
||||
|
||||
|
|
@ -263,13 +263,13 @@ func TestLook(t *testing.T) {
|
|||
t.Errorf("lastCmd.Env[len(lastCmd.Env)-1]: got: %s, expect: %s", gotEnv, expectEnv)
|
||||
}
|
||||
|
||||
err = look("github.com/motemen/_unknown")
|
||||
err = look("github.com/motemen/_unknown", false)
|
||||
expect := "no repository found"
|
||||
if !strings.HasPrefix(fmt.Sprintf("%s", err), expect) {
|
||||
t.Errorf("error should has prefix %q, but: %s", expect, err)
|
||||
}
|
||||
|
||||
err = look("gobump")
|
||||
err = look("gobump", false)
|
||||
expect = "More than one repositories are found; Try more precise name"
|
||||
if !strings.HasPrefix(fmt.Sprintf("%s", err), expect) {
|
||||
t.Errorf("error should has prefix %q, but: %s", expect, err)
|
||||
|
|
@ -277,6 +277,52 @@ func TestLook(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestBareLook(t *testing.T) {
|
||||
withFakeGitBackend(t, func(t *testing.T, tmproot string, _ *_cloneArgs, _ *_updateArgs) {
|
||||
os.MkdirAll(filepath.Join(tmproot, "github.com", "motemen", "ghq.git"), 0o755)
|
||||
os.MkdirAll(filepath.Join(tmproot, "github.com", "motemen", "gobump", ".git"), 0o755)
|
||||
defer func(orig func(cmd *exec.Cmd) error) {
|
||||
cmdutil.CommandRunner = orig
|
||||
}(cmdutil.CommandRunner)
|
||||
var lastCmd *exec.Cmd
|
||||
cmdutil.CommandRunner = func(cmd *exec.Cmd) error {
|
||||
lastCmd = cmd
|
||||
return nil
|
||||
}
|
||||
sh := detectShell()
|
||||
|
||||
err := newApp().Run([]string{"", "get", "--bare", "--look", "https://github.com/motemen/ghq.git"})
|
||||
if err != nil {
|
||||
t.Errorf("error should be nil, but: %s", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(lastCmd.Args, []string{sh}) {
|
||||
t.Errorf("lastCmd.Args: got: %v, expect: %v", lastCmd.Args, []string{sh})
|
||||
}
|
||||
dir := filepath.Join(tmproot, "github.com", "motemen", "ghq.git")
|
||||
if filepath.Clean(lastCmd.Dir) != dir {
|
||||
t.Errorf("lastCmd.Dir: got: %s, expect: %s", lastCmd.Dir, dir)
|
||||
}
|
||||
gotEnv := lastCmd.Env[len(lastCmd.Env)-1]
|
||||
expectEnv := "GHQ_LOOK=github.com/motemen/ghq.git"
|
||||
if gotEnv != expectEnv {
|
||||
t.Errorf("lastCmd.Env[len(lastCmd.Env)-1]: got: %s, expect: %s", gotEnv, expectEnv)
|
||||
}
|
||||
|
||||
err = look("github.com/motemen/ghq", false)
|
||||
expect := "no repository found"
|
||||
if !strings.HasPrefix(fmt.Sprintf("%s", err), expect) {
|
||||
t.Errorf("error should has prefix %q, but: %s", expect, err)
|
||||
}
|
||||
|
||||
err = look("github.com/motemen/gobump.git", true)
|
||||
expect = "no repository found"
|
||||
if !strings.HasPrefix(fmt.Sprintf("%s", err), expect) {
|
||||
t.Errorf("error should has prefix %q, but: %s", expect, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestDoGet_bulk(t *testing.T) {
|
||||
in := []string{
|
||||
"github.com/x-motemen/ghq",
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ func doList(c *cli.Context) error {
|
|||
vcsBackend = c.String("vcs")
|
||||
printFullPaths = c.Bool("full-path")
|
||||
printUniquePaths = c.Bool("unique")
|
||||
bare = c.Bool("bare")
|
||||
)
|
||||
|
||||
filterByQuery := func(_ *LocalRepository) bool {
|
||||
|
|
@ -26,7 +27,7 @@ func doList(c *cli.Context) error {
|
|||
if query != "" {
|
||||
if hasSchemePattern.MatchString(query) || scpLikeURLPattern.MatchString(query) {
|
||||
if url, err := newURL(query, false, false); err == nil {
|
||||
if repo, err := LocalRepositoryFromURL(url); err == nil {
|
||||
if repo, err := LocalRepositoryFromURL(url, bare); err == nil {
|
||||
query = filepath.ToSlash(repo.RelPath)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ var commandList = &cli.Command{
|
|||
&cli.StringFlag{Name: "vcs", Usage: "Specify `vcs` backend for matching"},
|
||||
&cli.BoolFlag{Name: "full-path", Aliases: []string{"p"}, Usage: "Print full paths"},
|
||||
&cli.BoolFlag{Name: "unique", Usage: "Print unique subpaths"},
|
||||
&cli.BoolFlag{Name: "bare", Usage: "Query bare repositories"},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -72,6 +73,7 @@ var commandCreate = &cli.Command{
|
|||
Action: doCreate,
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{Name: "vcs", Usage: "Specify `vcs` backend explicitly"},
|
||||
&cli.BoolFlag{Name: "bare", Usage: "Create a bare repository"},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
12
getter.go
12
getter.go
|
|
@ -46,7 +46,7 @@ func (g *getter) get(argURL string) error {
|
|||
// If isShallow is true, does shallow cloning. (no effect if already cloned or the VCS is Mercurial and git-svn)
|
||||
func (g *getter) getRemoteRepository(remote RemoteRepository, branch string) error {
|
||||
remoteURL := remote.URL()
|
||||
local, err := LocalRepositoryFromURL(remoteURL)
|
||||
local, err := LocalRepositoryFromURL(remoteURL, g.bare)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -89,6 +89,10 @@ func (g *getter) getRemoteRepository(remote RemoteRepository, branch string) err
|
|||
localRepoRoot = filepath.Join(local.RootPath, remoteURL.Hostname(), l)
|
||||
}
|
||||
|
||||
if g.bare {
|
||||
localRepoRoot = localRepoRoot + ".git"
|
||||
}
|
||||
|
||||
if remoteURL.Scheme == "codecommit" {
|
||||
repoURL, _ = url.Parse(remoteURL.Opaque)
|
||||
}
|
||||
|
|
@ -110,11 +114,17 @@ func (g *getter) getRemoteRepository(remote RemoteRepository, branch string) err
|
|||
if vcs == nil {
|
||||
return fmt.Errorf("failed to detect VCS for %q", fpath)
|
||||
}
|
||||
repoURL := remoteURL
|
||||
if remoteURL.Scheme == "codecommit" {
|
||||
repoURL, _ = url.Parse(remoteURL.Opaque)
|
||||
}
|
||||
if getRepoLock(localRepoRoot) {
|
||||
return vcs.Update(&vcsGetOption{
|
||||
url: repoURL,
|
||||
dir: localRepoRoot,
|
||||
silent: g.silent,
|
||||
recursive: g.recursive,
|
||||
bare: g.bare,
|
||||
})
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -72,12 +72,17 @@ func LocalRepositoryFromFullPath(fullPath string, backend *VCSBackend) (*LocalRe
|
|||
}
|
||||
|
||||
// LocalRepositoryFromURL resolve LocalRepository from URL
|
||||
func LocalRepositoryFromURL(remoteURL *url.URL) (*LocalRepository, error) {
|
||||
func LocalRepositoryFromURL(remoteURL *url.URL, bare bool) (*LocalRepository, error) {
|
||||
pathParts := append(
|
||||
[]string{remoteURL.Hostname()}, strings.Split(remoteURL.Path, "/")...,
|
||||
)
|
||||
relPath := strings.TrimSuffix(filepath.Join(pathParts...), ".git")
|
||||
pathParts[len(pathParts)-1] = strings.TrimSuffix(pathParts[len(pathParts)-1], ".git")
|
||||
if bare {
|
||||
// Force to append ".git" even if remoteURL does not end with ".git".
|
||||
relPath = relPath + ".git"
|
||||
pathParts[len(pathParts)-1] = pathParts[len(pathParts)-1] + ".git"
|
||||
}
|
||||
|
||||
var (
|
||||
localRepository *LocalRepository
|
||||
|
|
@ -232,6 +237,9 @@ func findVCSBackend(fpath, vcs string) *VCSBackend {
|
|||
if !ok {
|
||||
return nil
|
||||
}
|
||||
if vcsBackend == GitBackend && strings.HasSuffix(fpath, ".git") {
|
||||
return vcsBackend
|
||||
}
|
||||
for _, d := range vcsBackend.Contents {
|
||||
if _, err := os.Stat(filepath.Join(fpath, d)); err == nil {
|
||||
return vcsBackend
|
||||
|
|
@ -239,6 +247,9 @@ func findVCSBackend(fpath, vcs string) *VCSBackend {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
if strings.HasSuffix(fpath, ".git") {
|
||||
return GitBackend
|
||||
}
|
||||
for _, d := range vcsContents {
|
||||
if _, err := os.Stat(filepath.Join(fpath, d)); err == nil {
|
||||
return vcsContentsMap[d]
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ func TestNewLocalRepository(t *testing.T) {
|
|||
defer func(orig string) { _home = orig }(_home)
|
||||
_home = ""
|
||||
homeOnce = &sync.Once{}
|
||||
r, err := LocalRepositoryFromURL(mustParseURL(tc.url))
|
||||
r, err := LocalRepositoryFromURL(mustParseURL(tc.url), false)
|
||||
if err != nil {
|
||||
t.Errorf("error should be nil but: %s", err)
|
||||
}
|
||||
|
|
@ -249,6 +249,15 @@ func TestFindVCSBackend(t *testing.T) {
|
|||
setup func(t *testing.T) (string, string)
|
||||
expect *VCSBackend
|
||||
}{{
|
||||
name: "git-bare",
|
||||
setup: func(t *testing.T) (string, string) {
|
||||
dir := newTempDir(t)
|
||||
dir = dir + ".git"
|
||||
os.MkdirAll(dir, 0o755)
|
||||
return dir, ""
|
||||
},
|
||||
expect: GitBackend,
|
||||
}, {
|
||||
name: "git",
|
||||
setup: func(t *testing.T) (string, string) {
|
||||
dir := newTempDir(t)
|
||||
|
|
|
|||
9
vcs.go
9
vcs.go
|
|
@ -78,6 +78,9 @@ var GitBackend = &VCSBackend{
|
|||
if _, err := os.Stat(filepath.Join(vg.dir, ".git/svn")); err == nil {
|
||||
return GitsvnBackend.Update(vg)
|
||||
}
|
||||
if vg.bare {
|
||||
return runInDir(true)(vg.dir, "git", "fetch", vg.url.String(), "*:*")
|
||||
}
|
||||
err := runInDir(true)(vg.dir, "git", "rev-parse", "@{upstream}")
|
||||
if err != nil {
|
||||
err := runInDir(vg.silent)(vg.dir, "git", "fetch")
|
||||
|
|
@ -96,7 +99,11 @@ var GitBackend = &VCSBackend{
|
|||
return nil
|
||||
},
|
||||
Init: func(dir string) error {
|
||||
return cmdutil.RunInDir(dir, "git", "init")
|
||||
args := []string{"init"}
|
||||
if strings.HasSuffix(dir, ".git") {
|
||||
args = append(args, "--bare")
|
||||
}
|
||||
return cmdutil.RunInDir(dir, "git", args...)
|
||||
},
|
||||
Contents: []string{".git"},
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue