🌐 US-Proxy
class="logged-out env-production page-responsive full-width" style="word-wrap: break-word;" >
Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
0179381
Find PRs using @{push}
Frederick888 Jun 14, 2024
7fc35fd
Only find PRs w/ branch.<name>.merge if push.default = upstream/tracking
Frederick888 Jun 14, 2024
4254818
Find push remote using branch.<name>.pushRemote and remote.pushDefault
Frederick888 Jun 14, 2024
2d1e4d6
Add base gh pr view acceptance tests for changes
andyfeller Dec 16, 2024
eb16a75
Expand with gh pr status
andyfeller Dec 16, 2024
8bb2879
Reflect coverage for view and status subcommands
andyfeller Dec 16, 2024
be250b3
Add renamed acceptance tests
andyfeller Dec 16, 2024
0006091
Fix up intra-org fork test setup
andyfeller Dec 18, 2024
48e2681
Merge branch 'trunk' into find-pr-by-rev-parse-push
jtmcg Jan 14, 2025
0184380
Add missing git stubs to tests
jtmcg Jan 15, 2025
4a9fd95
Add comments and a bit of code cleanup
jtmcg Jan 16, 2025
d289ddd
Use PushRemoteURL instead of RemoteURL in prSelectorForCurrentBranch
jtmcg Jan 16, 2025
aef2642
fixup! Add comments and a bit of code cleanup
Frederick888 Jan 16, 2025
41729b0
Refactor finder.Find and replace parseCurrentBranch with parsePRRefs
jtmcg Jan 22, 2025
a72bef9
Error if push revision doesn't match a remote
williammartin Jan 24, 2025
6355ed7
WIP: push default defaults to simple
williammartin Jan 24, 2025
5a8dd35
Add PushDefault method to git client
jtmcg Jan 24, 2025
e4d8ed0
Remove @{push} from branch config
jtmcg Jan 24, 2025
cdead50
Moved remote.pushDefault out of ReadBranchConfig and into finder
jtmcg Jan 24, 2025
d684834
Refactor pr status to use the ParsePRRefs helper on the Finder
jtmcg Jan 24, 2025
4382bdf
Fix pr create tests
jtmcg Jan 24, 2025
62106dc
Cleanup comment
jtmcg Jan 24, 2025
e31bfd0
Cleaned up some naming and comments
jtmcg Jan 28, 2025
e0f624b
Rename PRRefs to PullRequestRefs and PR comment cleanup
jtmcg Jan 29, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Find push remote using branch.<name>.pushRemote and remote.pushDefault
When using a push.default = current triangular workflow, apart from
using @{push} to determine the remote branch name, we should also follow
the

1. branch.<name>.pushRemote
2. remote.pushDefault
3. branch.<name>.remote

...list to determine which remote Git pushes to.
  • Loading branch information
