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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy