-
Notifications
You must be signed in to change notification settings - Fork 893
Description
There are some related issues already though. I can reproduce the issue and may find the cause so would like to fix it.
How to reproduce
First clone a remote repository by shallow clone with depth 1.
r, err := git.CloneContext(ctx, storage, fs, &git.CloneOptions{
URL: _urlToRemoteRepository_,
Auth: ...,
ReferenceName: plumbing.NewBranchReferenceName("master"),
SingleBranch: true,
Depth: 1, // shallow clone
Tags: git.NoTags,
})
Next, add a new commit to the master branch of the repository. Now let's assume that we have these refs:
refs/remotes/origin/master:zzzzzrefs/heads/master:yyyyy- commits history
zzzzzyyyyyxxxxx- ....
And the storer contains a commit of yyyyy only. With this storer, pull the latest commits:
w.PullContext(ctx, &git.PullOptions{
Auth: ...,
ReferenceName: plumbing.NewBranchReferenceName("master"),
Depth: 0,
Force: true,
})
This returns plumbing.ErrObjectNotFound as object not found error as a result.
Expected behavior
The pull works without any errors.
Where the error happens
1.Worktree.PullContext()
2. Remote.fetch()
3. getHaves()
4. getHavesFromRef()
5. commitPreIterator.ForEach()
6. commitPreIterator.Next() => returning error
It seems getHaves() function checks local storage has what commits from local refs. So getHavesFromRef() function tries to traverse commits from the ref hash in local but the iterator refer a commit because the storage contains a partial commits. So in the case above, the iterator tries to refer xxxxx commit as next of yyyyy but xxxxx is not found in the storage.
I think this is unexpected behavior but I'm not sure what is the best to fix this.
Option 1: Fix the iterator to returns io.EOF instead of plumbing.ErrObjectNotFound on Next() when the object is not found.
This is easier to fix the issue because no need to fix callers but it may cause another bug.
Option 2: Fix callers to ignore plumbing.ErrObjectNotFound where using object.NewCommitPreorderIter.
This may reduce to break backward incompatibility.
I tried option2 by fixing getHavesFromRef and isFastForward function in remote.go like this.
err = iter.ForEach(func(c *object.Commit) error {
...
})
if err != nil && err != plumbing.ErrObjectNotFound {
return err
}
return nil
With this, the object nof found never happen again.