Document and rework pr create tracking branch lookup

This commit is contained in:
William Martin 2025-01-06 15:14:43 +01:00 committed by Caleb Brose
parent 67749480d5
commit 3ae4e5da20
2 changed files with 31 additions and 11 deletions

View file

@ -1,6 +1,7 @@
package git package git
import ( import (
"fmt"
"net/url" "net/url"
"strings" "strings"
) )
@ -64,6 +65,17 @@ func (r TrackingRef) String() string {
return "refs/remotes/" + r.RemoteName + "/" + r.BranchName return "refs/remotes/" + r.RemoteName + "/" + r.BranchName
} }
func ParseTrackingRef(text string) (TrackingRef, error) {
parts := strings.SplitN(string(text), "/", 4)
if len(parts) != 4 {
return TrackingRef{}, fmt.Errorf("invalid tracking ref: %s", text)
}
return TrackingRef{
RemoteName: parts[2],
BranchName: parts[3],
}, nil
}
type Commit struct { type Commit struct {
Sha string Sha string
Title string Title string

View file

@ -519,15 +519,14 @@ func initDefaultTitleBody(ctx CreateContext, state *shared.IssueMetadataState, u
} }
func determineTrackingBranch(gitClient *git.Client, remotes ghContext.Remotes, localBranchName string, headBranchConfig *git.BranchConfig) *git.TrackingRef { func determineTrackingBranch(gitClient *git.Client, remotes ghContext.Remotes, localBranchName string, headBranchConfig *git.BranchConfig) *git.TrackingRef {
// To try and determine the tracking ref for a local branch, we first construct a collection of refs
// that might be tracking, given the current branch's config, and the list of known remotes.
refsForLookup := []string{"HEAD"} refsForLookup := []string{"HEAD"}
var trackingRefs []git.TrackingRef if headBranchConfig.RemoteName != "" && headBranchConfig.MergeRef != "" {
if headBranchConfig.RemoteName != "" {
tr := git.TrackingRef{ tr := git.TrackingRef{
RemoteName: headBranchConfig.RemoteName, RemoteName: headBranchConfig.RemoteName,
BranchName: strings.TrimPrefix(headBranchConfig.MergeRef, "refs/heads/"), BranchName: strings.TrimPrefix(headBranchConfig.MergeRef, "refs/heads/"),
} }
trackingRefs = append(trackingRefs, tr)
refsForLookup = append(refsForLookup, tr.String()) refsForLookup = append(refsForLookup, tr.String())
} }
@ -536,22 +535,31 @@ func determineTrackingBranch(gitClient *git.Client, remotes ghContext.Remotes, l
RemoteName: remote.Name, RemoteName: remote.Name,
BranchName: localBranchName, BranchName: localBranchName,
} }
trackingRefs = append(trackingRefs, tr)
refsForLookup = append(refsForLookup, tr.String()) refsForLookup = append(refsForLookup, tr.String())
} }
// Then we ask git for details about these refs, for example, refs/remotes/origin/trunk might return a hash
// for the remote tracking branch, trunk, for the remote, origin. If there is no ref, the git client returns
// no ref information.
//
// We also first check for the HEAD ref, so that we have the hash of the currently checked out commit.
resolvedRefs, _ := gitClient.ShowRefs(context.Background(), refsForLookup) resolvedRefs, _ := gitClient.ShowRefs(context.Background(), refsForLookup)
// If there is more than one resolved ref, that means that at least one ref was found in addition to the HEAD.
if len(resolvedRefs) > 1 { if len(resolvedRefs) > 1 {
headRef := resolvedRefs[0]
for _, r := range resolvedRefs[1:] { for _, r := range resolvedRefs[1:] {
if r.Hash != resolvedRefs[0].Hash { // If the hash of the remote ref doesn't match the hash of HEAD then the remote branch is not in the same
// state, so it can't be used.
if r.Hash != headRef.Hash {
continue continue
} }
for _, tr := range trackingRefs { // Otherwise we can parse the returned ref into a tracking ref and return that
if tr.String() != r.Name { trackingRef, err := git.ParseTrackingRef(r.Name)
continue if err != nil {
} return nil
return &tr
} }
return &trackingRef
} }
} }