Skip to content

Commit a564909

Browse files
author
Nate Smith
authored
Merge pull request cli#4886 from g14a/feature/target-repo-fork-name
Feature/target repo fork name
2 parents 13b3c7c + 667671f commit a564909

File tree

7 files changed

+140
-68
lines changed

7 files changed

+140
-68
lines changed

api/client.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ func (c Client) REST(hostname string, method string, p string, body io.Reader, d
326326
if err != nil {
327327
return err
328328
}
329+
329330
err = json.Unmarshal(b, &data)
330331
if err != nil {
331332
return err

api/queries_repo.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"context"
66
"encoding/json"
77
"fmt"
8+
"github.com/cli/cli/v2/internal/ghinstance"
89
"io"
910
"net/http"
1011
"sort"
@@ -524,6 +525,37 @@ func ForkRepo(client *Client, repo ghrepo.Interface, org string) (*Repository, e
524525
}, nil
525526
}
526527

528+
// RenameRepo renames the repository on GitHub and returns the renamed repository
529+
func RenameRepo(client *Client, repo ghrepo.Interface, newRepoName string) (*Repository, error) {
530+
input := map[string]string{"name": newRepoName}
531+
body := &bytes.Buffer{}
532+
enc := json.NewEncoder(body)
533+
if err := enc.Encode(input); err != nil {
534+
return nil, err
535+
}
536+
537+
path := fmt.Sprintf("%srepos/%s",
538+
ghinstance.RESTPrefix(repo.RepoHost()),
539+
ghrepo.FullName(repo))
540+
541+
result := repositoryV3{}
542+
err := client.REST(repo.RepoHost(), "PATCH", path, body, &result)
543+
if err != nil {
544+
return nil, err
545+
}
546+
547+
return &Repository{
548+
ID: result.NodeID,
549+
Name: result.Name,
550+
CreatedAt: result.CreatedAt,
551+
Owner: RepositoryOwner{
552+
Login: result.Owner.Login,
553+
},
554+
ViewerPermission: "WRITE",
555+
hostname: repo.RepoHost(),
556+
}, nil
557+
}
558+
527559
func LastCommit(client *Client, repo ghrepo.Interface) (*Commit, error) {
528560
var responseData struct {
529561
Repository struct {

pkg/cmd/repo/fork/fork.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ type ForkOptions struct {
3939
PromptRemote bool
4040
RemoteName string
4141
Organization string
42+
ForkName string
4243
Rename bool
4344
}
4445

@@ -115,6 +116,7 @@ Additional 'git clone' flags can be passed in by listing them after '--'.`,
115116
cmd.Flags().BoolVar(&opts.Remote, "remote", false, "Add remote for fork {true|false}")
116117
cmd.Flags().StringVar(&opts.RemoteName, "remote-name", defaultRemoteName, "Specify a name for a fork's new remote.")
117118
cmd.Flags().StringVar(&opts.Organization, "org", "", "Create the fork in an organization")
119+
cmd.Flags().StringVar(&opts.ForkName, "fork-name", "", "Specify a name for the forked repo")
118120

119121
return cmd
120122
}
@@ -201,6 +203,17 @@ func forkRun(opts *ForkOptions) error {
201203
}
202204
}
203205

206+
// Rename the forked repo if ForkName is specified in opts.
207+
if opts.ForkName != "" {
208+
forkedRepo, err = api.RenameRepo(apiClient, forkedRepo, opts.ForkName)
209+
if err != nil {
210+
return fmt.Errorf("could not rename fork: %w", err)
211+
}
212+
if connectedToTerminal {
213+
fmt.Fprintf(stderr, "%s Renamed fork to %s\n", cs.SuccessIconWithColor(cs.Green), cs.Bold(ghrepo.FullName(forkedRepo)))
214+
}
215+
}
216+
204217
if (inParent && (!opts.Remote && !opts.PromptRemote)) || (!inParent && (!opts.Clone && !opts.PromptClone)) {
205218
return nil
206219
}

pkg/cmd/repo/fork/fork_test.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,16 @@ func TestNewCmdFork(t *testing.T) {
132132
wantErr: true,
133133
errMsg: "unknown flag: --depth\nSeparate git clone flags with '--'.",
134134
},
135+
{
136+
name: "with fork name",
137+
cli: "--fork-name new-fork",
138+
wants: ForkOptions{
139+
Remote: false,
140+
RemoteName: "origin",
141+
ForkName: "new-fork",
142+
Rename: false,
143+
},
144+
},
135145
}
136146

137147
for _, tt := range tests {
@@ -534,6 +544,78 @@ func TestRepoFork(t *testing.T) {
534544
cs.Register(`git -C REPO remote add -f upstream https://github\.com/OWNER/REPO\.git`, 0, "")
535545
},
536546
},
547+
{
548+
name: "non tty repo arg with fork-name",
549+
opts: &ForkOptions{
550+
Repository: "someone/REPO",
551+
Clone: false,
552+
ForkName: "NEW_REPO",
553+
},
554+
tty: false,
555+
httpStubs: func(reg *httpmock.Registry) {
556+
forkResult := `{
557+
"node_id": "123",
558+
"name": "REPO",
559+
"clone_url": "https://github.com/OWNER/REPO.git",
560+
"created_at": "2011-01-26T19:01:12Z",
561+
"owner": {
562+
"login": "OWNER"
563+
}
564+
}`
565+
renameResult := `{
566+
"node_id": "1234",
567+
"name": "NEW_REPO",
568+
"clone_url": "https://github.com/OWNER/NEW_REPO.git",
569+
"created_at": "2012-01-26T19:01:12Z",
570+
"owner": {
571+
"login": "OWNER"
572+
}
573+
}`
574+
reg.Register(
575+
httpmock.REST("POST", "repos/someone/REPO/forks"),
576+
httpmock.StringResponse(forkResult))
577+
reg.Register(
578+
httpmock.REST("PATCH", "repos/OWNER/REPO"),
579+
httpmock.StringResponse(renameResult))
580+
},
581+
wantErrOut: "",
582+
},
583+
{
584+
name: "tty repo arg with fork-name",
585+
opts: &ForkOptions{
586+
Repository: "someone/REPO",
587+
Clone: false,
588+
ForkName: "NEW_REPO",
589+
},
590+
tty: true,
591+
httpStubs: func(reg *httpmock.Registry) {
592+
forkResult := `{
593+
"node_id": "123",
594+
"name": "REPO",
595+
"clone_url": "https://github.com/OWNER/REPO.git",
596+
"created_at": "2011-01-26T19:01:12Z",
597+
"owner": {
598+
"login": "OWNER"
599+
}
600+
}`
601+
renameResult := `{
602+
"node_id": "1234",
603+
"name": "NEW_REPO",
604+
"clone_url": "https://github.com/OWNER/NEW_REPO.git",
605+
"created_at": "2012-01-26T19:01:12Z",
606+
"owner": {
607+
"login": "OWNER"
608+
}
609+
}`
610+
reg.Register(
611+
httpmock.REST("POST", "repos/someone/REPO/forks"),
612+
httpmock.StringResponse(forkResult))
613+
reg.Register(
614+
httpmock.REST("PATCH", "repos/OWNER/REPO"),
615+
httpmock.StringResponse(renameResult))
616+
},
617+
wantErrOut: "✓ Created fork OWNER/REPO\n✓ Renamed fork to OWNER/NEW_REPO\n",
618+
},
537619
}
538620

539621
for _, tt := range tests {

pkg/cmd/repo/rename/http.go

Lines changed: 0 additions & 61 deletions
This file was deleted.

pkg/cmd/repo/rename/rename.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package rename
22

33
import (
44
"fmt"
5+
"github.com/cli/cli/v2/api"
56
"net/http"
67

78
"github.com/AlecAivazis/survey/v2"
@@ -114,11 +115,15 @@ func renameRun(opts *RenameOptions) error {
114115
}
115116
}
116117

117-
newRepo, err := apiRename(httpClient, currRepo, newRepoName)
118+
apiClient := api.NewClientFromHTTP(httpClient)
119+
120+
newRepo, err := api.RenameRepo(apiClient, currRepo, newRepoName)
118121
if err != nil {
119122
return err
120123
}
121124

125+
renamedRepo := ghrepo.New(newRepo.Owner.Login, newRepo.Name)
126+
122127
cs := opts.IO.ColorScheme()
123128
if opts.IO.IsStdoutTTY() {
124129
fmt.Fprintf(opts.IO.Out, "%s Renamed repository %s\n", cs.SuccessIcon(), ghrepo.FullName(newRepo))
@@ -128,7 +133,7 @@ func renameRun(opts *RenameOptions) error {
128133
return nil
129134
}
130135

131-
remote, err := updateRemote(currRepo, newRepo, opts)
136+
remote, err := updateRemote(currRepo, renamedRepo, opts)
132137
if err != nil {
133138
fmt.Fprintf(opts.IO.ErrOut, "%s Warning: unable to update remote %q: %v\n", cs.WarningIcon(), remote.Name, err)
134139
} else if opts.IO.IsStdoutTTY() {

pkg/cmd/repo/rename/rename_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ func TestRenameRun(t *testing.T) {
123123
httpStubs: func(reg *httpmock.Registry) {
124124
reg.Register(
125125
httpmock.REST("PATCH", "repos/OWNER/REPO"),
126-
httpmock.StatusStringResponse(204, `{"name":"NEW_REPO","owner":{"login":"OWNER"}}`))
126+
httpmock.StatusStringResponse(200, `{"name":"NEW_REPO","owner":{"login":"OWNER"}}`))
127127
},
128128
execStubs: func(cs *run.CommandStubber) {
129129
cs.Register(`git remote set-url origin https://github.com/OWNER/NEW_REPO.git`, 0, "")
@@ -143,7 +143,7 @@ func TestRenameRun(t *testing.T) {
143143
httpStubs: func(reg *httpmock.Registry) {
144144
reg.Register(
145145
httpmock.REST("PATCH", "repos/OWNER/REPO"),
146-
httpmock.StatusStringResponse(204, `{"name":"NEW_REPO","owner":{"login":"OWNER"}}`))
146+
httpmock.StatusStringResponse(200, `{"name":"NEW_REPO","owner":{"login":"OWNER"}}`))
147147
},
148148
tty: true,
149149
},
@@ -156,7 +156,7 @@ func TestRenameRun(t *testing.T) {
156156
httpStubs: func(reg *httpmock.Registry) {
157157
reg.Register(
158158
httpmock.REST("PATCH", "repos/OWNER/REPO"),
159-
httpmock.StatusStringResponse(204, `{"name":"NEW_REPO","owner":{"login":"OWNER"}}`))
159+
httpmock.StatusStringResponse(200, `{"name":"NEW_REPO","owner":{"login":"OWNER"}}`))
160160
},
161161
execStubs: func(cs *run.CommandStubber) {
162162
cs.Register(`git remote set-url origin https://github.com/OWNER/NEW_REPO.git`, 0, "")
@@ -171,7 +171,7 @@ func TestRenameRun(t *testing.T) {
171171
httpStubs: func(reg *httpmock.Registry) {
172172
reg.Register(
173173
httpmock.REST("PATCH", "repos/OWNER/REPO"),
174-
httpmock.StatusStringResponse(204, `{"name":"NEW_REPO","owner":{"login":"OWNER"}}`))
174+
httpmock.StatusStringResponse(200, `{"name":"NEW_REPO","owner":{"login":"OWNER"}}`))
175175
},
176176
execStubs: func(cs *run.CommandStubber) {
177177
cs.Register(`git remote set-url origin https://github.com/OWNER/NEW_REPO.git`, 0, "")
@@ -192,7 +192,7 @@ func TestRenameRun(t *testing.T) {
192192
httpStubs: func(reg *httpmock.Registry) {
193193
reg.Register(
194194
httpmock.REST("PATCH", "repos/OWNER/REPO"),
195-
httpmock.StatusStringResponse(204, `{"name":"NEW_REPO","owner":{"login":"OWNER"}}`))
195+
httpmock.StatusStringResponse(200, `{"name":"NEW_REPO","owner":{"login":"OWNER"}}`))
196196
},
197197
execStubs: func(cs *run.CommandStubber) {
198198
cs.Register(`git remote set-url origin https://github.com/OWNER/NEW_REPO.git`, 0, "")

0 commit comments

Comments
 (0)