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

Commit b0f131a

Browse files
committed
remote: pull refactor to match default behaviour
1 parent e19163e commit b0f131a

File tree

3 files changed

+109
-6
lines changed

3 files changed

+109
-6
lines changed

COMPATIBILITY.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ is supported by go-git.
1010
| config || Reading and modifying per-repository configuration (`.git/config`) is supported. Global configuration (`$HOME/.gitconfig`) is not. |
1111
| **getting and creating repositories** |
1212
| init || Plain init and `--bare` are supported. Flags `--template`, `--separate-git-dir` and `--shared` are not. |
13-
| clone || Plain clone and equivalents to `--progress`, `--single-branch`, `--depth`, `--origin`, `--recurse-submodules` are supported. Others are not. |
13+
| clone || Plain clone and equivalents to `--progress`, `--single-branch`, `--depth`, `--origin`, `--recurse-submodules` are supported. Others are not. |
1414
| **basic snapshotting** |
1515
| add || Plain add is supported. Any other flag aren't supported |
1616
| status ||
@@ -27,7 +27,7 @@ is supported by go-git.
2727
| tag ||
2828
| **sharing and updating projects** |
2929
| fetch ||
30-
| pull ||
30+
| pull || Only supports merges where the merge can be resolved as a fast-forward. |
3131
| push ||
3232
| remote ||
3333
| submodule ||
@@ -108,4 +108,4 @@ is supported by go-git.
108108
| gitattributes ||
109109
| index version | |
110110
| packfile version | |
111-
| push-certs ||
111+
| push-certs ||

worktree.go

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"gopkg.in/src-d/go-git.v4/plumbing/filemode"
1616
"gopkg.in/src-d/go-git.v4/plumbing/format/index"
1717
"gopkg.in/src-d/go-git.v4/plumbing/object"
18+
"gopkg.in/src-d/go-git.v4/plumbing/storer"
1819
"gopkg.in/src-d/go-git.v4/utils/ioutil"
1920
"gopkg.in/src-d/go-git.v4/utils/merkletrie"
2021

