Skip to content

Commit ae552ce

Browse files
authored
Merge pull request #939 from dhoizner/fix-pull-after-shallow
git: stop iterating at oldest shallow when pulling. Fixes #305
2 parents cc1895b + 861009f commit ae552ce

File tree

3 files changed

+65
-7
lines changed

3 files changed

+65
-7
lines changed

remote.go

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,7 +1070,7 @@ func checkFastForwardUpdate(s storer.EncodedObjectStorer, remoteRefs storer.Refe
10701070
return fmt.Errorf("non-fast-forward update: %s", cmd.Name.String())
10711071
}
10721072

1073-
ff, err := isFastForward(s, cmd.Old, cmd.New)
1073+
ff, err := isFastForward(s, cmd.Old, cmd.New, nil)
10741074
if err != nil {
10751075
return err
10761076
}
@@ -1082,14 +1082,28 @@ func checkFastForwardUpdate(s storer.EncodedObjectStorer, remoteRefs storer.Refe
10821082
return nil
10831083
}
10841084

1085-
func isFastForward(s storer.EncodedObjectStorer, old, new plumbing.Hash) (bool, error) {
1085+
func isFastForward(s storer.EncodedObjectStorer, old, new plumbing.Hash, earliestShallow *plumbing.Hash) (bool, error) {
10861086
c, err := object.GetCommit(s, new)
10871087
if err != nil {
10881088
return false, err
10891089
}
10901090

1091+
parentsToIgnore := []plumbing.Hash{}
1092+
if earliestShallow != nil {
1093+
earliestCommit, err := object.GetCommit(s, *earliestShallow)
1094+
if err != nil {
1095+
return false, err
1096+
}
1097+
1098+
parentsToIgnore = earliestCommit.ParentHashes
1099+
}
1100+
10911101
found := false
1092-
iter := object.NewCommitPreorderIter(c, nil, nil)
1102+
// stop iterating at the earlist shallow commit, ignoring its parents
1103+
// note: when pull depth is smaller than the number of new changes on the remote, this fails due to missing parents.
1104+
// as far as i can tell, without the commits in-between the shallow pull and the earliest shallow, there's no
1105+
// real way of telling whether it will be a fast-forward merge.
1106+
iter := object.NewCommitPreorderIter(c, nil, parentsToIgnore)
10931107
err = iter.ForEach(func(c *object.Commit) error {
10941108
if c.Hash != old {
10951109
return nil
@@ -1205,7 +1219,7 @@ func (r *Remote) updateLocalReferenceStorage(
12051219
// If the ref exists locally as a non-tag and force is not
12061220
// specified, only update if the new ref is an ancestor of the old
12071221
if old != nil && !old.Name().IsTag() && !force && !spec.IsForceUpdate() {
1208-
ff, err := isFastForward(r.s, old.Hash(), new.Hash())
1222+
ff, err := isFastForward(r.s, old.Hash(), new.Hash(), nil)
12091223
if err != nil {
12101224
return updated, err
12111225
}
@@ -1390,7 +1404,6 @@ func pushHashes(
13901404
useRefDeltas bool,
13911405
allDelete bool,
13921406
) (*packp.ReportStatus, error) {
1393-
13941407
rd, wr := io.Pipe()
13951408

13961409
config, err := s.Config()

worktree.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,15 @@ func (w *Worktree) PullContext(ctx context.Context, o *PullOptions) error {
9595

9696
head, err := w.r.Head()
9797
if err == nil {
98-
headAheadOfRef, err := isFastForward(w.r.Storer, ref.Hash(), head.Hash())
98+
// if we don't have a shallows list, just ignore it
99+
shallowList, _ := w.r.Storer.Shallow()
100+
101+
var earliestShallow *plumbing.Hash
102+
if len(shallowList) > 0 {
103+
earliestShallow = &shallowList[0]
104+
}
105+
106+
headAheadOfRef, err := isFastForward(w.r.Storer, ref.Hash(), head.Hash(), earliestShallow)
99107
if err != nil {
100108
return err
101109
}
@@ -104,7 +112,7 @@ func (w *Worktree) PullContext(ctx context.Context, o *PullOptions) error {
104112
return NoErrAlreadyUpToDate
105113
}
106114

107-
ff, err := isFastForward(w.r.Storer, head.Hash(), ref.Hash())
115+
ff, err := isFastForward(w.r.Storer, head.Hash(), ref.Hash(), earliestShallow)
108116
if err != nil {
109117
return err
110118
}
@@ -188,6 +196,7 @@ func (w *Worktree) Checkout(opts *CheckoutOptions) error {
188196

189197
return w.Reset(ro)
190198
}
199+
191200
func (w *Worktree) createBranch(opts *CheckoutOptions) error {
192201
if err := opts.Branch.Validate(); err != nil {
193202
return err

worktree_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,42 @@ func (s *WorktreeSuite) TestPullDepth(c *C) {
313313
c.Assert(err, Equals, nil)
314314
}
315315

316+
func (s *WorktreeSuite) TestPullAfterShallowClone(c *C) {
317+
tempDir, clean := s.TemporalDir()
318+
defer clean()
319+
remoteURL := filepath.Join(tempDir, "remote")
320+
repoDir := filepath.Join(tempDir, "repo")
321+
322+
remote, err := PlainInit(remoteURL, false)
323+
c.Assert(err, IsNil)
324+
c.Assert(remote, NotNil)
325+
326+
_ = CommitNewFile(c, remote, "File1")
327+
_ = CommitNewFile(c, remote, "File2")
328+
329+
repo, err := PlainClone(repoDir, false, &CloneOptions{
330+
URL: remoteURL,
331+
Depth: 1,
332+
Tags: NoTags,
333+
SingleBranch: true,
334+
ReferenceName: "master",
335+
})
336+
c.Assert(err, IsNil)
337+
338+
_ = CommitNewFile(c, remote, "File3")
339+
_ = CommitNewFile(c, remote, "File4")
340+
341+
w, err := repo.Worktree()
342+
c.Assert(err, IsNil)
343+
344+
err = w.Pull(&PullOptions{
345+
RemoteName: DefaultRemoteName,
346+
SingleBranch: true,
347+
ReferenceName: plumbing.NewBranchReferenceName("master"),
348+
})
349+
c.Assert(err, IsNil)
350+
}
351+
316352
func (s *WorktreeSuite) TestCheckout(c *C) {
317353
fs := memfs.New()
318354
w := &Worktree{

0 commit comments

Comments
 (0)