-
Notifications
You must be signed in to change notification settings - Fork 0
/
manifest.go
119 lines (100 loc) · 2.06 KB
/
manifest.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package manifest
import (
"bytes"
"crypto/md5"
"encoding/hex"
"fmt"
"hash"
"io/ioutil"
"os"
"path/filepath"
"runtime"
"sort"
"strings"
"sync"
)
type ManifestEntry struct {
path string
checksum []byte
}
type Manifest []ManifestEntry
func (m Manifest) Len() int { return len(m) }
func (m Manifest) Swap(i, j int) { m[i], m[j] = m[j], m[i] }
type ByPath struct{ Manifest }
func (s ByPath) Less(i, j int) bool { return s.Manifest[i].path < s.Manifest[j].path }
func Compare (m, n Manifest) bool {
sort.Sort(ByPath{m})
sort.Sort(ByPath{n})
if m.String() == n.String() {
return true
}
return false
}
func (m Manifest) String() (s string) {
sort.Sort(ByPath{m})
buffer := bytes.NewBufferString("")
for _, entry := range m {
fmt.Fprintf(buffer, "%s\t%x\n", entry.path, entry.checksum)
}
return string(buffer.Bytes())
}
func listFiles(dir string) (files chan string) {
files = make(chan string, 65536)
go func() {
err := filepath.Walk("./data",
func(path string, f os.FileInfo, err error) error {
if f.IsDir() {
return nil
}
files <- filepath.Clean(path)
return nil
})
if err != nil {
panic(err)
}
close(files)
}()
return
}
func checksum(file string) ManifestEntry {
contents, _ := ioutil.ReadFile(file)
var h hash.Hash = md5.New()
var b []byte
h.Write([]byte(contents))
return ManifestEntry{file, h.Sum(b)}
}
func Load(s string) (m Manifest) {
lines := strings.Split(s, "\n")
for _, line := range lines {
fields := strings.Split(line, "\t")
if len(fields) > 1 {
checksum, _ := hex.DecodeString(fields[1])
path := fields[0]
me := ManifestEntry{path, checksum}
m = append(m, me)
}
}
return
}
func Create(dir string) (m Manifest) {
runtime.GOMAXPROCS(runtime.NumCPU())
files := listFiles(dir)
ch := make(chan ManifestEntry, 65536)
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for path := range files {
ch <- checksum(path)
}
}()
}
wg.Wait()
close(ch)
for me := range ch {
// grab off of a channel
m = append(m, me)
}
return
}