@@ -229,6 +229,20 @@ func Download(ctx context.Context, local, remote string, opts ...Opt) (*Result,
229229 return res , nil
230230 }
231231
232+ res , err := getCached (ctx , localPath , remote , o )
233+ if err != nil {
234+ return nil , err
235+ }
236+ if res != nil {
237+ return res , nil
238+ }
239+ return fetch (ctx , localPath , remote , o )
240+ }
241+
242+ // getCached tries to copy the file from the cache to local path. Return result,
243+ // nil if the file was copied, nil, nil if the file is not in the cache or the
244+ // cache needs update, or nil, error on fatal error.
245+ func getCached (ctx context.Context , localPath , remote string , o options ) (* Result , error ) {
232246 shad := cacheDirectoryPath (o .cacheDir , remote )
233247 shadData := filepath .Join (shad , "data" )
234248 shadTime := filepath .Join (shad , "time" )
@@ -237,41 +251,53 @@ func Download(ctx context.Context, local, remote string, opts ...Opt) (*Result,
237251 if err != nil {
238252 return nil , err
239253 }
240- if _ , err := os .Stat (shadData ); err == nil {
241- logrus .Debugf ("file %q is cached as %q" , localPath , shadData )
242- useCache := true
243- if _ , err := os .Stat (shadDigest ); err == nil {
244- logrus .Debugf ("Comparing digest %q with the cached digest file %q, not computing the actual digest of %q" ,
245- o .expectedDigest , shadDigest , shadData )
246- if err := validateCachedDigest (shadDigest , o .expectedDigest ); err != nil {
247- return nil , err
248- }
249- if err := copyLocal (ctx , localPath , shadData , ext , o .decompress , "" , "" ); err != nil {
254+ if _ , err := os .Stat (shadData ); err != nil {
255+ return nil , nil
256+ }
257+ ext := path .Ext (remote )
258+ logrus .Debugf ("file %q is cached as %q" , localPath , shadData )
259+ if _ , err := os .Stat (shadDigest ); err == nil {
260+ logrus .Debugf ("Comparing digest %q with the cached digest file %q, not computing the actual digest of %q" ,
261+ o .expectedDigest , shadDigest , shadData )
262+ if err := validateCachedDigest (shadDigest , o .expectedDigest ); err != nil {
263+ return nil , err
264+ }
265+ if err := copyLocal (ctx , localPath , shadData , ext , o .decompress , "" , "" ); err != nil {
266+ return nil , err
267+ }
268+ } else {
269+ if match , lmCached , lmRemote , err := matchLastModified (ctx , shadTime , remote ); err != nil {
270+ logrus .WithError (err ).Info ("Failed to retrieve last-modified for cached digest-less image; using cached image." )
271+ } else if match {
272+ if err := copyLocal (ctx , localPath , shadData , ext , o .decompress , o .description , o .expectedDigest ); err != nil {
250273 return nil , err
251274 }
252275 } else {
253- if match , lmCached , lmRemote , err := matchLastModified (ctx , shadTime , remote ); err != nil {
254- logrus .WithError (err ).Info ("Failed to retrieve last-modified for cached digest-less image; using cached image." )
255- } else if match {
256- if err := copyLocal (ctx , localPath , shadData , ext , o .decompress , o .description , o .expectedDigest ); err != nil {
257- return nil , err
258- }
259- } else {
260- logrus .Infof ("Re-downloading digest-less image: last-modified mismatch (cached: %q, remote: %q)" , lmCached , lmRemote )
261- useCache = false
262- }
263- }
264- if useCache {
265- res := & Result {
266- Status : StatusUsedCache ,
267- CachePath : shadData ,
268- LastModified : readTime (shadTime ),
269- ContentType : readFile (shadType ),
270- ValidatedDigest : o .expectedDigest != "" ,
271- }
272- return res , nil
276+ logrus .Infof ("Re-downloading digest-less image: last-modified mismatch (cached: %q, remote: %q)" , lmCached , lmRemote )
277+ return nil , nil
273278 }
274279 }
280+ res := & Result {
281+ Status : StatusUsedCache ,
282+ CachePath : shadData ,
283+ LastModified : readTime (shadTime ),
284+ ContentType : readFile (shadType ),
285+ ValidatedDigest : o .expectedDigest != "" ,
286+ }
287+ return res , nil
288+ }
289+
290+ // fetch downloads remote to the cache and copy the cached file to local path.
291+ func fetch (ctx context.Context , localPath , remote string , o options ) (* Result , error ) {
292+ shad := cacheDirectoryPath (o .cacheDir , remote )
293+ shadData := filepath .Join (shad , "data" )
294+ shadTime := filepath .Join (shad , "time" )
295+ shadType := filepath .Join (shad , "type" )
296+ shadDigest , err := cacheDigestPath (shad , o .expectedDigest )
297+ if err != nil {
298+ return nil , err
299+ }
300+ ext := path .Ext (remote )
275301 if err := os .MkdirAll (shad , 0o700 ); err != nil {
276302 return nil , err
277303 }
0 commit comments