Esempio n. 1
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
}
Esempio n. 2
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
}
Esempio n. 3
0
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
}
Esempio n. 4
0
File: tag.go Progetto: logtcn/TMSU
func tagPath(store *storage.Storage, tx *storage.Tx, path string, pairs []entities.TagIdValueIdPair, explicit, recursive, force bool, fileFingerprintAlg, dirFingerprintAlg, symlinkFingerprintAlg string, reportDuplicates bool) error {
	absPath, err := filepath.Abs(path)
	if err != nil {
		return fmt.Errorf("%v: could not get absolute path: %v", path, err)
	}

	stat, err := os.Stat(path)
	if err != nil {
		switch {
		case os.IsNotExist(err), os.IsPermission(err):
			if !force {
				return err
			} else {
				stat = emptyStat{}
			}
		default:
			return err
		}
	}

	log.Infof(2, "%v: checking if file exists in database", path)

	file, err := store.FileByPath(tx, absPath)
	if err != nil {
		return fmt.Errorf("%v: could not retrieve file: %v", path, err)
	}
	if file == nil {
		log.Infof(2, "%v: creating fingerprint", path)

		fp, err := fingerprint.Create(path, fileFingerprintAlg, dirFingerprintAlg, symlinkFingerprintAlg)
		if err != nil {
			if !force || !(os.IsNotExist(err) || os.IsPermission(err)) {
				return fmt.Errorf("%v: could not create fingerprint: %v", path, err)
			}
		}

		if fp != fingerprint.Empty && reportDuplicates {
			log.Infof(2, "%v: checking for duplicates", path)

			count, err := store.FileCountByFingerprint(tx, fp)
			if err != nil {
				return fmt.Errorf("%v: could not identify duplicates: %v", path, err)
			}
			if count != 0 {
				log.Warnf("'%v' is a duplicate", path)
			}
		}

		log.Infof(2, "%v: adding file", path)

		file, err = store.AddFile(tx, path, fp, stat.ModTime(), int64(stat.Size()), stat.IsDir())
		if err != nil {
			return fmt.Errorf("%v: could not add file to database: %v", path, err)
		}
	}

	if !explicit {
		pairs, err = removeAlreadyAppliedTagValuePairs(store, tx, pairs, file)
		if err != nil {
			return fmt.Errorf("%v: could not remove applied tags: %v", path, err)
		}
	}

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

	for _, pair := range pairs {
		if _, err = store.AddFileTag(tx, file.Id, pair.TagId, pair.ValueId); err != nil {
			return fmt.Errorf("%v: could not apply tags: %v", file.Path(), err)
		}
	}

	if recursive && stat.IsDir() {
		if err = tagRecursively(store, tx, path, pairs, explicit, force, fileFingerprintAlg, dirFingerprintAlg, symlinkFingerprintAlg, reportDuplicates); err != nil {
			return err
		}
	}

	return nil
}