diff --git a/CREDITS b/CREDITS index 96db919..6906c3f 100644 --- a/CREDITS +++ b/CREDITS @@ -422,6 +422,39 @@ SOFTWARE. ================================================================ +golang.org/x/crypto +https://golang.org/x/crypto +---------------------------------------------------------------- +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +================================================================ + golang.org/x/net https://golang.org/x/net ---------------------------------------------------------------- @@ -488,6 +521,39 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================ +golang.org/x/sys +https://golang.org/x/sys +---------------------------------------------------------------- +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +================================================================ + golang.org/x/tools https://golang.org/x/tools ---------------------------------------------------------------- diff --git a/README.adoc b/README.adoc index 54bed78..3859125 100644 --- a/README.adoc +++ b/README.adoc @@ -11,14 +11,13 @@ ghq - Manage remote repository clones $ ghq get https://github.com/motemen/ghq # Runs `git clone https://github.com/motemen/ghq ~/.ghq/github.com/motemen/ghq` -You can also list local repositories (+ghq list+) and bulk get repositories by list of URLs (+ghq import+). +You can also list local repositories (+ghq list+). == SYNOPSIS [verse] ghq get [-u] [-p] [--shallow] [--vcs] [--look] [--silent] [--branch] [--no-recursive] ( | // | / | ) ghq list [-p] [-e] [] -ghq import [-u] [-p] [--shalow] [--vcs] [--silent] [--no-recursive] [--parallel] < FILE ghq root [--all] == COMMANDS @@ -50,10 +49,6 @@ list:: If '-p' ('--full-path') is given, the full paths to the repository root are printed instead of relative ones. -import:: - If no extra arguments given, reads repository URLs from stdin line by line - and performs 'get' for each of them. - root:: Prints repositories' root (i.e. `ghq.root`). Without '--all' option, the primary one is shown. diff --git a/cmd_get.go b/cmd_get.go index f904b25..3a4bfb0 100644 --- a/cmd_get.go +++ b/cmd_get.go @@ -76,6 +76,9 @@ func doGet(c *cli.Context) error { if err := scr.Err(); err != nil { return fmt.Errorf("While reading input: %s", err) } + if err := eg.Wait(); err != nil { + return err + } if andLook && firstArg != "" { return look(firstArg) } diff --git a/cmd_get_test.go b/cmd_get_test.go index 5ddce4a..20f4b56 100644 --- a/cmd_get_test.go +++ b/cmd_get_test.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "fmt" "os" "os/exec" @@ -11,6 +12,7 @@ import ( "github.com/Songmu/gitconfig" "github.com/motemen/ghq/cmdutil" + "github.com/motemen/ghq/logger" ) func TestCommandGet(t *testing.T) { @@ -235,3 +237,54 @@ func TestLook(t *testing.T) { } }) } + +func TestDoGet_bulk(t *testing.T) { + in := []string{ + "github.com/motemen/ghq", + "github.com/motemen/gore", + } + + testCases := []struct { + name string + args []string + }{{ + name: "normal", + args: []string{}, + }, { + name: "parallel", + args: []string{"-parallel"}, + }} + + buf := &bytes.Buffer{} + logger.SetOutput(buf) + defer func() { logger.SetOutput(os.Stderr) }() + + withFakeGitBackend(t, func(t *testing.T, tmproot string, _ *_cloneArgs, _ *_updateArgs) { + for _, r := range in { + os.MkdirAll(filepath.Join(tmproot, r, ".git"), 0755) + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + buf.Reset() + out, _, err := captureWithInput(in, func() { + args := append([]string{"", "get"}, tc.args...) + if err := newApp().Run(args); err != nil { + t.Errorf("error should be nil but: %s", err) + } + }) + if err != nil { + t.Errorf("error should be nil, but: %s", err) + } + if out != "" { + t.Errorf("out should be empty, but: %s", out) + } + log := filepath.ToSlash(buf.String()) + for _, r := range in { + if !strings.Contains(log, r) { + t.Errorf("log should contains %q but not: %s", r, log) + } + } + }) + } + }) +} diff --git a/cmd_import.go b/cmd_import.go deleted file mode 100644 index f5c6811..0000000 --- a/cmd_import.go +++ /dev/null @@ -1,52 +0,0 @@ -package main - -import ( - "bufio" - "fmt" - "os" - - "github.com/motemen/ghq/logger" - "github.com/urfave/cli/v2" - "golang.org/x/sync/errgroup" -) - -func doImport(c *cli.Context) error { - var parallel = c.Bool("parallel") - g := &getter{ - update: c.Bool("update"), - shallow: c.Bool("shallow"), - ssh: c.Bool("p"), - vcs: c.String("vcs"), - silent: c.Bool("silent"), - recursive: !c.Bool("no-recursive"), - } - if parallel { - // force silent in parallel import - g.silent = true - } - - eg := &errgroup.Group{} - sem := make(chan struct{}, 6) - scanner := bufio.NewScanner(os.Stdin) - for scanner.Scan() { - line := scanner.Text() - if parallel { - eg.Go(func() error { - sem <- struct{}{} - defer func() { <-sem }() - if err := g.get(line); err != nil { - logger.Log("error", err.Error()) - } - return nil - }) - } else { - if err := g.get(line); err != nil { - logger.Log("error", err.Error()) - } - } - } - if err := scanner.Err(); err != nil { - return fmt.Errorf("While reading input: %s", err) - } - return eg.Wait() -} diff --git a/cmd_import_test.go b/cmd_import_test.go deleted file mode 100644 index bcab6a0..0000000 --- a/cmd_import_test.go +++ /dev/null @@ -1,62 +0,0 @@ -package main - -import ( - "bytes" - "os" - "path/filepath" - "strings" - "testing" - - "github.com/motemen/ghq/logger" -) - -func TestDoImport(t *testing.T) { - in := []string{ - "github.com/motemen/ghq", - "github.com/motemen/gore", - } - - testCases := []struct { - name string - args []string - }{{ - name: "normal", - args: []string{}, - }, { - name: "parallel", - args: []string{"-parallel"}, - }} - - buf := &bytes.Buffer{} - logger.SetOutput(buf) - defer func() { logger.SetOutput(os.Stderr) }() - - withFakeGitBackend(t, func(t *testing.T, tmproot string, _ *_cloneArgs, _ *_updateArgs) { - for _, r := range in { - os.MkdirAll(filepath.Join(tmproot, r, ".git"), 0755) - } - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - buf.Reset() - out, _, err := captureWithInput(in, func() { - args := append([]string{"", "import"}, tc.args...) - if err := newApp().Run(args); err != nil { - t.Errorf("error should be nil but: %s", err) - } - }) - if err != nil { - t.Errorf("error should be nil, but: %s", err) - } - if out != "" { - t.Errorf("out should be empty, but: %s", out) - } - log := filepath.ToSlash(buf.String()) - for _, r := range in { - if !strings.Contains(log, r) { - t.Errorf("log should contains %q but not: %s", r, log) - } - } - }) - } - }) -} diff --git a/commands.go b/commands.go index 0efe5d1..c3e8312 100644 --- a/commands.go +++ b/commands.go @@ -10,24 +10,10 @@ import ( var commands = []*cli.Command{ commandGet, commandList, - commandImport, commandRoot, commandCreate, } -// cloneFlags are comman flags of `get` and `import` subcommands -var cloneFlags = []cli.Flag{ - &cli.BoolFlag{Name: "update", Aliases: []string{"u"}, - Usage: "Update local repository if cloned already"}, - &cli.BoolFlag{Name: "p", Usage: "Clone with SSH"}, - &cli.BoolFlag{Name: "shallow", Usage: "Do a shallow clone"}, - &cli.BoolFlag{Name: "look", Aliases: []string{"l"}, Usage: "Look after get"}, - &cli.StringFlag{Name: "vcs", Usage: "Specify VCS backend for cloning"}, - &cli.BoolFlag{Name: "silent", Aliases: []string{"s"}, Usage: "clone or update silently"}, - &cli.BoolFlag{Name: "no-recursive", Usage: "prevent recursive fetching"}, - &cli.BoolFlag{Name: "parallel", Aliases: []string{"P"}, Usage: "Import parallely"}, -} - var commandGet = &cli.Command{ Name: "get", Usage: "Clone/sync with a remote repository", @@ -38,9 +24,19 @@ var commandGet = &cli.Command{ When you use '-p' option, the repository is cloned via SSH. `, Action: doGet, - Flags: append(cloneFlags, + Flags: []cli.Flag{ + &cli.BoolFlag{Name: "update", Aliases: []string{"u"}, + Usage: "Update local repository if cloned already"}, + &cli.BoolFlag{Name: "p", Usage: "Clone with SSH"}, + &cli.BoolFlag{Name: "shallow", Usage: "Do a shallow clone"}, + &cli.BoolFlag{Name: "look", Aliases: []string{"l"}, Usage: "Look after get"}, + &cli.StringFlag{Name: "vcs", Usage: "Specify VCS backend for cloning"}, + &cli.BoolFlag{Name: "silent", Aliases: []string{"s"}, Usage: "clone or update silently"}, + &cli.BoolFlag{Name: "no-recursive", Usage: "prevent recursive fetching"}, &cli.StringFlag{Name: "branch", Aliases: []string{"b"}, - Usage: "Specify branch name. This flag implies --single-branch on Git"}), + Usage: "Specify branch name. This flag implies --single-branch on Git"}, + &cli.BoolFlag{Name: "parallel", Aliases: []string{"P"}, Usage: "Import parallely"}, + }, } var commandList = &cli.Command{ @@ -62,13 +58,6 @@ var commandList = &cli.Command{ }, } -var commandImport = &cli.Command{ - Name: "import", - Usage: "Bulk get repositories from stdin", - Action: doImport, - Flags: cloneFlags, -} - var commandRoot = &cli.Command{ Name: "root", Usage: "Show repositories' root", @@ -95,7 +84,6 @@ type commandDoc struct { var commandDocs = map[string]commandDoc{ "get": {"", "[-u] [--vcs ] | [-u] [-p] /"}, "list": {"", "[-p] [-e] []"}, - "import": {"", "< file"}, "root": {"", ""}, "create": {"", " | / | //"}, }