@@ -54,8 +54,16 @@ type imageFSFile interface {
54
54
}
55
55
56
56
func New (parent vfs.FS , root string , image v1.Image , filesToCache []string ) (vfs.FS , error ) {
57
- var ifs * imageFS
57
+ if image == nil {
58
+ return nil , errors .New ("imagefs: image cannot be nil" )
59
+ }
58
60
61
+ layers , err := image .Layers ()
62
+ if err != nil {
63
+ return nil , errors .Wrap (err , "imagefs: get layers failed" )
64
+ }
65
+
66
+ var ifs * imageFS
59
67
// Multiple layers of imageFS might get confusing, enable delayering.
60
68
if pfs , ok := parent .(* imageFS ); ok {
61
69
pfs .mu .Lock ()
@@ -75,43 +83,66 @@ func New(parent vfs.FS, root string, image v1.Image, filesToCache []string) (vfs
75
83
}
76
84
}
77
85
86
+ logrus .Debugf ("imagefs: Caching files for %s" , root )
87
+
88
+ // Keep track of directories so we can cache all of their contents.
89
+ var dirsToCache []string
78
90
// Walk the image and cache file info and hash of the requested files.
79
- _ , err : = util .GetFSFromImage (root , image , func (dest string , hdr * tar.Header , cleanedName string , tr io.Reader ) error {
91
+ _ , err = util .GetFSFromLayers (root , layers , util . ExtractFunc ( func (dest string , hdr * tar.Header , cleanedName string , tr io.Reader ) error {
80
92
// Trim prefix for consistent path.
81
93
cleanedName = strings .TrimPrefix (cleanedName , "/" )
94
+ path := filepath .Join (dest , cleanedName )
95
+
96
+ cacheFile := func () error {
97
+ logrus .Debugf ("imagefs: Found cacheable file /%s (path=%s) (%d:%d)" , cleanedName , path , hdr .Uid , hdr .Gid )
98
+
99
+ cf := newCachedFileInfo (path , hdr )
100
+ if cf .IsDir () {
101
+ dirsToCache = append (dirsToCache , cleanedName )
102
+ }
103
+
104
+ sum , err := hashFile (hdr , tr )
105
+ if err != nil {
106
+ return errors .Wrap (err , "imagefs: hash file failed" )
107
+ }
108
+ ifs .files [path ] = newCachedFileInfoWithMD5Sum (cf , sum )
109
+
110
+ return nil
111
+ }
112
+
113
+ // All files inside a cached directory should be cached as well.
114
+ for _ , dir := range dirsToCache {
115
+ if strings .HasPrefix (cleanedName , dir + "/" ) {
116
+ return cacheFile ()
117
+ }
118
+ }
82
119
83
120
for _ , f := range filesToCache {
84
- dest := filepath .Join (root , cleanedName )
85
121
f = strings .TrimPrefix (f , "/" )
122
+ f = strings .TrimSuffix (f , "/" )
86
123
87
124
// Check if the file matches the requested file.
88
125
if ok , err := filepath .Match (f , cleanedName ); ok && err == nil {
89
- logrus .Debugf ("imagefs: Found cacheable file %q (%s) (%d:%d)" , f , dest , hdr .Uid , hdr .Gid )
90
-
91
- sum , err := hashFile (hdr , tr )
92
- if err != nil {
93
- return errors .Wrap (err , "imagefs: hash file failed" )
94
- }
95
-
96
- f := newCachedFileInfo (dest , hdr )
97
- ifs .files [dest ] = newCachedFileInfoWithMD5Sum (f , sum )
98
-
99
- return nil
126
+ return cacheFile ()
100
127
}
101
128
102
- // Parent directories are needed for lookup .
129
+ // Cache parent directories for directory lookups .
103
130
if cleanedName == "" || strings .HasPrefix (f , cleanedName + "/" ) {
104
- logrus .Debugf ("imagefs: Found cacheable file parent %q (%s)" , f , dest )
105
-
106
- ifs .files [dest ] = newCachedFileInfo (dest , hdr )
131
+ if _ , ok := ifs .files [path ]; ! ok {
132
+ logrus .Debugf ("imagefs: Found cacheable file parent /%s (file=/%s)" , cleanedName , f )
133
+ ifs .files [path ] = newCachedFileInfo (dest , hdr )
134
+ }
107
135
}
108
136
}
137
+
109
138
return nil
110
- })
139
+ }))
111
140
if err != nil {
112
141
return nil , errors .Wrap (err , "imagefs: walk image failed" )
113
142
}
114
143
144
+ logrus .Debugf ("imagefs: Creating cached directories for %s" , root )
145
+
115
146
for dir , d := range ifs .files {
116
147
if ! d .IsDir () {
117
148
continue
@@ -124,6 +155,8 @@ func New(parent vfs.FS, root string, image v1.Image, filesToCache []string) (vfs
124
155
}
125
156
}
126
157
158
+ logrus .Debugf ("imagefs: Cached files for %s" , root )
159
+
127
160
return ifs , nil
128
161
}
129
162
0 commit comments