@@ -36,6 +37,8 @@ type Worktree struct {
3637
// Pull incorporates changes from a remote repository into the current branch.
3738
// Returns nil if the operation is successful, NoErrAlreadyUpToDate if there are
3839
// no changes to be fetched, or an error.
40+
//
41+
// Pull only supports merges where the can be resolved as a fast-forward.
3942
func (w *Worktree) Pull(o *PullOptions) error {
4043
return w.PullContext(context.Background(), o)
4144
}
@@ -44,6 +47,8 @@ func (w *Worktree) Pull(o *PullOptions) error {
4447
// branch. Returns nil if the operation is successful, NoErrAlreadyUpToDate if
4548
// there are no changes to be fetched, or an error.
4649
//
50+
// Pull only supports merges where the can be resolved as a fast-forward.
51+
//
4752
// The provided Context must be non-nil. If the context expires before the
4853
// operation is complete, an error is returned. The context only affects to the
4954
// transport operations.
@@ -52,17 +57,55 @@ func (w *Worktree) PullContext(ctx context.Context, o *PullOptions) error {
5257
return err
5358
}
5459

55-
head, err := w.r.fetchAndUpdateReferences(ctx, &FetchOptions{
60+
remote, err := w.r.Remote(o.RemoteName)
61+
if err != nil {
62+
return err
63+
}
64+
65+
fetchHead, err := remote.fetch(ctx, &FetchOptions{
5666
RemoteName: o.RemoteName,
5767
Depth: o.Depth,
5868
Auth: o.Auth,
5969
Progress: o.Progress,
60-
}, o.ReferenceName)
70+
})
71+
72+
updated := true
73+
if err == NoErrAlreadyUpToDate {
74+
updated = false
75+
} else if err != nil {
76+
return err
77+
}
78+
79+
ref, err := storer.ResolveReference(fetchHead, o.ReferenceName)
6180
if err != nil {
6281
return err
6382
}
6483

65-
if err := w.Reset(&ResetOptions{Commit: head.Hash()}); err != nil {
84+
head, err := w.r.Head()
85+
if err == nil {
86+
if !updated && head.Hash() == ref.Hash() {
87+
return NoErrAlreadyUpToDate
88+
}
89+
90+
ff, err := isFastForward(w.r.Storer, head.Hash(), ref.Hash())
91+
if err != nil {
92+
return err
93+
}
94+
95+
if !ff {
96+
return fmt.Errorf("non-fast-forward update")
97+
}
98+
}
99+
100+
if err != nil && err != plumbing.ErrReferenceNotFound {
101+
return err
102+
}
103+
104+
if err := w.updateHEAD(ref.Hash()); err != nil {
105+
return err
106+
}
107+
108+
if err := w.Reset(&ResetOptions{Commit: ref.Hash()}); err != nil {
66109
return err
67110
}
68111

worktree_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,66 @@ func (s *WorktreeSuite) TestPullCheckout(c *C) {
5151
c.Assert(fi, HasLen, 8)
5252
}
5353

54+
func (s *WorktreeSuite) TestPullFastForward(c *C) {
55+
url := c.MkDir()
56+
path := fixtures.Basic().ByTag("worktree").One().Worktree().Root()
57+
58+
server, err := PlainClone(url, false, &CloneOptions{
59+
URL: path,
60+
})
61+
62+
r, err := PlainClone(c.MkDir(), false, &CloneOptions{
63+
URL: url,
64+
})
65+
66+
w, err := server.Worktree()
67+
c.Assert(err, IsNil)
68+
err = ioutil.WriteFile(filepath.Join(path, "foo"), []byte("foo"), 0755)
69+
c.Assert(err, IsNil)
70+
hash, err := w.Commit("foo", &CommitOptions{Author: defaultSignature()})
71+
c.Assert(err, IsNil)
72+
73+
w, err = r.Worktree()
74+
c.Assert(err, IsNil)
75+
76+
err = w.Pull(&PullOptions{})
77+
c.Assert(err, IsNil)
78+
79+
head, err := r.Head()
80+
c.Assert(err, IsNil)
81+
c.Assert(head.Hash(), Equals, hash)
82+
}
83+
84+
func (s *WorktreeSuite) TestPullNonFastForward(c *C) {
85+
url := c.MkDir()
86+
path := fixtures.Basic().ByTag("worktree").One().Worktree().Root()
87+
88+
server, err := PlainClone(url, false, &CloneOptions{
89+
URL: path,
90+
})
91+
92+
r, err := PlainClone(c.MkDir(), false, &CloneOptions{
93+
URL: url,
94+
})
95+
96+
w, err := server.Worktree()
97+
c.Assert(err, IsNil)
98+
err = ioutil.WriteFile(filepath.Join(path, "foo"), []byte("foo"), 0755)
99+
c.Assert(err, IsNil)
100+
_, err = w.Commit("foo", &CommitOptions{Author: defaultSignature()})
101+
c.Assert(err, IsNil)
102+
103+
w, err = r.Worktree()
104+
c.Assert(err, IsNil)
105+
err = ioutil.WriteFile(filepath.Join(path, "bar"), []byte("bar"), 0755)
106+
c.Assert(err, IsNil)
107+
_, err = w.Commit("bar", &CommitOptions{Author: defaultSignature()})
108+
c.Assert(err, IsNil)
109+
110+
err = w.Pull(&PullOptions{})
111+
c.Assert(err, ErrorMatches, "non-fast-forward update")
112+
}
113+
54114
func (s *WorktreeSuite) TestPullUpdateReferencesIfNeeded(c *C) {
55115
r, _ := Init(memory.NewStorage(), memfs.New())
56116
r.CreateRemote(&config.RemoteConfig{

0 commit comments

Comments
 (0)