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 #1008 from smola/clone-cleanup
Browse files Browse the repository at this point in the history
cleanup after failed clone
  • Loading branch information
mcuadros authored Oct 30, 2018
2 parents dfd6c82 + 3332e8d commit 8b6ded6
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 6 deletions.
72 changes: 71 additions & 1 deletion repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"context"
"errors"
"fmt"
"io"
stdioutil "io/ioutil"
"os"
"path"
Expand Down Expand Up @@ -342,12 +343,22 @@ func PlainClone(path string, isBare bool, o *CloneOptions) (*Repository, error)
//
// TODO(mcuadros): move isBare to CloneOptions in v5
func PlainCloneContext(ctx context.Context, path string, isBare bool, o *CloneOptions) (*Repository, error) {
dirExists, err := checkExistsAndIsEmptyDir(path)
if err != nil {
return nil, err
}

r, err := PlainInit(path, isBare)
if err != nil {
return nil, err
}

return r, r.clone(ctx, o)
err = r.clone(ctx, o)
if err != nil && err != ErrRepositoryAlreadyExists {
cleanUpDir(path, !dirExists)
}

return r, err
}

func newRepository(s storage.Storer, worktree billy.Filesystem) *Repository {
Expand All @@ -358,6 +369,65 @@ func newRepository(s storage.Storer, worktree billy.Filesystem) *Repository {
}
}

func checkExistsAndIsEmptyDir(path string) (exists bool, err error) {
fi, err := os.Stat(path)
if err != nil {
if os.IsNotExist(err) {
return false, nil
}

return false, err
}

if !fi.IsDir() {
return false, fmt.Errorf("path is not a directory: %s", path)
}

f, err := os.Open(path)
if err != nil {
return false, err
}

defer ioutil.CheckClose(f, &err)

_, err = f.Readdirnames(1)
if err == io.EOF {
return true, nil
}

if err != nil {
return true, err
}

return true, fmt.Errorf("directory is not empty: %s", path)
}

func cleanUpDir(path string, all bool) error {
if all {
return os.RemoveAll(path)
}

f, err := os.Open(path)
if err != nil {
return err
}

defer ioutil.CheckClose(f, &err)

names, err := f.Readdirnames(-1)
if err != nil {
return err
}

for _, name := range names {
if err := os.RemoveAll(filepath.Join(path, name)); err != nil {
return err
}
}

return nil
}

// Config return the repository config
func (r *Repository) Config() (*config.Config, error) {
return r.Storer.Config()
Expand Down
90 changes: 85 additions & 5 deletions repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -581,14 +581,94 @@ func (s *RepositorySuite) TestPlainCloneWithRemoteName(c *C) {
c.Assert(remote, NotNil)
}

func (s *RepositorySuite) TestPlainCloneContext(c *C) {
func (s *RepositorySuite) TestPlainCloneContextWithProperParameters(c *C) {
ctx, cancel := context.WithCancel(context.Background())
cancel()

_, err := PlainCloneContext(ctx, c.MkDir(), false, &CloneOptions{
r, err := PlainCloneContext(ctx, c.MkDir(), false, &CloneOptions{
URL: s.GetBasicLocalRepositoryURL(),
})

c.Assert(r, NotNil)
c.Assert(err, NotNil)
}

func (s *RepositorySuite) TestPlainCloneContextNonExistentWithExistentDir(c *C) {
ctx, cancel := context.WithCancel(context.Background())
cancel()

tmpDir := c.MkDir()
repoDir := tmpDir

r, err := PlainCloneContext(ctx, repoDir, false, &CloneOptions{
URL: "incorrectOnPurpose",
})
c.Assert(r, NotNil)
c.Assert(err, NotNil)

_, err = os.Stat(repoDir)
c.Assert(os.IsNotExist(err), Equals, false)

names, err := ioutil.ReadDir(repoDir)
c.Assert(err, IsNil)
c.Assert(names, HasLen, 0)
}

func (s *RepositorySuite) TestPlainCloneContextNonExistentWithNonExistentDir(c *C) {
ctx, cancel := context.WithCancel(context.Background())
cancel()

tmpDir := c.MkDir()
repoDir := filepath.Join(tmpDir, "repoDir")

r, err := PlainCloneContext(ctx, repoDir, false, &CloneOptions{
URL: "incorrectOnPurpose",
})
c.Assert(r, NotNil)
c.Assert(err, NotNil)

_, err = os.Stat(repoDir)
c.Assert(os.IsNotExist(err), Equals, true)
}

func (s *RepositorySuite) TestPlainCloneContextNonExistentWithNotDir(c *C) {
ctx, cancel := context.WithCancel(context.Background())
cancel()

tmpDir := c.MkDir()
repoDir := filepath.Join(tmpDir, "repoDir")
f, err := os.Create(repoDir)
c.Assert(err, IsNil)
c.Assert(f.Close(), IsNil)

r, err := PlainCloneContext(ctx, repoDir, false, &CloneOptions{
URL: "incorrectOnPurpose",
})
c.Assert(r, IsNil)
c.Assert(err, NotNil)

fi, err := os.Stat(repoDir)
c.Assert(err, IsNil)
c.Assert(fi.IsDir(), Equals, false)
}

func (s *RepositorySuite) TestPlainCloneContextNonExistentWithNotEmptyDir(c *C) {
ctx, cancel := context.WithCancel(context.Background())
cancel()

tmpDir := c.MkDir()
repoDirPath := filepath.Join(tmpDir, "repoDir")
err := os.Mkdir(repoDirPath, 0777)
c.Assert(err, IsNil)

dummyFile := filepath.Join(repoDirPath, "dummyFile")
err = ioutil.WriteFile(dummyFile, []byte(fmt.Sprint("dummyContent")), 0644)
c.Assert(err, IsNil)

r, err := PlainCloneContext(ctx, repoDirPath, false, &CloneOptions{
URL: "incorrectOnPurpose",
})
c.Assert(r, IsNil)
c.Assert(err, NotNil)
}

Expand Down Expand Up @@ -2104,9 +2184,9 @@ func (s *RepositorySuite) TestResolveRevisionWithErrors(c *C) {
c.Assert(err, IsNil)

datas := map[string]string{
"efs/heads/master~": "reference not found",
"HEAD^3": `Revision invalid : "3" found must be 0, 1 or 2 after "^"`,
"HEAD^{/whatever}": `No commit message match regexp : "whatever"`,
"efs/heads/master~": "reference not found",
"HEAD^3": `Revision invalid : "3" found must be 0, 1 or 2 after "^"`,
"HEAD^{/whatever}": `No commit message match regexp : "whatever"`,
"4e1243bd22c66e76c2ba9eddc1f91394e57f9f83": "reference not found",
"918c48b83bd081e863dbe1b80f8998f058cd8294": `refname "918c48b83bd081e863dbe1b80f8998f058cd8294" is ambiguous`,
}
Expand Down

0 comments on commit 8b6ded6

Please sign in to comment.