package filesystem import ( "bytes" "io" "os" "path/filepath" "gopkg.in/src-d/go-billy.v2" "gopkg.in/src-d/go-git.v4/plumbing" "gopkg.in/src-d/go-git.v4/plumbing/filemode" "gopkg.in/src-d/go-git.v4/utils/merkletrie/noder" ) var ignore = map[string]bool{ ".git": true, } func IsEquals(a, b noder.Hasher) bool { pathA := a.(noder.Path) pathB := b.(noder.Path) if pathA[len(pathA)-1].IsDir() || pathB[len(pathB)-1].IsDir() { return false } return bytes.Equal(a.Hash(), b.Hash()) } type Node struct { parent string name string isDir bool info billy.FileInfo fs billy.Filesystem } func NewRootNode(fs billy.Filesystem) (*Node, error) { info, err := fs.Stat("/") if err != nil && !os.IsNotExist(err) { return nil, err } return &Node{fs: fs, info: info, isDir: true, name: ""}, nil } func (n *Node) String() string { return filepath.Join(n.parent, n.name) } func (n *Node) Hash() []byte { if n.IsDir() { return nil } f, err := n.fs.Open(n.fullpath()) if err != nil { panic(err) } h := plumbing.NewHasher(plumbing.BlobObject, n.info.Size()) if _, err := io.Copy(h, f); err != nil { panic(err) } hash := h.Sum() mode, err := filemode.NewFromOSFileMode(n.info.Mode()) if err != nil { panic(err) } return append(hash[:], mode.Bytes()...) } func (n *Node) Name() string { return n.name } func (n *Node) IsDir() bool { return n.isDir } func (n *Node) Children() ([]noder.Noder, error) { files, err := n.readDir() if err != nil { return nil, err } path := n.fullpath() var c []noder.Noder for _, file := range files { if _, ok := ignore[file.Name()]; ok { continue } c = append(c, &Node{ fs: n.fs, parent: path, info: file, name: file.Name(), isDir: file.IsDir(), }) } return c, nil } func (n *Node) NumChildren() (int, error) { files, err := n.readDir() return len(files), err } func (n *Node) fullpath() string { return filepath.Join(n.parent, n.name) } func (n *Node) readDir() ([]billy.FileInfo, error) { if !n.IsDir() { return nil, nil } l, err := n.fs.ReadDir(n.fullpath()) if err != nil && os.IsNotExist(err) { return l, nil } return l, err }