From aa4b5f4c393881ca229edb5add004e675a1e8fdc Mon Sep 17 00:00:00 2001 From: Vincent Batts Date: Tue, 13 Sep 2016 09:52:12 -0400 Subject: [PATCH 01/11] findbase: walk up tree to find a suitable base dir Signed-off-by: Vincent Batts --- base/findbase.go | 67 ++++++++++++++++++++++++++++++++++++++ base/findbase_test.go | 75 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 base/findbase.go create mode 100644 base/findbase_test.go diff --git a/base/findbase.go b/base/findbase.go new file mode 100644 index 0000000..d8bf3fe --- /dev/null +++ b/base/findbase.go @@ -0,0 +1,67 @@ +package base + +import ( + "io/ioutil" + "os" + "path/filepath" + "syscall" +) + +// FindBase steps up the directory tree to find the top-level that is still on +// the same device as the path provided +func FindBase(path string) (string, error) { + stat, err := os.Lstat(path) + if err != nil { + return "", err + } + if stat.IsDir() { + return findBaseInfo(stat) + } + + return FindBase(filepath.Dir(path)) +} + +func findBaseInfo(stat os.FileInfo) (string, error) { + dirstat, err := os.Lstat(filepath.Dir(stat.Name())) + if err != nil { + return "", err + } + if stat.Name() == dirstat.Name() { + return stat.Name(), nil + } + + if sameDevice(stat, dirstat) { + return findBaseInfo(dirstat) + } + return stat.Name(), nil +} + +func hasPermission(path string) bool { + stat, err := os.Lstat(path) + if err != nil { + return false + } + if !stat.IsDir() { + path = filepath.Dir(path) + } + fh, err := ioutil.TempFile(path, "perm.test.") + if err != nil { + return false + } + os.Remove(fh.Name()) + return true +} + +func sameDevice(file1, file2 os.FileInfo) bool { + sys1 := file1.Sys().(*syscall.Stat_t) + sys2 := file2.Sys().(*syscall.Stat_t) + return ((major(sys1.Dev) == major(sys2.Dev)) && (minor(sys1.Dev) == minor(sys2.Dev))) +} + +func major(n uint64) uint64 { + return uint64(n / 256) +} + +func minor(n uint64) uint64 { + return uint64(n % 256) +} diff --git a/base/findbase_test.go b/base/findbase_test.go new file mode 100644 index 0000000..9d25d57 --- /dev/null +++ b/base/findbase_test.go @@ -0,0 +1,75 @@ +package base + +import ( + "io/ioutil" + "os" + "testing" +) + +func TestHasPermission(t *testing.T) { + if !hasPermission("/tmp") { + t.Error("expected to have permission to /tmp, but did not") + } + + if hasPermission("/") { + t.Error("expected to not have permission to /, but did") + } +} + +func TestSameDev(t *testing.T) { + file1, err := ioutil.TempFile("", "test") + if err != nil { + t.Fatal(err) + } + defer file1.Close() + file2, err := ioutil.TempFile("", "test") + if err != nil { + t.Fatal(err) + } + defer file2.Close() + + stat1, err := file1.Stat() + if err != nil { + t.Fatal(err) + } + stat2, err := file2.Stat() + if err != nil { + t.Fatal(err) + } + + if !sameDevice(stat1, stat2) { + t.Errorf("expected the two files to be on same device. But %q and %q are not", file1.Name(), file2.Name()) + } else { + os.Remove(stat1.Name()) + os.Remove(stat2.Name()) + } +} + +func TestNotSameDev(t *testing.T) { + file1, err := ioutil.TempFile("/tmp", "test") + if err != nil { + t.Fatal(err) + } + defer file1.Close() + file2, err := ioutil.TempFile("/home/vbatts", "test") + if err != nil { + t.Fatal(err) + } + defer file2.Close() + + stat1, err := file1.Stat() + if err != nil { + t.Fatal(err) + } + stat2, err := file2.Stat() + if err != nil { + t.Fatal(err) + } + + if sameDevice(stat1, stat2) { + t.Errorf("expected the two files _not_ to be on same device. But %q and %q are not", file1.Name(), file2.Name()) + } else { + os.Remove(stat1.Name()) + os.Remove(stat2.Name()) + } +} From c67d7baba39716881d25f468b33cf9f0fd45b6b1 Mon Sep 17 00:00:00 2001 From: Vincent Batts Date: Tue, 13 Sep 2016 09:53:47 -0400 Subject: [PATCH 02/11] base: fix test, minimize base root path Signed-off-by: Vincent Batts --- base/base.go | 5 ++--- base/base_test.go | 16 ++++++++++++---- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/base/base.go b/base/base.go index 3675653..88d92c3 100644 --- a/base/base.go +++ b/base/base.go @@ -15,13 +15,12 @@ import ( ) func NewBase(path string, hashName string) (*Base, error) { - root := filepath.Join(path, "dedup") for _, p := range []string{"blobs/" + hashName, "state", "tmp"} { - if err := os.MkdirAll(filepath.Join(root, p), 0755); err != nil && !os.IsExist(err) { + if err := os.MkdirAll(filepath.Join(path, p), 0755); err != nil && !os.IsExist(err) { return nil, err } } - return &Base{Path: root, HashName: hashName, Hash: cryptomap.DetermineHash(hashName)}, nil + return &Base{Path: path, HashName: hashName, Hash: cryptomap.DetermineHash(hashName)}, nil } type Base struct { diff --git a/base/base_test.go b/base/base_test.go index 41ec2d6..92cad39 100644 --- a/base/base_test.go +++ b/base/base_test.go @@ -2,7 +2,6 @@ package base import ( "bytes" - "fmt" "io/ioutil" "os" "path" @@ -50,7 +49,7 @@ func TestGetPut(t *testing.T) { t.Fatal(err) } - rHash := "deadbeaf" + rHash := "8f074e76e82ae6156c451019840a6f857bbe5157" rMsg := "this is the dead beef" r := bytes.NewReader([]byte(rMsg)) @@ -58,12 +57,18 @@ func TestGetPut(t *testing.T) { if err != nil { t.Error(err) } + if sum != rHash { + t.Errorf("expected %q; got %q", rHash, sum) + } fi, err := b.Stat(rHash) if err != nil { t.Error(err) } - fmt.Printf("%#v\n", fi.Sys()) + if fi == nil { + t.Fatal("did not find the blob " + rHash) + } + //fmt.Printf("%#v\n", fi.Sys()) if err = b.LinkTo(path.Join(srcDir, "beef1.txt"), rHash); err != nil { t.Error(err) @@ -72,7 +77,10 @@ func TestGetPut(t *testing.T) { if err != nil { t.Error(err) } - fmt.Printf("%#v\n", fi2.Sys()) + if fi2 == nil { + t.Fatal("did not find the linked file " + path.Join(srcDir, "beef1.txt")) + } + //fmt.Printf("%#v\n", fi2.Sys()) if err = b.LinkTo(path.Join(srcDir, "beef1.txt"), rHash); err != nil && !os.IsExist(err) { t.Error(err) From 7e2999aa4e3e18cd7aa817d967d4efbef4ff651a Mon Sep 17 00:00:00 2001 From: Vincent Batts Date: Tue, 13 Sep 2016 09:54:30 -0400 Subject: [PATCH 03/11] main: minimize root path Signed-off-by: Vincent Batts --- main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.go b/main.go index 2a7cbae..33217c1 100644 --- a/main.go +++ b/main.go @@ -14,7 +14,7 @@ import ( ) var ( - varBaseDir = filepath.Join(os.Getenv("HOME"), ".local/dedupe-linker/var") + varBaseDir = filepath.Join(os.Getenv("HOME"), ".dedupe-linker/") flVarBase = flag.String("b", varBaseDir, "base directory where files are duplicated") flCipher = flag.String("c", "sha1", "block cipher to use (sha1, or sha256)") From 267c9615032c478c978b69496da9a2d95b7792e8 Mon Sep 17 00:00:00 2001 From: Vincent Batts Date: Tue, 13 Sep 2016 10:27:38 -0400 Subject: [PATCH 04/11] base: golint Signed-off-by: Vincent Batts --- base/base.go | 18 +++++++++++++----- base/findbase.go | 12 +++--------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/base/base.go b/base/base.go index 88d92c3..3841e68 100644 --- a/base/base.go +++ b/base/base.go @@ -14,6 +14,7 @@ import ( "github.com/vbatts/dedupe-linker/file" ) +// NewBase populates the directories needed in a dedupe-base directory func NewBase(path string, hashName string) (*Base, error) { for _, p := range []string{"blobs/" + hashName, "state", "tmp"} { if err := os.MkdirAll(filepath.Join(path, p), 0755); err != nil && !os.IsExist(err) { @@ -23,12 +24,14 @@ func NewBase(path string, hashName string) (*Base, error) { return &Base{Path: path, HashName: hashName, Hash: cryptomap.DetermineHash(hashName)}, nil } +// Base is the destination for all hardlinks. Where stored objects are in a content addressible tree. type Base struct { Path string HashName string Hash crypto.Hash } +// Stat provides the os.FileInfo for the object of `sum` address func (b Base) Stat(sum string) (os.FileInfo, error) { return os.Stat(b.blobPath(sum)) } @@ -40,12 +43,15 @@ func (b Base) blobPath(sum string) string { return filepath.Join(b.Path, "blobs", b.HashName, sum[0:2], sum) } -type ReaderSeekerCloser interface { +// ReadSeekCloser is like an io.ReadCloser, but can Seek too +type ReadSeekCloser interface { io.Reader io.Seeker io.Closer } +// SameFile checks whether the object of `sum` address, and `path` file path are the same file. +// This checks by inode and device. func (b Base) SameFile(sum, path string) bool { var ( bInode, dInode uint64 @@ -65,7 +71,7 @@ func (b Base) SameFile(sum, path string) bool { } // GetBlob store the content from src, for the sum and hashType -func (b Base) GetBlob(sum string) (ReaderSeekerCloser, error) { +func (b Base) GetBlob(sum string) (ReadSeekCloser, error) { return os.Open(b.blobPath(sum)) } @@ -117,7 +123,8 @@ func (b Base) tmpFile() (*os.File, error) { return ioutil.TempFile(filepath.Join(b.Path, "tmp"), "put") } -// Hard link the file from src to the blob for sum +// LinkFrom make a hard link the file from src to the blob of address `sum`. +// TODO this function is going away, because it makes no assessment of the checksum of `src` func (b Base) LinkFrom(src, sum string) error { if err := os.MkdirAll(filepath.Dir(b.blobPath(sum)), 0756); err != nil && !os.IsExist(err) { return err @@ -134,7 +141,8 @@ func randomString() (string, error) { return fmt.Sprintf("%x", buf), nil } -// SafeLink overrides newname if it already exists. If there is an error in creating the link, the transaction is rolled back +// SafeLink overrides newname if it already exists. If there is an error in +// creating the link, the transaction is rolled back func SafeLink(oldname, newname string) error { var backupName string // check if newname exists @@ -168,7 +176,7 @@ func SafeLink(oldname, newname string) error { return nil } -// Hard link the file for sum to the path at dest +// LinkTo makes a hard link the file of address `sum` to the path at `dest` func (b Base) LinkTo(dest, sum string) error { if err := os.MkdirAll(filepath.Dir(dest), 0755); err != nil && !os.IsExist(err) { return err diff --git a/base/findbase.go b/base/findbase.go index d8bf3fe..414318d 100644 --- a/base/findbase.go +++ b/base/findbase.go @@ -5,6 +5,8 @@ import ( "os" "path/filepath" "syscall" + + "github.com/vbatts/dedupe-linker/file" ) // FindBase steps up the directory tree to find the top-level that is still on @@ -55,13 +57,5 @@ func hasPermission(path string) bool { func sameDevice(file1, file2 os.FileInfo) bool { sys1 := file1.Sys().(*syscall.Stat_t) sys2 := file2.Sys().(*syscall.Stat_t) - return ((major(sys1.Dev) == major(sys2.Dev)) && (minor(sys1.Dev) == minor(sys2.Dev))) -} - -func major(n uint64) uint64 { - return uint64(n / 256) -} - -func minor(n uint64) uint64 { - return uint64(n % 256) + return ((file.MajorDev(sys1.Dev) == file.MajorDev(sys2.Dev)) && (file.MinorDev(sys1.Dev) == file.MinorDev(sys2.Dev))) } From 7ea5cd6bc4d7568e6257e6f8487d502bc0e823d8 Mon Sep 17 00:00:00 2001 From: Vincent Batts Date: Tue, 13 Sep 2016 10:40:39 -0400 Subject: [PATCH 05/11] cryptomap: golint Signed-off-by: Vincent Batts --- cryptomap/crypto.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cryptomap/crypto.go b/cryptomap/crypto.go index 21aa6d6..e12826d 100644 --- a/cryptomap/crypto.go +++ b/cryptomap/crypto.go @@ -2,19 +2,24 @@ package cryptomap import ( "crypto" + "log" + "strings" + + // Importing all the currently supported hashes _ "crypto/md5" _ "crypto/sha1" _ "crypto/sha256" _ "crypto/sha512" - "log" - "strings" ) var knownCiphers = map[string]crypto.Hash{ "md5": crypto.MD5, } +// DetermineHash takes a generic string, like "sha1" and returns the +// corresponding crypto.Hash func DetermineHash(str string) (h crypto.Hash) { + // TODO make these strings discoverable, like a public variable switch strings.ToLower(str) { case "md5": h = crypto.MD5 From 18ae791748217cbfd9a1a97b4d95dc40fafa59bb Mon Sep 17 00:00:00 2001 From: Vincent Batts Date: Tue, 13 Sep 2016 10:41:29 -0400 Subject: [PATCH 06/11] walker: golint since this package was not even implemented yet, then make it not public Signed-off-by: Vincent Batts --- walker/walker.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/walker/walker.go b/walker/walker.go index bd34869..4c3c9fb 100644 --- a/walker/walker.go +++ b/walker/walker.go @@ -1,14 +1,15 @@ +// Package walker is a work-in-progress package walker import ( "github.com/vbatts/dedupe-linker/base" ) -type Walker struct { +type walker struct { Base *base.Base } -func (w Walker) Walk(path string, quit chan int) error { +func (w walker) Walk(path string, quit chan int) error { // XXX what is going on here? select { case <-quit: From e9488b60ffa5fe6d484f05b9c646bc56c89066aa Mon Sep 17 00:00:00 2001 From: Vincent Batts Date: Tue, 13 Sep 2016 10:55:19 -0400 Subject: [PATCH 07/11] cryptomap: discoverable mapping and defaults Signed-off-by: Vincent Batts --- cryptomap/crypto.go | 38 +++++++++++++++++--------------------- main.go | 2 +- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/cryptomap/crypto.go b/cryptomap/crypto.go index e12826d..99c0c08 100644 --- a/cryptomap/crypto.go +++ b/cryptomap/crypto.go @@ -12,31 +12,27 @@ import ( _ "crypto/sha512" ) -var knownCiphers = map[string]crypto.Hash{ - "md5": crypto.MD5, +// DefaultCipher is the crypto cipher default used if none is specified or +// specified is unknown. +var DefaultCipher = "sha1" + +// Ciphers is the known set of mappings for string to crypto.Hash +// use an init() to add custom hash ciphers +var Ciphers = map[string]crypto.Hash{ + "md5": crypto.MD5, + "sha1": crypto.SHA1, + "sha224": crypto.SHA224, + "sha256": crypto.SHA256, + "sha384": crypto.SHA384, + "sha512": crypto.SHA512, } // DetermineHash takes a generic string, like "sha1" and returns the // corresponding crypto.Hash func DetermineHash(str string) (h crypto.Hash) { - // TODO make these strings discoverable, like a public variable - switch strings.ToLower(str) { - case "md5": - h = crypto.MD5 - case "sha1": - h = crypto.SHA1 - case "sha224": - h = crypto.SHA224 - case "sha256": - h = crypto.SHA256 - case "sha384": - h = crypto.SHA384 - case "sha512": - h = crypto.SHA512 - default: - log.Printf("WARNING: unknown cipher %q. using 'sha1'", str) - h = crypto.SHA1 + if h, ok := Ciphers[strings.ToLower(str)]; ok { + return h } - - return h + log.Printf("WARNING: unknown cipher %q. using %q", str, DefaultCipher) + return Ciphers[DefaultCipher] } diff --git a/main.go b/main.go index 33217c1..a645d4b 100644 --- a/main.go +++ b/main.go @@ -17,7 +17,7 @@ var ( varBaseDir = filepath.Join(os.Getenv("HOME"), ".dedupe-linker/") flVarBase = flag.String("b", varBaseDir, "base directory where files are duplicated") - flCipher = flag.String("c", "sha1", "block cipher to use (sha1, or sha256)") + flCipher = flag.String("c", cryptomap.DefaultCipher, "block cipher to use (sha1, or sha256)") flWorkers = flag.Int("w", 2, "workers to do summing") flNoop = flag.Bool("noop", false, "don't do any moving or linking") flDebug = flag.Bool("debug", false, "enable debug output") From 9a2f27d08449ba8d015c8b49cea3b8d64a0cd24c Mon Sep 17 00:00:00 2001 From: Vincent Batts Date: Tue, 13 Sep 2016 11:08:37 -0400 Subject: [PATCH 08/11] file: golint Signed-off-by: Vincent Batts --- file/dev.go | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++ file/hash.go | 89 ++++++------------------------------------------- main.go | 4 +-- 3 files changed, 107 insertions(+), 80 deletions(-) create mode 100644 file/dev.go diff --git a/file/dev.go b/file/dev.go new file mode 100644 index 0000000..49ee224 --- /dev/null +++ b/file/dev.go @@ -0,0 +1,94 @@ +package file + +import ( + "fmt" + "os" + "syscall" +) + +// SameInodePaths checks whether path1 and path2 are the same inode +func SameInodePaths(path1, path2 string) (match bool, err error) { + var inode1, inode2 uint64 + if inode1, err = GetInode(path1); err != nil { + return false, err + } + if inode2, err = GetInode(path2); err != nil { + return false, err + } + return inode1 == inode2, nil +} + +// SameDevPaths checks whether path1 and path2 are on the same device +func SameDevPaths(path1, path2 string) (match bool, err error) { + var dev1, dev2 uint64 + if dev1, err = GetDev(path1); err != nil { + return false, err + } + if dev2, err = GetDev(path2); err != nil { + return false, err + } + return dev1 == dev2, nil +} + +// FormatDev has a scary name, but just pretty prints the stat_t.dev as "major:minor" +func FormatDev(stat *syscall.Stat_t) string { + return fmt.Sprintf("%d:%d", MajorDev(stat.Dev), MinorDev(stat.Dev)) +} + +// MajorDev provides the major device number from a stat_t.dev +func MajorDev(dev uint64) uint64 { + return (((dev >> 8) & 0xfff) | ((dev >> 32) & ^uint64(0xfff))) +} + +// MinorDev provides the minor device number from a stat_t.dev +func MinorDev(dev uint64) uint64 { + return ((dev & 0xff) | ((dev >> 12) & ^uint64(0xff))) +} + +// GetLstat returns the system stat_t for the file at path. +// (symlinks are not deferenced) +func GetLstat(path string) (*syscall.Stat_t, error) { + fi, err := os.Lstat(path) + if err != nil { + return nil, err + } + return fi.Sys().(*syscall.Stat_t), nil +} + +// GetStat returns the system stat_t for the file at path. +// (symlinks are deferenced) +func GetStat(path string) (*syscall.Stat_t, error) { + fi, err := os.Stat(path) + if err != nil { + return nil, err + } + return fi.Sys().(*syscall.Stat_t), nil +} + +// GetInode returns the inode for path +func GetInode(path string) (uint64, error) { + stat, err := GetStat(path) + if err != nil { + return 0, err + } + return stat.Ino, nil +} + +// GetDev returns the device for path +func GetDev(path string) (uint64, error) { + stat, err := GetStat(path) + if err != nil { + return 0, err + } + return stat.Dev, nil +} + +// GetNlink returns the number of links for path. For directories, that is +// number of entries. For regular files, that is number of hardlinks. +func GetNlink(path string) (uint64, error) { + stat, err := GetStat(path) + if err != nil { + return 0, err + } + return stat.Nlink, nil +} diff --git a/file/hash.go b/file/hash.go index 11874c7..8c8e9fe 100644 --- a/file/hash.go +++ b/file/hash.go @@ -6,11 +6,13 @@ import ( "io" "os" "path/filepath" - "syscall" "time" ) -type FileHashInfo struct { +// HashInfo for tracking the information regarding a file, it's checksum +// and status. +// If Err is set then the caller must take an appropriate action. +type HashInfo struct { HashType crypto.Hash Hash string Path string @@ -19,8 +21,10 @@ type FileHashInfo struct { Err error } -func HashFileGetter(path string, hash crypto.Hash, workers int, done <-chan struct{}) <-chan FileHashInfo { - out := make(chan FileHashInfo, workers) +// HashFileGetter walks the provided `path` with `workers` number of threads. +// The channel of HashInfo are for each regular file encountered. +func HashFileGetter(path string, hash crypto.Hash, workers int, done <-chan struct{}) <-chan HashInfo { + out := make(chan HashInfo, workers) go func() { err := filepath.Walk(path, func(path string, info os.FileInfo, err error) error { if err != nil { @@ -39,15 +43,15 @@ func HashFileGetter(path string, hash crypto.Hash, workers int, done <-chan stru } }) if err != nil { - out <- FileHashInfo{Err: err} + out <- HashInfo{Err: err} } close(out) }() return out } -func hashFile(path string, hash crypto.Hash, info os.FileInfo) *FileHashInfo { - fhi := FileHashInfo{HashType: hash, Path: path, ModTime: info.ModTime(), Size: info.Size()} +func hashFile(path string, hash crypto.Hash, info os.FileInfo) *HashInfo { + fhi := HashInfo{HashType: hash, Path: path, ModTime: info.ModTime(), Size: info.Size()} h := hash.New() fh, err := os.Open(path) if err != nil { @@ -63,74 +67,3 @@ func hashFile(path string, hash crypto.Hash, info os.FileInfo) *FileHashInfo { fhi.Hash = fmt.Sprintf("%x", h.Sum(nil)) return &fhi } - -// SameInodePaths checks whether path1 and path2 are the same inode -func SameInodePaths(path1, path2 string) (match bool, err error) { - var inode1, inode2 uint64 - if inode1, err = GetInode(path1); err != nil { - return false, err - } - if inode2, err = GetInode(path2); err != nil { - return false, err - } - return inode1 == inode2, nil -} - -// SameInodePaths checks whether path1 and path2 are on the same device -func SameDevPaths(path1, path2 string) (match bool, err error) { - var dev1, dev2 uint64 - if dev1, err = GetDev(path1); err != nil { - return false, err - } - if dev2, err = GetDev(path2); err != nil { - return false, err - } - return dev1 == dev2, nil -} - -func FormatDev(stat *syscall.Stat_t) string { - return fmt.Sprintf("%d:%d", MajorDev(stat.Dev), MinorDev(stat.Dev)) -} - -func MajorDev(dev uint64) uint64 { - return (((dev >> 8) & 0xfff) | ((dev >> 32) & ^uint64(0xfff))) -} - -func MinorDev(dev uint64) uint64 { - return ((dev & 0xff) | ((dev >> 12) & ^uint64(0xff))) -} - -func GetStat(path string) (*syscall.Stat_t, error) { - fi, err := os.Stat(path) - if err != nil { - return nil, err - } - return fi.Sys().(*syscall.Stat_t), nil -} - -// GetInode returns the inode for path -func GetInode(path string) (uint64, error) { - stat, err := GetStat(path) - if err != nil { - return 0, err - } - return stat.Ino, nil -} - -// GetDev returns the device for path -func GetDev(path string) (uint64, error) { - stat, err := GetStat(path) - if err != nil { - return 0, err - } - return stat.Dev, nil -} - -// GetNlink returns the number of links for path -func GetNlink(path string) (uint64, error) { - stat, err := GetStat(path) - if err != nil { - return 0, err - } - return stat.Nlink, nil -} diff --git a/main.go b/main.go index a645d4b..05c3928 100644 --- a/main.go +++ b/main.go @@ -53,8 +53,8 @@ func main() { var ( hash = cryptomap.DetermineHash(*flCipher) - //infos = []*file.FileHashInfo{} - //results := make(chan file.FileHashInfo, 2) + //infos = []*file.HashInfo{} + //results := make(chan file.HashInfo, 2) ) for _, arg := range flag.Args() { From 6a4df87d105fe3dd50416c712e3304018c1222fc Mon Sep 17 00:00:00 2001 From: Vincent Batts Date: Tue, 13 Sep 2016 11:12:42 -0400 Subject: [PATCH 09/11] main: go vet Signed-off-by: Vincent Batts --- main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.go b/main.go index 05c3928..6faf978 100644 --- a/main.go +++ b/main.go @@ -77,7 +77,7 @@ func main() { fmt.Printf("%s [%d] %s\n", fi.Hash, fi.Size, fi.Path) } else { if os.Getenv("DEBUG") != "" { - fmt.Printf("%q: %q\n", fi.Path, ourbase.HasBlob(fi.Hash)) + fmt.Printf("%q: %t\n", fi.Path, ourbase.HasBlob(fi.Hash)) } if ourbase.HasBlob(fi.Hash) && !ourbase.SameFile(fi.Hash, fi.Path) { if err := ourbase.LinkTo(fi.Path, fi.Hash); err != nil { From ebef1270a37271d3ad240fcc3cb8dc2451a1ba42 Mon Sep 17 00:00:00 2001 From: Vincent Batts Date: Tue, 13 Sep 2016 11:19:44 -0400 Subject: [PATCH 10/11] base: env variable, not hard code Signed-off-by: Vincent Batts --- base/findbase_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/findbase_test.go b/base/findbase_test.go index 9d25d57..07744eb 100644 --- a/base/findbase_test.go +++ b/base/findbase_test.go @@ -51,7 +51,7 @@ func TestNotSameDev(t *testing.T) { t.Fatal(err) } defer file1.Close() - file2, err := ioutil.TempFile("/home/vbatts", "test") + file2, err := ioutil.TempFile(os.Getenv("HOME"), "test") if err != nil { t.Fatal(err) } From 8b6015a474f001d9fbc80808e3d2a014f76dc85b Mon Sep 17 00:00:00 2001 From: Vincent Batts Date: Tue, 13 Sep 2016 11:40:00 -0400 Subject: [PATCH 11/11] base: ignore test for now Signed-off-by: Vincent Batts --- base/findbase_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/base/findbase_test.go b/base/findbase_test.go index 07744eb..ddc9c03 100644 --- a/base/findbase_test.go +++ b/base/findbase_test.go @@ -45,7 +45,8 @@ func TestSameDev(t *testing.T) { } } -func TestNotSameDev(t *testing.T) { +// perhaps this is naive. Travis' /tmp is on the same device and not sure how to request it be tmpfs w/o needing sudo +func testNotSameDev(t *testing.T) { file1, err := ioutil.TempFile("/tmp", "test") if err != nil { t.Fatal(err)