b8e7ad6b6d
Since at least PR #2706, and indeed earlier, the local and remote refs which are part of the RefUpdate structure have been referred to as the "left" and "right" refs, terminology which stems from the origin of this structure in the "git lfs pre-push" hook command, where each line of input contains commit information in the form: <local ref> <local sha1> <remote ref> <remote sha1> However, outside of this context, "left" and "right" are ambiguous terms, and may potentially be confused with the left and right refs specified in a Git-style two-dot range notation. We therefore replace these terms with "local" and "remote", which should help clarify their purpose throughout the codebase.
95 lines
2.2 KiB
Go
95 lines
2.2 KiB
Go
package git
|
||
|
||
import (
|
||
"fmt"
|
||
|
||
"github.com/rubyist/tracerx"
|
||
)
|
||
|
||
type RefUpdate struct {
|
||
git Env
|
||
remote string
|
||
localRef *Ref
|
||
remoteRef *Ref
|
||
}
|
||
|
||
func NewRefUpdate(g Env, remote string, localRef, remoteRef *Ref) *RefUpdate {
|
||
return &RefUpdate{
|
||
git: g,
|
||
remote: remote,
|
||
localRef: localRef,
|
||
remoteRef: remoteRef,
|
||
}
|
||
}
|
||
|
||
func (u *RefUpdate) LocalRef() *Ref {
|
||
return u.localRef
|
||
}
|
||
|
||
func (u *RefUpdate) LocalRefCommitish() string {
|
||
return refCommitish(u.LocalRef())
|
||
}
|
||
|
||
func (u *RefUpdate) RemoteRef() *Ref {
|
||
if u.remoteRef == nil {
|
||
u.remoteRef = defaultRemoteRef(u.git, u.remote, u.LocalRef())
|
||
}
|
||
return u.remoteRef
|
||
}
|
||
|
||
// defaultRemoteRef returns the remote ref receiving a push based on the current
|
||
// repository config and local ref being pushed.
|
||
//
|
||
// See push.default rules in https://git-scm.com/docs/git-config
|
||
func defaultRemoteRef(g Env, remote string, localRef *Ref) *Ref {
|
||
pushMode, _ := g.Get("push.default")
|
||
switch pushMode {
|
||
case "", "simple":
|
||
brRemote, _ := g.Get(fmt.Sprintf("branch.%s.remote", localRef.Name))
|
||
if brRemote == remote {
|
||
// in centralized workflow, work like 'upstream' with an added safety to
|
||
// refuse to push if the upstream branch’s name is different from the
|
||
// local one.
|
||
return trackingRef(g, localRef)
|
||
}
|
||
|
||
// When pushing to a remote that is different from the remote you normally
|
||
// pull from, work as current.
|
||
return localRef
|
||
case "upstream", "tracking":
|
||
// push the current branch back to the branch whose changes are usually
|
||
// integrated into the current branch
|
||
return trackingRef(g, localRef)
|
||
case "current":
|
||
// push the current branch to update a branch with the same name on the
|
||
// receiving end.
|
||
return localRef
|
||
default:
|
||
tracerx.Printf("WARNING: %q push mode not supported", pushMode)
|
||
return localRef
|
||
}
|
||
}
|
||
|
||
func trackingRef(g Env, localRef *Ref) *Ref {
|
||
if merge, ok := g.Get(fmt.Sprintf("branch.%s.merge", localRef.Name)); ok {
|
||
return ParseRef(merge, "")
|
||
}
|
||
return localRef
|
||
}
|
||
|
||
func (u *RefUpdate) RemoteRefCommitish() string {
|
||
return refCommitish(u.RemoteRef())
|
||
}
|
||
|
||
func refCommitish(r *Ref) string {
|
||
if len(r.Sha) > 0 {
|
||
return r.Sha
|
||
}
|
||
return r.Name
|
||
}
|
||
|
||
// copy of env
|
||
type Env interface {
|
||
Get(key string) (val string, ok bool)
|
||
}
|