You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
143 lines
4.2 KiB
143 lines
4.2 KiB
2 years ago
|
part of '../neon_files.dart';
|
||
|
|
||
|
class FilesSyncSources implements SyncSources<WebDavFile, FileSystemEntity> {
|
||
|
FilesSyncSources(
|
||
|
final NextcloudClient client,
|
||
|
final PathUri webdavBaseDir,
|
||
|
final Directory ioBaseDir,
|
||
|
) : sourceA = FilesSyncSourceWebDavFile(client, webdavBaseDir),
|
||
|
sourceB = FilesSyncSourceFileSystemEntity(client, ioBaseDir);
|
||
|
|
||
|
@override
|
||
|
final SyncSource<WebDavFile, FileSystemEntity> sourceA;
|
||
|
|
||
|
@override
|
||
|
final SyncSource<FileSystemEntity, WebDavFile> sourceB;
|
||
|
|
||
|
@override
|
||
|
SyncConflictSolution? findSolution(final SyncObject<WebDavFile> objectA, final SyncObject<FileSystemEntity> objectB) {
|
||
|
if (objectA.data.isDirectory && objectB.data is Directory) {
|
||
|
return SyncConflictSolution.overwriteA;
|
||
|
}
|
||
|
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class FilesSyncSourceWebDavFile implements SyncSource<WebDavFile, FileSystemEntity> {
|
||
|
FilesSyncSourceWebDavFile(
|
||
|
this.client,
|
||
|
this.baseDir,
|
||
|
);
|
||
|
|
||
|
/// [NextcloudClient] used by the WebDAV part.
|
||
|
final NextcloudClient client;
|
||
|
|
||
|
/// Base directory on the WebDAV server.
|
||
|
final PathUri baseDir;
|
||
|
|
||
|
final props = WebDavPropWithoutValues.fromBools(
|
||
|
davgetetag: true,
|
||
|
davgetlastmodified: true,
|
||
|
nchaspreview: true,
|
||
|
ocsize: true,
|
||
|
ocfavorite: true,
|
||
|
);
|
||
|
|
||
|
PathUri _uri(final SyncObject<dynamic> object) => baseDir.join(PathUri.parse(object.id));
|
||
|
|
||
|
@override
|
||
|
Future<List<SyncObject<WebDavFile>>> listObjects() async => (await client.webdav.propfind(
|
||
|
baseDir,
|
||
|
prop: props,
|
||
|
depth: WebDavDepth.infinity,
|
||
|
))
|
||
|
.toWebDavFiles()
|
||
|
.sublist(1)
|
||
|
.map(
|
||
|
(final file) => (
|
||
|
id: file.path.pathSegments.sublist(baseDir.pathSegments.length).join('/'),
|
||
|
data: file,
|
||
|
),
|
||
|
)
|
||
|
.toList();
|
||
|
|
||
|
@override
|
||
|
Future<String> getObjectETag(final SyncObject<WebDavFile> object) async =>
|
||
|
object.data.isDirectory ? '' : object.data.etag!;
|
||
|
|
||
|
@override
|
||
|
Future<SyncObject<WebDavFile>> writeObject(final SyncObject<FileSystemEntity> object) async {
|
||
|
if (object.data is File) {
|
||
|
final stat = await object.data.stat();
|
||
|
await client.webdav.putFile(
|
||
|
object.data as File,
|
||
|
stat,
|
||
|
_uri(object),
|
||
|
lastModified: stat.modified,
|
||
|
);
|
||
|
} else if (object.data is Directory) {
|
||
|
await client.webdav.mkcol(_uri(object));
|
||
|
} else {
|
||
|
throw Exception('Unable to sync FileSystemEntity of type ${object.data.runtimeType}');
|
||
|
}
|
||
|
return (
|
||
|
id: object.id,
|
||
|
data: (await client.webdav.propfind(
|
||
|
_uri(object),
|
||
|
prop: props,
|
||
|
depth: WebDavDepth.zero,
|
||
|
))
|
||
|
.toWebDavFiles()
|
||
|
.single,
|
||
|
);
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
Future<void> deleteObject(final SyncObject<WebDavFile> object) async => client.webdav.delete(_uri(object));
|
||
|
}
|
||
|
|
||
|
class FilesSyncSourceFileSystemEntity implements SyncSource<FileSystemEntity, WebDavFile> {
|
||
|
FilesSyncSourceFileSystemEntity(
|
||
|
this.client,
|
||
|
this.baseDir,
|
||
|
);
|
||
|
|
||
|
/// [NextcloudClient] used by the WebDAV part.
|
||
|
final NextcloudClient client;
|
||
|
|
||
|
/// Base directory on the local filesystem.
|
||
|
final Directory baseDir;
|
||
|
|
||
|
@override
|
||
|
Future<List<SyncObject<FileSystemEntity>>> listObjects() async => baseDir.listSync(recursive: true).map(
|
||
|
(final e) {
|
||
|
var path = p.relative(e.path, from: baseDir.path);
|
||
|
if (path.endsWith('/')) {
|
||
|
path = path.substring(0, path.length - 1);
|
||
|
}
|
||
|
return (id: path, data: e);
|
||
|
},
|
||
|
).toList();
|
||
|
|
||
|
@override
|
||
|
Future<String> getObjectETag(final SyncObject<FileSystemEntity> object) async =>
|
||
|
object.data is Directory ? '' : object.data.statSync().modified.millisecondsSinceEpoch.toString();
|
||
|
|
||
|
@override
|
||
|
Future<SyncObject<FileSystemEntity>> writeObject(final SyncObject<WebDavFile> object) async {
|
||
|
if (object.data.isDirectory) {
|
||
|
final dir = Directory(p.join(baseDir.path, object.id))..createSync();
|
||
|
return (id: object.id, data: dir);
|
||
|
} else {
|
||
|
final file = File(p.join(baseDir.path, object.id));
|
||
|
await client.webdav.getFile(object.data.path, file);
|
||
|
await file.setLastModified(object.data.lastModified!);
|
||
|
return (id: object.id, data: file);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
Future<void> deleteObject(final SyncObject<FileSystemEntity> object) async => object.data.delete();
|
||
|
}
|