aboutsummaryrefslogtreecommitdiffstats
path: root/worktree.go
diff options
context:
space:
mode:
authorMáximo Cuadros <mcuadros@gmail.com>2017-07-26 16:19:06 +0200
committerMáximo Cuadros <mcuadros@gmail.com>2017-07-26 16:19:06 +0200
commitb0f131a48cd4e72d641fcfb3c73fd6eeddafb931 (patch)
treea9ebfdfb6b8316773145c7727af3a92a9847d72d /worktree.go
parente19163e22eb19b352dd022f6edc9d81e1cd7a7ed (diff)
downloadgo-git-b0f131a48cd4e72d641fcfb3c73fd6eeddafb931.tar.gz
remote: pull refactor to match default behaviour
Diffstat (limited to 'worktree.go')
-rw-r--r--worktree.go49
1 files changed, 46 insertions, 3 deletions
diff --git a/worktree.go b/worktree.go
index 5768888..01f8b01 100644
--- a/worktree.go
+++ b/worktree.go
@@ -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"
@@ -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.
func (w *Worktree) Pull(o *PullOptions) error {
return w.PullContext(context.Background(), o)
}
@@ -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.
+//
// 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.
@@ -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
}