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

remote: pull refactor to match default behavior of cgit #511

Merged
merged 1 commit into from
Jul 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions COMPATIBILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ is supported by go-git.
| config | ✔ | Reading and modifying per-repository configuration (`.git/config`) is supported. Global configuration (`$HOME/.gitconfig`) is not. |
| **getting and creating repositories** |
| init | ✔ | Plain init and `--bare` are supported. Flags `--template`, `--separate-git-dir` and `--shared` are not. |
| clone | ✔ | Plain clone and equivalents to `--progress`, `--single-branch`, `--depth`, `--origin`, `--recurse-submodules` are supported. Others are not. |
| clone | ✔ | Plain clone and equivalents to `--progress`, `--single-branch`, `--depth`, `--origin`, `--recurse-submodules` are supported. Others are not. |
| **basic snapshotting** |
| add | ✔ | Plain add is supported. Any other flag aren't supported |
| status | ✔ |
Expand All @@ -27,7 +27,7 @@ is supported by go-git.
| tag | ✔ |
| **sharing and updating projects** |
| fetch | ✔ |
| pull | ✔ |
| pull | ✔ | Only supports merges where the merge can be resolved as a fast-forward. |
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe reword as Only supports fast-forward merges

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is copy from the git documentation

| push | ✔ |
| remote | ✔ |
| submodule | ✔ |
Expand Down Expand Up @@ -108,4 +108,4 @@ is supported by go-git.
| gitattributes | ✖ |
| index version | |
| packfile version | |
| push-certs | ✖ |
| push-certs | ✖ |
49 changes: 46 additions & 3 deletions worktree.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"gopkg.in/src-d/go-git.v4/plumbing/filemode"
"gopkg.in/src-d/go-git.v4/plumbing/format/index"
"gopkg.in/src-d/go-git.v4/plumbing/object"
"gopkg.in/src-d/go-git.v4/plumbing/storer"
"gopkg.in/src-d/go-git.v4/utils/ioutil"
"gopkg.in/src-d/go-git.v4/utils/merkletrie"

Expand All @@ -36,6 +37,8 @@ type Worktree struct {
// Pull incorporates changes from a remote repository into the current branch.
// Returns nil if the operation is successful, NoErrAlreadyUpToDate if there are
// no changes to be fetched, or an error.
//
// Pull only supports merges where the can be resolved as a fast-forward.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe reword, see previous comment.

func (w *Worktree) Pull(o *PullOptions) error {
return w.PullContext(context.Background(), o)
}
Expand All @@ -44,6 +47,8 @@ func (w *Worktree) Pull(o *PullOptions) error {
// branch. Returns nil if the operation is successful, NoErrAlreadyUpToDate if
// there are no changes to be fetched, or an error.
//
// Pull only supports merges where the can be resolved as a fast-forward.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

//
// The provided Context must be non-nil. If the context expires before the
// operation is complete, an error is returned. The context only affects to the
// transport operations.
Expand All @@ -52,17 +57,55 @@ func (w *Worktree) PullContext(ctx context.Context, o *PullOptions) error {
return err
}

head, err := w.r.fetchAndUpdateReferences(ctx, &FetchOptions{
remote, err := w.r.Remote(o.RemoteName)
if err != nil {
return err
}

fetchHead, err := remote.fetch(ctx, &FetchOptions{
RemoteName: o.RemoteName,
Depth: o.Depth,
Auth: o.Auth,
Progress: o.Progress,
}, o.ReferenceName)
})

updated := true
if err == NoErrAlreadyUpToDate {
updated = false
} else if err != nil {
return err
}

ref, err := storer.ResolveReference(fetchHead, o.ReferenceName)
if err != nil {
return err
}

if err := w.Reset(&ResetOptions{Commit: head.Hash()}); err != nil {
head, err := w.r.Head()
if err == nil {
if !updated && head.Hash() == ref.Hash() {
return NoErrAlreadyUpToDate
}

ff, err := isFastForward(w.r.Storer, head.Hash(), ref.Hash())
if err != nil {
return err
}

if !ff {
return fmt.Errorf("non-fast-forward update")
}
}

if err != nil && err != plumbing.ErrReferenceNotFound {
return err
}

if err := w.updateHEAD(ref.Hash()); err != nil {
return err
}

if err := w.Reset(&ResetOptions{Commit: ref.Hash()}); err != nil {
return err
}

Expand Down
60 changes: 60 additions & 0 deletions worktree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,66 @@ func (s *WorktreeSuite) TestPullCheckout(c *C) {
c.Assert(fi, HasLen, 8)
}

func (s *WorktreeSuite) TestPullFastForward(c *C) {
url := c.MkDir()
path := fixtures.Basic().ByTag("worktree").One().Worktree().Root()

server, err := PlainClone(url, false, &CloneOptions{
URL: path,
})

r, err := PlainClone(c.MkDir(), false, &CloneOptions{
URL: url,
})

w, err := server.Worktree()
c.Assert(err, IsNil)
err = ioutil.WriteFile(filepath.Join(path, "foo"), []byte("foo"), 0755)
c.Assert(err, IsNil)
hash, err := w.Commit("foo", &CommitOptions{Author: defaultSignature()})
c.Assert(err, IsNil)

w, err = r.Worktree()
c.Assert(err, IsNil)

err = w.Pull(&PullOptions{})
c.Assert(err, IsNil)

head, err := r.Head()
c.Assert(err, IsNil)
c.Assert(head.Hash(), Equals, hash)
}

func (s *WorktreeSuite) TestPullNonFastForward(c *C) {
url := c.MkDir()
path := fixtures.Basic().ByTag("worktree").One().Worktree().Root()

server, err := PlainClone(url, false, &CloneOptions{
URL: path,
})

r, err := PlainClone(c.MkDir(), false, &CloneOptions{
URL: url,
})

w, err := server.Worktree()
c.Assert(err, IsNil)
err = ioutil.WriteFile(filepath.Join(path, "foo"), []byte("foo"), 0755)
c.Assert(err, IsNil)
_, err = w.Commit("foo", &CommitOptions{Author: defaultSignature()})
c.Assert(err, IsNil)

w, err = r.Worktree()
c.Assert(err, IsNil)
err = ioutil.WriteFile(filepath.Join(path, "bar"), []byte("bar"), 0755)
c.Assert(err, IsNil)
_, err = w.Commit("bar", &CommitOptions{Author: defaultSignature()})
c.Assert(err, IsNil)

err = w.Pull(&PullOptions{})
c.Assert(err, ErrorMatches, "non-fast-forward update")
}

func (s *WorktreeSuite) TestPullUpdateReferencesIfNeeded(c *C) {
r, _ := Init(memory.NewStorage(), memfs.New())
r.CreateRemote(&config.RemoteConfig{
Expand Down