diff options
Diffstat (limited to 'repository.go')
-rw-r--r-- | repository.go | 106 |
1 files changed, 90 insertions, 16 deletions
diff --git a/repository.go b/repository.go index 507ff44..f548e9a 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() @@ -640,8 +710,9 @@ func (r *Repository) clone(ctx context.Context, o *CloneOptions) error { } c := &config.RemoteConfig{ - Name: o.RemoteName, - URLs: []string{o.URL}, + Name: o.RemoteName, + URLs: []string{o.URL}, + Fetch: r.cloneRefSpec(o), } if _, err := r.CreateRemote(c); err != nil { @@ -649,7 +720,7 @@ func (r *Repository) clone(ctx context.Context, o *CloneOptions) error { } ref, err := r.fetchAndUpdateReferences(ctx, &FetchOptions{ - RefSpecs: r.cloneRefSpec(o, c), + RefSpecs: c.Fetch, Depth: o.Depth, Auth: o.Auth, Progress: o.Progress, @@ -719,21 +790,26 @@ const ( refspecSingleBranchHEAD = "+HEAD:refs/remotes/%s/HEAD" ) -func (r *Repository) cloneRefSpec(o *CloneOptions, c *config.RemoteConfig) []config.RefSpec { - var rs string - +func (r *Repository) cloneRefSpec(o *CloneOptions) []config.RefSpec { switch { case o.ReferenceName.IsTag(): - rs = fmt.Sprintf(refspecTag, o.ReferenceName.Short()) + return []config.RefSpec{ + config.RefSpec(fmt.Sprintf(refspecTag, o.ReferenceName.Short())), + } case o.SingleBranch && o.ReferenceName == plumbing.HEAD: - rs = fmt.Sprintf(refspecSingleBranchHEAD, c.Name) + return []config.RefSpec{ + config.RefSpec(fmt.Sprintf(refspecSingleBranchHEAD, o.RemoteName)), + config.RefSpec(fmt.Sprintf(refspecSingleBranch, plumbing.Master.Short(), o.RemoteName)), + } case o.SingleBranch: - rs = fmt.Sprintf(refspecSingleBranch, o.ReferenceName.Short(), c.Name) + return []config.RefSpec{ + config.RefSpec(fmt.Sprintf(refspecSingleBranch, o.ReferenceName.Short(), o.RemoteName)), + } default: - return c.Fetch + return []config.RefSpec{ + config.RefSpec(fmt.Sprintf(config.DefaultFetchRefSpec, o.RemoteName)), + } } - - return []config.RefSpec{config.RefSpec(rs)} } func (r *Repository) setIsBare(isBare bool) error { @@ -751,9 +827,7 @@ func (r *Repository) updateRemoteConfigIfNeeded(o *CloneOptions, c *config.Remot return nil } - c.Fetch = []config.RefSpec{config.RefSpec(fmt.Sprintf( - refspecSingleBranch, head.Name().Short(), c.Name, - ))} + c.Fetch = r.cloneRefSpec(o) cfg, err := r.Storer.Config() if err != nil { |