JJ_MKVMaker/lib/app/copy_error_text.dart

64 lines
3.7 KiB
Dart

/// 약속 (modular_sync #6 · F18): 복사 · 이동 · 동기화가 사용자에게 보이는 실패 글 - 예외 이름 ("ProcessException:") · Dart 의 영어 파일 오류
/// ("Cannot copy file") 를 빼고 화면 언어로. 입력: 예외 (와 원본 경로들), 출력: 글. 원래 글 ('$e') 은 부르는 쪽이 작업 기록에 남긴다.
/// 쓰는 곳: 복사 · 이동 작업 (copy_center) · 실시간 동기화 상태 (live_sync)
library;
import 'dart:io';
import '../core/file_ops.dart' show isSameOrInside;
import '../l10n/tr.dart';
/// 237: 사용자에게 보이는 실패 글 - "ProcessException:" 같은 예외 이름 · "Command:" 줄은 빼고 내용만.
/// 원래 글 ('$e') 은 작업 기록에 그대로 남긴다.
/// 245: 앱이 직접 할 때의 파일 오류 (Dart 의 "Cannot delete file" 등 영어) 는 화면 언어로. [sources] 안의 파일을 못 지웠으면
/// rsync 때 (215) 와 같은 글 - 이동에서 원본만 남은 것
String userErrorText(Object e, {List<String> sources = const []}) => switch (e) {
ProcessException(:final message) when message.isNotEmpty => message,
FileSystemException(:final message, :final path, :final osError) => [
_fileErrorText(message, path, sources),
if (path != null && path.isNotEmpty) path,
if (osError != null && osError.message.isNotEmpty) osError.message,
].join(' · '),
_ => '$e'.replaceFirst(RegExp(r'^\w*(Exception|Error)(\([^)]*\))?: '), ''),
};
String _fileErrorText(String message, String? path, List<String> sources) {
final m = message.toLowerCase();
if (m.startsWith('cannot delete') || m.startsWith('deletion failed')) {
final inSource = path != null && sources.any((s) => isSameOrInside(path, s));
return inSource
? tr('원본 파일을 지우지 못했습니다 (권한이 없거나 사용 중). 대상에는 복사됐고 원본은 남아 있습니다.')
: tr('지우지 못했습니다 (권한이 없거나 사용 중)');
}
if (m.startsWith('cannot copy')) return tr('파일을 복사하지 못했습니다');
if (m.startsWith('cannot rename')) return tr('옮기거나 이름을 바꾸지 못했습니다');
if (m.startsWith('cannot open') || m.startsWith('cannot read')) return tr('파일을 읽지 못했습니다');
if (m.startsWith('cannot create') || m.startsWith('creation failed') || m.startsWith('cannot write')) {
return tr('만들거나 쓰지 못했습니다');
}
return message;
}
/// 215: rsync 가 실패했을 때 보일 글 - 원본을 못 지웠으면 쉬운 말 한 줄, 그리고 오류 · 권한 줄을 끝쪽부터 (전송한 파일 이름이 아니라).
/// 예전에는 출력의 앞쪽 8줄이라 파일 이름만 보이고 "Permission denied" · "rsync error … (code 23)" 가 빠지기 쉬웠다
String rsyncFailureText(int code, List<String> errLines, List<String> allLines) {
final all = [...errLines, ...allLines];
final removeFailed = all.any((l) {
final x = l.toLowerCase();
return x.contains('failed to remove') || x.contains('cannot delete') || x.contains('unable to remove');
});
bool important(String l) {
final x = l.toLowerCase();
return x.contains('error') || x.contains('fail') || x.contains('denied') || x.contains('cannot') || x.contains('permission');
}
final picked = errLines.where(important).toList();
final lines = picked.isNotEmpty ? picked : (errLines.isNotEmpty ? errLines : allLines);
final tail = lines.length > 6 ? lines.sublist(lines.length - 6) : lines;
return [
if (removeFailed) tr('원본 파일을 지우지 못했습니다 (권한이 없거나 사용 중). 대상에는 복사됐고 원본은 남아 있습니다.'),
trf('rsync 종료 코드 {0}', [code]),
...tail,
].join('\n');
}