Set upstream remote to track all branches after initial fetch (#7542)

This commit is contained in:
Sam Coe 2023-06-12 09:23:56 +09:00 committed by GitHub
parent 63a4319f6c
commit fac497108b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 145 additions and 50 deletions

View file

@ -36,6 +36,19 @@ type Client struct {
mu sync.Mutex
}
func (c *Client) Copy() *Client {
return &Client{
GhPath: c.GhPath,
RepoDir: c.RepoDir,
GitPath: c.GitPath,
Stderr: c.Stderr,
Stdin: c.Stdin,
Stdout: c.Stdout,
commandContext: c.commandContext,
}
}
func (c *Client) Command(ctx context.Context, args ...string) (*Command, error) {
if c.RepoDir != "" {
args = append([]string{"-C", c.RepoDir}, args...)
@ -408,6 +421,44 @@ func (c *Client) revParse(ctx context.Context, args ...string) ([]byte, error) {
return cmd.Output()
}
func (c *Client) IsLocalGitRepo(ctx context.Context) (bool, error) {
_, err := c.GitDir(ctx)
if err != nil {
var execError errWithExitCode
if errors.As(err, &execError) && execError.ExitCode() == 128 {
return false, nil
}
return false, err
}
return true, nil
}
func (c *Client) UnsetRemoteResolution(ctx context.Context, name string) error {
args := []string{"config", "--unset", fmt.Sprintf("remote.%s.gh-resolved", name)}
cmd, err := c.Command(ctx, args...)
if err != nil {
return err
}
_, err = cmd.Output()
if err != nil {
return err
}
return nil
}
func (c *Client) SetRemoteBranches(ctx context.Context, remote string, refspec string) error {
args := []string{"remote", "set-branches", remote, refspec}
cmd, err := c.Command(ctx, args...)
if err != nil {
return err
}
_, err = cmd.Output()
if err != nil {
return err
}
return nil
}
// Below are commands that make network calls and need authentication credentials supplied from gh.
func (c *Client) Fetch(ctx context.Context, remote string, refspec string, mods ...CommandModifier) error {
@ -513,31 +564,6 @@ func (c *Client) AddRemote(ctx context.Context, name, urlStr string, trackingBra
return remote, nil
}
func (c *Client) IsLocalGitRepo(ctx context.Context) (bool, error) {
_, err := c.GitDir(ctx)
if err != nil {
var execError errWithExitCode
if errors.As(err, &execError) && execError.ExitCode() == 128 {
return false, nil
}
return false, err
}
return true, nil
}
func (c *Client) UnsetRemoteResolution(ctx context.Context, name string) error {
args := []string{"config", "--unset", fmt.Sprintf("remote.%s.gh-resolved", name)}
cmd, err := c.Command(ctx, args...)
if err != nil {
return err
}
_, err = cmd.Output()
if err != nil {
return err
}
return nil
}
func resolveGitPath() (string, error) {
path, err := safeexec.LookPath("git")
if err != nil {

View file

@ -834,6 +834,84 @@ func TestClientPathFromRoot(t *testing.T) {
}
}
func TestClientUnsetRemoteResolution(t *testing.T) {
tests := []struct {
name string
cmdExitStatus int
cmdStdout string
cmdStderr string
wantCmdArgs string
wantErrorMsg string
}{
{
name: "unset remote resolution",
wantCmdArgs: `path/to/git config --unset remote.origin.gh-resolved`,
},
{
name: "git error",
cmdExitStatus: 1,
cmdStderr: "git error message",
wantCmdArgs: `path/to/git config --unset remote.origin.gh-resolved`,
wantErrorMsg: "failed to run git: git error message",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cmd, cmdCtx := createCommandContext(t, tt.cmdExitStatus, tt.cmdStdout, tt.cmdStderr)
client := Client{
GitPath: "path/to/git",
commandContext: cmdCtx,
}
err := client.UnsetRemoteResolution(context.Background(), "origin")
assert.Equal(t, tt.wantCmdArgs, strings.Join(cmd.Args[3:], " "))
if tt.wantErrorMsg == "" {
assert.NoError(t, err)
} else {
assert.EqualError(t, err, tt.wantErrorMsg)
}
})
}
}
func TestClientSetRemoteBranches(t *testing.T) {
tests := []struct {
name string
cmdExitStatus int
cmdStdout string
cmdStderr string
wantCmdArgs string
wantErrorMsg string
}{
{
name: "set remote branches",
wantCmdArgs: `path/to/git remote set-branches origin trunk`,
},
{
name: "git error",
cmdExitStatus: 1,
cmdStderr: "git error message",
wantCmdArgs: `path/to/git remote set-branches origin trunk`,
wantErrorMsg: "failed to run git: git error message",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cmd, cmdCtx := createCommandContext(t, tt.cmdExitStatus, tt.cmdStdout, tt.cmdStderr)
client := Client{
GitPath: "path/to/git",
commandContext: cmdCtx,
}
err := client.SetRemoteBranches(context.Background(), "origin", "trunk")
assert.Equal(t, tt.wantCmdArgs, strings.Join(cmd.Args[3:], " "))
if tt.wantErrorMsg == "" {
assert.NoError(t, err)
} else {
assert.EqualError(t, err, tt.wantErrorMsg)
}
})
}
}
func TestClientFetch(t *testing.T) {
tests := []struct {
name string

View file

@ -46,16 +46,9 @@ func (g *gitExecuter) Fetch(remote string, refspec string) error {
}
func (g *gitExecuter) ForRepo(repoDir string) gitClient {
return &gitExecuter{
client: &git.Client{
GhPath: g.client.GhPath,
RepoDir: repoDir,
GitPath: g.client.GitPath,
Stderr: g.client.Stderr,
Stdin: g.client.Stdin,
Stdout: g.client.Stdout,
},
}
gc := g.client.Copy()
gc.RepoDir = repoDir
return &gitExecuter{client: gc}
}
func (g *gitExecuter) Pull(remote, branch string) error {

View file

@ -175,12 +175,19 @@ func cloneRun(opts *CloneOptions) error {
upstreamName = canonicalRepo.Parent.RepoOwner()
}
_, err = gitClient.AddRemote(ctx, upstreamName, upstreamURL, []string{canonicalRepo.Parent.DefaultBranchRef.Name}, git.WithRepoDir(cloneDir))
gc := gitClient.Copy()
gc.RepoDir = cloneDir
_, err = gc.AddRemote(ctx, upstreamName, upstreamURL, []string{canonicalRepo.Parent.DefaultBranchRef.Name})
if err != nil {
return err
}
if err := gitClient.Fetch(ctx, upstreamName, "", git.WithRepoDir(cloneDir)); err != nil {
if err := gc.Fetch(ctx, upstreamName, ""); err != nil {
return err
}
if err := gc.SetRemoteBranches(ctx, upstreamName, `*`); err != nil {
return err
}
}

View file

@ -247,6 +247,7 @@ func Test_RepoClone_hasParent(t *testing.T) {
cs.Register(`git clone https://github.com/OWNER/REPO.git`, 0, "")
cs.Register(`git -C REPO remote add -t trunk upstream https://github.com/hubot/ORIG.git`, 0, "")
cs.Register(`git -C REPO fetch upstream`, 0, "")
cs.Register(`git -C REPO remote set-branches upstream *`, 0, "")
_, err := runCloneCommand(httpClient, "OWNER/REPO")
if err != nil {
@ -284,6 +285,7 @@ func Test_RepoClone_hasParent_upstreamRemoteName(t *testing.T) {
cs.Register(`git clone https://github.com/OWNER/REPO.git`, 0, "")
cs.Register(`git -C REPO remote add -t trunk test https://github.com/hubot/ORIG.git`, 0, "")
cs.Register(`git -C REPO fetch test`, 0, "")
cs.Register(`git -C REPO remote set-branches test *`, 0, "")
_, err := runCloneCommand(httpClient, "OWNER/REPO --upstream-remote-name test")
if err != nil {

View file

@ -662,8 +662,8 @@ func localInit(gitClient *git.Client, remoteURL, path string) error {
return err
}
// Clone the client so we do not modify the original client's RepoDir.
gc := cloneGitClient(gitClient)
// Copy the client so we do not modify the original client's RepoDir.
gc := gitClient.Copy()
gc.RepoDir = path
gitRemoteAdd, err := gc.Command(ctx, "remote", "add", "origin", remoteURL)
@ -794,14 +794,3 @@ func splitNameAndOwner(name string) (string, string, error) {
}
return repo.RepoName(), repo.RepoOwner(), nil
}
func cloneGitClient(c *git.Client) *git.Client {
return &git.Client{
GhPath: c.GhPath,
RepoDir: c.RepoDir,
GitPath: c.GitPath,
Stderr: c.Stderr,
Stdin: c.Stdin,
Stdout: c.Stdout,
}
}