From 6626ec2009a2e929b2142d969b35822488b9ad09 Mon Sep 17 00:00:00 2001 From: Tom Wiesing Date: Thu, 11 Apr 2019 20:16:10 +0200 Subject: [PATCH] ggman clone: Allow using native 'git' --- README.md | 2 +- src/commands/clone.go | 2 +- src/constants/usage.go | 2 +- src/gitwrap/clone.go | 44 +++++++++++++++++++++++++++++++++++++++--- src/main.go | 2 +- src/program/runtime.go | 14 ++++++++++---- 6 files changed, 55 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 5920a5b..26b2755 100644 --- a/README.md +++ b/README.md @@ -175,7 +175,7 @@ This page includes releases for Linux, Mac OS X and Windows. Note that these binaries are compressed with [`upx`](https://upx.github.io) in order to decrease executable size. After obtaining the binary (through either of the two means), simply place it in your `$PATH`. -`ggman` does not depend on any external software (no need for `git` even). +`ggman` does not depend on any external software (although having `git` in `$PATH` allows for passing through arguments to `clone`). ## LICENSE diff --git a/src/commands/clone.go b/src/commands/clone.go index a028e12..f0f8f7c 100644 --- a/src/commands/clone.go +++ b/src/commands/clone.go @@ -30,5 +30,5 @@ func CloneCommand(runtime *program.SubRuntime) (retval int, err string) { targetPath := path.Join(append([]string{root}, remote.Components()...)...) // and finish - return gitwrap.CloneRepository(cloneURI, targetPath) + return gitwrap.CloneRepository(cloneURI, targetPath, argv[1:]...) } diff --git a/src/constants/usage.go b/src/constants/usage.go index 18b479f..bb5c4a9 100644 --- a/src/constants/usage.go +++ b/src/constants/usage.go @@ -19,7 +19,7 @@ const StringSimulateFlagUsage string = "If set, only print what would be done. " const StringCompsURIUsage string = "Repository URI to print components of. " // StringCloneURIUsage represents the Clone URI usage string -const StringCloneURIUsage string = "URI of repository to clone. " +const StringCloneURIUsage string = "URI of repository to clone and arguments to pass to 'git clone'" // StringLinkPathUsage represents the Link PATH usage string const StringLinkPathUsage string = "Path of repository to symlink. " diff --git a/src/gitwrap/clone.go b/src/gitwrap/clone.go index 665b208..0362340 100644 --- a/src/gitwrap/clone.go +++ b/src/gitwrap/clone.go @@ -1,15 +1,17 @@ package gitwrap import ( + "errors" "fmt" "os" + "os/exec" "github.com/tkw1536/ggman/src/constants" git "gopkg.in/src-d/go-git.v4" ) // CloneRepository clones a repository into a given location -func CloneRepository(from string, to string) (retval int, err string) { +func CloneRepository(from string, to string, args ...string) (retval int, err string) { // tell the user what we are doing fmt.Printf("Cloning %q into %q ...\n", from, to) @@ -27,8 +29,7 @@ func CloneRepository(from string, to string) (retval int, err string) { return } - // do the clone - if _, e := git.PlainClone(to, false, &git.CloneOptions{URL: from, Progress: os.Stdout}); e != nil { + if e := cloneRepositorySmart(from, to, args...); e != nil { err = e.Error() retval = constants.ErrorCodeCustom return @@ -37,3 +38,40 @@ func CloneRepository(from string, to string) (retval int, err string) { // and be done return } + +// clones a repository either internally or externally +func cloneRepositorySmart(from string, to string, args ...string) error { + if hasExternalGit() { + return cloneRepositoryExternal(from, to, args...) + } else if len(args) != 0 { + return errors.New("External 'git' not found, can not pass any additional arguments to 'git clone'. ") + } else { + return cloneRepositoryInternal(from, to) + } +} + +// checks if we have an external git in $PATH +func hasExternalGit() bool { + _, err := exec.LookPath("git") + return err == nil +} + +// clones a repository using the built-in git +func cloneRepositoryInternal(from string, to string) error { + _, e := git.PlainClone(to, false, &git.CloneOptions{URL: from, Progress: os.Stdout}) + return e +} + +// clones a repository using an external 'git' command +func cloneRepositoryExternal(from string, to string, args ...string) error { + gargs := append([]string{"clone", from, to}, args...) + cmd := exec.Command("git", gargs...) + + cmd.Dir = to + + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + return cmd.Run() +} diff --git a/src/main.go b/src/main.go index 9e1e9bb..c6a17f0 100644 --- a/src/main.go +++ b/src/main.go @@ -30,7 +30,7 @@ func Main(argv []string) (retval int, err string) { ggman.Register("fix", commands.FixCommand, &program.SubOptions{ForArgument: program.OptionalFor, Flag: "--simulate", UsageDescription: constants.StringSimulateFlagUsage, NeedsRoot: true, NeedsCANFILE: true}) - ggman.Register("clone", commands.CloneCommand, &program.SubOptions{MinArgs: 1, MaxArgs: 1, Metavar: "URI", UsageDescription: constants.StringCloneURIUsage, NeedsRoot: true, NeedsCANFILE: true}) + ggman.Register("clone", commands.CloneCommand, &program.SubOptions{MinArgs: 1, MaxArgs: -1, Metavar: "ARG", UsageDescription: constants.StringCloneURIUsage, NeedsRoot: true, NeedsCANFILE: true}) ggman.Register("link", commands.LinkCommand, &program.SubOptions{MinArgs: 1, MaxArgs: 1, Metavar: "PATH", UsageDescription: constants.StringLinkPathUsage, NeedsRoot: true}) ggman.Register("license", commands.LicenseCommand, &program.SubOptions{}) diff --git a/src/program/runtime.go b/src/program/runtime.go index 67d0e57..3b24765 100644 --- a/src/program/runtime.go +++ b/src/program/runtime.go @@ -84,10 +84,16 @@ func (opt *SubOptions) Usage(name string) (usage string) { mv = "ARGUMENT" } - // write out the argument an appropriate number of times - flagString += strings.Repeat(" "+mv, opt.MinArgs) - flagString += strings.Repeat(" ["+mv, opt.MaxArgs-opt.MinArgs) - flagString += strings.Repeat("]", opt.MaxArgs-opt.MinArgs) + if opt.MaxArgs == -1 { + // write out the argument an appropriate number of times + flagString += strings.Repeat(" "+mv, opt.MinArgs) + flagString += " [" + mv + " ... ]" + } else { + // write out the argument an appropriate number of times + flagString += strings.Repeat(" "+mv, opt.MinArgs) + flagString += strings.Repeat(" ["+mv, opt.MaxArgs-opt.MinArgs) + flagString += strings.Repeat("]", opt.MaxArgs-opt.MinArgs) + } } usage += flagString