Skip to content
This repository has been archived by the owner on Sep 11, 2020. It is now read-only.

Commit

Permalink
Merge pull request #784 from mvdan/open-detect
Browse files Browse the repository at this point in the history
add PlainOpen variant to find .git in parent dirs
  • Loading branch information
mcuadros authored Apr 4, 2018
2 parents 247cf69 + 5e8e011 commit c4ace4d
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 6 deletions.
11 changes: 11 additions & 0 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -420,3 +420,14 @@ func (o *GrepOptions) Validate(w *Worktree) error {

return nil
}

// PlainOpenOptions describes how opening a plain repository should be
// performed.
type PlainOpenOptions struct {
// DetectDotGit defines whether parent directories should be
// walked until a .git directory or file is found.
DetectDotGit bool
}

// Validate validates the fields and sets the default values.
func (o *PlainOpenOptions) Validate() error { return nil }
38 changes: 32 additions & 6 deletions repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,14 @@ func PlainInit(path string, isBare bool) (*Repository, error) {
// repository is bare or a normal one. If the path doesn't contain a valid
// repository ErrRepositoryNotExists is returned
func PlainOpen(path string) (*Repository, error) {
dot, wt, err := dotGitToOSFilesystems(path)
return PlainOpenWithOptions(path, &PlainOpenOptions{})
}

// PlainOpen opens a git repository from the given path. It detects if the
// repository is bare or a normal one. If the path doesn't contain a valid
// repository ErrRepositoryNotExists is returned
func PlainOpenWithOptions(path string, o *PlainOpenOptions) (*Repository, error) {
dot, wt, err := dotGitToOSFilesystems(path, o.DetectDotGit)
if err != nil {
return nil, err
}
Expand All @@ -246,14 +253,33 @@ func PlainOpen(path string) (*Repository, error) {
return Open(s, wt)
}

func dotGitToOSFilesystems(path string) (dot, wt billy.Filesystem, err error) {
fs := osfs.New(path)
fi, err := fs.Stat(".git")
if err != nil {
func dotGitToOSFilesystems(path string, detect bool) (dot, wt billy.Filesystem, err error) {
if path, err = filepath.Abs(path); err != nil {
return nil, nil, err
}
var fs billy.Filesystem
var fi os.FileInfo
for {
fs = osfs.New(path)
fi, err = fs.Stat(".git")
if err == nil {
// no error; stop
break
}
if !os.IsNotExist(err) {
// unknown error; stop
return nil, nil, err
}

if detect {
// try its parent as long as we haven't reached
// the root dir
if dir := filepath.Dir(path); dir != path {
path = dir
continue
}
}
// not detecting via parent dirs and the dir does not exist;
// stop
return fs, nil, nil
}

Expand Down
30 changes: 30 additions & 0 deletions repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,36 @@ func (s *RepositorySuite) TestPlainOpenNotExists(c *C) {
c.Assert(r, IsNil)
}

func (s *RepositorySuite) TestPlainOpenDetectDotGit(c *C) {
dir, err := ioutil.TempDir("", "plain-open")
c.Assert(err, IsNil)
defer os.RemoveAll(dir)

subdir := filepath.Join(dir, "a", "b")
err = os.MkdirAll(subdir, 0755)
c.Assert(err, IsNil)

r, err := PlainInit(dir, false)
c.Assert(err, IsNil)
c.Assert(r, NotNil)

opt := &PlainOpenOptions{DetectDotGit: true}
r, err = PlainOpenWithOptions(subdir, opt)
c.Assert(err, IsNil)
c.Assert(r, NotNil)
}

func (s *RepositorySuite) TestPlainOpenNotExistsDetectDotGit(c *C) {
dir, err := ioutil.TempDir("", "plain-open")
c.Assert(err, IsNil)
defer os.RemoveAll(dir)

opt := &PlainOpenOptions{DetectDotGit: true}
r, err := PlainOpenWithOptions(dir, opt)
c.Assert(err, Equals, ErrRepositoryNotExists)
c.Assert(r, IsNil)
}

func (s *RepositorySuite) TestPlainClone(c *C) {
r, err := PlainClone(c.MkDir(), false, &CloneOptions{
URL: s.GetBasicLocalRepositoryURL(),
Expand Down

0 comments on commit c4ace4d

Please sign in to comment.