Skip to content

Commit d58cfaa

Browse files
committed
Optimize: Reduce full repo scans when look tag is set
fix #379
1 parent a80a252 commit d58cfaa

File tree

2 files changed

+57
-36
lines changed

2 files changed

+57
-36
lines changed

cmd_get.go

+28-15
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,11 @@ func doGet(c *cli.Context) error {
4040
}
4141

4242
var (
43-
firstArg string
43+
firstArg string // Look at the first repo only, if there are more than one
44+
argCnt int
45+
getInfo getInfo // For fetching and looking a single repo
4446
scr scanner
47+
err error
4548
)
4649
if len(args) > 0 {
4750
scr = &sliceScanner{slice: args}
@@ -52,36 +55,43 @@ func doGet(c *cli.Context) error {
5255
}
5356
scr = bufio.NewScanner(os.Stdin)
5457
}
58+
5559
eg := &errgroup.Group{}
5660
sem := make(chan struct{}, 6)
5761
for scr.Scan() {
5862
target := scr.Text()
5963
if firstArg == "" {
6064
firstArg = target
6165
}
66+
argCnt += 1
6267
if parallel {
6368
sem <- struct{}{}
6469
eg.Go(func() error {
6570
defer func() { <-sem }()
66-
if err := g.get(target); err != nil {
71+
if getInfo, err = g.get(target); err != nil {
6772
logger.Logf("error", "failed to get %q: %s", target, err)
6873
}
6974
return nil
7075
})
7176
} else {
72-
if err := g.get(target); err != nil {
77+
if getInfo, err = g.get(target); err != nil {
7378
return fmt.Errorf("failed to get %q: %w", target, err)
7479
}
7580
}
7681
}
77-
if err := scr.Err(); err != nil {
82+
if err = scr.Err(); err != nil {
7883
return fmt.Errorf("error occurred while reading input: %w", err)
7984
}
80-
if err := eg.Wait(); err != nil {
85+
if err = eg.Wait(); err != nil {
8186
return err
8287
}
83-
if andLook && firstArg != "" {
84-
return look(firstArg, g.bare)
88+
if andLook {
89+
if argCnt > 1 && firstArg != "" {
90+
return look(firstArg, g.bare)
91+
}
92+
if argCnt == 1 && getInfo.localRepository != nil {
93+
return lookByLocalRepository(getInfo.localRepository)
94+
}
8595
}
8696
return nil
8797
}
@@ -155,14 +165,7 @@ func look(name string, bare bool) error {
155165
case 0:
156166
return fmt.Errorf("no repository found")
157167
case 1:
158-
repo := reposFound[0]
159-
cmd := exec.Command(detectShell())
160-
cmd.Stdin = os.Stdin
161-
cmd.Stdout = os.Stdout
162-
cmd.Stderr = os.Stderr
163-
cmd.Dir = repo.FullPath
164-
cmd.Env = append(os.Environ(), "GHQ_LOOK="+filepath.ToSlash(repo.RelPath))
165-
return cmdutil.RunCommand(cmd, true)
168+
return lookByLocalRepository(reposFound[0])
166169
default:
167170
b := &strings.Builder{}
168171
b.WriteString("More than one repositories are found; Try more precise name\n")
@@ -172,3 +175,13 @@ func look(name string, bare bool) error {
172175
return errors.New(b.String())
173176
}
174177
}
178+
179+
func lookByLocalRepository(repo *LocalRepository) error {
180+
cmd := exec.Command(detectShell())
181+
cmd.Stdin = os.Stdin
182+
cmd.Stdout = os.Stdout
183+
cmd.Stderr = os.Stderr
184+
cmd.Dir = repo.FullPath
185+
cmd.Env = append(os.Environ(), "GHQ_LOOK="+filepath.ToSlash(repo.RelPath))
186+
return cmdutil.RunCommand(cmd, true)
187+
}

getter.go

+29-21
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,27 @@ func getRepoLock(localRepoRoot string) bool {
1919
return !loaded
2020
}
2121

22+
type getInfo struct {
23+
localRepository *LocalRepository
24+
}
25+
2226
type getter struct {
2327
update, shallow, silent, ssh, recursive, bare bool
2428
vcs, branch string
2529
}
2630

27-
func (g *getter) get(argURL string) error {
31+
func (g *getter) get(argURL string) (getInfo, error) {
2832
u, err := newURL(argURL, g.ssh, false)
2933
if err != nil {
30-
return fmt.Errorf("could not parse URL %q: %w", argURL, err)
34+
return getInfo{}, fmt.Errorf("could not parse URL %q: %w", argURL, err)
3135
}
3236
branch := g.branch
3337
if pos := strings.LastIndexByte(u.Path, '@'); pos >= 0 {
3438
u.Path, branch = u.Path[:pos], u.Path[pos+1:]
3539
}
3640
remote, err := NewRemoteRepository(u)
3741
if err != nil {
38-
return err
42+
return getInfo{}, err
3943
}
4044

4145
return g.getRemoteRepository(remote, branch)
@@ -44,11 +48,14 @@ func (g *getter) get(argURL string) error {
4448
// getRemoteRepository clones or updates a remote repository remote.
4549
// If doUpdate is true, updates the locally cloned repository. Otherwise does nothing.
4650
// If isShallow is true, does shallow cloning. (no effect if already cloned or the VCS is Mercurial and git-svn)
47-
func (g *getter) getRemoteRepository(remote RemoteRepository, branch string) error {
51+
func (g *getter) getRemoteRepository(remote RemoteRepository, branch string) (getInfo, error) {
4852
remoteURL := remote.URL()
4953
local, err := LocalRepositoryFromURL(remoteURL, g.bare)
5054
if err != nil {
51-
return err
55+
return getInfo{}, err
56+
}
57+
info := getInfo{
58+
localRepository: local,
5259
}
5360

5461
var (
@@ -63,7 +70,7 @@ func (g *getter) getRemoteRepository(remote RemoteRepository, branch string) err
6370
err = nil
6471
}
6572
if err != nil {
66-
return err
73+
return getInfo{}, err
6774
}
6875
}
6976

@@ -82,7 +89,7 @@ func (g *getter) getRemoteRepository(remote RemoteRepository, branch string) err
8289
if !ok {
8390
vcs, repoURL, err = remote.VCS()
8491
if err != nil {
85-
return err
92+
return getInfo{}, err
8693
}
8794
}
8895
if l := detectLocalRepoRoot(remoteURL.Path, repoURL.Path); l != "" {
@@ -97,40 +104,41 @@ func (g *getter) getRemoteRepository(remote RemoteRepository, branch string) err
97104
repoURL, _ = url.Parse(remoteURL.Opaque)
98105
}
99106
if getRepoLock(localRepoRoot) {
100-
return vcs.Clone(&vcsGetOption{
101-
url: repoURL,
102-
dir: localRepoRoot,
103-
shallow: g.shallow,
104-
silent: g.silent,
105-
branch: branch,
106-
recursive: g.recursive,
107-
bare: g.bare,
108-
})
107+
return info,
108+
vcs.Clone(&vcsGetOption{
109+
url: repoURL,
110+
dir: localRepoRoot,
111+
shallow: g.shallow,
112+
silent: g.silent,
113+
branch: branch,
114+
recursive: g.recursive,
115+
bare: g.bare,
116+
})
109117
}
110-
return nil
118+
return info, nil
111119
case g.update:
112120
logger.Log("update", fpath)
113121
vcs, localRepoRoot := local.VCS()
114122
if vcs == nil {
115-
return fmt.Errorf("failed to detect VCS for %q", fpath)
123+
return getInfo{}, fmt.Errorf("failed to detect VCS for %q", fpath)
116124
}
117125
repoURL := remoteURL
118126
if remoteURL.Scheme == "codecommit" {
119127
repoURL, _ = url.Parse(remoteURL.Opaque)
120128
}
121129
if getRepoLock(localRepoRoot) {
122-
return vcs.Update(&vcsGetOption{
130+
return info, vcs.Update(&vcsGetOption{
123131
url: repoURL,
124132
dir: localRepoRoot,
125133
silent: g.silent,
126134
recursive: g.recursive,
127135
bare: g.bare,
128136
})
129137
}
130-
return nil
138+
return info, nil
131139
}
132140
logger.Log("exists", fpath)
133-
return nil
141+
return info, nil
134142
}
135143

136144
func detectLocalRepoRoot(remotePath, repoPath string) string {

0 commit comments

Comments
 (0)