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

add PlainOpen variant to find .git in parent dirs #784

Merged
merged 1 commit into from
Apr 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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