func main() { PROG_NAME := filepath.Base(os.Args[0]) var moveFiles bool flag.BoolVar(&moveFiles, "m", false, "move files to destination instead of copying") flag.Parse() if len(flag.Args()) < 2 { fmt.Printf("error: Invalid parameters\n") fmt.Printf("usage: %s [-m] dst src ...\n", PROG_NAME) os.Exit(ERR_INVALID_PARAMS) } // Initialize LevelDB var dbh *leveldb.DB if dbDir, err := ioutil.TempDir("", PROG_NAME); err != nil { fmt.Printf("error: Creation of tmp dir failed: %s\n", err) os.Exit(ERR_CREATE_TMP_DIR_FAILED) } else { defer cleanupDbDir(dbDir) dbh, err = leveldb.Open(dbDir, &db.Options{}) if err != nil { fmt.Printf("error: Temporary working DB initialization failed: %s", err) os.Exit(ERR_OPEN_DB_FAILED) } defer dbh.Close() } // Create channels hashingCh := make(chan *fileEntry) defer close(hashingCh) processingCh := make(chan *fileEntry) // Go for it go hashFiles(hashingCh, processingCh) go processFile(dbh, processingCh, moveFiles) for _, d := range flag.Args()[1:] { filepath.Walk(d, getPathProcessor(hashingCh, d, flag.Args()[0])) } }
func processFile(dbh *leveldb.DB, processingCh <-chan *fileEntry, move bool) { var fent *fileEntry more := true for more { select { case fent, more = <-processingCh: if more { if _, err := dbh.Get(fent.csum, nil); err == db.ErrNotFound { // file not processed yet if move { DEBUG("moving file %s to %s\n", fent.srcPath, fent.dstPath) if err = os.MkdirAll(filepath.Dir(fent.dstPath), (os.ModeDir | 0750)); err != nil { fmt.Printf("%s\n", err) continue } if err = os.Rename(fent.srcPath, fent.dstPath); err != nil { fmt.Printf("error: renaming file %s to %s failed. trying to copy instead.\n", fent.srcPath, fent.dstPath) if err = Copy(fent.srcPath, fent.dstPath); err != nil { fmt.Printf("error: Couldn't copy file %s to %s: %s\n", fent.srcPath, fent.dstPath, err) continue } } } else { DEBUG("copying file %s to %s\n", fent.srcPath, fent.dstPath) if err = Copy(fent.srcPath, fent.dstPath); err != nil { fmt.Printf("error: Couldn't copy file %s to %s: %s\n", fent.srcPath, fent.dstPath, err) continue } } dbh.Set(fent.csum, []byte(fent.srcPath), nil) } else if err == nil { DEBUG("skipping file %s since it already exists.\n", fent.srcPath) } else { fmt.Printf("error: Unable to check whether %s exists: %s. Skipping.\n", fent.srcPath, err) continue } } } } }