Remove @{push} from branch config

This commit is contained in:
Tyler McGoffin 2025-01-24 10:20:04 -08:00
parent 5a8dd35ba7
commit e4d8ed0e60
5 changed files with 151 additions and 130 deletions

View file

@ -408,15 +408,10 @@ func (c *Client) ReadBranchConfig(ctx context.Context, branch string) (BranchCon
return BranchConfig{}, err
}
// Check to see if we can resolve the @{push} revision syntax. This is the easiest way to get
// the name of the push remote.
// We ignore errors resolving simple push.Default settings as these are handled downstream
revParseOut, _ := c.revParse(ctx, "--verify", "--quiet", "--abbrev-ref", branch+"@{push}")
return parseBranchConfig(outputLines(branchCfgOut), strings.TrimSuffix(remotePushDefaultOut, "\n"), firstLine(revParseOut)), nil
return parseBranchConfig(outputLines(branchCfgOut), strings.TrimSuffix(remotePushDefaultOut, "\n")), nil
}
func parseBranchConfig(branchConfigLines []string, remotePushDefault string, revParse string) BranchConfig {
func parseBranchConfig(branchConfigLines []string, remotePushDefault string) BranchConfig {
var cfg BranchConfig
// Read the config lines for the specific branch
@ -460,9 +455,6 @@ func parseBranchConfig(branchConfigLines []string, remotePushDefault string, rev
}
}
// The value returned by revParse is the easiest way to get the name of the push ref
cfg.Push = revParse
// Some `gh pr` workflows don't work if this is set to 'simple' or 'current'
cfg.RemotePushDefault = remotePushDefault
@ -497,6 +489,15 @@ func (c *Client) PushDefault(ctx context.Context) (string, error) {
return "", err
}
// ParsePushRevision gets the value of the @{push} revision syntax
// An error here doesn't necessarily mean something are broke, but may mean that the @{push}
// revision syntax couldn't be resolved, such as in non-centralized workflows with
// push.default = simple. Downstream consumers should consider how to handle this error.
func (c *Client) ParsePushRevision(ctx context.Context, branch string) (string, error) {
revParseOut, err := c.revParse(ctx, "--abbrev-ref", branch+"@{push}")
return firstLine(revParseOut), err
}
func (c *Client) DeleteLocalTag(ctx context.Context, tag string) error {
args := []string{"tag", "-d", tag}
cmd, err := c.Command(ctx, args...)

View file

@ -760,7 +760,7 @@ func TestClientReadBranchConfig(t *testing.T) {
},
},
{
name: "when the git reads the config, pushDefault isn't set, and rev-parse succeeds, it should return the correct BranchConfig",
name: "when the git reads the config, pushDefault isn't set, it should return the correct BranchConfig",
cmds: mockedCommands{
`path/to/git config --get-regexp ^branch\.trunk\.(remote|merge|pushremote|gh-merge-base)$`: {
Stdout: "branch.trunk.remote origin\n",
@ -768,20 +768,16 @@ func TestClientReadBranchConfig(t *testing.T) {
`path/to/git config remote.pushDefault`: {
ExitStatus: 1,
},
`path/to/git rev-parse --verify --quiet --abbrev-ref trunk@{push}`: {
Stdout: "origin/trunk",
},
},
branch: "trunk",
wantBranchConfig: BranchConfig{
RemoteName: "origin",
PushRemoteName: "origin",
Push: "origin/trunk",
},
wantError: nil,
},
{
name: "when the git reads the config, pushDefault is set, and rev-parse succeeds, it should return the correct BranchConfig",
name: "when the git reads the config, pushDefault is set, it should return the correct BranchConfig",
cmds: mockedCommands{
`path/to/git config --get-regexp ^branch\.trunk\.(remote|merge|pushremote|gh-merge-base)$`: {
Stdout: "branch.trunk.remote origin\n",
@ -789,15 +785,11 @@ func TestClientReadBranchConfig(t *testing.T) {
`path/to/git config remote.pushDefault`: {
Stdout: "remotePushDefault",
},
`path/to/git rev-parse --verify --quiet --abbrev-ref trunk@{push}`: {
Stdout: "origin/trunk",
},
},
branch: "trunk",
wantBranchConfig: BranchConfig{
RemoteName: "origin",
PushRemoteName: "remotePushDefault",
Push: "origin/trunk",
RemotePushDefault: "remotePushDefault",
},
wantError: nil,
@ -811,9 +803,6 @@ func TestClientReadBranchConfig(t *testing.T) {
`path/to/git config remote.pushDefault`: {
Stdout: "remotePushDefault",
},
`path/to/git rev-parse --verify --quiet --abbrev-ref trunk@{push}`: {
ExitStatus: 1,
},
},
branch: "trunk",
wantBranchConfig: BranchConfig{
@ -850,9 +839,6 @@ func TestClientReadBranchConfig(t *testing.T) {
`path/to/git config remote.pushDefault`: {
ExitStatus: 1,
},
`path/to/git rev-parse --verify --quiet --abbrev-ref trunk@{push}`: {
Stdout: "origin/trunk",
},
},
branch: "trunk",
wantBranchConfig: BranchConfig{
@ -860,7 +846,6 @@ func TestClientReadBranchConfig(t *testing.T) {
MergeRef: "refs/heads/trunk",
MergeBase: "merge-base",
PushRemoteName: "origin",
Push: "origin/trunk",
},
wantError: nil,
},
@ -873,16 +858,12 @@ func TestClientReadBranchConfig(t *testing.T) {
`path/to/git config remote.pushDefault`: {
ExitStatus: 1,
},
`path/to/git rev-parse --verify --quiet --abbrev-ref trunk@{push}`: {
Stdout: "origin/trunk-remote",
},
},
branch: "trunk",
wantBranchConfig: BranchConfig{
RemoteName: "origin",
MergeRef: "refs/heads/trunk-remote",
PushRemoteName: "origin",
Push: "origin/trunk-remote",
},
},
{
@ -894,16 +875,12 @@ func TestClientReadBranchConfig(t *testing.T) {
`path/to/git config remote.pushDefault`: {
ExitStatus: 1,
},
`path/to/git rev-parse --verify --quiet --abbrev-ref trunk@{push}`: {
Stdout: "origin/trunk",
},
},
branch: "trunk",
wantBranchConfig: BranchConfig{
RemoteName: "origin",
MergeRef: "refs/heads/main",
PushRemoteName: "origin",
Push: "origin/trunk",
},
},
{
@ -915,16 +892,12 @@ func TestClientReadBranchConfig(t *testing.T) {
`path/to/git config remote.pushDefault`: {
ExitStatus: 1,
},
`path/to/git rev-parse --verify --quiet --abbrev-ref trunk@{push}`: {
Stdout: "origin/trunk",
},
},
branch: "trunk",
wantBranchConfig: BranchConfig{
RemoteName: "upstream",
MergeRef: "refs/heads/main",
PushRemoteName: "origin",
Push: "origin/trunk",
},
},
{
@ -936,16 +909,12 @@ func TestClientReadBranchConfig(t *testing.T) {
`path/to/git config remote.pushDefault`: {
Stdout: "origin",
},
`path/to/git rev-parse --verify --quiet --abbrev-ref trunk@{push}`: {
Stdout: "origin/trunk",
},
},
branch: "trunk",
wantBranchConfig: BranchConfig{
RemoteName: "upstream",
MergeRef: "refs/heads/main",
PushRemoteName: "origin",
Push: "origin/trunk",
RemotePushDefault: "origin",
},
},
@ -958,9 +927,6 @@ func TestClientReadBranchConfig(t *testing.T) {
`path/to/git config remote.pushDefault`: {
Stdout: "current",
},
`path/to/git rev-parse --verify --quiet --abbrev-ref trunk@{push}`: {
ExitStatus: 1,
},
},
branch: "trunk",
wantBranchConfig: BranchConfig{
@ -979,9 +945,6 @@ func TestClientReadBranchConfig(t *testing.T) {
`path/to/git config remote.pushDefault`: {
Stdout: "origin",
},
`path/to/git rev-parse --verify --quiet --abbrev-ref trunk@{push}`: {
ExitStatus: 1,
},
},
branch: "trunk",
wantBranchConfig: BranchConfig{
@ -1018,7 +981,6 @@ func Test_parseBranchConfig(t *testing.T) {
name string
configLines []string
pushDefault string
revParse string
wantBranchConfig BranchConfig
}{
{
@ -1050,14 +1012,6 @@ func Test_parseBranchConfig(t *testing.T) {
PushRemoteName: "pushremote",
},
},
{
name: "rev parse specified",
configLines: []string{},
revParse: "origin/trunk",
wantBranchConfig: BranchConfig{
Push: "origin/trunk",
},
},
{
name: "push default specified",
configLines: []string{},
@ -1108,13 +1062,11 @@ func Test_parseBranchConfig(t *testing.T) {
"branch.trunk.merge refs/heads/trunk",
},
pushDefault: "remotePushDefault",
revParse: "origin/trunk",
wantBranchConfig: BranchConfig{
RemoteName: "remote",
PushRemoteName: "pushremote",
MergeBase: "gh-merge-base",
MergeRef: "refs/heads/trunk",
Push: "origin/trunk",
RemotePushDefault: "remotePushDefault",
},
},
@ -1131,12 +1083,11 @@ func Test_parseBranchConfig(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
branchConfig := parseBranchConfig(tt.configLines, tt.pushDefault, tt.revParse)
branchConfig := parseBranchConfig(tt.configLines, tt.pushDefault)
assert.Equalf(t, tt.wantBranchConfig.RemoteName, branchConfig.RemoteName, "unexpected RemoteName")
assert.Equalf(t, tt.wantBranchConfig.MergeRef, branchConfig.MergeRef, "unexpected MergeRef")
assert.Equalf(t, tt.wantBranchConfig.MergeBase, branchConfig.MergeBase, "unexpected MergeBase")
assert.Equalf(t, tt.wantBranchConfig.PushRemoteName, branchConfig.PushRemoteName, "unexpected PushRemoteName")
assert.Equalf(t, tt.wantBranchConfig.Push, branchConfig.Push, "unexpected Push")
assert.Equalf(t, tt.wantBranchConfig.RemotePushDefault, branchConfig.RemotePushDefault, "unexpected RemotePushDefault")
if tt.wantBranchConfig.RemoteURL != nil {
assert.Equalf(t, tt.wantBranchConfig.RemoteURL.String(), branchConfig.RemoteURL.String(), "unexpected RemoteURL")
@ -1253,6 +1204,60 @@ func TestClientPushDefault(t *testing.T) {
}
}
func TestClientParsePushRevision(t *testing.T) {
tests := []struct {
name string
branch string
commandResult commandResult
wantParsedPushRevision string
wantError *GitError
}{
{
name: "@{push} resolves to origin/branchName",
branch: "branchName",
commandResult: commandResult{
ExitStatus: 0,
Stdout: "origin/branchName",
},
wantParsedPushRevision: "origin/branchName",
},
{
name: "@{push} doesn't resolve",
commandResult: commandResult{
ExitStatus: 128,
Stderr: "fatal: git error",
},
wantParsedPushRevision: "",
wantError: &GitError{
ExitCode: 128,
Stderr: "fatal: git error",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cmd := fmt.Sprintf("path/to/git rev-parse --abbrev-ref %s@{push}", tt.branch)
cmdCtx := createMockedCommandContext(t, mockedCommands{
args(cmd): tt.commandResult,
})
client := Client{
GitPath: "path/to/git",
commandContext: cmdCtx,
}
pushDefault, err := client.ParsePushRevision(context.Background(), tt.branch)
if tt.wantError != nil {
var gitError *GitError
require.ErrorAs(t, err, &gitError)
assert.Equal(t, tt.wantError.ExitCode, gitError.ExitCode)
assert.Equal(t, tt.wantError.Stderr, gitError.Stderr)
} else {
require.NoError(t, err)
}
assert.Equal(t, tt.wantParsedPushRevision, pushDefault)
})
}
}
func TestClientDeleteLocalTag(t *testing.T) {
tests := []struct {
name string

View file

@ -68,8 +68,7 @@ type BranchConfig struct {
MergeRef string
// These are used to handle triangular workflows. They can be defined by either
// a remote.pushDefault or a branch.<name>.pushremote value set on the git config.
RemotePushDefault string
PushRemoteURL *url.URL
PushRemoteName string
Push string
RemotePushDefault string
}