fix(shorebird_cli): add helpful error message if cache clear fails on Windows (#964)
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:mason_logger/mason_logger.dart';
|
||||
import 'package:shorebird_cli/src/cache.dart';
|
||||
import 'package:shorebird_cli/src/command.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/platform.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
|
||||
/// {@template clean_cache_command}
|
||||
@@ -25,8 +27,34 @@ class CleanCacheCommand extends ShorebirdCommand with ShorebirdConfigMixin {
|
||||
|
||||
@override
|
||||
Future<int> run() async {
|
||||
cache.clear();
|
||||
logger.success('✅ Cleared Cache!');
|
||||
final progress = logger.progress('Clearing Cache');
|
||||
try {
|
||||
cache.clear();
|
||||
} on FileSystemException catch (error) {
|
||||
final cachePath = Cache.shorebirdCacheDirectory.path;
|
||||
progress.fail(
|
||||
'''Failed to delete cache directory $cachePath: $error''',
|
||||
);
|
||||
if (!platform.isWindows) {
|
||||
return ExitCode.software.code;
|
||||
}
|
||||
|
||||
final superuserLink = link(
|
||||
uri: Uri.parse(
|
||||
'https://superuser.com/questions/1333118/cant-delete-empty-folder-because-it-is-used',
|
||||
),
|
||||
);
|
||||
|
||||
logger.info(
|
||||
'''
|
||||
This could be because a program is using a file in the cache directory. To find and stop such a program, see:
|
||||
${lightCyan.wrap(superuserLink)}
|
||||
''',
|
||||
);
|
||||
return ExitCode.software.code;
|
||||
}
|
||||
|
||||
progress.complete('Cleared cache');
|
||||
return ExitCode.success.code;
|
||||
}
|
||||
}
|
||||
|
||||
+67
-2
@@ -1,19 +1,30 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:mason_logger/mason_logger.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:platform/platform.dart';
|
||||
import 'package:scoped/scoped.dart';
|
||||
import 'package:shorebird_cli/src/cache.dart';
|
||||
import 'package:shorebird_cli/src/commands/commands.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/platform.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
class _MockCache extends Mock implements Cache {}
|
||||
|
||||
class _MockLogger extends Mock implements Logger {}
|
||||
|
||||
class _MockCache extends Mock implements Cache {}
|
||||
class _MockPlatform extends Mock implements Platform {}
|
||||
|
||||
class _MockProgress extends Mock implements Progress {}
|
||||
|
||||
void main() {
|
||||
group('cache clean', () {
|
||||
late Cache cache;
|
||||
late Logger logger;
|
||||
late Platform platform;
|
||||
late Progress progress;
|
||||
late CleanCacheCommand command;
|
||||
|
||||
R runWithOverrides<R>(R Function() body) {
|
||||
@@ -22,6 +33,7 @@ void main() {
|
||||
values: {
|
||||
cacheRef.overrideWith(() => cache),
|
||||
loggerRef.overrideWith(() => logger),
|
||||
platformRef.overrideWith(() => platform),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -29,7 +41,21 @@ void main() {
|
||||
setUp(() {
|
||||
cache = _MockCache();
|
||||
logger = _MockLogger();
|
||||
platform = _MockPlatform();
|
||||
progress = _MockProgress();
|
||||
command = runWithOverrides(CleanCacheCommand.new);
|
||||
|
||||
when(() => logger.progress(any())).thenReturn(progress);
|
||||
when(() => platform.script).thenReturn(
|
||||
Uri.file(
|
||||
p.join(
|
||||
Directory.systemTemp.createTempSync().path,
|
||||
'bin',
|
||||
'cache',
|
||||
'shorebird.snapshot',
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
test('has a description', () {
|
||||
@@ -39,8 +65,47 @@ void main() {
|
||||
test('clears the cache', () async {
|
||||
final result = await runWithOverrides(command.run);
|
||||
expect(result, equals(ExitCode.success.code));
|
||||
verify(() => logger.success('✅ Cleared Cache!')).called(1);
|
||||
verify(() => progress.complete('Cleared cache')).called(1);
|
||||
verify(cache.clear).called(1);
|
||||
});
|
||||
|
||||
group('on failure', () {
|
||||
group('on Windows', () {
|
||||
setUp(() {
|
||||
when(() => platform.isWindows).thenReturn(true);
|
||||
});
|
||||
|
||||
test('tells the user how to find the issue and exits with code 70',
|
||||
() async {
|
||||
when(() => cache.clear()).thenThrow(
|
||||
const FileSystemException('Failed to delete'),
|
||||
);
|
||||
|
||||
final result = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.software.code));
|
||||
verify(() => progress.fail(any())).called(1);
|
||||
verify(() => logger.info(any())).called(1);
|
||||
});
|
||||
});
|
||||
|
||||
group('on a non-Windows OS', () {
|
||||
setUp(() {
|
||||
when(() => platform.isWindows).thenReturn(false);
|
||||
});
|
||||
|
||||
test('prints error message and exits with code 70', () async {
|
||||
when(() => cache.clear()).thenThrow(
|
||||
const FileSystemException('Failed to delete'),
|
||||
);
|
||||
|
||||
final result = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.software.code));
|
||||
verify(() => progress.fail(any())).called(1);
|
||||
verifyNever(() => logger.info(any()));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user