-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsimple.go
67 lines (60 loc) · 1.79 KB
/
simple.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
package fsdiffer
import (
"os"
"path/filepath"
)
type SimpleFSDiffer struct {
sourceDir string
destDir string
}
type fileInfo struct {
Path string
os.FileInfo
}
func NewSimpleFSDiffer(sourceDir string, destDir string) *SimpleFSDiffer {
return &SimpleFSDiffer{sourceDir: sourceDir, destDir: destDir}
}
// Creates the FSChanges between sourceDir and destDir.
// To detect if a file was changed it checks the file's size and mtime (like
// rsync does by default if no --checksum options is used)
func (s *SimpleFSDiffer) Diff() (FSChanges, error) {
changes := FSChanges{}
sourceFileInfos := make(map[string]fileInfo)
destFileInfos := make(map[string]fileInfo)
err := filepath.Walk(s.sourceDir, fsWalker(sourceFileInfos))
if err != nil {
return nil, err
}
err = filepath.Walk(s.destDir, fsWalker(destFileInfos))
if err != nil {
return nil, err
}
for _, destInfo := range destFileInfos {
relpath, _ := filepath.Rel(s.destDir, destInfo.Path)
sourceInfo, ok := sourceFileInfos[filepath.Join(s.sourceDir, relpath)]
if !ok {
changes = append(changes, &FSChange{Path: relpath, ChangeType: Added})
} else {
if sourceInfo.Size() != destInfo.Size() || sourceInfo.ModTime().Before(destInfo.ModTime()) {
changes = append(changes, &FSChange{Path: relpath, ChangeType: Modified})
}
}
}
for _, infoA := range sourceFileInfos {
relpath, _ := filepath.Rel(s.sourceDir, infoA.Path)
_, ok := destFileInfos[filepath.Join(s.destDir, relpath)]
if !ok {
changes = append(changes, &FSChange{Path: relpath, ChangeType: Deleted})
}
}
return changes, nil
}
func fsWalker(fileInfos map[string]fileInfo) filepath.WalkFunc {
return func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
fileInfos[path] = fileInfo{Path: path, FileInfo: info}
return nil
}
}