add --branch option to ghq get to specify branch

this option implies --single-branch on Git. It reduces the clone time
and amount of transferred objects maintaining a history of specific
branch.

this option is useful when you fork a large repository and want to
checkout only your PR branch.
This commit is contained in:
rhysd 2019-12-01 12:54:10 +09:00
parent c93b01d202
commit 44bbec4edf
3 changed files with 37 additions and 12 deletions

View file

@ -29,6 +29,7 @@ var cloneFlags = []cli.Flag{
&cli.BoolFlag{Name: "look, l", Usage: "Look after get"},
&cli.StringFlag{Name: "vcs", Usage: "Specify VCS backend for cloning"},
&cli.BoolFlag{Name: "silent, s", Usage: "clone or update silently"},
&cli.StringFlag{Name: "branch, b", Usage: "Specify branch name. This flag implies --single-branch on Git"},
}
var commandGet = cli.Command{
@ -140,6 +141,7 @@ func doGet(c *cli.Context) error {
ssh: c.Bool("p"),
vcs: c.String("vcs"),
silent: c.Bool("silent"),
branch: c.String("branch"),
}
if argURL == "" {

View file

@ -28,7 +28,7 @@ func getRepoLock(localRepoRoot string) bool {
type getter struct {
update, shallow, silent, ssh bool
vcs string
vcs, branch string
}
func (g *getter) get(argURL string) error {
@ -135,7 +135,7 @@ func (g *getter) getRemoteRepository(remote RemoteRepository) error {
}
if getRepoLock(localRepoRoot) {
return vcs.Clone(repoURL, localRepoRoot, g.shallow, g.silent)
return vcs.Clone(repoURL, localRepoRoot, g.shallow, g.silent, g.branch)
}
return nil
}

43
vcs.go
View file

@ -26,14 +26,14 @@ func runInDir(silent bool) func(dir, command string, args ...string) error {
// A VCSBackend represents a VCS backend.
type VCSBackend struct {
// Clones a remote repository to local path.
Clone func(*url.URL, string, bool, bool) error
Clone func(*url.URL, string, bool, bool, string) error
// Updates a cloned local repository.
Update func(string, bool) error
}
var GitBackend = &VCSBackend{
// support submodules?
Clone: func(remote *url.URL, local string, shallow, silent bool) error {
Clone: func(remote *url.URL, local string, shallow, silent bool, branch string) error {
dir, _ := filepath.Split(local)
err := os.MkdirAll(dir, 0755)
if err != nil {
@ -44,6 +44,9 @@ var GitBackend = &VCSBackend{
if shallow {
args = append(args, "--depth", "1")
}
if branch != "" {
args = append(args, "--branch", branch, "--single-branch")
}
args = append(args, remote.String(), local)
return run(silent)("git", args...)
@ -54,7 +57,7 @@ var GitBackend = &VCSBackend{
}
var SubversionBackend = &VCSBackend{
Clone: func(remote *url.URL, local string, shallow, silent bool) error {
Clone: func(remote *url.URL, local string, shallow, silent bool, branch string) error {
dir, _ := filepath.Split(local)
err := os.MkdirAll(dir, 0755)
if err != nil {
@ -65,6 +68,9 @@ var SubversionBackend = &VCSBackend{
if shallow {
args = append(args, "--depth", "1")
}
if branch != "" {
remote.Path += "/branches/" + url.PathEscape(branch)
}
args = append(args, remote.String(), local)
return run(silent)("svn", args...)
@ -76,12 +82,15 @@ var SubversionBackend = &VCSBackend{
var GitsvnBackend = &VCSBackend{
// git-svn seems not supporting shallow clone currently.
Clone: func(remote *url.URL, local string, ignoredShallow, silent bool) error {
Clone: func(remote *url.URL, local string, ignoredShallow, silent bool, branch string) error {
dir, _ := filepath.Split(local)
err := os.MkdirAll(dir, 0755)
if err != nil {
return err
}
if branch != "" {
remote.Path += "/branches/" + url.PathEscape(branch)
}
return run(silent)("git", "svn", "clone", remote.String(), local)
},
@ -92,14 +101,18 @@ var GitsvnBackend = &VCSBackend{
var MercurialBackend = &VCSBackend{
// Mercurial seems not supporting shallow clone currently.
Clone: func(remote *url.URL, local string, ignoredShallow, silent bool) error {
Clone: func(remote *url.URL, local string, ignoredShallow, silent bool, branch string) error {
dir, _ := filepath.Split(local)
err := os.MkdirAll(dir, 0755)
if err != nil {
return err
}
args := []string{"clone", remote.String(), local}
if branch != "" {
args = append(args, "--branch", branch)
}
return run(silent)("hg", "clone", remote.String(), local)
return run(silent)("hg", args...)
},
Update: func(local string, silent bool) error {
return runInDir(silent)(local, "hg", "pull", "--update")
@ -107,7 +120,11 @@ var MercurialBackend = &VCSBackend{
}
var DarcsBackend = &VCSBackend{
Clone: func(remote *url.URL, local string, shallow, silent bool) error {
Clone: func(remote *url.URL, local string, shallow, silent bool, branch string) error {
if branch != "" {
return errors.New("Darcs does not support branch")
}
dir, _ := filepath.Split(local)
err := os.MkdirAll(dir, 0755)
if err != nil {
@ -128,7 +145,7 @@ var DarcsBackend = &VCSBackend{
}
var cvsDummyBackend = &VCSBackend{
Clone: func(remote *url.URL, local string, ignoredShallow, silent bool) error {
Clone: func(remote *url.URL, local string, ignoredShallow, silent bool, branch string) error {
return errors.New("CVS clone is not supported")
},
Update: func(local string, silent bool) error {
@ -139,7 +156,10 @@ var cvsDummyBackend = &VCSBackend{
const fossilRepoName = ".fossil" // same as Go
var FossilBackend = &VCSBackend{
Clone: func(remote *url.URL, local string, shallow, silent bool) error {
Clone: func(remote *url.URL, local string, shallow, silent bool, branch string) error {
if branch != "" {
return errors.New("Fossil does not support cloning specific branch")
}
if err := os.MkdirAll(local, 0755); err != nil {
return err
}
@ -156,7 +176,10 @@ var FossilBackend = &VCSBackend{
var BazaarBackend = &VCSBackend{
// bazaar seems not supporting shallow clone currently.
Clone: func(remote *url.URL, local string, ignoredShallow, silent bool) error {
Clone: func(remote *url.URL, local string, ignoredShallow, silent bool, branch string) error {
if branch != "" {
return errors.New("--branch option is unavailable for Bazaar since branch is included in remote URL")
}
dir, _ := filepath.Split(local)
err := os.MkdirAll(dir, 0755)
if err != nil {