Skip to content

Commit bec58ed

Browse files
committed
respect ssh
this adds recognition of the git_protocol setting when: - creating a repo - cloning a repo - forking a repo - forking/pushing during pr create - checking out a PR additionally, it: - consolidates remote adding to use AddRemote; this introduces a fetch where there previously hadn't been one - changes repo clone to accept an ssh url - changes repo fork to accept an ssh url i just added basic unit tests; adding new test cases for all of the above scenarios seemed like diminishing returns.
1 parent 80d7513 commit bec58ed

File tree

7 files changed

+94
-28
lines changed

7 files changed

+94
-28
lines changed

command/pr_checkout.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ func prCheckout(cmd *cobra.Command, args []string) error {
4747

4848
baseRemote, _ := remotes.FindByRepo(baseRepo.RepoOwner(), baseRepo.RepoName())
4949
// baseRemoteSpec is a repository URL or a remote name to be used in git fetch
50-
baseURLOrName := fmt.Sprintf("https://github.com/%s.git", ghrepo.FullName(baseRepo))
50+
baseURLOrName := formatRemoteURL(cmd, ghrepo.FullName(baseRepo))
5151
if baseRemote != nil {
5252
baseURLOrName = baseRemote.Name
5353
}
@@ -97,7 +97,7 @@ func prCheckout(cmd *cobra.Command, args []string) error {
9797
remote := baseURLOrName
9898
mergeRef := ref
9999
if pr.MaintainerCanModify {
100-
remote = fmt.Sprintf("https://github.com/%s/%s.git", pr.HeadRepositoryOwner.Login, pr.HeadRepository.Name)
100+
remote = formatRemoteURL(cmd, fmt.Sprintf("%s/%s", pr.HeadRepositoryOwner.Login, pr.HeadRepository.Name))
101101
mergeRef = fmt.Sprintf("refs/heads/%s", pr.HeadRefName)
102102
}
103103
if mc, err := git.Config(fmt.Sprintf("branch.%s.merge", newBranchName)); err != nil || mc == "" {

command/pr_create.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,8 @@ func prCreate(cmd *cobra.Command, _ []string) error {
250250
// In either case, we want to add the head repo as a new git remote so we
251251
// can push to it.
252252
if headRemote == nil {
253-
// TODO: support non-HTTPS git remote URLs
254-
headRepoURL := fmt.Sprintf("https://github.com/%s.git", ghrepo.FullName(headRepo))
253+
headRepoURL := formatRemoteURL(cmd, ghrepo.FullName(headRepo))
254+
255255
// TODO: prevent clashes with another remote of a same name
256256
gitRemote, err := git.AddRemote("fork", headRepoURL)
257257
if err != nil {

command/repo.go

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ func runClone(cloneURL string, args []string) (target string, err error) {
127127
func repoClone(cmd *cobra.Command, args []string) error {
128128
cloneURL := args[0]
129129
if !strings.Contains(cloneURL, ":") {
130-
cloneURL = fmt.Sprintf("https://github.com/%s.git", cloneURL)
130+
cloneURL = formatRemoteURL(cmd, cloneURL)
131131
}
132132

133133
var repo ghrepo.Interface
@@ -158,7 +158,7 @@ func repoClone(cmd *cobra.Command, args []string) error {
158158
}
159159

160160
if parentRepo != nil {
161-
err := addUpstreamRemote(parentRepo, cloneDir)
161+
err := addUpstreamRemote(cmd, parentRepo, cloneDir)
162162
if err != nil {
163163
return err
164164
}
@@ -167,9 +167,8 @@ func repoClone(cmd *cobra.Command, args []string) error {
167167
return nil
168168
}
169169

170-
func addUpstreamRemote(parentRepo ghrepo.Interface, cloneDir string) error {
171-
// TODO: support SSH remote URLs
172-
upstreamURL := fmt.Sprintf("https://github.com/%s.git", ghrepo.FullName(parentRepo))
170+
func addUpstreamRemote(cmd *cobra.Command, parentRepo ghrepo.Interface, cloneDir string) error {
171+
upstreamURL := formatRemoteURL(cmd, ghrepo.FullName(parentRepo))
173172

174173
cloneCmd := git.GitCommand("-C", cloneDir, "remote", "add", "-f", "upstream", upstreamURL)
175174
cloneCmd.Stdout = os.Stdout
@@ -267,14 +266,10 @@ func repoCreate(cmd *cobra.Command, args []string) error {
267266
fmt.Fprintln(out, repo.URL)
268267
}
269268

270-
remoteURL := repo.URL + ".git"
269+
remoteURL := formatRemoteURL(cmd, ghrepo.FullName(repo))
271270

272271
if projectDirErr == nil {
273-
// TODO: use git.AddRemote
274-
remoteAdd := git.GitCommand("remote", "add", "origin", remoteURL)
275-
remoteAdd.Stdout = os.Stdout
276-
remoteAdd.Stderr = os.Stderr
277-
err = run.PrepareCmd(remoteAdd).Run()
272+
_, err = git.AddRemote("origin", remoteURL)
278273
if err != nil {
279274
return err
280275
}
@@ -361,6 +356,15 @@ func repoFork(cmd *cobra.Command, args []string) error {
361356
return fmt.Errorf("did not understand argument: %w", err)
362357
}
363358

359+
} else if strings.HasPrefix(repoArg, "git@") {
360+
parsedURL, err := git.ParseURL(repoArg)
361+
if err != nil {
362+
return fmt.Errorf("did not understand argument: %w", err)
363+
}
364+
toFork, err = ghrepo.FromURL(parsedURL)
365+
if err != nil {
366+
return fmt.Errorf("did not understand argument: %w", err)
367+
}
364368
} else {
365369
toFork = ghrepo.FromFullName(repoArg)
366370
if toFork.RepoName() == "" || toFork.RepoOwner() == "" {
@@ -437,7 +441,9 @@ func repoFork(cmd *cobra.Command, args []string) error {
437441
fmt.Fprintf(out, "%s Renamed %s remote to %s\n", greenCheck, utils.Bold(remoteName), utils.Bold(renameTarget))
438442
}
439443

440-
_, err = git.AddRemote(remoteName, forkedRepo.CloneURL)
444+
forkedRepoCloneURL := formatRemoteURL(cmd, ghrepo.FullName(forkedRepo))
445+
446+
_, err = git.AddRemote(remoteName, forkedRepoCloneURL)
441447
if err != nil {
442448
return fmt.Errorf("failed to add remote: %w", err)
443449
}
@@ -458,7 +464,7 @@ func repoFork(cmd *cobra.Command, args []string) error {
458464
return fmt.Errorf("failed to clone fork: %w", err)
459465
}
460466

461-
err = addUpstreamRemote(toFork, cloneDir)
467+
err = addUpstreamRemote(cmd, toFork, cloneDir)
462468
if err != nil {
463469
return err
464470
}

command/repo_test.go

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ func TestRepoFork_in_parent_yes(t *testing.T) {
153153

154154
expectedCmds := []string{
155155
"git remote rename origin upstream",
156-
"git remote add -f origin https://github.com/someone/repo.git",
156+
"git remote add -f origin https://github.com/someone/REPO.git",
157157
}
158158

159159
for x, cmd := range seenCmds {
@@ -287,7 +287,7 @@ func TestRepoFork_in_parent_survey_yes(t *testing.T) {
287287

288288
expectedCmds := []string{
289289
"git remote rename origin upstream",
290-
"git remote add -f origin https://github.com/someone/repo.git",
290+
"git remote add -f origin https://github.com/someone/REPO.git",
291291
}
292292

293293
for x, cmd := range seenCmds {
@@ -499,7 +499,11 @@ func TestRepoCreate(t *testing.T) {
499499
{ "data": { "createRepository": {
500500
"repository": {
501501
"id": "REPOID",
502-
"url": "https://github.com/OWNER/REPO"
502+
"url": "https://github.com/OWNER/REPO",
503+
"name": "REPO",
504+
"owner": {
505+
"login": "OWNER"
506+
}
503507
}
504508
} } }
505509
`))
@@ -522,7 +526,7 @@ func TestRepoCreate(t *testing.T) {
522526
if seenCmd == nil {
523527
t.Fatal("expected a command to run")
524528
}
525-
eq(t, strings.Join(seenCmd.Args, " "), "git remote add origin https://github.com/OWNER/REPO.git")
529+
eq(t, strings.Join(seenCmd.Args, " "), "git remote add -f origin https://github.com/OWNER/REPO.git")
526530

527531
var reqBody struct {
528532
Query string
@@ -564,7 +568,11 @@ func TestRepoCreate_org(t *testing.T) {
564568
{ "data": { "createRepository": {
565569
"repository": {
566570
"id": "REPOID",
567-
"url": "https://github.com/ORG/REPO"
571+
"url": "https://github.com/ORG/REPO",
572+
"name": "REPO",
573+
"owner": {
574+
"login": "ORG"
575+
}
568576
}
569577
} } }
570578
`))
@@ -587,7 +595,7 @@ func TestRepoCreate_org(t *testing.T) {
587595
if seenCmd == nil {
588596
t.Fatal("expected a command to run")
589597
}
590-
eq(t, strings.Join(seenCmd.Args, " "), "git remote add origin https://github.com/ORG/REPO.git")
598+
eq(t, strings.Join(seenCmd.Args, " "), "git remote add -f origin https://github.com/ORG/REPO.git")
591599

592600
var reqBody struct {
593601
Query string
@@ -629,7 +637,11 @@ func TestRepoCreate_orgWithTeam(t *testing.T) {
629637
{ "data": { "createRepository": {
630638
"repository": {
631639
"id": "REPOID",
632-
"url": "https://github.com/ORG/REPO"
640+
"url": "https://github.com/ORG/REPO",
641+
"name": "REPO",
642+
"owner": {
643+
"login": "ORG"
644+
}
633645
}
634646
} } }
635647
`))
@@ -652,7 +664,7 @@ func TestRepoCreate_orgWithTeam(t *testing.T) {
652664
if seenCmd == nil {
653665
t.Fatal("expected a command to run")
654666
}
655-
eq(t, strings.Join(seenCmd.Args, " "), "git remote add origin https://github.com/ORG/REPO.git")
667+
eq(t, strings.Join(seenCmd.Args, " "), "git remote add -f origin https://github.com/ORG/REPO.git")
656668

657669
var reqBody struct {
658670
Query string

command/root.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,3 +222,22 @@ func determineBaseRepo(cmd *cobra.Command, ctx context.Context) (ghrepo.Interfac
222222

223223
return baseRepo, nil
224224
}
225+
226+
func formatRemoteURL(cmd *cobra.Command, fullRepoName string) string {
227+
ctx := contextForCommand(cmd)
228+
229+
protocol := "https"
230+
cfg, err := ctx.Config()
231+
if err != nil {
232+
fmt.Fprintf(colorableErr(cmd), "%s failed to load config: %s. using defaults\n", utils.Yellow("!"), err)
233+
} else {
234+
cfgProtocol, _ := cfg.Get(defaultHostname, "git_protocol")
235+
protocol = cfgProtocol
236+
}
237+
238+
if protocol == "ssh" {
239+
return fmt.Sprintf("git@%s:%s.git", defaultHostname, fullRepoName)
240+
}
241+
242+
return fmt.Sprintf("https://%s/%s.git", defaultHostname, fullRepoName)
243+
}

command/root_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,22 @@ func TestChangelogURL(t *testing.T) {
4040
t.Errorf("expected %s to create url %s but got %s", tag, url, result)
4141
}
4242
}
43+
44+
func TestRemoteURLFormatting_no_config(t *testing.T) {
45+
initBlankContext("", "OWNER/REPO", "master")
46+
result := formatRemoteURL(repoForkCmd, "OWNER/REPO")
47+
eq(t, result, "https://github.com/OWNER/REPO.git")
48+
}
49+
50+
func TestRemoteURLFormatting_ssh_config(t *testing.T) {
51+
cfg := `---
52+
hosts:
53+
github.com:
54+
user: OWNER
55+
oauth_token: MUSTBEHIGHCUZIMATOKEN
56+
git_protocol: ssh
57+
`
58+
initBlankContext(cfg, "OWNER/REPO", "master")
59+
result := formatRemoteURL(repoForkCmd, "OWNER/REPO")
60+
eq(t, result, "git@github.com:OWNER/REPO.git")
61+
}

git/remote.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,19 @@ func AddRemote(name, u string) (*Remote, error) {
7979
return nil, err
8080
}
8181

82-
urlParsed, err := url.Parse(u)
83-
if err != nil {
84-
return nil, err
82+
var urlParsed *url.URL
83+
if strings.HasPrefix(u, "https") {
84+
urlParsed, err = url.Parse(u)
85+
if err != nil {
86+
return nil, err
87+
}
88+
89+
} else {
90+
urlParsed, err = ParseURL(u)
91+
if err != nil {
92+
return nil, err
93+
}
94+
8595
}
8696

8797
return &Remote{

0 commit comments

Comments
 (0)