func renameTag(store *storage.Storage, tx *storage.Tx, currentName, newName string) error { sourceTag, err := store.TagByName(tx, currentName) if err != nil { return fmt.Errorf("could not retrieve tag '%v': %v", currentName, err) } if sourceTag == nil { return fmt.Errorf("no such tag '%v'", currentName) } destTag, err := store.TagByName(tx, newName) if err != nil { return fmt.Errorf("could not retrieve tag '%v': %v", newName, err) } if destTag != nil { return fmt.Errorf("tag '%v' already exists", newName) } log.Infof(2, "renaming tag '%v' to '%v'.", currentName, newName) _, err = store.RenameTag(tx, sourceTag.Id, newName) if err != nil { return fmt.Errorf("could not rename tag '%v' to '%v': %v", currentName, newName, err) } return nil }
func listValuesForTag(store *storage.Storage, tx *storage.Tx, tagName string, showCount, onePerLine bool) error { tag, err := store.TagByName(tx, tagName) if err != nil { return fmt.Errorf("could not retrieve tag '%v': %v", tagName, err) } if tag == nil { return fmt.Errorf("no such tag, '%v'", tagName) } log.Infof(2, "retrieving values for tag '%v'.", tagName) values, err := store.ValuesByTag(tx, tag.Id) if err != nil { return fmt.Errorf("could not retrieve values for tag '%v': %v", tagName, err) } if showCount { fmt.Println(len(values)) } else { if onePerLine { for _, value := range values { fmt.Println(escape(value.Name, '=', ' ')) } } else { valueNames := make([]string, len(values)) for index, value := range values { valueNames[index] = escape(value.Name, '=', ' ') } terminal.PrintColumns(valueNames) } } return nil }
func deleteImplications(store *storage.Storage, tx *storage.Tx, tagArgs []string) (error, warnings) { log.Infof(2, "loading settings") 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 { return NoSuchTagError{implyingTagName}, nil } implyingValue, err := store.ValueByName(tx, implyingValueName) if err != nil { return err, nil } if implyingValue == nil { return NoSuchValueError{implyingValueName}, nil } warnings := make(warnings, 0, 10) for _, impliedTagArg := range impliedTagArgs { log.Infof(2, "removing tag implication %v -> %v.", implyingTagArg, impliedTagArg) impliedTagName, impliedValueName := parseTagEqValueName(impliedTagArg) impliedTag, err := store.TagByName(tx, impliedTagName) if err != nil { return err, warnings } if impliedTag == nil { warnings = append(warnings, fmt.Sprintf("no such tag '%v'", impliedTagName)) } impliedValue, err := store.ValueByName(tx, impliedValueName) if err != nil { return err, warnings } if impliedValue == nil { warnings = append(warnings, fmt.Sprintf("no such value '%v'", impliedValueName)) } if err := store.DeleteImplication(tx, entities.TagIdValueIdPair{implyingTag.Id, implyingValue.Id}, entities.TagIdValueIdPair{impliedTag.Id, impliedValue.Id}); err != nil { return fmt.Errorf("could not delete tag implication of %v to %v: %v", implyingTagArg, impliedTagArg, err), warnings } } return nil, warnings }
func mergeTags(store *storage.Storage, tx *storage.Tx, sourceTagNames []string, destTagName string) (error, warnings) { destTag, err := store.TagByName(tx, destTagName) if err != nil { return fmt.Errorf("could not retrieve tag '%v': %v", destTagName, err), nil } if destTag == nil { return fmt.Errorf("no such tag '%v'", destTagName), nil } warnings := make(warnings, 0, 10) for _, sourceTagName := range sourceTagNames { if sourceTagName == destTagName { warnings = append(warnings, fmt.Sprintf("cannot merge tag '%v' into itself", sourceTagName)) continue } sourceTag, err := store.TagByName(tx, sourceTagName) if err != nil { return fmt.Errorf("could not retrieve tag '%v': %v", sourceTagName, err), warnings } if sourceTag == nil { warnings = append(warnings, fmt.Sprintf("no such tag '%v'", sourceTagName)) continue } log.Infof(2, "finding files tagged '%v'.", sourceTagName) fileTags, err := store.FileTagsByTagId(tx, sourceTag.Id, true) if err != nil { return fmt.Errorf("could not retrieve files for tag '%v': %v", sourceTagName, err), warnings } log.Infof(2, "applying tag '%v' to these files.", destTagName) for _, fileTag := range fileTags { if _, err = store.AddFileTag(tx, fileTag.FileId, destTag.Id, fileTag.ValueId); err != nil { return fmt.Errorf("could not apply tag '%v' to file #%v: %v", destTagName, fileTag.FileId, err), warnings } } log.Infof(2, "deleting tag '%v'.", sourceTagName) if err = store.DeleteTag(tx, sourceTag.Id); err != nil { return fmt.Errorf("could not delete tag '%v': %v", sourceTagName, err), warnings } } return nil, warnings }
func listValuesForTags(store *storage.Storage, tx *storage.Tx, tagNames []string, showCount, onePerLine bool) (error, warnings) { warnings := make(warnings, 0, 10) for _, tagName := range tagNames { tag, err := store.TagByName(tx, tagName) if err != nil { return fmt.Errorf("could not retrieve tag '%v': %v", tagName, err), warnings } if tag == nil { warnings = append(warnings, fmt.Sprintf("no such tag, '%v'.", tagName)) continue } log.Infof(2, "retrieving values for tag '%v'.", tagName) values, err := store.ValuesByTag(tx, tag.Id) if err != nil { return fmt.Errorf("could not retrieve values for tag '%v': %v", tagName, err), warnings } if showCount { fmt.Printf("%v: %v\n", tagName, len(values)) } else { if onePerLine { fmt.Println(tagName) for _, value := range values { fmt.Println(escape(value.Name, '=', ' ')) } fmt.Println() } else { valueNames := make([]string, len(values)) for index, value := range values { valueNames[index] = escape(value.Name, '=', ' ') } fmt.Printf("%v: %v\n", tagName, strings.Join(valueNames, " ")) } } } return nil, warnings }
func createTagsValues(store *storage.Storage, tx *storage.Tx, tagArgs []string) (error, warnings) { warnings := make(warnings, 0, 10) for _, tagArg := range tagArgs { name := parseTagOrValueName(tagArg) if name[0] == '=' { name = name[1:] value, err := store.ValueByName(tx, name) if err != nil { return fmt.Errorf("could not check if value '%v' exists: %v", name, err), warnings } if value == nil { if _, err := store.AddValue(tx, name); err != nil { return fmt.Errorf("could not create value '%v': %v", name, err), warnings } } else { warnings = append(warnings, fmt.Sprintf("value '%v' already exists", name)) } } else { tag, err := store.TagByName(tx, name) if err != nil { return fmt.Errorf("could not check if tag '%v' exists: %v", name, err), warnings } if tag == nil { if _, err := store.AddTag(tx, name); err != nil { return fmt.Errorf("could not create tag '%v': %v", name, err), warnings } } else { warnings = append(warnings, fmt.Sprintf("tag '%v' already exists", name)) } } } return nil, warnings }
func deleteTag(store *storage.Storage, tx *storage.Tx, tagArgs []string) (error, warnings) { warnings := make(warnings, 0, 10) for _, tagArg := range tagArgs { tagName := parseTagOrValueName(tagArg) tag, err := store.TagByName(tx, tagName) if err != nil { return fmt.Errorf("could not retrieve tag '%v': %v", tagName, err), warnings } if tag == nil { warnings = append(warnings, fmt.Sprintf("no such tag '%v'", tagName)) continue } err = store.DeleteTag(tx, tag.Id) if err != nil { return fmt.Errorf("could not delete tag '%v': %v", tagName, err), warnings } } 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 untagPaths(store *storage.Storage, tx *storage.Tx, paths, tagArgs []string, recursive, followSymlinks bool) (error, warnings) { warnings := make(warnings, 0, 10) files := make(entities.Files, 0, len(paths)) for _, path := range paths { absPath, err := filepath.Abs(path) if err != nil { return fmt.Errorf("%v: could not get absolute path: %v", path, err), warnings } log.Infof(2, "%v: resolving path", path) stat, err := os.Lstat(absPath) if err != nil { switch { case os.IsNotExist(err), os.IsPermission(err): // ignore default: return err, nil } } else if stat.Mode()&os.ModeSymlink != 0 && followSymlinks { absPath, err = _path.Dereference(absPath) if err != nil { return err, nil } } file, err := store.FileByPath(tx, absPath) if err != nil { return fmt.Errorf("%v: could not retrieve file: %v", path, err), warnings } if file == nil { warnings = append(warnings, fmt.Sprintf("%v: file is not tagged", path)) continue } files = append(files, file) if recursive { childFiles, err := store.FilesByDirectory(tx, file.Path()) if err != nil { return fmt.Errorf("%v: could not retrieve files for directory: %v", file.Path()), warnings } files = append(files, childFiles...) } } for _, tagArg := range tagArgs { tagName, valueName := parseTagEqValueName(tagArg) tag, err := store.TagByName(tx, tagName) if err != nil { return fmt.Errorf("could not retrieve tag '%v': %v", tagName, err), warnings } if tag == nil { warnings = append(warnings, fmt.Sprintf("no such tag '%v'", tagName)) continue } value, err := store.ValueByName(tx, valueName) if err != nil { return fmt.Errorf("could not retrieve value '%v': %v", valueName, err), warnings } if value == nil { warnings = append(warnings, fmt.Sprintf("no such value '%v'", valueName)) continue } for _, file := range files { if err := store.DeleteFileTag(tx, file.Id, tag.Id, value.Id); err != nil { switch err.(type) { case storage.FileTagDoesNotExist: exists, err := store.FileTagExists(tx, file.Id, tag.Id, value.Id, false) if err != nil { return fmt.Errorf("could not check if tag exists: %v", err), warnings } if exists { if value.Id != 0 { warnings = append(warnings, fmt.Sprintf("%v: cannot remove '%v=%v': delete implication to remove this tag.", file.Path(), tag.Name, value.Name)) } else { warnings = append(warnings, fmt.Sprintf("%v: cannot remove '%v': delete implication to remove this tag.", file.Path(), tag.Name)) } } else { if value.Id != 0 { warnings = append(warnings, fmt.Sprintf("%v: file is not tagged '%v=%v'.", file.Path(), tag.Name, value.Name)) } else { warnings = append(warnings, fmt.Sprintf("%v: file is not tagged '%v'.", file.Path(), tag.Name)) } } default: return fmt.Errorf("%v: could not remove tag '%v', value '%v': %v", file.Path(), tag.Name, value.Name, 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 }