func tagFrom(store *storage.Storage, tx *storage.Tx, fromPath string, paths []string, explicit, recursive, force, followSymlinks bool) (error, warnings) { log.Infof(2, "loading settings") settings, err := store.Settings(tx) if err != nil { return fmt.Errorf("could not retrieve settings: %v", err), nil } stat, err := os.Lstat(fromPath) if err != nil { return err, nil } if stat.Mode()&os.ModeSymlink != 0 && followSymlinks { fromPath, err = _path.Dereference(fromPath) if err != nil { return err, nil } } file, err := store.FileByPath(tx, fromPath) if err != nil { return fmt.Errorf("%v: could not retrieve file: %v", fromPath, err), nil } if file == nil { return fmt.Errorf("%v: path is not tagged", fromPath), nil } fileTags, err := store.FileTagsByFileId(tx, file.Id, true) if err != nil { return fmt.Errorf("%v: could not retrieve filetags: %v", fromPath, err), nil } pairs := make([]entities.TagIdValueIdPair, len(fileTags)) for index, fileTag := range fileTags { pairs[index] = entities.TagIdValueIdPair{fileTag.TagId, fileTag.ValueId} } warnings := make(warnings, 0, 10) for _, path := range paths { if err := tagPath(store, tx, path, pairs, explicit, recursive, force, followSymlinks, settings.FileFingerprintAlgorithm(), settings.DirectoryFingerprintAlgorithm(), settings.SymlinkFingerprintAlgorithm(), settings.ReportDuplicates()); err != nil { switch { case os.IsPermission(err): warnings = append(warnings, fmt.Sprintf("%v: permisison denied", path)) case os.IsNotExist(err): warnings = append(warnings, fmt.Sprintf("%v: no such file", path)) default: return fmt.Errorf("%v: could not stat file: %v", path, err), warnings } } } return nil, warnings }
func listAllSettings(store *storage.Storage, tx *storage.Tx) error { settings, err := store.Settings(tx) if err != nil { return fmt.Errorf("could not retrieve settings: %v", err) } for _, setting := range settings { printSettingAndValue(setting.Name, setting.Value) } 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 tagPaths(store *storage.Storage, tx *storage.Tx, tagArgs, paths []string, explicit, recursive, force bool) (error, warnings) { log.Infof(2, "loading settings") settings, err := store.Settings(tx) if err != nil { return err, nil } pairs := make(entities.TagIdValueIdPairs, 0, len(tagArgs)) warnings := make(warnings, 0, 10) for _, tagArg := range tagArgs { tagName, valueName := parseTagEqValueName(tagArg) tag, err := store.TagByName(tx, tagName) if err != nil { return err, warnings } if tag == nil { if settings.AutoCreateTags() { tag, err = createTag(store, tx, tagName) if err != nil { return err, warnings } } else { warnings = append(warnings, fmt.Sprintf("no such tag '%v'", tagName)) continue } } value, err := store.ValueByName(tx, valueName) if err != nil { return err, warnings } if value == nil { if settings.AutoCreateValues() { value, err = createValue(store, tx, valueName) if err != nil { return err, warnings } } else { warnings = append(warnings, fmt.Sprintf("no such value '%v'", valueName)) continue } } pairs = append(pairs, entities.TagIdValueIdPair{tag.Id, value.Id}) } for _, path := range paths { if err := tagPath(store, tx, path, pairs, explicit, recursive, force, settings.FileFingerprintAlgorithm(), settings.DirectoryFingerprintAlgorithm(), settings.SymlinkFingerprintAlgorithm(), settings.ReportDuplicates()); err != nil { switch { case os.IsPermission(err): warnings = append(warnings, fmt.Sprintf("%v: permisison denied", path)) case os.IsNotExist(err): warnings = append(warnings, fmt.Sprintf("%v: no such file", path)) default: return fmt.Errorf("%v: could not stat file: %v", path, err), warnings } } } return nil, warnings }
func addImplications(store *storage.Storage, tx *storage.Tx, tagArgs []string) (error, warnings) { log.Infof(2, "loading settings") settings, err := store.Settings(tx) if err != nil { return err, nil } implyingTagArg := tagArgs[0] impliedTagArgs := tagArgs[1:] implyingTagName, implyingValueName := parseTagEqValueName(implyingTagArg) implyingTag, err := store.TagByName(tx, implyingTagName) if err != nil { return err, nil } if implyingTag == nil { if settings.AutoCreateTags() { implyingTag, err = createTag(store, tx, implyingTagName) if err != nil { return err, nil } } else { return NoSuchTagError{implyingTagName}, nil } } implyingValue, err := store.ValueByName(tx, implyingValueName) if err != nil { return err, nil } if implyingValue == nil { if settings.AutoCreateValues() { implyingValue, err = createValue(store, tx, implyingValueName) if err != nil { return err, nil } } else { return NoSuchValueError{implyingValueName}, nil } } warnings := make(warnings, 0, 10) for _, impliedTagArg := range impliedTagArgs { impliedTagName, impliedValueName := parseTagEqValueName(impliedTagArg) impliedTag, err := store.TagByName(tx, impliedTagName) if err != nil { return err, warnings } if impliedTag == nil { if settings.AutoCreateTags() { impliedTag, err = createTag(store, tx, impliedTagName) if err != nil { return err, warnings } } else { warnings = append(warnings, fmt.Sprintf("no such tag '%v'", impliedTagName)) continue } } impliedValue, err := store.ValueByName(tx, impliedValueName) if err != nil { return err, warnings } if impliedValue == nil { if settings.AutoCreateValues() { impliedValue, err = createValue(store, tx, impliedValueName) if err != nil { return err, warnings } } else { warnings = append(warnings, fmt.Sprintf("no such value '%v'", impliedValueName)) continue } } log.Infof(2, "adding tag implication of '%v' to '%v'", implyingTagArg, impliedTagArg) if err = store.AddImplication(tx, entities.TagIdValueIdPair{implyingTag.Id, implyingValue.Id}, entities.TagIdValueIdPair{impliedTag.Id, impliedValue.Id}); err != nil { return fmt.Errorf("cannot add implication of '%v' to '%v': %v", implyingTagArg, impliedTagArg, err), warnings } } return nil, warnings }
func fullRepair(store *storage.Storage, tx *storage.Tx, searchPaths []string, limitPath string, removeMissing, recalcUnmodified, rationalize, pretend bool) error { absLimitPath := "" if limitPath != "" { var err error absLimitPath, err = filepath.Abs(limitPath) if err != nil { return fmt.Errorf("%v: could not determine absolute path", err) } } settings, err := store.Settings(tx) if err != nil { return err } log.Infof(2, "retrieving files under '%v' from the database", absLimitPath) dbFiles, err := store.FilesByDirectory(tx, absLimitPath) if err != nil { return fmt.Errorf("could not retrieve files from storage: %v", err) } dbFile, err := store.FileByPath(tx, absLimitPath) if err != nil { return fmt.Errorf("could not retrieve file from storage: %v", err) } if dbFile != nil { dbFiles = append(dbFiles, dbFile) } log.Infof(2, "retrieved %v files from the database for path '%v'", len(dbFiles), absLimitPath) unmodfied, modified, missing := determineStatuses(dbFiles) if recalcUnmodified { if err = repairUnmodified(store, tx, unmodfied, pretend, settings); err != nil { return err } } if err = repairModified(store, tx, modified, pretend, settings); err != nil { return err } if err = repairMoved(store, tx, missing, searchPaths, pretend, settings); err != nil { return err } if err = repairMissing(store, tx, missing, pretend, removeMissing); err != nil { return err } if err = deleteUntaggedFiles(store, tx, dbFiles); err != nil { return err } if rationalize { if err = rationalizeFileTags(store, tx, dbFiles); err != nil { return err } } return nil }