diff --git a/flutter_cache_manager/lib/src/cache_store.dart b/flutter_cache_manager/lib/src/cache_store.dart index 44ffbfeb..738c1cce 100644 --- a/flutter_cache_manager/lib/src/cache_store.dart +++ b/flutter_cache_manager/lib/src/cache_store.dart @@ -161,13 +161,19 @@ class CacheStore { Future emptyCache() async { final provider = await _cacheInfoRepository; - final toRemove = []; final allObjects = await provider.getAllObjects(); - var futures = []; + + // Remove the cache files from the filesystem + await _removeCacheDir(); + + // Delete objects from store + final toRemove = {}; for (final cacheObject in allObjects) { - futures.add(_removeCachedFile(cacheObject, toRemove)); + if (cacheObject.id != null) { + toRemove.add(cacheObject.id!); + } } - await Future.wait(futures); + await provider.deleteAll(toRemove); } @@ -207,6 +213,18 @@ class CacheStore { } } + Future _removeCacheDir() async { + _memCache.clear(); + _futureCache.clear(); + + try { + await fileSystem.deleteCacheDir(); + } on FileSystemException { + // If the filesystem implementation doesn't check if the file + // exists before deleting it could fail + } + } + bool memoryCacheContainsKey(String key) { return _memCache.containsKey(key); } diff --git a/flutter_cache_manager/lib/src/storage/file_system/file_system.dart b/flutter_cache_manager/lib/src/storage/file_system/file_system.dart index 2cd9764b..3f7a77a6 100644 --- a/flutter_cache_manager/lib/src/storage/file_system/file_system.dart +++ b/flutter_cache_manager/lib/src/storage/file_system/file_system.dart @@ -4,6 +4,10 @@ export 'file_system_web.dart'; import 'package:file/file.dart'; +/// FileSystem works in the context of a directory where filenames are stored. abstract class FileSystem { Future createFile(String name); + + /// Deletes the directory that contains all the cached filed in the current context. + Future deleteCacheDir(); } diff --git a/flutter_cache_manager/lib/src/storage/file_system/file_system_io.dart b/flutter_cache_manager/lib/src/storage/file_system/file_system_io.dart index 15ab3901..861aeb60 100644 --- a/flutter_cache_manager/lib/src/storage/file_system/file_system_io.dart +++ b/flutter_cache_manager/lib/src/storage/file_system/file_system_io.dart @@ -28,4 +28,13 @@ class IOFileSystem implements FileSystem { } return directory.childFile(name); } + + @override + Future deleteCacheDir() async { + final directory = await _fileDir; + + if (await directory.exists()) { + await directory.delete(recursive: true); + } + } } diff --git a/flutter_cache_manager/lib/src/storage/file_system/file_system_web.dart b/flutter_cache_manager/lib/src/storage/file_system/file_system_web.dart index ac080452..b660f006 100644 --- a/flutter_cache_manager/lib/src/storage/file_system/file_system_web.dart +++ b/flutter_cache_manager/lib/src/storage/file_system/file_system_web.dart @@ -1,12 +1,33 @@ -import 'package:file/file.dart' show File; +import 'package:file/file.dart' show File, Directory; import 'package:file/memory.dart'; import 'package:flutter_cache_manager/src/storage/file_system/file_system.dart'; class MemoryCacheSystem implements FileSystem { - final directory = MemoryFileSystem().systemTempDirectory.createTemp('cache'); + Future _fileDir; + + MemoryCacheSystem() : _fileDir = _createTempDirectory(); @override Future createFile(String name) async { - return (await directory).childFile(name); + Directory directory = await _fileDir; + if (!(await directory.exists())) { + // Because _createTempDirectory assigns a new name we need to reassing the future + _fileDir = _createTempDirectory(); + directory = await _fileDir; + } + + return directory.childFile(name); + } + + static Future _createTempDirectory() async { + return MemoryFileSystem().systemTempDirectory.createTemp('cache'); + } + + @override + Future deleteCacheDir() async { + final dir = await _fileDir; + if (await dir.exists()) { + await dir.delete(recursive: true); + } } } diff --git a/flutter_cache_manager/test/cache_store_test.dart b/flutter_cache_manager/test/cache_store_test.dart index 412a35f1..00338639 100644 --- a/flutter_cache_manager/test/cache_store_test.dart +++ b/flutter_cache_manager/test/cache_store_test.dart @@ -406,7 +406,6 @@ void main() { var config = createTestConfig(); var store = CacheStore(config); store.cleanupRunMinInterval = const Duration(milliseconds: 1); - await config.returnsFile('testimage.png'); var co1 = CacheObject( 'baseflow.com/test.png', @@ -427,12 +426,32 @@ void main() { validTill: clock.now().add(const Duration(days: 7)), ); + final cacheObjects = [co1, co2, co3]; + + // Write the cache files to the filesystem + final List cacheFiles = []; + for (var cacheObject in cacheObjects) { + final f = await config.returnsFile(cacheObject.relativePath); + cacheFiles.add(f); + } + + // Include an extra file + // This could be a desync between the store and the filesystem + cacheFiles.add( + await config.returnsFile("non-existent-file-in-store.png"), + ); + when( config.mockRepo.getAllObjects(), - ).thenAnswer((_) => Future.value([co1, co2, co3])); + ).thenAnswer((_) => Future.value(cacheObjects)); await store.emptyCache(); + // make sure that all cached files in the filesystem are deleted + for (var cacheFile in cacheFiles) { + expect(await cacheFile.exists(), isFalse); + } + verify( config.mockRepo.deleteAll( argThat(containsAll([co1.id, co2.id, co3.id])), diff --git a/flutter_cache_manager/test/helpers/test_configuration.dart b/flutter_cache_manager/test/helpers/test_configuration.dart index 64379633..f2fffbcd 100644 --- a/flutter_cache_manager/test/helpers/test_configuration.dart +++ b/flutter_cache_manager/test/helpers/test_configuration.dart @@ -26,4 +26,12 @@ class TestFileSystem extends FileSystem { await dir.create(recursive: true); return dir.childFile(name); } + + @override + Future deleteCacheDir() async { + var dir = await directoryFuture; + if (await dir.exists()) { + await dir.delete(recursive: true); + } + } }