From 09f5f2a35f0f4c42b2def0642540f32e59fdeeb3 Mon Sep 17 00:00:00 2001 From: "Santiago M. Mola" Date: Mon, 10 Jul 2017 18:25:28 +0200 Subject: improve delete support on push * server: implement delete-refs and announce it. * remote: check if server announced delete-refs before trying to delete and fail fast if it does not. Note that the client does not need no send 'delete-refs' back to the server to be able to delete references: ``` delete-refs ----------- If the server sends back the 'delete-refs' capability, it means that it is capable of accepting a zero-id value as the target value of a reference update. It is not sent back by the client, it simply informs the client that it can be sent zero-id values to delete references. ``` So our server implementation does not check if the client sent delete-refs back, it just accepts deletes if it receives them. --- remote.go | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'remote.go') diff --git a/remote.go b/remote.go index 9bc31ff..7ebb843 100644 --- a/remote.go +++ b/remote.go @@ -21,7 +21,10 @@ import ( "gopkg.in/src-d/go-git.v4/utils/ioutil" ) -var NoErrAlreadyUpToDate = errors.New("already up-to-date") +var ( + NoErrAlreadyUpToDate = errors.New("already up-to-date") + ErrDeleteRefNotSupported = errors.New("server does not support delete-refs") +) // Remote represents a connection to a remote repository. type Remote struct { @@ -56,7 +59,6 @@ func (r *Remote) Fetch(o *FetchOptions) error { // Push performs a push to the remote. Returns NoErrAlreadyUpToDate if the // remote was already up-to-date. func (r *Remote) Push(o *PushOptions) (err error) { - // TODO: Support deletes. // TODO: Sideband support if o.RemoteName == "" { @@ -88,6 +90,18 @@ func (r *Remote) Push(o *PushOptions) (err error) { return err } + isDelete := false + for _, rs := range o.RefSpecs { + if rs.IsDelete() { + isDelete = true + break + } + } + + if isDelete && !ar.Capabilities.Supports(capability.DeleteRefs) { + return ErrDeleteRefNotSupported + } + req := packp.NewReferenceUpdateRequestFromCapabilities(ar.Capabilities) if err := r.addReferencesToUpdate(o.RefSpecs, remoteRefs, req); err != nil { return err @@ -284,8 +298,8 @@ func (r *Remote) deleteReferences(rs config.RefSpec, cmd := &packp.Command{ Name: ref.Name(), - Old: ref.Hash(), - New: plumbing.ZeroHash, + Old: ref.Hash(), + New: plumbing.ZeroHash, } req.Commands = append(req.Commands, cmd) return nil -- cgit