mirror of
https://github.com/x-motemen/ghq.git
synced 2026-09-10 07:26:27 -04:00
drop import subcommand
This commit is contained in:
parent
194ef6016b
commit
b41935d35c
66
CREDITS
66
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
|
||||
----------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -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] (<repository URL> | <host>/<user>/<project> | <user>/<project> | <project>)
|
||||
ghq list [-p] [-e] [<query>]
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
36
commands.go
36
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 <vcs>] <repository URL> | [-u] [-p] <user>/<project>"},
|
||||
"list": {"", "[-p] [-e] [<query>]"},
|
||||
"import": {"", "< file"},
|
||||
"root": {"", ""},
|
||||
"create": {"", "<project> | <user>/<project> | <host>/<user>/<project>"},
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue