aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMáximo Cuadros <mcuadros@gmail.com>2018-10-30 14:17:07 +0100
committerGitHub <noreply@github.com>2018-10-30 14:17:07 +0100
commit8b6ded6e7d6057a57619521c51127160b783169a (patch)
treed737ffe63ecd0059439517ee66a4168c0565807d
parentdfd6c820e3dc7477eaaf517d4ad3b34b62e6c42e (diff)
parent3332e8d67dbe810d1607285d43fcd79470cf9961 (diff)
downloadgo-git-8b6ded6e7d6057a57619521c51127160b783169a.tar.gz
Merge pull request #1008 from smola/clone-cleanup
cleanup after failed clone
-rw-r--r--repository.go72
-rw-r--r--repository_test.go90
2 files changed, 156 insertions, 6 deletions
diff --git a/repository.go b/repository.go
index 507ff44..9420af9 100644
--- a/repository.go
+++ b/repository.go
@@ -5,6 +5,7 @@ import (
"context"
"errors"
"fmt"
+ "io"
stdioutil "io/ioutil"
"os"
"path"
@@ -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 {
@@ -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()
diff --git a/repository_test.go b/repository_test.go
index 07c3570..ba2cf1a 100644
--- a/repository_test.go
+++ b/repository_test.go
@@ -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)
}
@@ -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`,
}