func repairModified(store *storage.Storage, modified fileIdAndInfoMap, pretend bool, fingerprintAlgorithm string) error { log.Infof(2, "repairing modified files") for path, fileIdAndStat := range modified { fileId := fileIdAndStat.fileId stat := fileIdAndStat.stat log.Infof(1, "%v: modified", path) fingerprint, err := fingerprint.Create(path, fingerprintAlgorithm) if err != nil { return fmt.Errorf("%v: could not create fingerprint: %v", path, err) } if !pretend { _, err := store.UpdateFile(fileId, path, fingerprint, stat.ModTime(), stat.Size(), stat.IsDir()) if err != nil { return fmt.Errorf("%v: could not update file in database: %v", path, err) } } } return nil }
func addFile(store *storage.Storage, path string, modTime time.Time, size uint, isDir bool, fingerprintAlgorithm string) (*entities.File, error) { log.Infof(2, "%v: creating fingerprint", path) fingerprint, err := fingerprint.Create(path, fingerprintAlgorithm) if err != nil { return nil, fmt.Errorf("%v: could not create fingerprint: %v", path, err) } log.Infof(2, "%v: adding file.", path) file, err := store.AddFile(path, fingerprint, modTime, int64(size), isDir) if err != nil { return nil, fmt.Errorf("%v: could not add file to database: %v", path, err) } return file, nil }
func repairMoved(store *storage.Storage, missing databaseFileMap, untagged fileInfoMap, pretend bool, fingerprintAlgorithm string) error { log.Infof(2, "repairing moved files") moved := make([]string, 0, 10) for path, dbFile := range missing { log.Infof(2, "%v: searching for new location", path) for candidatePath, stat := range untagged { if stat.Size() == dbFile.Size { fingerprint, err := fingerprint.Create(candidatePath, fingerprintAlgorithm) if err != nil { return fmt.Errorf("%v: could not create fingerprint: %v", path, err) } if fingerprint == dbFile.Fingerprint { log.Infof(1, "%v: moved to %v", path, candidatePath) moved = append(moved, path) if !pretend { _, err := store.UpdateFile(dbFile.Id, candidatePath, dbFile.Fingerprint, stat.ModTime(), dbFile.Size, dbFile.IsDir) if err != nil { return fmt.Errorf("%v: could not update file in database: %v", path, err) } } delete(untagged, candidatePath) break } } } } for _, path := range moved { delete(missing, path) } return nil }
func findDuplicatesOf(paths []string, recursive bool) error { store, err := storage.Open() if err != nil { return fmt.Errorf("could not open storage: %v", err) } defer store.Close() fingerprintAlgorithmSetting, err := store.Setting("fingerprintAlgorithm") if err != nil { return fmt.Errorf("could not retrieve fingerprint algorithm: %v", err) } wereErrors := false for _, path := range paths { _, err := os.Stat(path) if err != nil { switch { case os.IsNotExist(err): log.Warnf("%v: no such file", path) wereErrors = true continue case os.IsPermission(err): log.Warnf("%v: permission denied", path) wereErrors = true continue default: return err } } } if wereErrors { return blankError } if recursive { p, err := _path.Enumerate(paths) if err != nil { return fmt.Errorf("could not enumerate paths: %v", err) } paths = make([]string, len(p)) for index, path := range p { paths[index] = path.Path } } first := true for _, path := range paths { log.Infof(2, "%v: identifying duplicate files.", path) fp, err := fingerprint.Create(path, fingerprintAlgorithmSetting.Value) if err != nil { return fmt.Errorf("%v: could not create fingerprint: %v", path, err) } if fp == fingerprint.Fingerprint("") { continue } files, err := store.FilesByFingerprint(fp) if err != nil { return fmt.Errorf("%v: could not retrieve files matching fingerprint '%v': %v", path, fp, err) } absPath, err := filepath.Abs(path) if err != nil { return fmt.Errorf("%v: could not determine absolute path: %v", path, err) } // filter out the file we're searching on dupes := files.Where(func(file *entities.File) bool { return file.Path() != absPath }) if len(paths) > 1 && len(dupes) > 0 { if first { first = false } else { fmt.Println() } fmt.Printf("%v:\n", path) for _, dupe := range dupes { relPath := _path.Rel(dupe.Path()) fmt.Printf(" %v\n", relPath) } } else { for _, dupe := range dupes { relPath := _path.Rel(dupe.Path()) fmt.Println(relPath) } } } return nil }