diff --git a/check.go b/check.go index 29e05e3..0e63e5a 100644 --- a/check.go +++ b/check.go @@ -5,18 +5,18 @@ package mtree // If keywords is nil, the check all present in the DirectoryHierarchy // // This is equivalent to creating a new DirectoryHierarchy with Walk(root, nil, -// keywords, fs) and then doing a Compare(dh, newDh, keywords). +// keywords, fs) and then doing a Compare(dh, curDh, keywords). func Check(root string, dh *DirectoryHierarchy, keywords []Keyword, fs FsEval) ([]InodeDelta, error) { if keywords == nil { keywords = dh.UsedKeywords() } - newDh, err := Walk(root, nil, keywords, fs) + curDh, err := Walk(root, nil, keywords, fs) if err != nil { return nil, err } - return Compare(dh, newDh, keywords) + return Compare(dh, curDh, keywords) } // TarCheck is the tar equivalent of checking a file hierarchy spec against a diff --git a/compare.go b/compare.go index 5394832..daa5676 100644 --- a/compare.go +++ b/compare.go @@ -3,6 +3,7 @@ package mtree import ( "encoding/json" "fmt" + "sort" "strconv" ) @@ -325,13 +326,17 @@ func compareEntry(oldEntry, newEntry Entry) ([]KeyDelta, error) { // missing entries and the like). A missing or extra key is treated as a // Modified type. // -// If oldDh or newDh are empty, we assume they are a hierarchy that is +// If thisDh or thatDh are empty, we assume they are a hierarchy that is // completely empty. This is purely for helping callers create synthetic // InodeDeltas. // +// Comparing this directory hierarchy to that directory hierarchy is that +// sometimes it has few than all files, or may not have directories, etc., +// so lack of presence of entries in thisDh may not be reportable. +// // NB: The order of the parameters matters (old, new) because Extra and // Missing are considered as different discrepancy types. -func Compare(oldDh, newDh *DirectoryHierarchy, keys []Keyword) ([]InodeDelta, error) { +func Compare(thisDh, thatDh *DirectoryHierarchy, keys []Keyword) ([]InodeDelta, error) { // Represents the new and old states for an entry. type stateT struct { Old *Entry @@ -343,8 +348,9 @@ func Compare(oldDh, newDh *DirectoryHierarchy, keys []Keyword) ([]InodeDelta, er diffs := map[string]*stateT{} // First, iterate over the old hierarchy. If nil, pretend it's empty. - if oldDh != nil { - for _, e := range oldDh.Entries { + if thisDh != nil { + sort.Sort(byName(thisDh.Entries)) + for _, e := range thisDh.Entries { if e.Type == RelativeType || e.Type == FullType { path, err := e.Path() if err != nil { @@ -365,8 +371,9 @@ func Compare(oldDh, newDh *DirectoryHierarchy, keys []Keyword) ([]InodeDelta, er } // Then, iterate over the new hierarchy. If nil, pretend it's empty. - if newDh != nil { - for _, e := range newDh.Entries { + if thatDh != nil { + sort.Sort(byName(thatDh.Entries)) + for _, e := range thatDh.Entries { if e.Type == RelativeType || e.Type == FullType { path, err := e.Path() if err != nil { diff --git a/entry.go b/entry.go index fc8c1c9..d983afc 100644 --- a/entry.go +++ b/entry.go @@ -14,6 +14,33 @@ func (bp byPos) Len() int { return len(bp) } func (bp byPos) Less(i, j int) bool { return bp[i].Pos < bp[j].Pos } func (bp byPos) Swap(i, j int) { bp[i], bp[j] = bp[j], bp[i] } +type byName []Entry + +func (bp byName) Len() int { return len(bp) } +func (bp byName) Less(i, j int) bool { + var iParent string + var jParent string + var err error + if bp[i].Parent != nil { + iParent, err = bp[i].Parent.Path() + if err != nil { + return false + } + } + iName := filepath.Clean(filepath.Join(iParent, bp[i].Name)) + + if bp[j].Parent != nil { + jParent, err = bp[j].Parent.Path() + if err != nil { + return false + } + } + jName := filepath.Clean(filepath.Join(jParent, bp[j].Name)) + + return iName < jName +} +func (bp byName) Swap(i, j int) { bp[i], bp[j] = bp[j], bp[i] } + // Entry is each component of content in the mtree spec file type Entry struct { Parent *Entry // up