예제 #1
0
파일: repair.go 프로젝트: logtcn/TMSU
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
}
예제 #2
0
파일: dupes.go 프로젝트: peer23peer/TMSU
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
}
예제 #3
0
파일: status.go 프로젝트: logtcn/TMSU
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
}
예제 #4
0
파일: files.go 프로젝트: peer23peer/TMSU
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
}
예제 #5
0
파일: untagged.go 프로젝트: logtcn/TMSU
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
}
예제 #6
0
파일: untagged.go 프로젝트: peer23peer/TMSU
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)
}
예제 #7
0
파일: status.go 프로젝트: logtcn/TMSU
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
}
예제 #8
0
파일: dupes.go 프로젝트: peer23peer/TMSU
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
}
예제 #9
0
파일: status.go 프로젝트: peer23peer/TMSU
func printRow(row Row) {
	relPath := _path.Rel(row.Path)
	fmt.Printf("%v %v\n", string(row.Status), relPath)
}