Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

Commit 35861a4

Browse files
committed
remote: fix push delete, closes #466
Refspecs for deletes were not being used to produce delete commands on the update request.
1 parent 102d4b5 commit 35861a4

File tree

2 files changed

+95
-12
lines changed

2 files changed

+95
-12
lines changed

remote.go

+48-12
Original file line numberDiff line numberDiff line change
@@ -238,24 +238,60 @@ func (r *Remote) addReferencesToUpdate(refspecs []config.RefSpec,
238238
req *packp.ReferenceUpdateRequest) error {
239239

240240
for _, rs := range refspecs {
241-
iter, err := r.s.IterReferences()
242-
if err != nil {
243-
return err
244-
}
245-
246-
err = iter.ForEach(func(ref *plumbing.Reference) error {
247-
return r.addReferenceIfRefSpecMatches(
248-
rs, remoteRefs, ref, req,
249-
)
250-
})
251-
if err != nil {
252-
return err
241+
if rs.IsDelete() {
242+
if err := r.deleteReferences(rs, remoteRefs, req); err != nil {
243+
return err
244+
}
245+
} else {
246+
if err := r.addOrUpdateReferences(rs, remoteRefs, req); err != nil {
247+
return err
248+
}
253249
}
254250
}
255251

256252
return nil
257253
}
258254

255+
func (r *Remote) addOrUpdateReferences(rs config.RefSpec,
256+
remoteRefs storer.ReferenceStorer, req *packp.ReferenceUpdateRequest) error {
257+
iter, err := r.s.IterReferences()
258+
if err != nil {
259+
return err
260+
}
261+
262+
return iter.ForEach(func(ref *plumbing.Reference) error {
263+
return r.addReferenceIfRefSpecMatches(
264+
rs, remoteRefs, ref, req,
265+
)
266+
})
267+
}
268+
269+
func (r *Remote) deleteReferences(rs config.RefSpec,
270+
remoteRefs storer.ReferenceStorer, req *packp.ReferenceUpdateRequest) error {
271+
iter, err := remoteRefs.IterReferences()
272+
if err != nil {
273+
return err
274+
}
275+
276+
return iter.ForEach(func(ref *plumbing.Reference) error {
277+
if ref.Type() != plumbing.HashReference {
278+
return nil
279+
}
280+
281+
if rs.Dst("") != ref.Name() {
282+
return nil
283+
}
284+
285+
cmd := &packp.Command{
286+
Name: ref.Name(),
287+
Old: ref.Hash(),
288+
New: plumbing.ZeroHash,
289+
}
290+
req.Commands = append(req.Commands, cmd)
291+
return nil
292+
})
293+
}
294+
259295
func (r *Remote) addReferenceIfRefSpecMatches(rs config.RefSpec,
260296
remoteRefs storer.ReferenceStorer, localRef *plumbing.Reference,
261297
req *packp.ReferenceUpdateRequest) error {

remote_test.go

+47
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55
"io"
66
"io/ioutil"
77
"os"
8+
"path/filepath"
9+
"strings"
810

911
"github.com/src-d/go-git-fixtures"
1012
"gopkg.in/src-d/go-git.v4/config"
@@ -334,6 +336,32 @@ func (s *RemoteSuite) TestPushNoErrAlreadyUpToDate(c *C) {
334336
c.Assert(err, Equals, NoErrAlreadyUpToDate)
335337
}
336338

339+
func (s *RemoteSuite) TestPushDeleteReference(c *C) {
340+
f := fixtures.Basic().One()
341+
sto, err := filesystem.NewStorage(f.DotGit())
342+
c.Assert(err, IsNil)
343+
344+
dstFs := f.DotGit()
345+
dstSto, err := filesystem.NewStorage(dstFs)
346+
c.Assert(err, IsNil)
347+
prepareRepo(c, dstFs.Root())
348+
349+
url := dstFs.Root()
350+
r := newRemote(sto, &config.RemoteConfig{
351+
Name: DefaultRemoteName,
352+
URL: url,
353+
})
354+
355+
rs := config.RefSpec(":refs/heads/branch")
356+
err = r.Push(&PushOptions{
357+
RefSpecs: []config.RefSpec{rs},
358+
})
359+
c.Assert(err, IsNil)
360+
361+
_, err = dstSto.Reference(plumbing.ReferenceName("refs/heads/branch"))
362+
c.Assert(err, Equals, plumbing.ErrReferenceNotFound)
363+
}
364+
337365
func (s *RemoteSuite) TestPushRejectNonFastForward(c *C) {
338366
f := fixtures.Basic().One()
339367
sto, err := filesystem.NewStorage(f.DotGit())
@@ -470,3 +498,22 @@ func (s *RemoteSuite) TestPushWrongRemoteName(c *C) {
470498
})
471499
c.Assert(err, ErrorMatches, ".*remote names don't match.*")
472500
}
501+
502+
const bareConfig = `[core]
503+
repositoryformatversion = 0
504+
filemode = true
505+
bare = true`
506+
507+
func prepareRepo(c *C, path string) {
508+
// git-receive-pack refuses to update refs/heads/master on non-bare repo
509+
// so we ensure bare repo config.
510+
config := filepath.Join(path, "config")
511+
if _, err := os.Stat(config); err == nil {
512+
f, err := os.OpenFile(config, os.O_TRUNC|os.O_WRONLY, 0)
513+
c.Assert(err, IsNil)
514+
content := strings.NewReader(bareConfig)
515+
_, err = io.Copy(f, content)
516+
c.Assert(err, IsNil)
517+
c.Assert(f.Close(), IsNil)
518+
}
519+
}

0 commit comments

Comments
 (0)