11package create
22
33import (
4+ "context"
45 "errors"
56 "fmt"
6- "io"
77 "net/http"
88 "net/url"
99 "strings"
@@ -12,7 +12,7 @@ import (
1212 "github.com/AlecAivazis/survey/v2"
1313 "github.com/MakeNowJust/heredoc"
1414 "github.com/cli/cli/v2/api"
15- "github.com/cli/cli/v2/context"
15+ remotesContext "github.com/cli/cli/v2/context"
1616 "github.com/cli/cli/v2/git"
1717 "github.com/cli/cli/v2/internal/config"
1818 "github.com/cli/cli/v2/internal/ghrepo"
@@ -28,17 +28,17 @@ type browser interface {
2828 Browse (string ) error
2929}
3030
31- //go:generate mockery --name gitClient --structname GitClient
31+ //go:generate moq -fmt goimports -rm -skip-ensure -out git_client_mock.go . gitClient
3232type gitClient interface {
33- Push (args [] string , stdout io. Writer , stderr io. Writer ) error
33+ Push (ctx context. Context , opts git. PushOptions ) error
3434}
3535
3636type CreateOptions struct {
3737 // This struct stores user input and factory functions
3838 HttpClient func () (* http.Client , error )
3939 Config func () (config.Config , error )
4040 IO * iostreams.IOStreams
41- Remotes func () (context .Remotes , error )
41+ Remotes func () (remotesContext .Remotes , error )
4242 Branch func () (string , error )
4343 Browser browser
4444 Git gitClient
@@ -72,14 +72,14 @@ type CreateOptions struct {
7272type CreateContext struct {
7373 // This struct stores contextual data about the creation process and is for building up enough
7474 // data to create a pull request
75- RepoContext * context .ResolvedRemotes
75+ RepoContext * remotesContext .ResolvedRemotes
7676 BaseRepo * api.Repository
7777 HeadRepo ghrepo.Interface
7878 BaseTrackingBranch string
7979 BaseBranch string
8080 HeadBranch string
8181 HeadBranchLabel string
82- HeadRemote * context .Remote
82+ HeadRemote * remotesContext .Remote
8383 IsPushEnabled bool
8484 Client * api.Client
8585}
@@ -92,7 +92,11 @@ func NewCmdCreate(f *cmdutil.Factory, runF func(*CreateOptions) error) *cobra.Co
9292 Remotes : f .Remotes ,
9393 Branch : f .Branch ,
9494 Browser : f .Browser ,
95- Git : & gitClientExec {gitCommand : git .GitCommand },
95+ Git : & git.LocalRepo {
96+ Stdin : f .IOStreams .In ,
97+ Stdout : f .IOStreams .Out ,
98+ Stderr : f .IOStreams .ErrOut ,
99+ },
96100 }
97101
98102 var bodyFile string
@@ -393,7 +397,7 @@ func initDefaultTitleBody(ctx CreateContext, state *shared.IssueMetadataState) e
393397 return nil
394398}
395399
396- func determineTrackingBranch (remotes context .Remotes , headBranch string ) * git.TrackingRef {
400+ func determineTrackingBranch (remotes remotesContext .Remotes , headBranch string ) * git.TrackingRef {
397401 refsForLookup := []string {"HEAD" }
398402 var trackingRefs []git.TrackingRef
399403
@@ -478,7 +482,7 @@ func NewCreateContext(opts *CreateOptions) (*CreateContext, error) {
478482 return nil , err
479483 }
480484
481- repoContext , err := context .ResolveRemotesToRepos (remotes , client , opts .RepoOverride )
485+ repoContext , err := remotesContext .ResolveRemotesToRepos (remotes , client , opts .RepoOverride )
482486 if err != nil {
483487 return nil , err
484488 }
@@ -518,7 +522,7 @@ func NewCreateContext(opts *CreateOptions) (*CreateContext, error) {
518522 }
519523
520524 var headRepo ghrepo.Interface
521- var headRemote * context .Remote
525+ var headRemote * remotesContext .Remote
522526
523527 if isPushEnabled {
524528 // determine whether the head branch is already pushed to a remote
@@ -717,7 +721,7 @@ func handlePush(opts CreateOptions, ctx CreateContext) error {
717721 if err != nil {
718722 return fmt .Errorf ("error adding remote: %w" , err )
719723 }
720- headRemote = & context .Remote {
724+ headRemote = & remotesContext .Remote {
721725 Remote : gitRemote ,
722726 Repo : headRepo ,
723727 }
@@ -727,14 +731,15 @@ func handlePush(opts CreateOptions, ctx CreateContext) error {
727731 if ctx .IsPushEnabled {
728732 pushTries := 0
729733 maxPushTries := 3
734+ ct := context .TODO ()
730735 for {
731- args := [] string { "--set-upstream" }
732- if opts . IO . IsStderrTTY () {
733- args = append ( args , "--progress" )
734- }
735- args = append ( args , headRemote . Name , fmt . Sprintf ( "HEAD:%s" , ctx . HeadBranch ))
736- if err := opts . Git . Push ( args , opts . IO . Out , opts . IO . ErrOut ); err != nil {
737- if didForkRepo && pushTries < maxPushTries {
736+ if err := opts . Git . Push ( ct , git. PushOptions {
737+ RemoteName : headRemote . Name ,
738+ TargetBranch : ctx . HeadBranch ,
739+ SetUpstream : true ,
740+ ShowProgress : opts . IO . IsStderrTTY (),
741+ } ); err != nil {
742+ if ct . Err () == nil && didForkRepo && pushTries < maxPushTries {
738743 pushTries ++
739744 // first wait 2 seconds after forking, then 4s, then 6s
740745 waitSeconds := 2 * pushTries
0 commit comments