-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdirectory.go
170 lines (138 loc) · 3.13 KB
/
directory.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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
package directory
import (
"crypto/sha256"
"encoding/hex"
"errors"
"os"
)
type DirManager struct {
Path string
}
type FileHash struct {
Name string
Hash string
Size int64
}
// Init a new DirManager
func NewDirManager(path string) (*DirManager, error) {
_, err := os.Stat(path)
if err != nil {
return nil, err
}
d := &DirManager{
Path: path,
}
return d, nil
}
// Get file names in directory
func (d DirManager) GetFileNames() ([]string, error) {
if d.Path == "" {
return nil, errors.New("dir manager is uninitialized")
}
dirEntries, err := os.ReadDir(d.Path)
if err != nil {
return nil, err
}
var names []string
for _, entry := range dirEntries {
names = append(names, entry.Name())
}
return names, nil
}
// Get file hashes
func (d DirManager) GetFileHashes(fileNames []string) ([]FileHash, error) {
if len(fileNames) == 0 {
return d.getAllFileHashes()
}
var hashes []FileHash
for _, file := range fileNames {
entry, err := d.findFileEntry(file)
if err != nil {
return nil, err
}
hash, err := d.hashFile(entry)
if err != nil {
return nil, err
}
hashes = append(hashes, hash)
}
return hashes, nil
}
// Get hashes of all files in directory
func (d DirManager) getAllFileHashes() ([]FileHash, error) {
var hashes []FileHash
var err error
dirEntries, err := os.ReadDir(d.Path)
if err != nil {
return nil, err
}
for _, entry := range dirEntries {
if !entry.IsDir() {
hash, err := d.hashFile(entry)
if err != nil {
return []FileHash{}, err
}
hashes = append(hashes, hash)
}
}
return hashes, err
}
// Return the SHA256 hash of file
func (d DirManager) hashFile(entry os.DirEntry) (FileHash, error) {
// Get file as DirEntry
// entry, err := d.findFileEntry(fileName)
// if err != nil {
// return FileHash{}, err
// }
// Open + read file
file, err := os.Open(d.Path + "/" + entry.Name())
if err != nil {
return FileHash{}, err
}
fileData := make([]byte, 0)
file.Read(fileData)
// Hash raw file data
hash := sha256.Sum256(fileData)
encodedHash := hex.EncodeToString(hash[:])
result := FileHash{
Name: entry.Name(),
Hash: encodedHash,
}
return result, nil
}
// Find file entry in DirManager path with matching name
func (d DirManager) findFileEntry(fileName string) (os.DirEntry, error) {
if d.Path == "" {
return nil, errors.New("dir manager is uninitialized")
}
dirEntries, err := os.ReadDir(d.Path)
if err != nil {
return nil, err
}
// Return true if file name match is found in cwd
for _, currEntry := range dirEntries {
if !currEntry.IsDir() && (currEntry.Name() == fileName) {
return currEntry, nil
}
}
return nil, errors.New("file not found")
}
// Return unique values in hashesA but not in hashesB
func GetUniqueHashes(hashesA []FileHash, hashesB []FileHash) *[]FileHash {
sharedHashes := new([]FileHash)
for _, hash := range hashesA {
if !containsHash(hashesB, hash) {
*sharedHashes = append(*sharedHashes, hash)
}
}
return sharedHashes
}
// Check if a hash is found in a slice of hashes
func containsHash(hashes []FileHash, hash FileHash) bool {
for _, h := range hashes {
if h == hash {
return true
}
}
return false
}