Merge pull request #512 from mcuadros/idx-64bits

format: idxfile, support for >2Gb packfiles
diff --git a/COMPATIBILITY.md b/COMPATIBILITY.md
index 948eb14..fa998bf 100644
--- a/COMPATIBILITY.md
+++ b/COMPATIBILITY.md
@@ -10,7 +10,7 @@
 | 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                                | ✔ |
@@ -27,7 +27,7 @@
 | tag                                   | ✔ |
 | **sharing and updating projects** |
 | fetch                                 | ✔ |
-| pull                                  | ✔ |
+| pull                                  | ✔ | Only supports merges where the merge can be resolved as a fast-forward. |
 | push                                  | ✔ |
 | remote                                | ✔ |
 | submodule                             | ✔ |
@@ -108,4 +108,4 @@
 | gitattributes                         | ✖ |
 | index version                         | |
 | packfile version                      | |
-| push-certs                            | ✖ |
\ No newline at end of file
+| push-certs                            | ✖ |
diff --git a/repository.go b/repository.go
index b80f8d9..00ffaf7 100644
--- a/repository.go
+++ b/repository.go
@@ -844,7 +844,7 @@
 		return nil, ErrIsBareRepository
 	}
 
-	return &Worktree{r: r, fs: r.wt}, nil
+	return &Worktree{r: r, Filesystem: r.wt}, nil
 }
 
 // ResolveRevision resolves revision to corresponding hash.
diff --git a/repository_test.go b/repository_test.go
index 7f984f6..558149b 100644
--- a/repository_test.go
+++ b/repository_test.go
@@ -1138,7 +1138,7 @@
 	r, _ := Init(memory.NewStorage(), def)
 	w, err := r.Worktree()
 	c.Assert(err, IsNil)
-	c.Assert(w.fs, Equals, def)
+	c.Assert(w.Filesystem, Equals, def)
 }
 
 func (s *RepositorySuite) TestWorktreeBare(c *C) {
diff --git a/submodule.go b/submodule.go
index ac027c2..fbaddfd 100644
--- a/submodule.go
+++ b/submodule.go
@@ -115,7 +115,7 @@
 	}
 
 	var worktree billy.Filesystem
-	if worktree, err = s.w.fs.Chroot(s.c.Path); err != nil {
+	if worktree, err = s.w.Filesystem.Chroot(s.c.Path); err != nil {
 		return nil, err
 	}
 
diff --git a/submodule_test.go b/submodule_test.go
index dd797c5..e4f3013 100644
--- a/submodule_test.go
+++ b/submodule_test.go
@@ -128,7 +128,7 @@
 
 	c.Assert(err, IsNil)
 
-	fs := s.Worktree.fs
+	fs := s.Worktree.Filesystem
 	_, err = fs.Stat(fs.Join("itself", "basic", "LICENSE"))
 	c.Assert(err, IsNil)
 }
diff --git a/worktree.go b/worktree.go
index 5768888..4e4d544 100644
--- a/worktree.go
+++ b/worktree.go
@@ -15,6 +15,7 @@
 	"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"
 
@@ -29,13 +30,17 @@
 
 // Worktree represents a git worktree.
 type Worktree struct {
-	r  *Repository
-	fs billy.Filesystem
+	// Filesystem underlying filesystem.
+	Filesystem billy.Filesystem
+
+	r *Repository
 }
 
 // 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 +49,8 @@
 // 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 +59,55 @@
 		return err
 	}
 
-	head, err := w.r.fetchAndUpdateReferences(ctx, &FetchOptions{
-		RemoteName: o.RemoteName,
-		Depth:      o.Depth,
-		Auth:       o.Auth,
-		Progress:   o.Progress,
-	}, o.ReferenceName)
+	remote, err := w.r.Remote(o.RemoteName)
 	if err != nil {
 		return err
 	}
 
