예제 #1
0
파일: main.go 프로젝트: quincy/photo_spool
// visit is called for each file found in a directory walk.  If the file is a
// directory then it is pruned if empty.  Otherwise the file is spooled.
func visit(filePath string, f os.FileInfo, err error) error {
	log.Println("Visiting", filePath)

	// If we visit a directory check to see if it's empty and prune if so.
	if f.IsDir() {
		return pruneDir(filePath)
	}

	matched, err := regexp.MatchString(spooler.ImagePattern, filePath)
	if err != nil {
		log.Fatalf("Error compiling regular expression '%s'.  %v", spooler.ImagePattern, err)
	}

	if !matched {
		log.Printf("Found unhandled file type [%s].  Moving the file to %s.\n", filePath, spool.ErrorPath)
		if noop {
			log.Println("DRY RUN Skipping move file.")
		} else {
			file.MoveTo(spool.ErrorPath, filePath)
		}
		return nil
	}

	spoolError := spool.Spool(filePath)
	if spoolError != nil {
		log.Println(spoolError)
	}

	return pruneDir(filepath.Dir(filePath))
}
예제 #2
0
// Spool copies the photo given by filename to the correct directory with the correct name.
func (sp *Spooler) Spool(filename string) error {
	if sp.closed {
		return fmt.Errorf("This Spooler is already closed.")
	}

	// calculate an md5 sum for the file
	hash := getHash(filename)

	// get the Time from the DateTimeOriginal exif tag
	dateTime, err := getDateTime(filename)
	if err != nil {
		log.Printf("Could not read the DateTimeOriginal tag. %v", err)
		log.Printf("Moving %s to %s.\n", filename, sp.ErrorPath)
		if sp.noop {
			log.Println("DRY RUN Skipping move file.")
		} else if mverr := file.MoveTo(sp.ErrorPath, filename); mverr != nil {
			log.Fatal(mverr)
		}
		return err
	}

	// check if the hash already exists in the db
	if sp.database.ContainsKey(hash) {
		msg := "A db entry already exists for " + filename + "."
		errorName := filepath.Join(sp.ErrorPath, strings.Join([]string{filepath.Base(filename), "DUPLICATE"}, "."))
		log.Printf("Mv(%s, %s)\n", errorName, filename)
		if sp.noop {
			log.Println("DRY RUN Skipping move file.")
		} else {
			err := file.Mv(errorName, filename)
			if err != nil {
				return err
			}
		}
		return errors.New(msg)
	}

	// calculate the path to copy the file to, including a new file name
	newPath := sp.getDestination(filename, sp.Destination, dateTime)

	// ensure the new path doesn't already exist
	for file.Exists(newPath) {
		dateTime = dateTime.Add(1 * time.Second)
		newPath = sp.getDestination(filename, sp.Destination, dateTime)
	}

	log.Printf("Mv(%s, %s)\n", newPath, filename)
	if file.Exists(newPath) {
		fields := strings.Split(filepath.Base(filename), ".")
		errorName := filepath.Join(sp.ErrorPath, strings.Join([]string{fields[0], filepath.Base(newPath)}, "::"))
		if sp.noop {
			log.Println("DRY RUN Skipping move file.")
		} else {
			err := file.Mv(errorName, filename)
			if err != nil {
				log.Println(err)
				return err
			}
		}
		msg := "A file with that named " + newPath + " already exists at the destination.  Moving to " + errorName
		log.Println(msg) // TODO This logging sucks.
		// TODO send an e-mail.
		return errors.New(msg)
	}

	// move the file to its new home
	if sp.noop {
		log.Println("DRY RUN Skipping move file.")
	} else if err := file.Mv(newPath, filename); err != nil {
		log.Println(err)
		return err
	}

	// add an entry to the hashmap db
	if err := sp.database.Insert(newPath, hash); err != nil {
		return err // TODO plain errors suck...
	}

	return nil
}