From d871da679b237397dc9a4df2aa9073cf46f686db Mon Sep 17 00:00:00 2001 From: leavesster <11785335+leavesster@users.noreply.github.com> Date: Wed, 28 Jun 2023 12:07:42 +0800 Subject: [PATCH] Change how remotes are treated during `pr create` when repo is forked (#7330) --- pkg/cmd/pr/create/create.go | 39 +++++++++++++++++++++++++++----- pkg/cmd/pr/create/create_test.go | 7 +++--- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/pkg/cmd/pr/create/create.go b/pkg/cmd/pr/create/create.go index 83421d88b..4c0c6286b 100644 --- a/pkg/cmd/pr/create/create.go +++ b/pkg/cmd/pr/create/create.go @@ -736,24 +736,51 @@ func handlePush(opts CreateOptions, ctx CreateContext) error { // missing: // 1. the head repo was just created by auto-forking; // 2. an existing fork was discovered by querying the API. - // // In either case, we want to add the head repo as a new git remote so we - // can push to it. + // can push to it. We will try to add the head repo as the "origin" remote + // and fallback to the "fork" remote if it is unavailable. Also, if the + // base repo is the "origin" remote we will rename it "upstream". if headRemote == nil && ctx.IsPushEnabled { cfg, err := opts.Config() if err != nil { return err } + + remotes, err := opts.Remotes() + if err != nil { + return err + } + cloneProtocol, _ := cfg.GetOrDefault(headRepo.RepoHost(), "git_protocol") - headRepoURL := ghrepo.FormatRemoteURL(headRepo, cloneProtocol) - - // TODO: prevent clashes with another remote of a same name gitClient := ctx.GitClient - gitRemote, err := gitClient.AddRemote(context.Background(), "fork", headRepoURL, []string{}) + origin, _ := remotes.FindByName("origin") + upstream, _ := remotes.FindByName("upstream") + remoteName := "origin" + + if origin != nil { + remoteName = "fork" + } + + if origin != nil && upstream == nil && ghrepo.IsSame(origin, ctx.BaseRepo) { + renameCmd, err := gitClient.Command(context.Background(), "remote", "rename", "origin", "upstream") + if err != nil { + return err + } + if _, err = renameCmd.Output(); err != nil { + return fmt.Errorf("error renaming origin remote: %w", err) + } + remoteName = "origin" + fmt.Fprintf(opts.IO.ErrOut, "Changed %s remote to %q\n", ghrepo.FullName(ctx.BaseRepo), "upstream") + } + + gitRemote, err := gitClient.AddRemote(context.Background(), remoteName, headRepoURL, []string{}) if err != nil { return fmt.Errorf("error adding remote: %w", err) } + + fmt.Fprintf(opts.IO.ErrOut, "Added %s as remote %q\n", ghrepo.FullName(headRepo), remoteName) + headRemote = &ghContext.Remote{ Remote: gitRemote, Repo: headRepo, diff --git a/pkg/cmd/pr/create/create_test.go b/pkg/cmd/pr/create/create_test.go index 84b5cf6fa..5b5fe2ee4 100644 --- a/pkg/cmd/pr/create/create_test.go +++ b/pkg/cmd/pr/create/create_test.go @@ -466,8 +466,9 @@ func Test_createRun(t *testing.T) { cmdStubs: func(cs *run.CommandStubber) { cs.Register(`git config --get-regexp.+branch\\\.feature\\\.`, 0, "") cs.Register(`git show-ref --verify -- HEAD refs/remotes/origin/feature`, 0, "") - cs.Register(`git remote add fork https://github.com/monalisa/REPO.git`, 0, "") - cs.Register(`git push --set-upstream fork HEAD:feature`, 0, "") + cs.Register("git remote rename origin upstream", 0, "") + cs.Register(`git remote add origin https://github.com/monalisa/REPO.git`, 0, "") + cs.Register(`git push --set-upstream origin HEAD:feature`, 0, "") }, promptStubs: func(pm *prompter.PrompterMock) { pm.SelectFunc = func(p, _ string, opts []string) (int, error) { @@ -479,7 +480,7 @@ func Test_createRun(t *testing.T) { } }, expectedOut: "https://github.com/OWNER/REPO/pull/12\n", - expectedErrOut: "\nCreating pull request for monalisa:feature into master in OWNER/REPO\n\n", + expectedErrOut: "\nCreating pull request for monalisa:feature into master in OWNER/REPO\n\nChanged OWNER/REPO remote to \"upstream\"\nAdded monalisa/REPO as remote \"origin\"\n", }, { name: "pushed to non base repo",