diff options
author | Máximo Cuadros <mcuadros@gmail.com> | 2021-12-10 06:44:42 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-10 06:44:42 +0100 |
commit | 152fefc2179ad63e4936eda644a77b84a44a6eab (patch) | |
tree | 651b84e5b41f4a19a444f22b7ad12e671cba1dd5 /remote.go | |
parent | 605e273ea37d638802cd96f955d55ace59c1ce9b (diff) | |
parent | 7db545b14827462679760b2d584782d69695acf4 (diff) | |
download | go-git-152fefc2179ad63e4936eda644a77b84a44a6eab.tar.gz |
Merge pull request #404 from john-cai/jc-force-with-lease
Remote: Push, add ForceWithLease Push Option
Diffstat (limited to 'remote.go')
-rw-r--r-- | remote.go | 43 |
1 files changed, 37 insertions, 6 deletions
@@ -326,7 +326,7 @@ func (r *Remote) newReferenceUpdateRequest( } } - if err := r.addReferencesToUpdate(o.RefSpecs, localRefs, remoteRefs, req, o.Prune); err != nil { + if err := r.addReferencesToUpdate(o.RefSpecs, localRefs, remoteRefs, req, o.Prune, o.ForceWithLease); err != nil { return nil, err } @@ -568,6 +568,7 @@ func (r *Remote) addReferencesToUpdate( remoteRefs storer.ReferenceStorer, req *packp.ReferenceUpdateRequest, prune bool, + forceWithLease *ForceWithLease, ) error { // This references dictionary will be used to search references by name. refsDict := make(map[string]*plumbing.Reference) @@ -581,7 +582,7 @@ func (r *Remote) addReferencesToUpdate( return err } } else { - err := r.addOrUpdateReferences(rs, localRefs, refsDict, remoteRefs, req) + err := r.addOrUpdateReferences(rs, localRefs, refsDict, remoteRefs, req, forceWithLease) if err != nil { return err } @@ -603,6 +604,7 @@ func (r *Remote) addOrUpdateReferences( refsDict map[string]*plumbing.Reference, remoteRefs storer.ReferenceStorer, req *packp.ReferenceUpdateRequest, + forceWithLease *ForceWithLease, ) error { // If it is not a wilcard refspec we can directly search for the reference // in the references dictionary. @@ -616,11 +618,11 @@ func (r *Remote) addOrUpdateReferences( return nil } - return r.addReferenceIfRefSpecMatches(rs, remoteRefs, ref, req) + return r.addReferenceIfRefSpecMatches(rs, remoteRefs, ref, req, forceWithLease) } for _, ref := range localRefs { - err := r.addReferenceIfRefSpecMatches(rs, remoteRefs, ref, req) + err := r.addReferenceIfRefSpecMatches(rs, remoteRefs, ref, req, forceWithLease) if err != nil { return err } @@ -706,7 +708,7 @@ func (r *Remote) addCommit(rs config.RefSpec, func (r *Remote) addReferenceIfRefSpecMatches(rs config.RefSpec, remoteRefs storer.ReferenceStorer, localRef *plumbing.Reference, - req *packp.ReferenceUpdateRequest) error { + req *packp.ReferenceUpdateRequest, forceWithLease *ForceWithLease) error { if localRef.Type() != plumbing.HashReference { return nil @@ -738,7 +740,11 @@ func (r *Remote) addReferenceIfRefSpecMatches(rs config.RefSpec, return nil } - if !rs.IsForceUpdate() { + if forceWithLease != nil { + if err = r.checkForceWithLease(localRef, cmd, forceWithLease); err != nil { + return err + } + } else if !rs.IsForceUpdate() { if err := checkFastForwardUpdate(r.s, remoteRefs, cmd); err != nil { return err } @@ -748,6 +754,31 @@ func (r *Remote) addReferenceIfRefSpecMatches(rs config.RefSpec, return nil } +func (r *Remote) checkForceWithLease(localRef *plumbing.Reference, cmd *packp.Command, forceWithLease *ForceWithLease) error { + remotePrefix := fmt.Sprintf("refs/remotes/%s/", r.Config().Name) + + ref, err := storer.ResolveReference( + r.s, + plumbing.ReferenceName(remotePrefix+strings.Replace(localRef.Name().String(), "refs/heads/", "", -1))) + if err != nil { + return err + } + + if forceWithLease.RefName.String() == "" || (forceWithLease.RefName == cmd.Name) { + expectedOID := ref.Hash() + + if !forceWithLease.Hash.IsZero() { + expectedOID = forceWithLease.Hash + } + + if cmd.Old != expectedOID { + return fmt.Errorf("non-fast-forward update: %s", cmd.Name.String()) + } + } + + return nil +} + func (r *Remote) references() ([]*plumbing.Reference, error) { var localRefs []*plumbing.Reference |