X Tutup
Skip to content

Commit 43b28f7

Browse files
authored
Merge pull request cli#727 from thefotios/respect-clone-target
Respect clone target Closes cli#721
2 parents 250114e + 6428e3d commit 43b28f7

File tree

2 files changed

+112
-20
lines changed

2 files changed

+112
-20
lines changed

command/repo.go

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,12 @@ A repository can be supplied as an argument in any of the following formats:
5151
}
5252

5353
var repoCloneCmd = &cobra.Command{
54-
Use: "clone <repo>",
54+
Use: "clone <repo> [<directory>]",
5555
Args: cobra.MinimumNArgs(1),
5656
Short: "Clone a repository locally",
5757
Long: `Clone a GitHub repository locally.
5858
59-
To pass 'git clone' options, separate them with '--'.`,
59+
To pass 'git clone' flags, separate them with '--'.`,
6060
RunE: repoClone,
6161
}
6262

@@ -87,6 +87,41 @@ With no argument, the repository for the current directory is displayed.`,
8787
RunE: repoView,
8888
}
8989

90+
func parseCloneArgs(extraArgs []string) (args []string, target string) {
91+
args = extraArgs
92+
93+
if len(args) > 0 {
94+
if !strings.HasPrefix(args[0], "-") {
95+
target, args = args[0], args[1:]
96+
}
97+
}
98+
return
99+
}
100+
101+
func runClone(cloneURL string, args []string) (target string, err error) {
102+
cloneArgs, target := parseCloneArgs(args)
103+
104+
cloneArgs = append(cloneArgs, cloneURL)
105+
106+
// If the args contain an explicit target, pass it to clone
107+
// otherwise, parse the URL to determine where git cloned it to so we can return it
108+
if target != "" {
109+
cloneArgs = append(cloneArgs, target)
110+
} else {
111+
target = path.Base(strings.TrimSuffix(cloneURL, ".git"))
112+
}
113+
114+
cloneArgs = append([]string{"clone"}, cloneArgs...)
115+
116+
cloneCmd := git.GitCommand(cloneArgs...)
117+
cloneCmd.Stdin = os.Stdin
118+
cloneCmd.Stdout = os.Stdout
119+
cloneCmd.Stderr = os.Stderr
120+
121+
err = run.PrepareCmd(cloneCmd).Run()
122+
return
123+
}
124+
90125
func repoClone(cmd *cobra.Command, args []string) error {
91126
cloneURL := args[0]
92127
if !strings.Contains(cloneURL, ":") {
@@ -115,21 +150,13 @@ func repoClone(cmd *cobra.Command, args []string) error {
115150
}
116151
}
117152

118-
cloneArgs := []string{"clone"}
119-
cloneArgs = append(cloneArgs, args[1:]...)
120-
cloneArgs = append(cloneArgs, cloneURL)
121-
122-
cloneCmd := git.GitCommand(cloneArgs...)
123-
cloneCmd.Stdin = os.Stdin
124-
cloneCmd.Stdout = os.Stdout
125-
cloneCmd.Stderr = os.Stderr
126-
err := run.PrepareCmd(cloneCmd).Run()
153+
cloneDir, err := runClone(cloneURL, args[1:])
127154
if err != nil {
128155
return err
129156
}
130157

131158
if parentRepo != nil {
132-
err := addUpstreamRemote(parentRepo, cloneURL)
159+
err := addUpstreamRemote(parentRepo, cloneDir)
133160
if err != nil {
134161
return err
135162
}
@@ -138,10 +165,9 @@ func repoClone(cmd *cobra.Command, args []string) error {
138165
return nil
139166
}
140167

141-
func addUpstreamRemote(parentRepo ghrepo.Interface, cloneURL string) error {
168+
func addUpstreamRemote(parentRepo ghrepo.Interface, cloneDir string) error {
142169
// TODO: support SSH remote URLs
143170
upstreamURL := fmt.Sprintf("https://github.com/%s.git", ghrepo.FullName(parentRepo))
144-
cloneDir := path.Base(strings.TrimSuffix(cloneURL, ".git"))
145171

146172
cloneCmd := git.GitCommand("-C", cloneDir, "remote", "add", "upstream", upstreamURL)
147173
cloneCmd.Stdout = os.Stdout
@@ -425,16 +451,12 @@ func repoFork(cmd *cobra.Command, args []string) error {
425451
}
426452
}
427453
if cloneDesired {
428-
cloneCmd := git.GitCommand("clone", forkedRepo.CloneURL)
429-
cloneCmd.Stdin = os.Stdin
430-
cloneCmd.Stdout = os.Stdout
431-
cloneCmd.Stderr = os.Stderr
432-
err = run.PrepareCmd(cloneCmd).Run()
454+
cloneDir, err := runClone(forkedRepo.CloneURL, []string{})
433455
if err != nil {
434456
return fmt.Errorf("failed to clone fork: %w", err)
435457
}
436458

437-
err = addUpstreamRemote(toFork, forkedRepo.CloneURL)
459+
err = addUpstreamRemote(toFork, cloneDir)
438460
if err != nil {
439461
return err
440462
}

command/repo_test.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"encoding/json"
66
"io/ioutil"
77
"os/exec"
8+
"reflect"
89
"regexp"
910
"strings"
1011
"testing"
@@ -337,6 +338,65 @@ func TestRepoFork_in_parent_survey_no(t *testing.T) {
337338
}
338339
}
339340

341+
func TestParseExtraArgs(t *testing.T) {
342+
type Wanted struct {
343+
args []string
344+
dir string
345+
}
346+
tests := []struct {
347+
name string
348+
args []string
349+
want Wanted
350+
}{
351+
{
352+
name: "args and target",
353+
args: []string{"target_directory", "-o", "upstream", "--depth", "1"},
354+
want: Wanted{
355+
args: []string{"-o", "upstream", "--depth", "1"},
356+
dir: "target_directory",
357+
},
358+
},
359+
{
360+
name: "only args",
361+
args: []string{"-o", "upstream", "--depth", "1"},
362+
want: Wanted{
363+
args: []string{"-o", "upstream", "--depth", "1"},
364+
dir: "",
365+
},
366+
},
367+
{
368+
name: "only target",
369+
args: []string{"target_directory"},
370+
want: Wanted{
371+
args: []string{},
372+
dir: "target_directory",
373+
},
374+
},
375+
{
376+
name: "no args",
377+
args: []string{},
378+
want: Wanted{
379+
args: []string{},
380+
dir: "",
381+
},
382+
},
383+
}
384+
for _, tt := range tests {
385+
t.Run(tt.name, func(t *testing.T) {
386+
args, dir := parseCloneArgs(tt.args)
387+
got := Wanted{
388+
args: args,
389+
dir: dir,
390+
}
391+
392+
if !reflect.DeepEqual(got, tt.want) {
393+
t.Errorf("got %#v want %#v", got, tt.want)
394+
}
395+
})
396+
}
397+
398+
}
399+
340400
func TestRepoClone(t *testing.T) {
341401
tests := []struct {
342402
name string
@@ -348,11 +408,21 @@ func TestRepoClone(t *testing.T) {
348408
args: "repo clone OWNER/REPO",
349409
want: "git clone https://github.com/OWNER/REPO.git",
350410
},
411+
{
412+
name: "shorthand with directory",
413+
args: "repo clone OWNER/REPO target_directory",
414+
want: "git clone https://github.com/OWNER/REPO.git target_directory",
415+
},
351416
{
352417
name: "clone arguments",
353418
args: "repo clone OWNER/REPO -- -o upstream --depth 1",
354419
want: "git clone -o upstream --depth 1 https://github.com/OWNER/REPO.git",
355420
},
421+
{
422+
name: "clone arguments with directory",
423+
args: "repo clone OWNER/REPO target_directory -- -o upstream --depth 1",
424+
want: "git clone -o upstream --depth 1 https://github.com/OWNER/REPO.git target_directory",
425+
},
356426
{
357427
name: "HTTPS URL",
358428
args: "repo clone https://github.com/OWNER/REPO",

0 commit comments

Comments
 (0)
X Tutup