From 035664a0a7ac0e3744c562223844d0b6d27c4617 Mon Sep 17 00:00:00 2001 From: Joe Hattori Date: Mon, 4 May 2020 23:25:00 +0900 Subject: [PATCH 1/5] shorthand of clone without username Signed-off-by: Joe Hattori --- command/repo.go | 9 +++++++++ command/repo_test.go | 10 ++++++++++ 2 files changed, 19 insertions(+) diff --git a/command/repo.go b/command/repo.go index ad208a27777..c3d629a73a4 100644 --- a/command/repo.go +++ b/command/repo.go @@ -127,6 +127,15 @@ func runClone(cloneURL string, args []string) (target string, err error) { func repoClone(cmd *cobra.Command, args []string) error { cloneURL := args[0] if !strings.Contains(cloneURL, ":") { + if !strings.Contains(cloneURL, "/") { + ctx := contextForCommand(cmd) + currentUsername, err := ctx.AuthLogin() + if err != nil { + return err + } + fmt.Printf("currentUesrname: %s\n", currentUsername) + cloneURL = currentUsername + "/" + cloneURL + } cloneURL = formatRemoteURL(cmd, cloneURL) } diff --git a/command/repo_test.go b/command/repo_test.go index 760298231df..9799c821694 100644 --- a/command/repo_test.go +++ b/command/repo_test.go @@ -429,6 +429,11 @@ func TestRepoClone(t *testing.T) { args: "repo clone OWNER/REPO", want: "git clone https://github.com/OWNER/REPO.git", }, + { + name: "shorthand without username", + args: "repo clone REPO", + want: "git clone https://github.com/OWNER/REPO.git", + }, { name: "shorthand with directory", args: "repo clone OWNER/REPO target_directory", @@ -457,6 +462,11 @@ func TestRepoClone(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + ctx := context.NewBlank() + ctx.SetAuthLogin("OWNER") + initContext = func() context.Context { + return ctx + } http := initFakeHTTP() http.StubResponse(200, bytes.NewBufferString(` { "data": { "repository": { From e89ddd745df873c5ea825ca227fdcd79b955b06d Mon Sep 17 00:00:00 2001 From: Joe Hattori Date: Wed, 3 Jun 2020 22:49:09 +0900 Subject: [PATCH 2/5] write test Signed-off-by: Joe Hattori --- command/repo.go | 18 ++++++++---------- command/repo_test.go | 41 +++++++++++++++++++++++++++++++---------- 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/command/repo.go b/command/repo.go index c3d629a73a4..f2572f7325e 100644 --- a/command/repo.go +++ b/command/repo.go @@ -125,16 +125,20 @@ func runClone(cloneURL string, args []string) (target string, err error) { } func repoClone(cmd *cobra.Command, args []string) error { + ctx := contextForCommand(cmd) + apiClient, err := apiClientForContext(ctx) + if err != nil { + return err + } + cloneURL := args[0] if !strings.Contains(cloneURL, ":") { if !strings.Contains(cloneURL, "/") { - ctx := contextForCommand(cmd) - currentUsername, err := ctx.AuthLogin() + currentUser, err := api.CurrentLoginName(apiClient) if err != nil { return err } - fmt.Printf("currentUesrname: %s\n", currentUsername) - cloneURL = currentUsername + "/" + cloneURL + cloneURL = currentUser + "/" + cloneURL } cloneURL = formatRemoteURL(cmd, cloneURL) } @@ -149,12 +153,6 @@ func repoClone(cmd *cobra.Command, args []string) error { } if repo != nil { - ctx := contextForCommand(cmd) - apiClient, err := apiClientForContext(ctx) - if err != nil { - return err - } - parentRepo, err = api.RepoParent(apiClient, repo) if err != nil { return err diff --git a/command/repo_test.go b/command/repo_test.go index 9799c821694..9f1a4eda126 100644 --- a/command/repo_test.go +++ b/command/repo_test.go @@ -15,6 +15,7 @@ import ( "github.com/cli/cli/context" "github.com/cli/cli/internal/run" + "github.com/cli/cli/pkg/httpmock" "github.com/cli/cli/test" "github.com/cli/cli/utils" ) @@ -429,11 +430,6 @@ func TestRepoClone(t *testing.T) { args: "repo clone OWNER/REPO", want: "git clone https://github.com/OWNER/REPO.git", }, - { - name: "shorthand without username", - args: "repo clone REPO", - want: "git clone https://github.com/OWNER/REPO.git", - }, { name: "shorthand with directory", args: "repo clone OWNER/REPO target_directory", @@ -462,11 +458,6 @@ func TestRepoClone(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - ctx := context.NewBlank() - ctx.SetAuthLogin("OWNER") - initContext = func() context.Context { - return ctx - } http := initFakeHTTP() http.StubResponse(200, bytes.NewBufferString(` { "data": { "repository": { @@ -518,6 +509,36 @@ func TestRepoClone_hasParent(t *testing.T) { eq(t, strings.Join(cs.Calls[1].Args, " "), "git -C REPO remote add -f upstream https://github.com/hubot/ORIG.git") } +func TestRepo_withoutUsername(t *testing.T) { + http := initFakeHTTP() + http.Register( + httpmock.GraphQL(`\bviewer\b`), + httpmock.StringResponse(` + { "data": { "viewer": { + "login": "OWNER" + }}}`)) + http.StubResponse(200, bytes.NewBufferString(` + { "data": { "repository": { + "parent": null + } } } + `)) + + cs, restore := test.InitCmdStubber() + defer restore() + + cs.Stub("") // git clone + + output, err := RunCommand("repo clone REPO") + if err != nil { + t.Fatalf("error running command `repo clone`: %v", err) + } + + eq(t, output.String(), "") + eq(t, output.Stderr(), "") + eq(t, cs.Count, 1) + eq(t, strings.Join(cs.Calls[0].Args, " "), "git clone https://github.com/OWNER/REPO.git") +} + func TestRepoCreate(t *testing.T) { ctx := context.NewBlank() ctx.SetBranch("master") From 47e71b12fae6ce5871e0eabe2d15cc94421b6b6a Mon Sep 17 00:00:00 2001 From: Joe Hattori Date: Thu, 4 Jun 2020 20:54:24 +0900 Subject: [PATCH 3/5] add documentation of this feature --- command/repo.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/command/repo.go b/command/repo.go index f2572f7325e..363aaa05436 100644 --- a/command/repo.go +++ b/command/repo.go @@ -56,6 +56,8 @@ var repoCloneCmd = &cobra.Command{ Short: "Clone a repository locally", Long: `Clone a GitHub repository locally. +Without username, e.g. "gh repo clone REPO", clones a presonal repository. + To pass 'git clone' flags, separate them with '--'.`, RunE: repoClone, } From d59ebfd6e856dd5e7185a718776ec1219bb5ae42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Fri, 5 Jun 2020 13:00:40 +0200 Subject: [PATCH 4/5] repo clone: clarify defaulting to current username --- command/repo.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/command/repo.go b/command/repo.go index 363aaa05436..f459c2310b3 100644 --- a/command/repo.go +++ b/command/repo.go @@ -56,7 +56,8 @@ var repoCloneCmd = &cobra.Command{ Short: "Clone a repository locally", Long: `Clone a GitHub repository locally. -Without username, e.g. "gh repo clone REPO", clones a presonal repository. +If the "OWNER/" portion of the "OWNER/REPO" repository argument is omitted, it +defaults to the name of the authenticating user. To pass 'git clone' flags, separate them with '--'.`, RunE: repoClone, From a395290d879d43551350349a0df7a4c51cc63b00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Fri, 5 Jun 2020 13:29:44 +0200 Subject: [PATCH 5/5] Use new httpmock API in test --- command/repo_test.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/command/repo_test.go b/command/repo_test.go index 9f1a4eda126..ff882d12ee7 100644 --- a/command/repo_test.go +++ b/command/repo_test.go @@ -517,11 +517,12 @@ func TestRepo_withoutUsername(t *testing.T) { { "data": { "viewer": { "login": "OWNER" }}}`)) - http.StubResponse(200, bytes.NewBufferString(` - { "data": { "repository": { - "parent": null - } } } - `)) + http.Register( + httpmock.GraphQL(`\brepository\(`), + httpmock.StringResponse(` + { "data": { "repository": { + "parent": null + } } }`)) cs, restore := test.InitCmdStubber() defer restore()