1
0
Fork 0
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:
Aleksa Sarai 2025-09-16 12:06:54 +10:00
parent ed28104f71
commit 9e8bfa26d0
No known key found for this signature in database
GPG key ID: 2897FAD2B7E9446F

View file

@ -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 {
for _, e := range newDh.Entries {
if e.Type == RelativeType || e.Type == FullType {
path, err := e.Path()
if err != nil { if err != nil {
return nil, err return nil, err
} }
newEntries, err := toEntryMap(newDh)
// Cannot take &kv because it's the iterator. if err != nil {
cEntry := new(Entry) return nil, err
*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,
}) })
} }