func manualRepair(store *storage.Storage, tx *storage.Tx, fromPath, toPath string, pretend bool) error { absFromPath, err := filepath.Abs(fromPath) if err != nil { return fmt.Errorf("%v: could not determine absolute path", err) } absToPath, err := filepath.Abs(toPath) if err != nil { return fmt.Errorf("%v: could not determine absolute path", err) } log.Infof(2, "retrieving files under '%v' from the database", fromPath) dbFile, err := store.FileByPath(tx, absFromPath) if err != nil { return fmt.Errorf("%v: could not retrieve file: %v", fromPath, err) } if dbFile != nil { log.Infof(2, "%v: updating to %v", fromPath, toPath) if !pretend { if err := manualRepairFile(store, tx, dbFile, absToPath); err != nil { return err } } } dbFiles, err := store.FilesByDirectory(tx, absFromPath) if err != nil { return fmt.Errorf("could not retrieve files from storage: %v", err) } for _, dbFile = range dbFiles { relFileFromPath := _path.Rel(dbFile.Path()) absFileToPath := strings.Replace(dbFile.Path(), absFromPath, absToPath, 1) relFileToPath := _path.Rel(absFileToPath) log.Infof(2, "%v: updating to %v", relFileFromPath, relFileToPath) if !pretend { if err := manualRepairFile(store, tx, dbFile, absFileToPath); err != nil { return err } } } return nil }
func findDuplicatesInDb(store *storage.Storage, tx *storage.Tx) error { log.Info(2, "identifying duplicate files.") fileSets, err := store.DuplicateFiles(tx) if err != nil { return fmt.Errorf("could not identify duplicate files: %v", err) } log.Infof(2, "found %v sets of duplicate files.", len(fileSets)) for index, fileSet := range fileSets { if index > 0 { fmt.Println() } fmt.Printf("Set of %v duplicates:\n", len(fileSet)) for _, file := range fileSet { relPath := _path.Rel(file.Path()) fmt.Printf(" %v\n", relPath) } } return nil }
func statusCheckFile(file *entities.File, report *StatusReport) error { relPath := path.Rel(file.Path()) log.Infof(2, "%v: checking file status.", file.Path()) stat, err := os.Stat(file.Path()) if err != nil { switch { case os.IsNotExist(err): log.Infof(2, "%v: file is missing.", file.Path()) report.AddRow(Row{relPath, MISSING}) return nil case os.IsPermission(err): log.Warnf("%v: permission denied.", file.Path()) case strings.Contains(err.Error(), "not a directory"): report.AddRow(Row{relPath, MISSING}) return nil default: return fmt.Errorf("%v: could not stat: %v", file.Path(), err) } } else { if stat.Size() != file.Size || !stat.ModTime().UTC().Equal(file.ModTime) { log.Infof(2, "%v: file is modified.", file.Path()) report.AddRow(Row{relPath, MODIFIED}) } else { log.Infof(2, "%v: file is unchanged.", file.Path()) report.AddRow(Row{relPath, TAGGED}) } } return nil }
func listFiles(tx *storage.Tx, files entities.Files, dirOnly, fileOnly, print0, showCount bool) error { relPaths := make([]string, 0, len(files)) for _, file := range files { if fileOnly && file.IsDir { continue } if dirOnly && !file.IsDir { continue } absPath := file.Path() relPath := path.Rel(absPath) relPaths = append(relPaths, relPath) } if showCount { fmt.Println(len(relPaths)) } else { for _, relPath := range relPaths { if print0 { fmt.Printf("%v\000", relPath) } else { fmt.Println(relPath) } } } return nil }
func findUntagged(store *storage.Storage, tx *storage.Tx, paths []string, recursive bool) error { for _, path := range paths { absPath, err := filepath.Abs(path) if err != nil { return fmt.Errorf("%v: could not get absolute path: %v", path, err) } //TODO PERF no need to retrieve file: we merely need to know it exists file, err := store.FileByPath(tx, absPath) if err != nil { return fmt.Errorf("%v: could not retrieve file: %v", path, err) } if file == nil { relPath := _path.Rel(absPath) fmt.Println(relPath) } if recursive { entries, err := directoryEntries(path) if err != nil { return err } findUntagged(store, tx, entries, true) } } return nil }
func findUntagged(store *storage.Storage, tx *storage.Tx, paths []string, recursive, followSymlinks bool) error { var action = func(absPath string) { relPath := _path.Rel(absPath) fmt.Println(relPath) } return findUntaggedFunc(store, tx, paths, recursive, followSymlinks, action) }
func findNewFiles(searchPath string, report *StatusReport, dirOnly bool) error { log.Infof(2, "%v: finding new files.", searchPath) relPath := path.Rel(searchPath) if !report.ContainsRow(relPath) { report.AddRow(Row{relPath, UNTAGGED}) } absPath, err := filepath.Abs(searchPath) if err != nil { return fmt.Errorf("%v: could not get absolute path: %v", searchPath, err) } stat, err := os.Stat(absPath) if err != nil { switch { case os.IsNotExist(err): return nil case os.IsPermission(err): log.Warnf("%v: permission denied.", searchPath) return nil default: return fmt.Errorf("%v: could not stat: %v", searchPath, err) } } if !dirOnly && stat.IsDir() { dir, err := os.Open(absPath) if err != nil { return fmt.Errorf("%v: could not open file: %v", searchPath, err) } dirNames, err := dir.Readdirnames(0) if err != nil { return fmt.Errorf("%v: could not read directory listing: %v", searchPath, err) } sort.Strings(dirNames) for _, dirName := range dirNames { dirPath := filepath.Join(searchPath, dirName) err = findNewFiles(dirPath, report, dirOnly) if err != nil { return err } } } return nil }
func findDuplicatesOf(store *storage.Storage, tx *storage.Tx, paths []string, recursive bool) (error, warnings) { settings, err := store.Settings(tx) if err != nil { return err, nil } warnings := make(warnings, 0, 10) for _, path := range paths { _, err := os.Stat(path) if err != nil { switch { case os.IsNotExist(err): warnings = append(warnings, fmt.Sprintf("%v: no such file", path)) continue case os.IsPermission(err): warnings = append(warnings, fmt.Sprintf("%v: permission denied", path)) continue default: return err, warnings } } } if recursive { p, err := filesystem.Enumerate(paths...) if err != nil { return fmt.Errorf("could not enumerate paths: %v", err), warnings } 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, settings.FileFingerprintAlgorithm(), settings.DirectoryFingerprintAlgorithm(), settings.SymlinkFingerprintAlgorithm()) if err != nil { return fmt.Errorf("%v: could not create fingerprint: %v", path, err), warnings } if fp == fingerprint.Fingerprint("") { continue } files, err := store.FilesByFingerprint(tx, fp) if err != nil { return fmt.Errorf("%v: could not retrieve files matching fingerprint '%v': %v", path, fp, err), warnings } absPath, err := filepath.Abs(path) if err != nil { return fmt.Errorf("%v: could not determine absolute path: %v", path, err), warnings } // 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, warnings }
func printRow(row Row) { relPath := _path.Rel(row.Path) fmt.Printf("%v %v\n", string(row.Status), relPath) }