From 66acb6d0cd557f1c24a0e503825143b3d2ac2526 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 4 May 2016 02:59:40 -0500 Subject: [PATCH] Decouple cmds from Get/Init/Update See also: https://github.com/Masterminds/vcs/issues/39 --- bzr.go | 22 ++++++++++++++++++---- git.go | 32 ++++++++++++++++++++++++++++---- hg.go | 21 ++++++++++++++++++--- repo.go | 18 ++++++++++++++++++ svn.go | 29 ++++++++++++++++++++++------- 5 files changed, 104 insertions(+), 18 deletions(-) diff --git a/bzr.go b/bzr.go index 1d36137..ee1a302 100644 --- a/bzr.go +++ b/bzr.go @@ -65,9 +65,12 @@ func (s BzrRepo) Vcs() Type { return Bzr } +func (s *BzrRepo) GetCmd() (string, []string) { + return "bzr", []string{"branch", s.Remote(), s.LocalPath()} +} + // Get is used to perform an initial clone of a repository. func (s *BzrRepo) Get() error { - basePath := filepath.Dir(filepath.FromSlash(s.LocalPath())) if _, err := os.Stat(basePath); os.IsNotExist(err) { err = os.MkdirAll(basePath, 0755) @@ -76,7 +79,8 @@ func (s *BzrRepo) Get() error { } } - out, err := s.run("bzr", "branch", s.Remote(), s.LocalPath()) + name, args := s.GetCmd() + out, err := s.run(name, args...) if err != nil { return NewRemoteError("Unable to get repository", err, string(out)) } @@ -84,9 +88,14 @@ func (s *BzrRepo) Get() error { return nil } +func (s *BzrRepo) InitCmd() (string, []string) { + return "bzr", []string{"init", s.LocalPath()} +} + // Init initializes a bazaar repository at local location. func (s *BzrRepo) Init() error { - out, err := s.run("bzr", "init", s.LocalPath()) + name, args := s.InitCmd() + out, err := s.run(name, args...) // There are some windows cases where bazaar cannot create the parent // directory if it does not already exist, to the location it's trying @@ -114,9 +123,14 @@ func (s *BzrRepo) Init() error { return nil } +func (s *BzrRepo) UpdateCmd() (string, []string) { + return "bzr", []string{"pull"} +} + // Update performs a Bzr pull and update to an existing checkout. func (s *BzrRepo) Update() error { - out, err := s.RunFromDir("bzr", "pull") + name, args := s.UpdateCmd() + out, err := s.run(name, args...) if err != nil { return NewRemoteError("Unable to update repository", err, string(out)) } diff --git a/git.go b/git.go index 26d50ee..68d760e 100644 --- a/git.go +++ b/git.go @@ -64,13 +64,22 @@ func (s GitRepo) Vcs() Type { return Git } +func (s *GitRepo) GetCmd() (string, []string) { + return "git", []string{"clone", s.Remote(), s.LocalPath()} +} + // Get is used to perform an initial clone of a repository. func (s *GitRepo) Get() error { - out, err := s.run("git", "clone", s.Remote(), s.LocalPath()) + name, args := s.GetCmd() + out, err := s.run(name, args...) // There are some windows cases where Git cannot create the parent directory, // if it does not already exist, to the location it's trying to create the // repo. Catch that error and try to handle it. + return s.HandleError(out, err) +} + +func (s *GitRepo) HandleError(out []byte, err error) error { if err != nil && s.isUnableToCreateDir(err) { basePath := filepath.Dir(filepath.FromSlash(s.LocalPath())) @@ -94,9 +103,14 @@ func (s *GitRepo) Get() error { return nil } +func (s *GitRepo) InitCmd() (string, []string) { + return "git", []string{"init", s.LocalPath()} +} + // Init initializes a git repository at local location. func (s *GitRepo) Init() error { - out, err := s.run("git", "init", s.LocalPath()) + name, args := s.InitCmd() + out, err := s.run(name, args...) // There are some windows cases where Git cannot create the parent directory, // if it does not already exist, to the location it's trying to create the @@ -124,10 +138,19 @@ func (s *GitRepo) Init() error { return nil } +func (s *GitRepo) FetchCmd() (string, []string) { + return "git", []string{"fetch", s.RemoteLocation} +} + +func (s *GitRepo) UpdateCmd() (string, []string) { + return "git", []string{"pull"} +} + // Update performs an Git fetch and pull to an existing checkout. func (s *GitRepo) Update() error { // Perform a fetch to make sure everything is up to date. - out, err := s.RunFromDir("git", "fetch", s.RemoteLocation) + cmd, args := s.FetchCmd() + out, err := s.RunFromDir(cmd, args...) if err != nil { return NewRemoteError("Unable to update repository", err, string(out)) } @@ -143,7 +166,8 @@ func (s *GitRepo) Update() error { return nil } - out, err = s.RunFromDir("git", "pull") + cmd, args = s.UpdateCmd() + out, err = s.RunFromDir(cmd, args...) if err != nil { return NewRemoteError("Unable to update repository", err, string(out)) } diff --git a/hg.go b/hg.go index 4ce055c..e1c7852 100644 --- a/hg.go +++ b/hg.go @@ -64,27 +64,42 @@ func (s HgRepo) Vcs() Type { return Hg } +func (s *HgRepo) GetCmd() (string, []string) { + return "hg", []string{"clone", s.Remote(), s.LocalPath()} +} + // Get is used to perform an initial clone of a repository. func (s *HgRepo) Get() error { - out, err := s.run("hg", "clone", s.Remote(), s.LocalPath()) + name, args := s.GetCmd() + out, err := s.run(name, args...) if err != nil { return NewRemoteError("Unable to get repository", err, string(out)) } return nil } +func (s *HgRepo) InitCmd() (string, []string) { + return "hg", []string{"init", s.LocalPath()} +} + // Init will initialize a mercurial repository at local location. func (s *HgRepo) Init() error { - out, err := s.run("hg", "init", s.LocalPath()) + name, args := s.InitCmd() + out, err := s.run(name, args...) if err != nil { return NewLocalError("Unable to initialize repository", err, string(out)) } return nil } +func (s *HgRepo) UpdateCmd() (string, []string) { + return "hg", []string{"update"} +} + // Update performs a Mercurial pull to an existing checkout. func (s *HgRepo) Update() error { - out, err := s.RunFromDir("hg", "update") + name, args := s.UpdateCmd() + out, err := s.run(name, args...) if err != nil { return NewRemoteError("Unable to update repository", err, string(out)) } diff --git a/repo.go b/repo.go index 61a39a0..1c839c5 100644 --- a/repo.go +++ b/repo.go @@ -80,12 +80,21 @@ type Repo interface { // Get is used to perform an initial clone/checkout of a repository. Get() error + // GetCmd retrieves the arguments for the GetCommand + GetCmd() (string, []string) + // Initializes a new repository locally. Init() error + // InitCmd retrieves the command to initialize repo. + InitCmd() (string, []string) + // Update performs an update to an existing checkout of a repository. Update() error + // UpdateCmd returns command to update repo + UpdateCmd() (string, []string) + // UpdateVersion sets the version of a package of a repository. UpdateVersion(string) error @@ -202,6 +211,15 @@ func (b *base) setLocalPath(local string) { b.local = local } +func (b base) command(cmd string, args ...string) ([]byte, error) { + out, err := exec.Command(cmd, args...).CombinedOutput() + b.log(out) + if err != nil { + err = fmt.Errorf("%s: %s", out, err) + } + return out, err +} + func (b base) run(cmd string, args ...string) ([]byte, error) { out, err := exec.Command(cmd, args...).CombinedOutput() b.log(out) diff --git a/svn.go b/svn.go index 85f60b5..3d4044c 100644 --- a/svn.go +++ b/svn.go @@ -64,24 +64,34 @@ func (s SvnRepo) Vcs() Type { return Svn } -// Get is used to perform an initial checkout of a repository. -// Note, because SVN isn't distributed this is a checkout without -// a clone. -func (s *SvnRepo) Get() error { +func (s *SvnRepo) GetCmd() (string, []string) { remote := s.Remote() if strings.HasPrefix(remote, "/") { remote = "file://" + remote } - out, err := s.run("svn", "checkout", remote, s.LocalPath()) + return "svn", []string{"checkout", remote, s.LocalPath()} +} + +// Get is used to perform an initial checkout of a repository. +// Note, because SVN isn't distributed this is a checkout without +// a clone. +func (s *SvnRepo) Get() error { + name, args := s.GetCmd() + out, err := s.run(name, args...) if err != nil { return NewRemoteError("Unable to get repository", err, string(out)) } return nil } +func (s *SvnRepo) InitCmd() (string, []string) { + return "svn", []string{"svnadmin", "create", s.Remote()} +} + // Init will create a svn repository at remote location. func (s *SvnRepo) Init() error { - out, err := s.run("svnadmin", "create", s.Remote()) + name, args := s.InitCmd() + out, err := s.run(name, args...) if err != nil && s.isUnableToCreateDir(err) { @@ -106,9 +116,14 @@ func (s *SvnRepo) Init() error { return nil } +func (s *SvnRepo) UpdateCmd() (string, []string) { + return "svn", []string{"update"} +} + // Update performs an SVN update to an existing checkout. func (s *SvnRepo) Update() error { - out, err := s.RunFromDir("svn", "update") + cmd, args := s.UpdateCmd() + out, err := s.RunFromDir(cmd, args...) if err != nil { return NewRemoteError("Unable to update repository", err, string(out)) }