Add diff.compareEntry helper to compare attribute entries

- Use it to compare the entry attributes for all entry types.
  Allows comparing differences in file attributes among the
  contents of two directories. This is useful for verifying
  restored contents in end-to-end tests.

- Print message about modified entries only when both entries
  are files and they are being compared.
This commit is contained in:
Julio Lopez
2019-12-05 16:35:04 -08:00
committed by Jarek Kowalski
parent 5c58b306a4
commit d3f324f59b
2 changed files with 58 additions and 7 deletions

View File

@@ -38,7 +38,7 @@ func runDiffCommand(ctx context.Context, rep *repo.Repository) error {
return errors.New("arguments do diff must both be directories or both non-directories")
}
d, err := diff.NewComparer(rep, os.Stdout)
d, err := diff.NewComparer(os.Stdout)
if err != nil {
return err
}

View File

@@ -13,7 +13,6 @@
"github.com/kopia/kopia/fs"
"github.com/kopia/kopia/internal/kopialogging"
"github.com/kopia/kopia/repo"
"github.com/kopia/kopia/repo/object"
)
@@ -21,7 +20,6 @@
// Comparer outputs diff information between two filesystems.
type Comparer struct {
rep *repo.Repository
out io.Writer
tmpDir string
@@ -109,6 +107,8 @@ func (c *Comparer) compareEntry(ctx context.Context, e1, e2 fs.Entry, path strin
return nil
}
compareEntry(e1, e2, path, c.out)
dir1, isDir1 := e1.(fs.Directory)
dir2, isDir2 := e2.(fs.Directory)
@@ -128,10 +128,10 @@ func (c *Comparer) compareEntry(ctx context.Context, e1, e2 fs.Entry, path strin
return nil
}
c.output("changed %v at %v (size %v -> %v)\n", path, e2.ModTime().String(), e1.Size(), e2.Size())
if f1, ok := e1.(fs.File); ok {
if f2, ok := e2.(fs.File); ok {
c.output("changed %v at %v (size %v -> %v)\n", path, e2.ModTime().String(), e1.Size(), e2.Size())
if err := c.compareFiles(ctx, f1, f2, path); err != nil {
return err
}
@@ -141,6 +141,57 @@ func (c *Comparer) compareEntry(ctx context.Context, e1, e2 fs.Entry, path strin
return nil
}
func compareEntry(e1, e2 fs.Entry, fullpath string, out io.Writer) bool {
if e1 == e2 { // in particular e1 == nil && e2 == nil
return true
}
if e1 == nil {
fmt.Fprintln(out, fullpath, "does not exist in source directory")
return false
}
if e2 == nil {
fmt.Fprintln(out, fullpath, "does not exist in destination directory")
return false
}
equal := true
if m1, m2 := e1.Mode(), e2.Mode(); m1 != m2 {
equal = false
fmt.Fprintln(out, fullpath, "modes differ: ", m1, m2)
}
if s1, s2 := e1.Size(), e2.Size(); s1 != s2 {
equal = false
fmt.Fprintln(out, fullpath, "sizes differ: ", s1, s2)
}
if mt1, mt2 := e1.ModTime(), e2.ModTime(); !mt1.Equal(mt2) {
equal = false
fmt.Fprintln(out, fullpath, "modification times differ: ", mt1, mt2)
}
o1, o2 := e1.Owner(), e2.Owner()
if o1.UserID != o2.UserID {
equal = false
fmt.Fprintln(out, fullpath, "owner users differ: ", o1.UserID, o2.UserID)
}
if o1.GroupID != o2.GroupID {
equal = false
fmt.Fprintln(out, fullpath, "owner groups differ: ", o1.GroupID, o2.GroupID)
}
return equal
}
func (c *Comparer) compareDirectoryEntries(ctx context.Context, entries1, entries2 fs.Entries, dirPath string) error {
e1byname := map[string]fs.Entry{}
for _, e1 := range entries1 {
@@ -238,11 +289,11 @@ func (c *Comparer) output(msg string, args ...interface{}) {
}
// NewComparer creates a comparer for a given repository that will output the results to a given writer.
func NewComparer(rep *repo.Repository, out io.Writer) (*Comparer, error) {
func NewComparer(out io.Writer) (*Comparer, error) {
tmp, err := ioutil.TempDir("", "kopia")
if err != nil {
return nil, err
}
return &Comparer{rep: rep, out: out, tmpDir: tmp}, nil
return &Comparer{out: out, tmpDir: tmp}, nil
}