-	if err := w.Reset(&ResetOptions{Commit: head.Hash()}); err != nil {
+	fetchHead, err := remote.fetch(ctx, &FetchOptions{
+		RemoteName: o.RemoteName,
+		Depth:      o.Depth,
+		Auth:       o.Auth,
+		Progress:   o.Progress,
+	})
+
+	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
+	}
+
+	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
 	}
 
@@ -355,13 +400,13 @@
 			return err
 		}
 
-		if err := w.fs.MkdirAll(name, mode); err != nil {
+		if err := w.Filesystem.MkdirAll(name, mode); err != nil {
 			return err
 		}
 
 		return w.addIndexFromTreeEntry(name, e, idx)
 	case merkletrie.Delete:
-		if err := rmFileAndDirIfEmpty(w.fs, name); err != nil {
+		if err := rmFileAndDirIfEmpty(w.Filesystem, name); err != nil {
 			return err
 		}
 
@@ -385,7 +430,7 @@
 
 		// to apply perm changes the file is deleted, billy doesn't implement
 		// chmod
-		if err := w.fs.Remove(name); err != nil {
+		if err := w.Filesystem.Remove(name); err != nil {
 			return err
 		}
 
@@ -402,7 +447,7 @@
 
 		return w.addIndexFromFile(name, e.Hash, idx)
 	case merkletrie.Delete:
-		if err := rmFileAndDirIfEmpty(w.fs, name); err != nil {
+		if err := rmFileAndDirIfEmpty(w.Filesystem, name); err != nil {
 			return err
 		}
 
@@ -429,7 +474,7 @@
 
 	defer ioutil.CheckClose(from, &err)
 
-	to, err := w.fs.OpenFile(f.Name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, mode.Perm())
+	to, err := w.Filesystem.OpenFile(f.Name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, mode.Perm())
 	if err != nil {
 		return
 	}
@@ -453,7 +498,7 @@
 		return
 	}
 
-	err = w.fs.Symlink(string(bytes), f.Name)
+	err = w.Filesystem.Symlink(string(bytes), f.Name)
 	return
 }
 
@@ -468,7 +513,7 @@
 }
 
 func (w *Worktree) addIndexFromFile(name string, h plumbing.Hash, idx *index.Index) error {
-	fi, err := w.fs.Lstat(name)
+	fi, err := w.Filesystem.Lstat(name)
 	if err != nil {
 		return err
 	}
@@ -577,7 +622,7 @@
 }
 
 func (w *Worktree) readGitmodulesFile() (*config.Modules, error) {
-	f, err := w.fs.Open(gitmodulesFile)
+	f, err := w.Filesystem.Open(gitmodulesFile)
 	if err != nil {
 		if os.IsNotExist(err) {
 			return nil, nil
diff --git a/worktree_commit.go b/worktree_commit.go
index 02a5d03..e5d0a11 100644
--- a/worktree_commit.go
+++ b/worktree_commit.go
@@ -32,7 +32,7 @@
 	}
 
 	h := &buildTreeHelper{
-		fs: w.fs,
+		fs: w.Filesystem,
 		s:  w.r.Storer,
 	}
 
diff --git a/worktree_commit_test.go b/worktree_commit_test.go
index 8f3b7b0..f6744bc 100644
--- a/worktree_commit_test.go
+++ b/worktree_commit_test.go
@@ -54,8 +54,8 @@
 
 	fs := memfs.New()
 	w := &Worktree{
-		r:  s.Repository,
-		fs: fs,
+		r:          s.Repository,
+		Filesystem: fs,
 	}
 
 	err := w.Checkout(&CheckoutOptions{})
@@ -78,8 +78,8 @@
 
 	fs := memfs.New()
 	w := &Worktree{
-		r:  s.Repository,
-		fs: fs,
+		r:          s.Repository,
+		Filesystem: fs,
 	}
 
 	err := w.Checkout(&CheckoutOptions{})
diff --git a/worktree_status.go b/worktree_status.go
index a662516..9b0773e 100644
--- a/worktree_status.go
+++ b/worktree_status.go
@@ -116,7 +116,7 @@
 		return nil, err
 	}
 
-	to := filesystem.NewRootNode(w.fs, submodules)
+	to := filesystem.NewRootNode(w.Filesystem, submodules)
 	res, err := merkletrie.DiffTree(from, to, diffTreeIsEquals)
 	if err == nil {
 		res = w.excludeIgnoredChanges(res)
@@ -125,7 +125,7 @@
 }
 
 func (w *Worktree) excludeIgnoredChanges(changes merkletrie.Changes) merkletrie.Changes {
-	patterns, err := gitignore.ReadPatterns(w.fs, nil)
+	patterns, err := gitignore.ReadPatterns(w.Filesystem, nil)
 	if err != nil || len(patterns) == 0 {
 		return changes
 	}
@@ -251,7 +251,7 @@
 }
 
 func (w *Worktree) copyFileToStorage(path string) (hash plumbing.Hash, err error) {
-	fi, err := w.fs.Lstat(path)
+	fi, err := w.Filesystem.Lstat(path)
 	if err != nil {
 		return plumbing.ZeroHash, err
 	}
@@ -281,7 +281,7 @@
 }
 
 func (w *Worktree) fillEncodedObjectFromFile(dst io.Writer, path string, fi os.FileInfo) (err error) {
-	src, err := w.fs.Open(path)
+	src, err := w.Filesystem.Open(path)
 	if err != nil {
 		return err
 	}
@@ -296,7 +296,7 @@
 }
 
 func (w *Worktree) fillEncodedObjectFromSymlink(dst io.Writer, path string, fi os.FileInfo) error {
-	target, err := w.fs.Readlink(path)
+	target, err := w.Filesystem.Readlink(path)
 	if err != nil {
 		return err
 	}
@@ -337,7 +337,7 @@
 }
 
 func (w *Worktree) doUpdateFileToIndex(e *index.Entry, filename string, h plumbing.Hash) error {
-	info, err := w.fs.Lstat(filename)
+	info, err := w.Filesystem.Lstat(filename)
 	if err != nil {
 		return err
 	}
@@ -382,7 +382,7 @@
 }
 
 func (w *Worktree) deleteFromFilesystem(path string) error {
-	err := w.fs.Remove(path)
+	err := w.Filesystem.Remove(path)
 	if os.IsNotExist(err) {
 		return nil
 	}
@@ -393,11 +393,11 @@
 // Move moves or rename a file in the worktree and the index, directories are
 // not supported.
 func (w *Worktree) Move(from, to string) (plumbing.Hash, error) {
-	if _, err := w.fs.Lstat(from); err != nil {
+	if _, err := w.Filesystem.Lstat(from); err != nil {
 		return plumbing.ZeroHash, err
 	}
 
-	if _, err := w.fs.Lstat(to); err == nil {
+	if _, err := w.Filesystem.Lstat(to); err == nil {
 		return plumbing.ZeroHash, ErrDestinationExists
 	}
 
@@ -406,7 +406,7 @@
 		return plumbing.ZeroHash, err
 	}
 
-	if err := w.fs.Rename(from, to); err != nil {
+	if err := w.Filesystem.Rename(from, to); err != nil {
 		return hash, err
 	}
 
diff --git a/worktree_test.go b/worktree_test.go
index 150176f..10774a4 100644
--- a/worktree_test.go
+++ b/worktree_test.go
@@ -51,6 +51,66 @@
 	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{
@@ -192,8 +252,8 @@
 func (s *WorktreeSuite) TestCheckout(c *C) {
 	fs := memfs.New()
 	w := &Worktree{
-		r:  s.Repository,
-		fs: fs,
+		r:          s.Repository,
+		Filesystem: fs,
 	}
 
 	err := w.Checkout(&CheckoutOptions{})
@@ -225,12 +285,12 @@
 	w, err := r.Worktree()
 	c.Assert(err, IsNil)
 
-	w.fs.Symlink("not-exists", "bar")
+	w.Filesystem.Symlink("not-exists", "bar")
 	w.Add("bar")
 	w.Commit("foo", &CommitOptions{Author: defaultSignature()})
 
 	r.Storer.SetIndex(&index.Index{Version: 2})
-	w.fs = osfs.New(filepath.Join(dir, "worktree-empty"))
+	w.Filesystem = osfs.New(filepath.Join(dir, "worktree-empty"))
 
 	err = w.Checkout(&CheckoutOptions{})
 	c.Assert(err, IsNil)
@@ -239,7 +299,7 @@
 	c.Assert(err, IsNil)
 	c.Assert(status.IsClean(), Equals, true)
 
-	target, err := w.fs.Readlink("bar")
+	target, err := w.Filesystem.Readlink("bar")
 	c.Assert(target, Equals, "not-exists")
 	c.Assert(err, IsNil)
 }
@@ -280,8 +340,8 @@
 func (s *WorktreeSuite) TestCheckoutIndexMem(c *C) {
 	fs := memfs.New()
 	w := &Worktree{
-		r:  s.Repository,
-		fs: fs,
+		r:          s.Repository,
+		Filesystem: fs,
 	}
 
 	err := w.Checkout(&CheckoutOptions{})
@@ -310,8 +370,8 @@
 
 	fs := osfs.New(filepath.Join(dir, "worktree"))
 	w := &Worktree{
-		r:  s.Repository,
-		fs: fs,
+		r:          s.Repository,
+		Filesystem: fs,
 	}
 
 	err = w.Checkout(&CheckoutOptions{})
@@ -335,8 +395,8 @@
 
 func (s *WorktreeSuite) TestCheckoutBranch(c *C) {
 	w := &Worktree{
-		r:  s.Repository,
-		fs: memfs.New(),
+		r:          s.Repository,
+		Filesystem: memfs.New(),
 	}
 
 	err := w.Checkout(&CheckoutOptions{
@@ -355,8 +415,8 @@
 
 func (s *WorktreeSuite) TestCheckoutCreateWithHash(c *C) {
 	w := &Worktree{
-		r:  s.Repository,
-		fs: memfs.New(),
+		r:          s.Repository,
+		Filesystem: memfs.New(),
 	}
 
 	err := w.Checkout(&CheckoutOptions{
@@ -378,8 +438,8 @@
 
 func (s *WorktreeSuite) TestCheckoutCreate(c *C) {
 	w := &Worktree{
-		r:  s.Repository,
-		fs: memfs.New(),
+		r:          s.Repository,
+		Filesystem: memfs.New(),
 	}
 
 	err := w.Checkout(&CheckoutOptions{
@@ -400,8 +460,8 @@
 
 func (s *WorktreeSuite) TestCheckoutBranchAndHash(c *C) {
 	w := &Worktree{
-		r:  s.Repository,
-		fs: memfs.New(),
+		r:          s.Repository,
+		Filesystem: memfs.New(),
 	}
 
 	err := w.Checkout(&CheckoutOptions{
@@ -414,8 +474,8 @@
 
 func (s *WorktreeSuite) TestCheckoutCreateMissingBranch(c *C) {
 	w := &Worktree{
-		r:  s.Repository,
-		fs: memfs.New(),
+		r:          s.Repository,
+		Filesystem: memfs.New(),
 	}
 
 	err := w.Checkout(&CheckoutOptions{
@@ -497,8 +557,8 @@
 func (s *WorktreeSuite) TestCheckoutWithGitignore(c *C) {
 	fs := memfs.New()
 	w := &Worktree{
-		r:  s.Repository,
-		fs: fs,
+		r:          s.Repository,
+		Filesystem: fs,
 	}
 
 	err := w.Checkout(&CheckoutOptions{})
@@ -526,8 +586,8 @@
 func (s *WorktreeSuite) TestStatus(c *C) {
 	fs := memfs.New()
 	w := &Worktree{
-		r:  s.Repository,
-		fs: fs,
+		r:          s.Repository,
+		Filesystem: fs,
 	}
 
 	status, err := w.Status()
@@ -575,8 +635,8 @@
 func (s *WorktreeSuite) TestReset(c *C) {
 	fs := memfs.New()
 	w := &Worktree{
-		r:  s.Repository,
-		fs: fs,
+		r:          s.Repository,
+		Filesystem: fs,
 	}
 
 	commit := plumbing.NewHash("35e85108805c84807bc66a02d91535e1e24b38b9")
@@ -599,8 +659,8 @@
 func (s *WorktreeSuite) TestResetMerge(c *C) {
 	fs := memfs.New()
 	w := &Worktree{
-		r:  s.Repository,
-		fs: fs,
+		r:          s.Repository,
+		Filesystem: fs,
 	}
 
 	commit := plumbing.NewHash("35e85108805c84807bc66a02d91535e1e24b38b9")
@@ -626,8 +686,8 @@
 func (s *WorktreeSuite) TestResetHard(c *C) {
 	fs := memfs.New()
 	w := &Worktree{
-		r:  s.Repository,
-		fs: fs,
+		r:          s.Repository,
+		Filesystem: fs,
 	}
 
 	commit := plumbing.NewHash("35e85108805c84807bc66a02d91535e1e24b38b9")
@@ -653,8 +713,8 @@
 func (s *WorktreeSuite) TestStatusAfterCheckout(c *C) {
 	fs := memfs.New()
 	w := &Worktree{
-		r:  s.Repository,
-		fs: fs,
+		r:          s.Repository,
+		Filesystem: fs,
 	}
 
 	err := w.Checkout(&CheckoutOptions{Force: true})
@@ -672,8 +732,8 @@
 
 	fs := osfs.New(filepath.Join(dir, "worktree"))
 	w := &Worktree{
-		r:  s.Repository,
-		fs: fs,
+		r:          s.Repository,
+		Filesystem: fs,
 	}
 
 	err = w.Checkout(&CheckoutOptions{})
@@ -695,8 +755,8 @@
 func (s *WorktreeSuite) TestStatusIgnored(c *C) {
 	fs := memfs.New()
 	w := &Worktree{
-		r:  s.Repository,
-		fs: fs,
+		r:          s.Repository,
+		Filesystem: fs,
 	}
 
 	w.Checkout(&CheckoutOptions{})
@@ -742,14 +802,14 @@
 func (s *WorktreeSuite) TestStatusUntracked(c *C) {
 	fs := memfs.New()
 	w := &Worktree{
-		r:  s.Repository,
-		fs: fs,
+		r:          s.Repository,
+		Filesystem: fs,
 	}
 
 	err := w.Checkout(&CheckoutOptions{Force: true})
 	c.Assert(err, IsNil)
 
-	f, err := w.fs.Create("foo")
+	f, err := w.Filesystem.Create("foo")
 	c.Assert(err, IsNil)
 	c.Assert(f.Close(), IsNil)
 
@@ -765,8 +825,8 @@
 
 	fs := osfs.New(filepath.Join(dir, "worktree"))
 	w := &Worktree{
-		r:  s.Repository,
-		fs: fs,
+		r:          s.Repository,
+		Filesystem: fs,
 	}
 
 	err = w.Checkout(&CheckoutOptions{})
@@ -812,8 +872,8 @@
 func (s *WorktreeSuite) TestAddUntracked(c *C) {
 	fs := memfs.New()
 	w := &Worktree{
-		r:  s.Repository,
-		fs: fs,
+		r:          s.Repository,
+		Filesystem: fs,
 	}
 
 	err := w.Checkout(&CheckoutOptions{Force: true})
@@ -823,7 +883,7 @@
 	c.Assert(err, IsNil)
 	c.Assert(idx.Entries, HasLen, 9)
 
-	err = util.WriteFile(w.fs, "foo", []byte("FOO"), 0755)
+	err = util.WriteFile(w.Filesystem, "foo", []byte("FOO"), 0755)
 	c.Assert(err, IsNil)
 
 	hash, err := w.Add("foo")
@@ -856,8 +916,8 @@
 func (s *WorktreeSuite) TestAddModified(c *C) {
 	fs := memfs.New()
 	w := &Worktree{
-		r:  s.Repository,
-		fs: fs,
+		r:          s.Repository,
+		Filesystem: fs,
 	}
 
 	err := w.Checkout(&CheckoutOptions{Force: true})
@@ -867,7 +927,7 @@
 	c.Assert(err, IsNil)
 	c.Assert(idx.Entries, HasLen, 9)
 
-	err = util.WriteFile(w.fs, "LICENSE", []byte("FOO"), 0644)
+	err = util.WriteFile(w.Filesystem, "LICENSE", []byte("FOO"), 0644)
 	c.Assert(err, IsNil)
 
 	hash, err := w.Add("LICENSE")
@@ -895,8 +955,8 @@
 func (s *WorktreeSuite) TestAddUnmodified(c *C) {
 	fs := memfs.New()
 	w := &Worktree{
-		r:  s.Repository,
-		fs: fs,
+		r:          s.Repository,
+		Filesystem: fs,
 	}
 
 	err := w.Checkout(&CheckoutOptions{Force: true})
@@ -938,8 +998,8 @@
 func (s *WorktreeSuite) TestRemove(c *C) {
 	fs := memfs.New()
 	w := &Worktree{
-		r:  s.Repository,
-		fs: fs,
+		r:          s.Repository,
+		Filesystem: fs,
 	}
 
 	err := w.Checkout(&CheckoutOptions{Force: true})
@@ -958,8 +1018,8 @@
 func (s *WorktreeSuite) TestRemoveNotExistentEntry(c *C) {
 	fs := memfs.New()
 	w := &Worktree{
-		r:  s.Repository,
-		fs: fs,
+		r:          s.Repository,
+		Filesystem: fs,
 	}
 
 	err := w.Checkout(&CheckoutOptions{Force: true})
@@ -973,8 +1033,8 @@
 func (s *WorktreeSuite) TestRemoveDeletedFromWorktree(c *C) {
 	fs := memfs.New()
 	w := &Worktree{
-		r:  s.Repository,
-		fs: fs,
+		r:          s.Repository,
+		Filesystem: fs,
 	}
 
 	err := w.Checkout(&CheckoutOptions{Force: true})
@@ -996,8 +1056,8 @@
 func (s *WorktreeSuite) TestMove(c *C) {
 	fs := memfs.New()
 	w := &Worktree{
-		r:  s.Repository,
-		fs: fs,
+		r:          s.Repository,
+		Filesystem: fs,
 	}
 
 	err := w.Checkout(&CheckoutOptions{Force: true})
@@ -1018,8 +1078,8 @@
 func (s *WorktreeSuite) TestMoveNotExistentEntry(c *C) {
 	fs := memfs.New()
 	w := &Worktree{
-		r:  s.Repository,
-		fs: fs,
+		r:          s.Repository,
+		Filesystem: fs,
 	}
 
 	err := w.Checkout(&CheckoutOptions{Force: true})
@@ -1033,8 +1093,8 @@
 func (s *WorktreeSuite) TestMoveToExistent(c *C) {
 	fs := memfs.New()
 	w := &Worktree{
-		r:  s.Repository,
-		fs: fs,
+		r:          s.Repository,
+		Filesystem: fs,
 	}
 
 	err := w.Checkout(&CheckoutOptions{Force: true})