diff --git a/fs/operations/dedupe.go b/fs/operations/dedupe.go index 7dfc9afc4..2851c219e 100644 --- a/fs/operations/dedupe.go +++ b/fs/operations/dedupe.go @@ -211,12 +211,18 @@ func dedupeFindDuplicateDirs(ctx context.Context, f fs.Fs) ([][]fs.Directory, er if err != nil { return nil, errors.Wrap(err, "find duplicate dirs") } - duplicateDirs := [][]fs.Directory{} - for _, ds := range dirs { + // make sure parents are before children + duplicateNames := []string{} + for name, ds := range dirs { if len(ds) > 1 { - duplicateDirs = append(duplicateDirs, ds) + duplicateNames = append(duplicateNames, name) } } + sort.Strings(duplicateNames) + duplicateDirs := [][]fs.Directory{} + for _, name := range duplicateNames { + duplicateDirs = append(duplicateDirs, dirs[name]) + } return duplicateDirs, nil } @@ -235,7 +241,8 @@ func dedupeMergeDuplicateDirs(ctx context.Context, f fs.Fs, duplicateDirs [][]fs fs.Infof(dirs[0], "Merging contents of duplicate directories") err := mergeDirs(ctx, dirs) if err != nil { - return errors.Wrap(err, "merge duplicate dirs") + err = fs.CountError(err) + fs.Errorf(nil, "merge duplicate dirs: %v", err) } } else { fs.Infof(dirs[0], "NOT Merging contents of duplicate directories as --dry-run") @@ -251,23 +258,16 @@ func dedupeMergeDuplicateDirs(ctx context.Context, f fs.Fs, duplicateDirs [][]fs func Deduplicate(ctx context.Context, f fs.Fs, mode DeduplicateMode) error { fs.Infof(f, "Looking for duplicates using %v mode.", mode) - // Find duplicate directories first and fix them - repeat - // until all fixed - for { - duplicateDirs, err := dedupeFindDuplicateDirs(ctx, f) - if err != nil { - return err - } - if len(duplicateDirs) == 0 { - break - } + // Find duplicate directories first and fix them + duplicateDirs, err := dedupeFindDuplicateDirs(ctx, f) + if err != nil { + return err + } + if len(duplicateDirs) != 0 { err = dedupeMergeDuplicateDirs(ctx, f, duplicateDirs) if err != nil { return err } - if fs.Config.DryRun { - break - } } // find a hash to use @@ -275,7 +275,7 @@ func Deduplicate(ctx context.Context, f fs.Fs, mode DeduplicateMode) error { // Now find duplicate files files := map[string][]fs.Object{} - err := walk.ListR(ctx, f, "", true, fs.Config.MaxDepth, walk.ListObjects, func(entries fs.DirEntries) error { + err = walk.ListR(ctx, f, "", true, fs.Config.MaxDepth, walk.ListObjects, func(entries fs.DirEntries) error { entries.ForObject(func(o fs.Object) { remote := o.Remote() files[remote] = append(files[remote], o)