import '../l10n/tr.dart'; import 'webdav.dart' show DavItem, DavException; /// 원격 저장소 (WebDAV · SFTP) 의 공통 동작. vfs 가 경로의 서버 종류 (dav:// · sftp://) 에 맞는 것을 부른다. /// 경로 [rel] 은 서버 기준 ("/" 로 시작, 맨 위는 "/"). abstract class RemoteClient { Future> list(String rel); /// 없으면 null Future stat(String rel); /// 폴더를 만든다 (위 폴더까지). 서버마다 [remoteMkdirs] 를 부른다 - 이미 폴더면 그대로, 같은 이름의 파일이 있으면 [RemoteNameIsFile] Future mkdirs(String rel); /// 지우기 (폴더면 안의 것까지) Future delete(String rel); /// 같은 서버 안에서 옮기기 · 이름 바꾸기 Future move(String from, String to, {bool overwrite = false}); Future>> openRead(String rel); Future write(String rel, Stream> 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 remoteMkdirs(RemoteClient c, String rel, Future 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); }