JJ_MKVMaker/lib/core/remote_fs.dart

50 lines
2.3 KiB
Dart

import '../l10n/tr.dart';
import 'webdav.dart' show DavItem, DavException;
/// 원격 저장소 (WebDAV · SFTP) 의 공통 동작. vfs 가 경로의 서버 종류 (dav:// · sftp://) 에 맞는 것을 부른다.
/// 경로 [rel] 은 서버 기준 ("/" 로 시작, 맨 위는 "/").
abstract class RemoteClient {
Future<List<DavItem>> list(String rel);
/// 없으면 null
Future<DavItem?> stat(String rel);
/// 폴더를 만든다 (위 폴더까지). 서버마다 [remoteMkdirs] 를 부른다 - 이미 폴더면 그대로, 같은 이름의 파일이 있으면 [RemoteNameIsFile]
Future<void> mkdirs(String rel);
/// 지우기 (폴더면 안의 것까지)
Future<void> delete(String rel);
/// 같은 서버 안에서 옮기기 · 이름 바꾸기
Future<void> move(String from, String to, {bool overwrite = false});
Future<Stream<List<int>>> openRead(String rel);
Future<void> write(String rel, Stream<List<int>> data, {int? length});
/// (남은 공간, 쓴 공간) - 모르면 null
Future<(int?, int?)> quota();
void close();
}
/// modular_sync #6 RemoteFs: 같은 이름의 파일이 있어 폴더를 만들 수 없음 - 서버 종류와 상관없이 같은 오류 (F11: 예전에는 SFTP · SMB 만 알리고
/// FTP 는 조용히 넘어가 뒤의 쓰기가 엉뚱한 오류로, WebDAV 는 서버 오류로 끝났다)
class RemoteNameIsFile extends DavException {
RemoteNameIsFile(this.rel) : super(trf('같은 이름의 파일이 있어 폴더를 만들 수 없습니다: {0}', [rel]));
final String rel;
}
/// 원격 경로의 위 폴더 ("/a/b" → "/a", 맨 위는 "/")
String remoteParent(String rel) => rel.lastIndexOf('/') <= 0 ? '/' : rel.substring(0, rel.lastIndexOf('/'));
/// 약속 (#6, 모든 원격 서버의 mkdirs): [rel] 까지 폴더를 만든다. 이미 폴더면 그대로 · 같은 이름의 파일이면 [RemoteNameIsFile] ·
/// 위 폴더부터 차례로. 서버마다 다른 것은 한 칸 만들기 [mkdirOne] 뿐 (그 사이 다른 곳이 만들었으면 그대로 두는 것은 [mkdirOne] 이)
Future<void> remoteMkdirs(RemoteClient c, String rel, Future<void> Function(String rel) mkdirOne) async {
if (rel == '/' || rel.isEmpty) return;
final st = await c.stat(rel);
if (st != null) {
if (st.isDir) return;
throw RemoteNameIsFile(rel);
}
await remoteMkdirs(c, remoteParent(rel), mkdirOne);
await mkdirOne(rel);
}