11package fs
22
33import (
4- "fmt"
5- "path/filepath "
6- "os "
7- "strings"
4+ "fmt"
5+ "os "
6+ "path/filepath "
7+ "strings"
88)
99
1010type ChangeType int
1111
1212const (
13- ChangeModify = iota
14- ChangeAdd
15- ChangeDelete
13+ ChangeModify = iota
14+ ChangeAdd
15+ ChangeDelete
1616)
1717
1818type Change struct {
19- Path string
20- Kind ChangeType
19+ Path string
20+ Kind ChangeType
2121}
2222
2323func (change * Change ) String () string {
24- var kind string
25- switch change .Kind {
26- case ChangeModify :
27- kind = "C"
28- case ChangeAdd :
29- kind = "A"
30- case ChangeDelete :
31- kind = "D"
32- }
33- return fmt .Sprintf ("%s %s" , kind , change .Path )
24+ var kind string
25+ switch change .Kind {
26+ case ChangeModify :
27+ kind = "C"
28+ case ChangeAdd :
29+ kind = "A"
30+ case ChangeDelete :
31+ kind = "D"
32+ }
33+ return fmt .Sprintf ("%s %s" , kind , change .Path )
3434}
3535
3636func (store * Store ) Changes (mp * Mountpoint ) ([]Change , error ) {
37- var changes []Change
38- image , err := store .Get (mp .Image )
39- if err != nil {
40- return nil , err
41- }
42- layers , err := image .layers ()
43- if err != nil {
44- return nil , err
45- }
46-
47- err = filepath .Walk (mp .Rw , func (path string , f os.FileInfo , err error ) error {
48- if err != nil {
49- return err
50- }
51-
52- // Rebase path
53- path , err = filepath .Rel (mp .Rw , path )
54- if err != nil {
55- return err
56- }
57- path = filepath .Join ("/" , path )
58-
59- // Skip root
60- if path == "/" {
61- return nil
62- }
63-
64- // Skip AUFS metadata
65- if matched , err := filepath .Match ("/.wh..wh.*" , path ); err != nil || matched {
66- return err
67- }
68-
69- change := Change {
70- Path : path ,
71- }
72-
73- // Find out what kind of modification happened
74- file := filepath .Base (path )
75- // If there is a whiteout, then the file was removed
76- if strings .HasPrefix (file , ".wh." ) {
77- originalFile := strings .TrimLeft (file , ".wh." )
78- change .Path = filepath .Join (filepath .Dir (path ), originalFile )
79- change .Kind = ChangeDelete
80- } else {
81- // Otherwise, the file was added
82- change .Kind = ChangeAdd
83-
84- // ...Unless it already existed in a top layer, in which case, it's a modification
85- for _ , layer := range layers {
86- stat , err := os .Stat (filepath .Join (layer , path ))
87- if err != nil && ! os .IsNotExist (err ) {
88- return err
89- }
90- if err == nil {
91- // The file existed in the top layer, so that's a modification
92-
93- // However, if it's a directory, maybe it wasn't actually modified.
94- // If you modify /foo/bar/baz, then /foo will be part of the changed files only because it's the parent of bar
95- if stat .IsDir () && f .IsDir () {
96- if f .Size () == stat .Size () && f .Mode () == stat .Mode () && f .ModTime () == stat .ModTime () {
97- // Both directories are the same, don't record the change
98- return nil
99- }
100- }
101- change .Kind = ChangeModify
102- break
103- }
104- }
105- }
106-
107- // Record change
108- changes = append (changes , change )
109- return nil
110- })
111- if err != nil {
112- return nil , err
113- }
114- return changes , nil
37+ var changes []Change
38+ image , err := store .Get (mp .Image )
39+ if err != nil {
40+ return nil , err
41+ }
42+ layers , err := image .layers ()
43+ if err != nil {
44+ return nil , err
45+ }
46+
47+ err = filepath .Walk (mp .Rw , func (path string , f os.FileInfo , err error ) error {
48+ if err != nil {
49+ return err
50+ }
51+
52+ // Rebase path
53+ path , err = filepath .Rel (mp .Rw , path )
54+ if err != nil {
55+ return err
56+ }
57+ path = filepath .Join ("/" , path )
58+
59+ // Skip root
60+ if path == "/" {
61+ return nil
62+ }
63+
64+ // Skip AUFS metadata
65+ if matched , err := filepath .Match ("/.wh..wh.*" , path ); err != nil || matched {
66+ return err
67+ }
68+
69+ change := Change {
70+ Path : path ,
71+ }
72+
73+ // Find out what kind of modification happened
74+ file := filepath .Base (path )
75+ // If there is a whiteout, then the file was removed
76+ if strings .HasPrefix (file , ".wh." ) {
77+ originalFile := strings .TrimLeft (file , ".wh." )
78+ change .Path = filepath .Join (filepath .Dir (path ), originalFile )
79+ change .Kind = ChangeDelete
80+ } else {
81+ // Otherwise, the file was added
82+ change .Kind = ChangeAdd
83+
84+ // ...Unless it already existed in a top layer, in which case, it's a modification
85+ for _ , layer := range layers {
86+ stat , err := os .Stat (filepath .Join (layer , path ))
87+ if err != nil && ! os .IsNotExist (err ) {
88+ return err
89+ }
90+ if err == nil {
91+ // The file existed in the top layer, so that's a modification
92+
93+ // However, if it's a directory, maybe it wasn't actually modified.
94+ // If you modify /foo/bar/baz, then /foo will be part of the changed files only because it's the parent of bar
95+ if stat .IsDir () && f .IsDir () {
96+ if f .Size () == stat .Size () && f .Mode () == stat .Mode () && f .ModTime () == stat .ModTime () {
97+ // Both directories are the same, don't record the change
98+ return nil
99+ }
100+ }
101+ change .Kind = ChangeModify
102+ break
103+ }
104+ }
105+ }
106+
107+ // Record change
108+ changes = append (changes , change )
109+ return nil
110+ })
111+ if err != nil {
112+ return nil , err
113+ }
114+ return changes , nil
115115}
116116
117117// Reset removes all changes to the filesystem, reverting it to its initial state.
118118func (mp * Mountpoint ) Reset () error {
119- if err := os .RemoveAll (mp .Rw ); err != nil {
120- return err
121- }
122- // We removed the RW directory itself along with its content: let's re-create an empty one.
123- if err := mp .createFolders (); err != nil {
124- return err
125- }
126- return nil
119+ if err := os .RemoveAll (mp .Rw ); err != nil {
120+ return err
121+ }
122+ // We removed the RW directory itself along with its content: let's re-create an empty one.
123+ if err := mp .createFolders (); err != nil {
124+ return err
125+ }
126+ return nil
127127}
128128
129129// Open opens the named file for reading.
@@ -141,4 +141,4 @@ func (mp *Mountpoint) Reset() error {
141141// return nil, err
142142// }
143143// return ioutil.ReadDir(filepath.Join(fs.RootFS, dirname))
144- // }
144+ // }
0 commit comments