Frederick888 committed Jan 6, 2025
commit 4254818dbdfa59b4f51e524687bd6cd49e7b61c2
31 changes: 21 additions & 10 deletions git/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ func (c *Client) lookupCommit(ctx context.Context, sha, format string) ([]byte,
// ReadBranchConfig parses the `branch.BRANCH.(remote|merge|gh-merge-base)` part of git config.
func (c *Client) ReadBranchConfig(ctx context.Context, branch string) (cfg BranchConfig) {
prefix := regexp.QuoteMeta(fmt.Sprintf("branch.%s.", branch))
args := []string{"config", "--get-regexp", fmt.Sprintf("^%s(remote|merge|%s)$", prefix, MergeBaseConfig)}
args := []string{"config", "--get-regexp", fmt.Sprintf("^%s(remote|merge|pushremote|%s)$", prefix, MergeBaseConfig)}
cmd, err := c.Command(ctx, args...)
if err != nil {
return
Expand All @@ -397,21 +397,22 @@ func (c *Client) ReadBranchConfig(ctx context.Context, branch string) (cfg Branc
keys := strings.Split(parts[0], ".")
switch keys[len(keys)-1] {
case "remote":
if strings.Contains(parts[1], ":") {
u, err := ParseURL(parts[1])
if err != nil {
continue
}
cfg.RemoteURL = u
} else if !isFilesystemPath(parts[1]) {
cfg.RemoteName = parts[1]
}
parseRemoteURLOrName(parts[1], &cfg.RemoteURL, &cfg.RemoteName)
case "pushremote":
parseRemoteURLOrName(parts[1], &cfg.PushRemoteURL, &cfg.PushRemoteName)
case "merge":
cfg.MergeRef = parts[1]
case MergeBaseConfig:
cfg.MergeBase = parts[1]
}
}
if cfg.PushRemoteURL == nil && cfg.PushRemoteName == "" {
if conf, err := c.Config(ctx, "remote.pushDefault"); err == nil && conf != "" {
parseRemoteURLOrName(conf, &cfg.PushRemoteURL, &cfg.PushRemoteName)
} else {
cfg.PushRemoteName = cfg.RemoteName
}
}
if out, err = c.revParse(ctx, "--verify", "--quiet", "--abbrev-ref", branch+"@{push}"); err == nil {
cfg.Push = strings.TrimSuffix(string(out), "\n")
}
Expand Down Expand Up @@ -776,6 +777,16 @@ func parseRemotes(remotesStr []string) RemoteSet {
return remotes
}

func parseRemoteURLOrName(value string, remoteURL **url.URL, remoteName *string) {
if strings.Contains(value, ":") {
if u, err := ParseURL(value); err == nil {
*remoteURL = u
}
} else if !isFilesystemPath(value) {
*remoteName = value
}
}

func populateResolvedRemotes(remotes RemoteSet, resolved []string) {
for _, l := range resolved {
parts := strings.SplitN(l, " ", 2)
Expand Down
157 changes: 143 additions & 14 deletions git/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -725,31 +725,160 @@ func TestClientCommitBody(t *testing.T) {
}

func TestClientReadBranchConfig(t *testing.T) {
type cmdTest struct {
exitStatus int
stdOut string
stdErr string
wantArgs string
}
tests := []struct {
name string
cmdExitStatus []int
cmdStdout []string
cmdStderr []string
wantCmdArgs []string
cmds []cmdTest
wantBranchConfig BranchConfig
}{
{
name: "read branch config",
cmdExitStatus: []int{0, 0},
cmdStdout: []string{"branch.trunk.remote origin\nbranch.trunk.merge refs/heads/trunk\nbranch.trunk.gh-merge-base trunk", "origin/trunk"},
cmdStderr: []string{"", ""},
wantCmdArgs: []string{`path/to/git config --get-regexp ^branch\.trunk\.(remote|merge|gh-merge-base)$`, `path/to/git rev-parse --verify --quiet --abbrev-ref trunk@{push}`},
wantBranchConfig: BranchConfig{RemoteName: "origin", MergeRef: "refs/heads/trunk", MergeBase: "trunk", Push: "origin/trunk"},
name: "read branch config, central",
cmds: []cmdTest{
{
stdOut: "branch.trunk.remote origin\nbranch.trunk.merge refs/heads/trunk\nbranch.trunk.gh-merge-base trunk",
wantArgs: `path/to/git config --get-regexp ^branch\.trunk\.(remote|merge|pushremote|gh-merge-base)$`,
},
{
wantArgs: `path/to/git config remote.pushDefault`,
},
{
stdOut: "origin/trunk",
wantArgs: `path/to/git rev-parse --verify --quiet --abbrev-ref trunk@{push}`,
},
},
wantBranchConfig: BranchConfig{RemoteName: "origin", MergeRef: "refs/heads/trunk", MergeBase: "trunk", PushRemoteName: "origin", Push: "origin/trunk"},
},
{
name: "read branch config, central, push.default = upstream",
cmds: []cmdTest{
{
stdOut: "branch.trunk.remote origin\nbranch.trunk.merge refs/heads/trunk-remote",
wantArgs: `path/to/git config --get-regexp ^branch\.trunk\.(remote|merge|pushremote|gh-merge-base)$`,
},
{
wantArgs: `path/to/git config remote.pushDefault`,
},
{
stdOut: "origin/trunk-remote",
wantArgs: `path/to/git rev-parse --verify --quiet --abbrev-ref trunk@{push}`,
},
},
wantBranchConfig: BranchConfig{RemoteName: "origin", MergeRef: "refs/heads/trunk-remote", PushRemoteName: "origin", Push: "origin/trunk-remote"},
},
{
name: "read branch config, central, push.default = current",
cmds: []cmdTest{
{
stdOut: "branch.trunk.remote origin\nbranch.trunk.merge refs/heads/main",
wantArgs: `path/to/git config --get-regexp ^branch\.trunk\.(remote|merge|pushremote|gh-merge-base)$`,
},
{
wantArgs: `path/to/git config remote.pushDefault`,
},
{
stdOut: "origin/trunk",
wantArgs: `path/to/git rev-parse --verify --quiet --abbrev-ref trunk@{push}`,
},
},
wantBranchConfig: BranchConfig{RemoteName: "origin", MergeRef: "refs/heads/main", PushRemoteName: "origin", Push: "origin/trunk"},
},
Comment thread
jtmcg marked this conversation as resolved.
{
name: "read branch config, central, push.default = current, target branch not pushed, no existing remote branch",
cmds: []cmdTest{
{
stdOut: "branch.trunk.remote .\nbranch.trunk.merge refs/heads/trunk-middle",
wantArgs: `path/to/git config --get-regexp ^branch\.trunk\.(remote|merge|pushremote|gh-merge-base)$`,
},
{
stdOut: "origin",
wantArgs: `path/to/git config remote.pushDefault`,
},
{
exitStatus: 1,
wantArgs: `path/to/git rev-parse --verify --quiet --abbrev-ref trunk@{push}`,
},
},
wantBranchConfig: BranchConfig{MergeRef: "refs/heads/trunk-middle", PushRemoteName: "origin"},
},
{
name: "read branch config, triangular, push.default = current, has existing remote branch, branch.trunk.pushremote effective",
cmds: []cmdTest{
{
stdOut: "branch.trunk.remote upstream\nbranch.trunk.merge refs/heads/main\nbranch.trunk.pushremote origin",
wantArgs: `path/to/git config --get-regexp ^branch\.trunk\.(remote|merge|pushremote|gh-merge-base)$`,
},
{
stdOut: "origin/trunk",
wantArgs: `path/to/git rev-parse --verify --quiet --abbrev-ref trunk@{push}`,
},
},
wantBranchConfig: BranchConfig{RemoteName: "upstream", MergeRef: "refs/heads/main", PushRemoteName: "origin", Push: "origin/trunk"},
},
Comment thread
jtmcg marked this conversation as resolved.
{
name: "read branch config, triangular, push.default = current, has existing remote branch, remote.pushDefault effective",
cmds: []cmdTest{
{
stdOut: "branch.trunk.remote upstream\nbranch.trunk.merge refs/heads/main",
wantArgs: `path/to/git config --get-regexp ^branch\.trunk\.(remote|merge|pushremote|gh-merge-base)$`,
},
{
stdOut: "origin",
wantArgs: `path/to/git config remote.pushDefault`,
},
{
stdOut: "origin/trunk",
wantArgs: `path/to/git rev-parse --verify --quiet --abbrev-ref trunk@{push}`,
},
},
wantBranchConfig: BranchConfig{RemoteName: "upstream", MergeRef: "refs/heads/main", PushRemoteName: "origin", Push: "origin/trunk"},
},
{
name: "read branch config, triangular, push.default = current, no existing remote branch, branch.trunk.pushremote effective",
cmds: []cmdTest{
{
stdOut: "branch.trunk.remote upstream\nbranch.trunk.merge refs/heads/main\nbranch.trunk.pushremote origin",
wantArgs: `path/to/git config --get-regexp ^branch\.trunk\.(remote|merge|pushremote|gh-merge-base)$`,
},
{
exitStatus: 1,
wantArgs: `path/to/git rev-parse --verify --quiet --abbrev-ref trunk@{push}`,
},
},
wantBranchConfig: BranchConfig{RemoteName: "upstream", MergeRef: "refs/heads/main", PushRemoteName: "origin"},
},
{
name: "read branch config, triangular, push.default = current, no existing remote branch, remote.pushDefault effective",
cmds: []cmdTest{
{
stdOut: "branch.trunk.remote upstream\nbranch.trunk.merge refs/heads/main",
wantArgs: `path/to/git config --get-regexp ^branch\.trunk\.(remote|merge|pushremote|gh-merge-base)$`,
},
{
stdOut: "origin",
wantArgs: `path/to/git config remote.pushDefault`,
},
{
exitStatus: 1,
wantArgs: `path/to/git rev-parse --verify --quiet --abbrev-ref trunk@{push}`,
},
},
wantBranchConfig: BranchConfig{RemoteName: "upstream", MergeRef: "refs/heads/main", PushRemoteName: "origin"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var cmds []*exec.Cmd
var cmdCtxs []commandCtx
for i := 0; i < len(tt.cmdExitStatus); i++ {
cmd, cmdCtx := createCommandContext(t, tt.cmdExitStatus[i], tt.cmdStdout[i], tt.cmdStderr[i])
for _, c := range tt.cmds {
cmd, cmdCtx := createCommandContext(t, c.exitStatus, c.stdOut, c.stdErr)
cmds = append(cmds, cmd)
cmdCtxs = append(cmdCtxs, cmdCtx)

}
i := -1
client := Client{
Expand All @@ -761,8 +890,8 @@ func TestClientReadBranchConfig(t *testing.T) {
},
}
branchConfig := client.ReadBranchConfig(context.Background(), "trunk")
for i := 0; i < len(tt.cmdExitStatus); i++ {
assert.Equal(t, tt.wantCmdArgs[i], strings.Join(cmds[i].Args[3:], " "))
for i := 0; i < len(tt.cmds); i++ {
assert.Equal(t, tt.cmds[i].wantArgs, strings.Join(cmds[i].Args[3:], " "))
}
assert.Equal(t, tt.wantBranchConfig, branchConfig)
})
Expand Down
8 changes: 5 additions & 3 deletions git/objects.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ type BranchConfig struct {
RemoteName string
RemoteURL *url.URL
// MergeBase is the optional base branch to target in a new PR if `--base` is not specified.
MergeBase string
MergeRef string
Push string
MergeBase string
MergeRef string
PushRemoteURL *url.URL
PushRemoteName string
Push string
}
Loading