Skip to content

Commit

Permalink
Merge pull request #368 from dochang/bare
Browse files Browse the repository at this point in the history
Append ".git" to directory name for bare git repositories
  • Loading branch information
Songmu authored Apr 4, 2024
2 parents ce5049f + e883e7d commit 8ab8ffe
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 12 deletions.
3 changes: 2 additions & 1 deletion cmd_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 == "" {
Expand All @@ -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
}
Expand Down
6 changes: 3 additions & 3 deletions cmd_get.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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
Expand All @@ -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
}
Expand Down
52 changes: 49 additions & 3 deletions cmd_get_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"})

Expand Down Expand Up @@ -263,20 +263,66 @@ 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)
}
})
}

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",
Expand Down
3 changes: 2 additions & 1 deletion cmd_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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)
}
}
Expand Down
2 changes: 2 additions & 0 deletions commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,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"},
},
}

Expand Down Expand Up @@ -83,6 +84,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"},
},
}

Expand Down
12 changes: 11 additions & 1 deletion getter.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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)
}
Expand All @@ -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
Expand Down
13 changes: 12 additions & 1 deletion local_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -234,13 +239,19 @@ 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
}
}
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]
Expand Down
11 changes: 10 additions & 1 deletion local_repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down Expand Up @@ -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)
Expand Down
9 changes: 8 additions & 1 deletion vcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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"},
}
Expand Down

0 comments on commit 8ab8ffe

Please sign in to comment.