2014-09-12 20:04:20 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"flag"
|
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"runtime"
|
2014-09-12 20:10:10 +00:00
|
|
|
|
2016-07-18 15:23:33 +00:00
|
|
|
"github.com/vbatts/dedupe-linker/base"
|
|
|
|
"github.com/vbatts/dedupe-linker/cryptomap"
|
|
|
|
"github.com/vbatts/dedupe-linker/file"
|
2014-09-12 20:04:20 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2016-09-13 13:54:30 +00:00
|
|
|
varBaseDir = filepath.Join(os.Getenv("HOME"), ".dedupe-linker/")
|
2016-09-12 18:55:10 +00:00
|
|
|
|
|
|
|
flVarBase = flag.String("b", varBaseDir, "base directory where files are duplicated")
|
2016-09-13 14:55:19 +00:00
|
|
|
flCipher = flag.String("c", cryptomap.DefaultCipher, "block cipher to use (sha1, or sha256)")
|
2014-09-12 20:04:20 +00:00
|
|
|
flWorkers = flag.Int("w", 2, "workers to do summing")
|
2014-10-14 20:54:28 +00:00
|
|
|
flNoop = flag.Bool("noop", false, "don't do any moving or linking")
|
2016-09-08 18:13:53 +00:00
|
|
|
flDebug = flag.Bool("debug", false, "enable debug output")
|
2014-09-12 20:04:20 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
// give ourselves a little wiggle room
|
|
|
|
if runtime.NumCPU() > 1 && len(os.Getenv("GOMAXPROCS")) == 0 {
|
|
|
|
runtime.GOMAXPROCS(2)
|
|
|
|
}
|
2016-09-12 18:55:10 +00:00
|
|
|
|
|
|
|
if os.Getenv("VARBASEDIR") != "" {
|
|
|
|
varBaseDir = filepath.Clean(os.Getenv("VARBASEDIR"))
|
|
|
|
}
|
2023-04-11 18:14:54 +00:00
|
|
|
|
|
|
|
flag.Usage = func() {
|
|
|
|
fmt.Fprintf(flag.CommandLine.Output(), "Usage of %s:\n", os.Args[0])
|
|
|
|
fmt.Fprintf(flag.CommandLine.Output(), "\nThis app will make hardlinks of a directory tree, to a content addressible collection in the 'basedir'\n\n")
|
|
|
|
flag.PrintDefaults()
|
|
|
|
}
|
2014-09-12 20:04:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
flag.Parse()
|
2014-09-16 21:12:52 +00:00
|
|
|
|
2016-09-08 18:13:53 +00:00
|
|
|
if *flDebug {
|
|
|
|
os.Setenv("DEBUG", "1")
|
|
|
|
}
|
|
|
|
|
2016-09-12 18:55:10 +00:00
|
|
|
if os.Getenv("DEBUG") != "" {
|
|
|
|
fmt.Fprintf(os.Stderr, "VARBASEDIR=%q\n", *flVarBase)
|
|
|
|
}
|
|
|
|
|
2014-09-16 21:12:52 +00:00
|
|
|
// TODO the *flCipher has not been checked yet, and would cause the directory to get created
|
|
|
|
ourbase, err := base.NewBase(*flVarBase, *flCipher)
|
|
|
|
if err != nil {
|
2014-09-12 20:04:20 +00:00
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var (
|
2023-04-12 14:59:00 +00:00
|
|
|
ignoreSuffixes = []string{}
|
|
|
|
hash = cryptomap.DetermineHash(*flCipher)
|
2016-09-13 15:08:37 +00:00
|
|
|
//infos = []*file.HashInfo{}
|
|
|
|
//results := make(chan file.HashInfo, 2)
|
2014-09-12 20:04:20 +00:00
|
|
|
)
|
|
|
|
|
2023-04-12 14:59:00 +00:00
|
|
|
bpath, err := filepath.Abs(*flVarBase)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
for _, arg := range flag.Args() {
|
|
|
|
apath, err := filepath.Abs(arg)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
rel, err := filepath.Rel(apath, bpath)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
ignoreSuffixes = append(ignoreSuffixes, rel)
|
|
|
|
}
|
|
|
|
if os.Getenv("DEBUG") != "" {
|
|
|
|
fmt.Printf("[DEBUG] ignoreSuffixes: %#v\n", ignoreSuffixes)
|
|
|
|
}
|
|
|
|
|
2014-09-12 20:04:20 +00:00
|
|
|
for _, arg := range flag.Args() {
|
2014-10-15 03:28:37 +00:00
|
|
|
if !*flNoop {
|
|
|
|
if m, err := file.SameDevPaths(*flVarBase, arg); err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
} else if !m {
|
|
|
|
log.Printf("SKIPPING: %q is not on the same device as %q", arg, *flVarBase)
|
|
|
|
continue
|
|
|
|
}
|
2014-09-12 20:04:20 +00:00
|
|
|
}
|
|
|
|
done := make(chan struct{})
|
2023-04-12 14:59:00 +00:00
|
|
|
infos := file.HashFileGetter(arg, hash, ignoreSuffixes, *flWorkers, done)
|
2014-09-12 20:04:20 +00:00
|
|
|
for fi := range infos {
|
|
|
|
if fi.Err != nil {
|
|
|
|
log.Println(fi.Err)
|
2014-10-14 21:07:13 +00:00
|
|
|
//done <- struct{}{}
|
2014-09-12 20:04:20 +00:00
|
|
|
}
|
2014-10-14 20:54:28 +00:00
|
|
|
if *flNoop {
|
|
|
|
fmt.Printf("%s [%d] %s\n", fi.Hash, fi.Size, fi.Path)
|
2014-09-12 20:10:10 +00:00
|
|
|
} else {
|
2016-09-08 18:13:53 +00:00
|
|
|
if os.Getenv("DEBUG") != "" {
|
2023-04-11 18:31:28 +00:00
|
|
|
fmt.Printf("[%s] exists? %t (%q)\n", fi.Hash, ourbase.HasBlob(fi.Hash), fi.Path)
|
2016-09-08 18:13:53 +00:00
|
|
|
}
|
2014-10-14 20:54:28 +00:00
|
|
|
if ourbase.HasBlob(fi.Hash) && !ourbase.SameFile(fi.Hash, fi.Path) {
|
|
|
|
if err := ourbase.LinkTo(fi.Path, fi.Hash); err != nil {
|
|
|
|
log.Println("ERROR-1", err)
|
|
|
|
}
|
2016-09-08 18:13:53 +00:00
|
|
|
} else if !ourbase.HasBlob(fi.Hash) {
|
2014-10-14 20:54:28 +00:00
|
|
|
if err := ourbase.LinkFrom(fi.Path, fi.Hash); err != nil {
|
|
|
|
log.Println("ERROR-2", err)
|
|
|
|
}
|
|
|
|
}
|
2014-09-12 20:10:10 +00:00
|
|
|
}
|
2014-09-12 20:04:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
//if len(infos) > 0 {
|
|
|
|
//fmt.Println("collected", len(infos), "sums")
|
|
|
|
//}
|
|
|
|
}
|