6
0
mirror of https://github.com/grdl/git-get.git synced 2026-02-15 16:55:07 +00:00

Add a --branch flag that specifies which branch or tag to check out after cloning

This commit is contained in:
Grzegorz Dlugoszewski
2020-06-08 21:37:26 +02:00
parent 919359f26f
commit dfef6151d1
5 changed files with 72 additions and 12 deletions

View File

@@ -23,6 +23,8 @@ const (
DefPrivateKey = "id_rsa"
KeyOutput = "out"
DefOutput = OutFlat
KeyBranch = "branch"
DefBranch = "master"
KeyFetch = "fetch"
KeyList = "list"
)

View File

@@ -34,12 +34,14 @@ func init() {
cmd.PersistentFlags().StringP(cfg.KeyReposRoot, "r", "", "repos root")
cmd.PersistentFlags().StringP(cfg.KeyPrivateKey, "p", "", "SSH private key path")
cmd.PersistentFlags().StringP(cfg.KeyOutput, "o", cfg.DefOutput, "output format.")
cmd.PersistentFlags().StringP(cfg.KeyBranch, "b", cfg.DefBranch, "Branch (or tag) to checkout after cloning")
viper.BindPFlag(cfg.KeyList, cmd.PersistentFlags().Lookup(cfg.KeyList))
viper.BindPFlag(cfg.KeyFetch, cmd.PersistentFlags().Lookup(cfg.KeyFetch))
viper.BindPFlag(cfg.KeyReposRoot, cmd.PersistentFlags().Lookup(cfg.KeyReposRoot))
viper.BindPFlag(cfg.KeyPrivateKey, cmd.PersistentFlags().Lookup(cfg.KeyReposRoot))
viper.BindPFlag(cfg.KeyOutput, cmd.PersistentFlags().Lookup(cfg.KeyOutput))
viper.BindPFlag(cfg.KeyBranch, cmd.PersistentFlags().Lookup(cfg.KeyBranch))
}
func Run(cmd *cobra.Command, args []string) {
@@ -74,9 +76,10 @@ func Run(cmd *cobra.Command, args []string) {
url, err := path.ParseURL(args[0])
exitIfError(err)
repoPath := pathpkg.Join(root, path.URLToPath(url))
_, err = git.CloneRepo(url, repoPath, false)
branch := viper.GetString(cfg.KeyBranch)
repoPath := pathpkg.Join(root, path.URLToPath(url))
_, err = git.CloneRepo(url, repoPath, branch, false)
exitIfError(err)
}

View File

@@ -4,6 +4,8 @@ import (
"fmt"
"git-get/cfg"
"github.com/go-git/go-git/v5/plumbing"
"io"
"io/ioutil"
"net/url"
@@ -24,7 +26,7 @@ type Repo struct {
Status *RepoStatus
}
func CloneRepo(url *url.URL, path string, quiet bool) (*Repo, error) {
func CloneRepo(url *url.URL, path string, branch string, quiet bool) (*Repo, error) {
var progress io.Writer
if !quiet {
progress = os.Stdout
@@ -40,11 +42,18 @@ func CloneRepo(url *url.URL, path string, quiet bool) (*Repo, error) {
}
}
// If branch name is actually a tag (ie. is prefixed with refs/tags) - check out that tag.
// Otherwise, assume it's a branch name and check it out.
refName := plumbing.ReferenceName(branch)
if !refName.IsTag() {
refName = plumbing.NewBranchReferenceName(branch)
}
opts := &git.CloneOptions{
URL: url.String(),
Auth: auth,
RemoteName: git.DefaultRemoteName,
ReferenceName: "",
ReferenceName: refName,
SingleBranch: false,
NoCheckout: false,
Depth: 0,

View File

@@ -83,7 +83,7 @@ func newRepoWithLocalBranch(t *testing.T) *Repo {
func newRepoWithClonedBranch(t *testing.T) *Repo {
origin := newRepoWithCommit(t)
r := origin.clone(t)
r := origin.clone(t, "master")
r.newBranch(t, "local")
r.checkoutBranch(t, "local")
@@ -105,7 +105,7 @@ func newRepoWithDetachedHead(t *testing.T) *Repo {
func newRepoWithBranchAhead(t *testing.T) *Repo {
origin := newRepoWithCommit(t)
r := origin.clone(t)
r := origin.clone(t, "master")
r.writeFile(t, "new", "I'm a new file")
r.addFile(t, "new")
r.newCommit(t, "new commit")
@@ -116,7 +116,7 @@ func newRepoWithBranchAhead(t *testing.T) *Repo {
func newRepoWithBranchBehind(t *testing.T) *Repo {
origin := newRepoWithCommit(t)
r := origin.clone(t)
r := origin.clone(t, "master")
origin.writeFile(t, "origin.new", "I'm a new file on origin")
origin.addFile(t, "origin.new")
@@ -130,7 +130,7 @@ func newRepoWithBranchBehind(t *testing.T) *Repo {
func newRepoWithBranchAheadAndBehind(t *testing.T) *Repo {
origin := newRepoWithCommit(t)
r := origin.clone(t)
r := origin.clone(t, "master")
r.writeFile(t, "local.new", "local 1")
r.addFile(t, "local.new")
r.newCommit(t, "1st local commit")
@@ -155,6 +155,22 @@ func newRepoWithBranchAheadAndBehind(t *testing.T) *Repo {
return r
}
func newRepoWithCheckedOutBranch(t *testing.T) *Repo {
origin := newRepoWithCommit(t)
origin.newBranch(t, "feature/branch1")
r := origin.clone(t, "feature/branch1")
return r
}
func newRepoWithCheckedOutTag(t *testing.T) *Repo {
origin := newRepoWithCommit(t)
origin.newTag(t, "v1.0.0")
r := origin.clone(t, "refs/tags/v1.0.0")
return r
}
func newTempDir(t *testing.T) string {
dir, err := ioutil.TempDir("", "git-get-repo-")
checkFatal(t, errors.Wrap(err, "Failed creating test repo directory"))
@@ -216,12 +232,22 @@ func (r *Repo) newBranch(t *testing.T, name string) {
checkFatal(t, err)
}
func (r *Repo) clone(t *testing.T) *Repo {
func (r *Repo) newTag(t *testing.T, name string) {
head, err := r.Head()
checkFatal(t, err)
ref := plumbing.NewHashReference(plumbing.NewTagReferenceName(name), head.Hash())
err = r.Storer.SetReference(ref)
checkFatal(t, err)
}
func (r *Repo) clone(t *testing.T, branch string) *Repo {
dir := newTempDir(t)
repoURL, err := url.Parse("file://" + r.Path)
checkFatal(t, err)
repo, err := CloneRepo(repoURL, dir, true)
repo, err := CloneRepo(repoURL, dir, branch, true)
checkFatal(t, err)
return repo

View File

@@ -155,16 +155,36 @@ func TestStatus(t *testing.T) {
},
},
}},
{newRepoWithCheckedOutBranch, &RepoStatus{
HasUntrackedFiles: false,
HasUncommittedChanges: false,
CurrentBranch: "feature/branch1",
Branches: []*BranchStatus{
{
Name: "feature/branch1",
Upstream: "origin/feature/branch1",
Behind: 0,
Ahead: 0,
},
},
}},
{newRepoWithCheckedOutTag, &RepoStatus{
HasUntrackedFiles: false,
HasUncommittedChanges: false,
// TODO: is this correct? Can we show tag name instead of "detached HEAD"?
CurrentBranch: StatusDetached,
Branches: nil,
}},
}
for _, test := range tests {
for i, test := range tests {
repo := test.makeTestRepo(t)
err := repo.LoadStatus()
checkFatal(t, err)
if !reflect.DeepEqual(repo.Status, test.want) {
t.Errorf("Wrong repo status, got: %+v; want: %+v", repo.Status, test.want)
t.Errorf("Failed test case %d, got: %+v; want: %+v", i, repo.Status, test.want)
}
}
}