Пример #1
0
func showUsage(store *storage.Storage, tx *storage.Tx, colour bool) error {
	tagUsages, err := store.TagUsage(tx)
	if err != nil {
		return fmt.Errorf("could not retrieve tag usage: %v", err)
	}

	maxLength := 0
	maxCountWidth := 0

	for _, tagUsage := range tagUsages {
		countWidth := int(math.Log(float64(tagUsage.FileCount)))
		if countWidth > maxCountWidth {
			maxCountWidth = countWidth
		}
		if len(tagUsage.Name) > maxLength {
			maxLength = len(tagUsage.Name)
		}
	}

	fmt.Println()
	for _, tagUsage := range tagUsages {
		fileCount := strconv.FormatUint(uint64(tagUsage.FileCount), 10)
		if colour {
			fileCount = ansi.Yellow(fileCount)
		}

		fmt.Printf("  %*s %*v\n", -maxLength, tagUsage.Name, maxCountWidth, fileCount)
	}

	return nil
}
Пример #2
0
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
}
Пример #3
0
func repairModified(store *storage.Storage, tx *storage.Tx, modified entities.Files, pretend bool, settings entities.Settings) error {
	log.Infof(2, "repairing modified files")

	for _, dbFile := range modified {
		stat, err := os.Stat(dbFile.Path())
		if err != nil {
			return err
		}

		fingerprint, err := fingerprint.Create(dbFile.Path(), settings.FileFingerprintAlgorithm(), settings.DirectoryFingerprintAlgorithm(), settings.SymlinkFingerprintAlgorithm())
		if err != nil {
			log.Warnf("%v: could not create fingerprint: %v", dbFile.Path(), err)
			continue
		}

		if !pretend {
			_, err := store.UpdateFile(tx, dbFile.Id, dbFile.Path(), fingerprint, stat.ModTime(), stat.Size(), stat.IsDir())
			if err != nil {
				return fmt.Errorf("%v: could not update file in database: %v", dbFile.Path(), err)
			}
		}

		fmt.Printf("%v: updated fingerprint\n", dbFile.Path())
	}

	return nil
}
Пример #4
0
func statusDatabase(store *storage.Storage, tx *storage.Tx, dirOnly, followSymlinks bool) (*StatusReport, error) {
	report := NewReport()

	log.Info(2, "retrieving all files from database.")

	files, err := store.Files(tx, "name")
	if err != nil {
		return nil, fmt.Errorf("could not retrieve files: %v", err)
	}

	err = statusCheckFiles(files, report)
	if err != nil {
		return nil, err
	}

	tree := _path.NewTree()
	for _, file := range files {
		tree.Add(file.Path(), file.IsDir)
	}

	topLevelPaths := tree.TopLevel().Paths()
	if err != nil {
		return nil, err
	}

	for _, path := range topLevelPaths {
		if err = findNewFiles(path, report, dirOnly, followSymlinks); err != nil {
			return nil, err
		}
	}

	return report, nil
}
Пример #5
0
func listAllTags(store *storage.Storage, tx *storage.Tx, showCount, onePerLine bool) error {
	log.Info(2, "retrieving all tags.")

	if showCount {
		count, err := store.TagCount(tx)
		if err != nil {
			return fmt.Errorf("could not retrieve tag count: %v", err)
		}

		fmt.Println(count)
	} else {
		tags, err := store.Tags(tx)
		if err != nil {
			return fmt.Errorf("could not retrieve tags: %v", err)
		}

		if onePerLine {
			for _, tag := range tags {
				fmt.Println(escape(tag.Name, '=', ' '))
			}
		} else {
			tagNames := make([]string, len(tags))
			for index, tag := range tags {
				tagNames[index] = escape(tag.Name, '=', ' ')
			}

			terminal.PrintColumns(tagNames)
		}
	}

	return nil
}
Пример #6
0
func manualRepairFile(store *storage.Storage, tx *storage.Tx, file *entities.File, toPath string) error {
	var fingerprint fingerprint.Fingerprint
	var modTime time.Time
	var size int64
	var isDir bool

	stat, err := os.Stat(toPath)
	if err != nil {
		switch {
		case os.IsPermission(err):
			return fmt.Errorf("%v: permission denied", toPath)
		case os.IsNotExist(err):
			return fmt.Errorf("%v: file not found", toPath)
		default:
			return err
		}

		modTime = file.ModTime
		size = file.Size
		isDir = file.IsDir
	} else {
		modTime = stat.ModTime()
		size = stat.Size()
		isDir = stat.IsDir()
	}

	_, err = store.UpdateFile(tx, file.Id, toPath, fingerprint, modTime, size, isDir)

	return err
}
Пример #7
0
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
}
Пример #8
0
func listAllValues(store *storage.Storage, tx *storage.Tx, showCount, onePerLine bool) error {
	log.Info(2, "retrieving all values.")

	if showCount {
		count, err := store.ValueCount(tx)
		if err != nil {
			return fmt.Errorf("could not retrieve value count: %v", err)
		}

		fmt.Println(count)
	} else {
		values, err := store.Values(tx)
		if err != nil {
			return fmt.Errorf("could not retrieve values: %v", err)
		}

		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
}
Пример #9
0
func listImplications(store *storage.Storage, tx *storage.Tx, colour bool) error {
	log.Infof(2, "retrieving tag implications.")

	implications, err := store.Implications(tx)
	if err != nil {
		return fmt.Errorf("could not retrieve implications: %v", err)
	}

	width := 0
	for _, implication := range implications {
		length := len(implication.ImplyingTag.Name)
		if implication.ImplyingValue.Id != 0 {
			length += 1 + len(implication.ImplyingValue.Name)
		}

		if length > width {
			width = length
		}
	}

	if len(implications) > 0 {
		for _, implication := range implications {
			implying := formatTagValueName(implication.ImplyingTag.Name, implication.ImplyingValue.Name, colour, false, true)
			implied := formatTagValueName(implication.ImpliedTag.Name, implication.ImpliedValue.Name, colour, true, false)

			fmt.Printf("%*v -> %v\n", width, implying, implied)
		}
	}

	return nil
}
Пример #10
0
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
}
Пример #11
0
func repairMoved(store *storage.Storage, tx *storage.Tx, missing entities.Files, searchPaths []string, pretend bool, settings entities.Settings) error {
	log.Infof(2, "repairing moved files")

	if len(missing) == 0 || len(searchPaths) == 0 {
		// don't bother enumerating filesystem if nothing to do
		return nil
	}

	pathsBySize, err := buildPathBySizeMap(searchPaths)
	if err != nil {
		return err
	}

	for index, dbFile := range missing {
		log.Infof(2, "%v: searching for new location", dbFile.Path())

		pathsOfSize := pathsBySize[dbFile.Size]
		log.Infof(2, "%v: file is of size %v, identified %v files of this size", dbFile.Path(), dbFile.Size, len(pathsOfSize))

		for _, candidatePath := range pathsOfSize {
			candidateFile, err := store.FileByPath(tx, candidatePath)
			if err != nil {
				return err
			}
			if candidateFile != nil {
				// file is already tagged
				continue
			}

			stat, err := os.Stat(candidatePath)
			if err != nil {
				return fmt.Errorf("%v: could not stat file: %v", candidatePath, err)
			}

			fingerprint, err := fingerprint.Create(candidatePath, settings.FileFingerprintAlgorithm(), settings.DirectoryFingerprintAlgorithm(), settings.SymlinkFingerprintAlgorithm())
			if err != nil {
				return fmt.Errorf("%v: could not create fingerprint: %v", candidatePath, err)
			}

			if fingerprint == dbFile.Fingerprint {
				if !pretend {
					_, err := store.UpdateFile(tx, 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", dbFile.Path(), err)
					}
				}

				fmt.Printf("%v: updated path to %v\n", dbFile.Path(), candidatePath)

				missing[index] = nil

				break
			}
		}
	}

	return nil
}
Пример #12
0
func deleteUntaggedFiles(store *storage.Storage, tx *storage.Tx, files entities.Files) error {
	log.Infof(2, "purging untagged files")

	fileIds := make([]entities.FileId, len(files))
	for index, file := range files {
		fileIds[index] = file.Id
	}

	return store.DeleteUntaggedFiles(tx, fileIds)
}
Пример #13
0
func createTag(store *storage.Storage, tx *storage.Tx, tagName string) (*entities.Tag, error) {
	tag, err := store.AddTag(tx, tagName)
	if err != nil {
		return nil, err
	}

	log.Warnf("new tag '%v'", tagName)

	return tag, nil
}
Пример #14
0
func createValue(store *storage.Storage, tx *storage.Tx, valueName string) (*entities.Value, error) {
	value, err := store.AddValue(tx, valueName)
	if err != nil {
		return nil, err
	}

	log.Warnf("new value '%v'", valueName)

	return value, nil
}
Пример #15
0
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
}
Пример #16
0
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
}
Пример #17
0
func mergeValues(store *storage.Storage, tx *storage.Tx, sourceValueNames []string, destValueName string) (error, warnings) {
	destValue, err := store.ValueByName(tx, destValueName)
	if err != nil {
		return fmt.Errorf("could not retrieve value '%v': %v", destValueName, err), nil
	}
	if destValue == nil {
		return fmt.Errorf("no such value '%v'", destValueName), nil
	}

	warnings := make(warnings, 0, 10)

	for _, sourceValueName := range sourceValueNames {
		if sourceValueName == destValueName {
			warnings = append(warnings, fmt.Sprintf("cannot merge value '%v' into itself", sourceValueName))
			continue
		}

		sourceValue, err := store.ValueByName(tx, sourceValueName)
		if err != nil {
			return fmt.Errorf("could not retrieve value '%v': %v", sourceValueName, err), warnings
		}
		if sourceValue == nil {
			warnings = append(warnings, fmt.Sprintf("no such value '%v'", sourceValueName))
			continue
		}

		log.Infof(2, "finding files tagged with value '%v'.", sourceValueName)

		fileTags, err := store.FileTagsByValueId(tx, sourceValue.Id)
		if err != nil {
			return fmt.Errorf("could not retrieve files for value '%v': %v", sourceValueName, err), warnings
		}

		log.Infof(2, "applying value '%v' to these files.", destValueName)

		for _, fileTag := range fileTags {
			if _, err = store.AddFileTag(tx, fileTag.FileId, fileTag.TagId, destValue.Id); err != nil {
				return fmt.Errorf("could not apply value '%v' to file #%v: %v", destValueName, fileTag.FileId, err), warnings
			}
		}

		log.Infof(2, "deleting value '%v'.", sourceValueName)

		if err = store.DeleteValue(tx, sourceValue.Id); err != nil {
			return fmt.Errorf("could not delete value '%v': %v", sourceValueName, err), warnings
		}
	}

	return nil, warnings
}
Пример #18
0
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
}
Пример #19
0
func untagPathsAll(store *storage.Storage, tx *storage.Tx, paths []string, recursive, followSymlinks bool) (error, warnings) {
	warnings := make(warnings, 0, 10)

	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
		}

		log.Infof(2, "%v: removing all tags.", path)

		if err := store.DeleteFileTagsByFileId(tx, file.Id); err != nil {
			return fmt.Errorf("%v: could not remove file's tags: %v", path, err), warnings
		}

		if recursive {
			childFiles, err := store.FilesByDirectory(tx, file.Path())
			if err != nil {
				return fmt.Errorf("%v: could not retrieve files for directory: %v", path, err), warnings
			}

			for _, childFile := range childFiles {
				if err := store.DeleteFileTagsByFileId(tx, childFile.Id); err != nil {
					return fmt.Errorf("%v: could not remove file's tags: %v", childFile.Path(), err), warnings
				}
			}
		}
	}

	return nil, warnings
}
Пример #20
0
func printSetting(store *storage.Storage, tx *storage.Tx, name string) error {
	if name == "" {
		return fmt.Errorf("setting name must be specified")
	}

	setting, err := store.Setting(tx, name)
	if err != nil {
		return fmt.Errorf("could not retrieve setting '%v'", err)
	}
	if setting == nil {
		return fmt.Errorf("no such setting '%v'", name)
	}

	printSettingAndValue(setting.Name, setting.Value)

	return nil
}
Пример #21
0
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
}
Пример #22
0
func statusPaths(store *storage.Storage, tx *storage.Tx, paths []string, dirOnly bool) (*StatusReport, error) {
	report := NewReport()

	for _, path := range paths {
		absPath, err := filepath.Abs(path)
		if err != nil {
			return nil, fmt.Errorf("%v: could not get absolute path: %v", path, err)
		}

		file, err := store.FileByPath(tx, absPath)
		if err != nil {
			return nil, fmt.Errorf("%v: could not retrieve file: %v", path, err)
		}
		if file != nil {
			err = statusCheckFile(file, report)
			if err != nil {
				return nil, err
			}
		}

		if !dirOnly {
			log.Infof(2, "%v: retrieving files from database.", path)

			files, err := store.FilesByDirectory(tx, absPath)
			if err != nil {
				return nil, fmt.Errorf("%v: could not retrieve files for directory: %v", path, err)
			}

			err = statusCheckFiles(files, report)
			if err != nil {
				return nil, err
			}
		}

		err = findNewFiles(absPath, report, dirOnly)
		if err != nil {
			return nil, err
		}
	}

	return report, nil
}
Пример #23
0
func repairMissing(store *storage.Storage, tx *storage.Tx, missing entities.Files, pretend, force bool) error {
	for _, dbFile := range missing {
		if dbFile == nil {
			continue
		}

		if force {
			if !pretend {
				if err := store.DeleteFileTagsByFileId(tx, dbFile.Id); err != nil {
					return fmt.Errorf("%v: could not delete file-tags: %v", dbFile.Path(), err)
				}
			}

			fmt.Printf("%v: removed\n", dbFile.Path())
		} else {
			fmt.Printf("%v: missing\n", dbFile.Path())
		}
	}

	return nil
}
Пример #24
0
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
}
Пример #25
0
func renameValue(store *storage.Storage, tx *storage.Tx, currentName, newName string) error {
	sourceValue, err := store.ValueByName(tx, currentName)
	if err != nil {
		return fmt.Errorf("could not retrieve value '%v': %v", currentName, err)
	}
	if sourceValue == nil {
		return fmt.Errorf("no such value '%v'", currentName)
	}

	destValue, err := store.ValueByName(tx, newName)
	if err != nil {
		return fmt.Errorf("could not retrieve value '%v': %v", newName, err)
	}
	if destValue != nil {
		return fmt.Errorf("value '%v' already exists", newName)
	}

	log.Infof(2, "renaming value '%v' to '%v'.", currentName, newName)

	_, err = store.RenameValue(tx, sourceValue.Id, newName)
	if err != nil {
		return fmt.Errorf("could not rename value '%v' to '%v': %v", currentName, newName, err)
	}

	return nil
}
Пример #26
0
func amendSetting(store *storage.Storage, tx *storage.Tx, name, value string) error {
	if name == "" {
		return fmt.Errorf("setting name must be specified")
	}
	if value == "" {
		return fmt.Errorf("setting '%v' value must be specified", name)
	}

	setting, err := store.Setting(tx, name)
	if err != nil {
		return fmt.Errorf("could not retrieve setting '%v'", err)
	}
	if setting == nil {
		return fmt.Errorf("no such setting '%v'", name)
	}

	if _, err = store.UpdateSetting(tx, name, value); err != nil {
		return fmt.Errorf("could not update setting '%v': %v", name, err)
	}

	return nil
}
Пример #27
0
func rationalizeFileTags(store *storage.Storage, tx *storage.Tx, files entities.Files) error {
	log.Infof(2, "rationalizing file tags")

	for _, file := range files {
		fileTags, err := store.FileTagsByFileId(tx, file.Id, false)
		if err != nil {
			return fmt.Errorf("could not determine tags for file '%v': %v", file.Path(), err)
		}

		for _, fileTag := range fileTags {
			if fileTag.Implicit && fileTag.Explicit {
				log.Infof(2, "%v: removing explicit tagging %v as implicit tagging exists", file.Path(), fileTag.TagId)

				if err := store.DeleteFileTag(tx, fileTag.FileId, fileTag.TagId, fileTag.ValueId); err != nil {
					return fmt.Errorf("could not delete file tag for file %v, tag %v and value %v", fileTag.FileId, fileTag.TagId, fileTag.ValueId)
				}
			}
		}
	}

	return nil
}
Пример #28
0
func deleteValue(store *storage.Storage, tx *storage.Tx, valueArgs []string) (error, warnings) {
	warnings := make(warnings, 0, 10)

	for _, valueArg := range valueArgs {
		valueName := parseTagOrValueName(valueArg)

		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
		}

		if err = store.DeleteValue(tx, value.Id); err != nil {
			return fmt.Errorf("could not delete value '%v': %v", valueName, err), warnings
		}
	}

	return nil, warnings
}
Пример #29
0
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
}
Пример #30
0
func findUntaggedFunc(store *storage.Storage, tx *storage.Tx, paths []string, recursive, followSymlinks bool, action func(absPath string)) 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)
		}

		if followSymlinks {
			log.Infof(2, "%v: resolving path", path)

			absPath, err = _path.Dereference(absPath)
			if err != nil {
				return fmt.Errorf("%v: could not dereference 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 {
			action(absPath)
		}

		if recursive {
			entries, err := directoryEntries(path)
			if err != nil {
				return err
			}

			findUntaggedFunc(store, tx, entries, true, followSymlinks, action)
		}
	}

	return nil
}