aboutsummaryrefslogtreecommitdiff
path: root/difftrees.go
diff options
context:
space:
mode:
Diffstat (limited to 'difftrees.go')
-rw-r--r--difftrees.go207
1 files changed, 0 insertions, 207 deletions
diff --git a/difftrees.go b/difftrees.go
deleted file mode 100644
index ea21687c..00000000
--- a/difftrees.go
+++ /dev/null
@@ -1,207 +0,0 @@
-package furgit
-
-// TreeDiffEntryKind represents the type of difference between two tree entries.
-type TreeDiffEntryKind int
-
-const (
- // TreeDiffEntryKindInvalid indicates an invalid difference type.
- TreeDiffEntryKindInvalid TreeDiffEntryKind = iota
- // TreeDiffEntryKindDeleted indicates that the entry was deleted.
- TreeDiffEntryKindDeleted
- // TreeDiffEntryKindAdded indicates that the entry was added.
- TreeDiffEntryKindAdded
- // TreeDiffEntryKindModified indicates that the entry was modified.
- TreeDiffEntryKindModified
-)
-
-// TreeDiffEntry represents a difference between two tree entries.
-type TreeDiffEntry struct {
- // Path is the full slash-separated path relative to the root
- // of the repository.
- Path []byte
- // Kind indicates the type of difference.
- Kind TreeDiffEntryKind
- // Old is the old tree entry (nil iff added).
- Old *TreeEntry
- // New is the new tree entry (nil iff deleted).
- New *TreeEntry
-}
-
-// DiffTrees compares two trees rooted at a and b and returns all differences
-// as a flat slice of TreeDiffEntry. Differences are discovered recursively.
-func (repo *Repository) DiffTrees(a, b *StoredTree) ([]TreeDiffEntry, error) {
- var out []TreeDiffEntry
- err := repo.diffTreesRecursive(a, b, nil, &out)
- return out, err
-}
-
-func (repo *Repository) diffTreesRecursive(a, b *StoredTree, prefix []byte, out *[]TreeDiffEntry) error {
- if a == nil && b == nil {
- return nil
- }
-
- if a == nil {
- for i := range b.Entries {
- entry := &b.Entries[i]
- full := joinPath(prefix, entry.Name)
-
- *out = append(*out, TreeDiffEntry{
- Path: full,
- Kind: TreeDiffEntryKindAdded,
- Old: nil,
- New: entry,
- })
-
- if entry.Mode == FileModeDir {
- sub, err := repo.readTree(entry.ID)
- if err != nil {
- return err
- }
- if err := repo.diffTreesRecursive(nil, sub, full, out); err != nil {
- return err
- }
- }
- }
- return nil
- }
- if b == nil {
- for i := range a.Entries {
- entry := &a.Entries[i]
- full := joinPath(prefix, entry.Name)
-
- *out = append(*out, TreeDiffEntry{
- Path: full,
- Kind: TreeDiffEntryKindDeleted,
- Old: entry,
- New: nil,
- })
-
- if entry.Mode == FileModeDir {
- sub, err := repo.readTree(entry.ID)
- if err != nil {
- return err
- }
- if err := repo.diffTreesRecursive(sub, nil, full, out); err != nil {
- return err
- }
- }
- }
- return nil
- }
-
- left := make(map[string]*TreeEntry, len(a.Entries))
- for i := range a.Entries {
- e := &a.Entries[i]
- left[string(e.Name)] = e
- }
- right := make(map[string]*TreeEntry, len(b.Entries))
- for i := range b.Entries {
- e := &b.Entries[i]
- right[string(e.Name)] = e
- }
-
- seen := make(map[string]bool, len(a.Entries)+len(b.Entries))
- for n := range left {
- seen[n] = true
- }
- for n := range right {
- seen[n] = true
- }
-
- for name := range seen {
- le := left[name]
- re := right[name]
-
- full := joinPath(prefix, []byte(name))
-
- switch {
- case le == nil && re != nil:
- *out = append(*out, TreeDiffEntry{
- Path: full,
- Kind: TreeDiffEntryKindAdded,
- Old: nil,
- New: re,
- })
-
- if re.Mode == FileModeDir {
- sub, err := repo.readTree(re.ID)
- if err != nil {
- return err
- }
- if err := repo.diffTreesRecursive(nil, sub, full, out); err != nil {
- return err
- }
- }
-
- case le != nil && re == nil:
- *out = append(*out, TreeDiffEntry{
- Path: full,
- Kind: TreeDiffEntryKindDeleted,
- Old: le,
- New: nil,
- })
-
- if le.Mode == FileModeDir {
- sub, err := repo.readTree(le.ID)
- if err != nil {
- return err
- }
- if err := repo.diffTreesRecursive(sub, nil, full, out); err != nil {
- return err
- }
- }
-
- default:
- modified := (le.Mode != re.Mode) || (le.ID != re.ID)
- if modified {
- *out = append(*out, TreeDiffEntry{
- Path: full,
- Kind: TreeDiffEntryKindModified,
- Old: le,
- New: re,
- })
- }
-
- if le.Mode == FileModeDir && re.Mode == FileModeDir && le.ID != re.ID {
- ls, err := repo.readTree(le.ID)
- if err != nil {
- return err
- }
- rs, err := repo.readTree(re.ID)
- if err != nil {
- return err
- }
- if err := repo.diffTreesRecursive(ls, rs, full, out); err != nil {
- return err
- }
- }
- }
- }
-
- return nil
-}
-
-func joinPath(prefix, name []byte) []byte {
- if len(prefix) == 0 {
- out := make([]byte, len(name))
- copy(out, name)
- return out
- }
- out := make([]byte, len(prefix)+1+len(name))
- copy(out, prefix)
- out[len(prefix)] = '/'
- copy(out[len(prefix)+1:], name)
- return out
-}
-
-func (repo *Repository) readTree(id Hash) (*StoredTree, error) {
- obj, err := repo.ReadObject(id)
- if err != nil {
- return nil, err
- }
- tree, ok := obj.(*StoredTree)
- if !ok {
- return nil, ErrInvalidObject
- }
- return tree, nil
-}