aboutsummaryrefslogtreecommitdiffstats
path: root/plumbing
diff options
context:
space:
mode:
authorMáximo Cuadros <mcuadros@gmail.com>2017-04-12 15:18:41 +0200
committerGitHub <noreply@github.com>2017-04-12 15:18:41 +0200
commit932ced9f55f556de02610425cfa161c35c6a758b (patch)
tree9b5dd9ad1665fad8424dfbdc5bd93b531f714b09 /plumbing
parent9b45f468c61a0756dd19d09b64c2b1a88cc99ec5 (diff)
parent5bcf802213e801c4d52102612f007defa5d0397f (diff)
downloadgo-git-932ced9f55f556de02610425cfa161c35c6a758b.tar.gz
Merge pull request #339 from mcuadros/status
worktree, status and reset implementation based on merkletrie
Diffstat (limited to 'plumbing')
-rw-r--r--plumbing/format/index/index.go26
-rw-r--r--plumbing/object/difftree.go4
-rw-r--r--plumbing/object/tree.go8
-rw-r--r--plumbing/object/tree_test.go6
-rw-r--r--plumbing/object/treenoder.go26
5 files changed, 49 insertions, 21 deletions
diff --git a/plumbing/format/index/index.go b/plumbing/format/index/index.go
index ee50efd..61e7d66 100644
--- a/plumbing/format/index/index.go
+++ b/plumbing/format/index/index.go
@@ -2,8 +2,11 @@ package index
import (
"errors"
+ "fmt"
"time"
+ "bytes"
+
"gopkg.in/src-d/go-git.v4/plumbing"
"gopkg.in/src-d/go-git.v4/plumbing/filemode"
)
@@ -47,6 +50,16 @@ type Index struct {
ResolveUndo *ResolveUndo
}
+// String is equivalent to `git ls-files --stage --debug`
+func (i *Index) String() string {
+ buf := bytes.NewBuffer(nil)
+ for _, e := range i.Entries {
+ buf.WriteString(e.String())
+ }
+
+ return buf.String()
+}
+
// Entry represents a single file (or stage of a file) in the cache. An entry
// represents exactly one stage of a file. If a file path is unmerged then
// multiple Entry instances may appear for the same path name.
@@ -78,6 +91,19 @@ type Entry struct {
IntentToAdd bool
}
+func (e Entry) String() string {
+ buf := bytes.NewBuffer(nil)
+
+ fmt.Fprintf(buf, "%06o %s %d\t%s\n", e.Mode, e.Hash, e.Stage, e.Name)
+ fmt.Fprintf(buf, " ctime: %d:%d\n", e.CreatedAt.Unix(), e.CreatedAt.Nanosecond())
+ fmt.Fprintf(buf, " mtime: %d:%d\n", e.ModifiedAt.Unix(), e.ModifiedAt.Nanosecond())
+ fmt.Fprintf(buf, " dev: %d\tino: %d\n", e.Dev, e.Inode)
+ fmt.Fprintf(buf, " uid: %d\tgid: %d\n", e.UID, e.GID)
+ fmt.Fprintf(buf, " size: %d\tflags: %x\n", e.Size, 0)
+
+ return buf.String()
+}
+
// Tree contains pre-computed hashes for trees that can be derived from the
// index. It helps speed up tree object generation from index for a new commit.
type Tree struct {
diff --git a/plumbing/object/difftree.go b/plumbing/object/difftree.go
index 87a7153..ac58c4d 100644
--- a/plumbing/object/difftree.go
+++ b/plumbing/object/difftree.go
@@ -10,8 +10,8 @@ import (
// DiffTree compares the content and mode of the blobs found via two
// tree objects.
func DiffTree(a, b *Tree) (Changes, error) {
- from := newTreeNoder(a)
- to := newTreeNoder(b)
+ from := NewTreeRootNode(a)
+ to := NewTreeRootNode(b)
hashEqual := func(a, b noder.Hasher) bool {
return bytes.Equal(a.Hash(), b.Hash())
diff --git a/plumbing/object/tree.go b/plumbing/object/tree.go
index e70b5cd..d2265a8 100644
--- a/plumbing/object/tree.go
+++ b/plumbing/object/tree.go
@@ -67,7 +67,7 @@ type TreeEntry struct {
// File returns the hash of the file identified by the `path` argument.
// The path is interpreted as relative to the tree receiver.
func (t *Tree) File(path string) (*File, error) {
- e, err := t.findEntry(path)
+ e, err := t.FindEntry(path)
if err != nil {
return nil, ErrFileNotFound
}
@@ -86,7 +86,7 @@ func (t *Tree) File(path string) (*File, error) {
// Tree returns the tree identified by the `path` argument.
// The path is interpreted as relative to the tree receiver.
func (t *Tree) Tree(path string) (*Tree, error) {
- e, err := t.findEntry(path)
+ e, err := t.FindEntry(path)
if err != nil {
return nil, ErrDirectoryNotFound
}
@@ -109,7 +109,8 @@ func (t *Tree) TreeEntryFile(e *TreeEntry) (*File, error) {
return NewFile(e.Name, e.Mode, blob), nil
}
-func (t *Tree) findEntry(path string) (*TreeEntry, error) {
+// FindEntry search a TreeEntry in this tree or any subtree.
+func (t *Tree) FindEntry(path string) (*TreeEntry, error) {
pathParts := strings.Split(path, "/")
var tree *Tree
@@ -146,6 +147,7 @@ func (t *Tree) entry(baseName string) (*TreeEntry, error) {
if t.m == nil {
t.buildMap()
}
+
entry, ok := t.m[baseName]
if !ok {
return nil, errEntryNotFound
diff --git a/plumbing/object/tree_test.go b/plumbing/object/tree_test.go
index cf5ad5f..aa86517 100644
--- a/plumbing/object/tree_test.go
+++ b/plumbing/object/tree_test.go
@@ -107,6 +107,12 @@ func (s *TreeSuite) TestFiles(c *C) {
c.Assert(count, Equals, 9)
}
+func (s *TreeSuite) TestFindEntry(c *C) {
+ e, err := s.Tree.FindEntry("vendor/foo.go")
+ c.Assert(err, IsNil)
+ c.Assert(e.Name, Equals, "foo.go")
+}
+
// This plumbing.EncodedObject implementation has a reader that only returns 6
// bytes at a time, this should simulate the conditions when a read
// returns less bytes than asked, for example when reading a hash which
diff --git a/plumbing/object/treenoder.go b/plumbing/object/treenoder.go
index 4da8298..bd65abc 100644
--- a/plumbing/object/treenoder.go
+++ b/plumbing/object/treenoder.go
@@ -1,13 +1,5 @@
package object
-// A treenoder is a helper type that wraps git trees into merkletrie
-// noders.
-//
-// As a merkletrie noder doesn't understand the concept of modes (e.g.
-// file permissions), the treenoder includes the mode of the git tree in
-// the hash, so changes in the modes will be detected as modifications
-// to the file contents by the merkletrie difftree algorithm. This is
-// consistent with how the "git diff-tree" command works.
import (
"io"
@@ -16,6 +8,14 @@ import (
"gopkg.in/src-d/go-git.v4/utils/merkletrie/noder"
)
+// A treenoder is a helper type that wraps git trees into merkletrie
+// noders.
+//
+// As a merkletrie noder doesn't understand the concept of modes (e.g.
+// file permissions), the treenoder includes the mode of the git tree in
+// the hash, so changes in the modes will be detected as modifications
+// to the file contents by the merkletrie difftree algorithm. This is
+// consistent with how the "git diff-tree" command works.
type treeNoder struct {
parent *Tree // the root node is its own parent
name string // empty string for the root node
@@ -24,7 +24,8 @@ type treeNoder struct {
children []noder.Noder // memoized
}
-func newTreeNoder(t *Tree) *treeNoder {
+// NewTreeRootNode returns the root node of a Tree
+func NewTreeRootNode(t *Tree) noder.Noder {
if t == nil {
return &treeNoder{}
}
@@ -45,13 +46,6 @@ func (t *treeNoder) String() string {
return "treeNoder <" + t.name + ">"
}
-// The hash of a treeNoder is the result of concatenating the hash of
-// its contents and its mode; that way the difftree algorithm will
-// detect changes in the contents of files and also in their mode.
-//
-// Files with Regular and Deprecated file modes are considered the same
-// for the purpose of difftree, so Regular will be used as the mode for
-// Deprecated files here.
func (t *treeNoder) Hash() []byte {
if t.mode == filemode.Deprecated {
return append(t.hash[:], filemode.Regular.Bytes()...)