mirror of
https://github.com/vbatts/go-mtree.git
synced 2025-10-04 04:31:00 +00:00
compare: modernise DirectoryHierarchy compare impl
This is fairly similar to the compareEntry modernisation, but there was no need to use maps.Insert or maps.Collect since we want to pre-allocate the map sizes anyway. Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
This commit is contained in:
parent
ed28104f71
commit
9e8bfa26d0
1 changed files with 29 additions and 56 deletions
85
compare.go
85
compare.go
|
@ -354,88 +354,61 @@ func compareEntry(oldEntry, newEntry Entry) ([]KeyDelta, error) {
|
||||||
|
|
||||||
// compare is the actual workhorse for Compare() and CompareSame()
|
// compare is the actual workhorse for Compare() and CompareSame()
|
||||||
func compare(oldDh, newDh *DirectoryHierarchy, keys []Keyword, same bool) ([]InodeDelta, error) {
|
func compare(oldDh, newDh *DirectoryHierarchy, keys []Keyword, same bool) ([]InodeDelta, error) {
|
||||||
// Represents the new and old states for an entry.
|
toEntryMap := func(dh *DirectoryHierarchy) (map[string]Entry, error) {
|
||||||
type stateT struct {
|
if dh == nil {
|
||||||
Old *Entry
|
// treat nil DirectoryHierarchy as empty
|
||||||
New *Entry
|
return make(map[string]Entry), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// To deal with different orderings of the entries, use a path-keyed
|
// pre-allocate the map to avoid resizing
|
||||||
// map to make sure we don't start comparing unrelated entries.
|
entries := make(map[string]Entry, len(dh.Entries))
|
||||||
diffs := map[string]*stateT{}
|
for _, e := range dh.Entries {
|
||||||
|
|
||||||
// First, iterate over the old hierarchy. If nil, pretend it's empty.
|
|
||||||
if oldDh != nil {
|
|
||||||
for _, e := range oldDh.Entries {
|
|
||||||
if e.Type == RelativeType || e.Type == FullType {
|
if e.Type == RelativeType || e.Type == FullType {
|
||||||
path, err := e.Path()
|
path, err := e.Path()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
entries[path] = e
|
||||||
// Cannot take &kv because it's the iterator.
|
|
||||||
cEntry := new(Entry)
|
|
||||||
*cEntry = e
|
|
||||||
|
|
||||||
_, ok := diffs[path]
|
|
||||||
if !ok {
|
|
||||||
diffs[path] = &stateT{}
|
|
||||||
}
|
|
||||||
diffs[path].Old = cEntry
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return entries, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then, iterate over the new hierarchy. If nil, pretend it's empty.
|
oldEntries, err := toEntryMap(oldDh)
|
||||||
if newDh != nil {
|
if err != nil {
|
||||||
for _, e := range newDh.Entries {
|
return nil, err
|
||||||
if e.Type == RelativeType || e.Type == FullType {
|
}
|
||||||
path, err := e.Path()
|
newEntries, err := toEntryMap(newDh)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
|
||||||
|
|
||||||
// Cannot take &kv because it's the iterator.
|
|
||||||
cEntry := new(Entry)
|
|
||||||
*cEntry = e
|
|
||||||
|
|
||||||
_, ok := diffs[path]
|
|
||||||
if !ok {
|
|
||||||
diffs[path] = &stateT{}
|
|
||||||
}
|
|
||||||
diffs[path].New = cEntry
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we compute the diff.
|
// Now we compute the diff.
|
||||||
var results []InodeDelta
|
var results []InodeDelta
|
||||||
for path, diff := range diffs {
|
for path := range iterMapsKeys(oldEntries, newEntries) {
|
||||||
// Invalid
|
old, oldHas := oldEntries[path]
|
||||||
if diff.Old == nil && diff.New == nil {
|
gnu, gnuHas := newEntries[path] // avoid shadowing "new" builtin
|
||||||
return nil, fmt.Errorf("invalid state: both old and new are nil: path=%s", path)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
// Missing
|
// Missing
|
||||||
case diff.New == nil:
|
case !gnuHas:
|
||||||
results = append(results, InodeDelta{
|
results = append(results, InodeDelta{
|
||||||
diff: Missing,
|
diff: Missing,
|
||||||
path: path,
|
path: path,
|
||||||
old: *diff.Old,
|
old: old,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Extra
|
// Extra
|
||||||
case diff.Old == nil:
|
case !oldHas:
|
||||||
results = append(results, InodeDelta{
|
results = append(results, InodeDelta{
|
||||||
diff: Extra,
|
diff: Extra,
|
||||||
path: path,
|
path: path,
|
||||||
new: *diff.New,
|
new: gnu,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Modified
|
// Modified
|
||||||
default:
|
default:
|
||||||
changed, err := compareEntry(*diff.Old, *diff.New)
|
changed, err := compareEntry(old, gnu)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("comparison failed %s: %s", path, err)
|
return nil, fmt.Errorf("comparison failed %s: %s", path, err)
|
||||||
}
|
}
|
||||||
|
@ -457,8 +430,8 @@ func compare(oldDh, newDh *DirectoryHierarchy, keys []Keyword, same bool) ([]Ino
|
||||||
results = append(results, InodeDelta{
|
results = append(results, InodeDelta{
|
||||||
diff: Modified,
|
diff: Modified,
|
||||||
path: path,
|
path: path,
|
||||||
old: *diff.Old,
|
old: old,
|
||||||
new: *diff.New,
|
new: gnu,
|
||||||
keys: changed,
|
keys: changed,
|
||||||
})
|
})
|
||||||
} else if same {
|
} else if same {
|
||||||
|
@ -467,8 +440,8 @@ func compare(oldDh, newDh *DirectoryHierarchy, keys []Keyword, same bool) ([]Ino
|
||||||
results = append(results, InodeDelta{
|
results = append(results, InodeDelta{
|
||||||
diff: Same,
|
diff: Same,
|
||||||
path: path,
|
path: path,
|
||||||
old: *diff.Old,
|
old: old,
|
||||||
new: *diff.New,
|
new: gnu,
|
||||||
keys: changed,
|
keys: changed,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue