aboutsummaryrefslogtreecommitdiffstats
path: root/remote.go
diff options
context:
space:
mode:
authorNick Thomas <nick@gitlab.com>2017-07-22 09:50:40 +0100
committerJeremy Stribling <strib@alum.mit.edu>2017-11-27 11:38:14 -0800
commit702718fd59be0aa4b8bf8492403c465107ca17af (patch)
tree00724b2409b9dee0f9fe5fc6b86d9da2cf91f0ce /remote.go
parent147a1b7d2e8a08d5c6228de0f98b3f5a1497f95a (diff)
downloadgo-git-702718fd59be0aa4b8bf8492403c465107ca17af.tar.gz
Support non-force fetches
Diffstat (limited to 'remote.go')
-rw-r--r--remote.go28
1 files changed, 26 insertions, 2 deletions
diff --git a/remote.go b/remote.go
index 2416152..91ae2fa 100644
--- a/remote.go
+++ b/remote.go
@@ -25,6 +25,7 @@ import (
var (
NoErrAlreadyUpToDate = errors.New("already up-to-date")
ErrDeleteRefNotSupported = errors.New("server does not support delete-refs")
+ ErrForceNeeded = errors.New("some refs were not updated")
)
const (
@@ -302,7 +303,7 @@ func (r *Remote) fetch(ctx context.Context, o *FetchOptions) (storer.ReferenceSt
}
}
- updated, err := r.updateLocalReferenceStorage(o.RefSpecs, refs, remoteRefs, o.Tags)
+ updated, err := r.updateLocalReferenceStorage(o.RefSpecs, refs, remoteRefs, o.Tags, o.Force)
if err != nil {
return nil, err
}
@@ -773,8 +774,11 @@ func (r *Remote) updateLocalReferenceStorage(
specs []config.RefSpec,
fetchedRefs, remoteRefs memory.ReferenceStorage,
tagMode TagMode,
+ force bool,
) (updated bool, err error) {
isWildcard := true
+ forceNeeded := false
+
for _, spec := range specs {
if !spec.IsWildcard() {
isWildcard = false
@@ -789,7 +793,23 @@ func (r *Remote) updateLocalReferenceStorage(
continue
}
- new := plumbing.NewHashReference(spec.Dst(ref.Name()), ref.Hash())
+ localName := spec.Dst(ref.Name())
+ old, _ := storer.ResolveReference(r.s, localName)
+ new := plumbing.NewHashReference(localName, ref.Hash())
+
+ // If the ref exists locally as a branch and force is not specified,
+ // only update if the new ref is an ancestor of the old
+ if old != nil && old.Name().IsBranch() && !force {
+ ff, err := isFastForward(r.s, old.Hash(), new.Hash())
+ if err != nil {
+ return updated, err
+ }
+
+ if !ff {
+ forceNeeded = true
+ continue
+ }
+ }
refUpdated, err := updateReferenceStorerIfNeeded(r.s, new)
if err != nil {
@@ -819,6 +839,10 @@ func (r *Remote) updateLocalReferenceStorage(
updated = true
}
+ if err == nil && forceNeeded {
+ err = ErrForceNeeded
+ }
+
return
}