write method

  1. @override
Future<TomFileRevision> write(
  1. Uri uri,
  2. Uint8List bytes, {
  3. TomFileRevision? expected,
})
override

Writes bytes to uri atomically. With expected, refuses with a TomFileConflict when the file is no longer that revision. Answers the revision written.

Implementation

@override
Future<TomFileRevision> write(
  Uri uri,
  Uint8List bytes, {
  TomFileRevision? expected,
}) async {
  final target = File(localPathOf(uri));
  final existed = target.existsSync();
  if (expected != null) {
    final current = existed
        ? TomFileRevision.of(
            await target.readAsBytes(),
            await target.lastModified(),
          )
        : null;
    if (current != expected) throw TomFileConflict(absolute(uri), current);
  }
  // Atomic: a sibling temporary file, flushed, renamed over the target. A
  // crash leaves either the old file or the new one, never half of one.
  final temp = File(
    p.join(
      target.parent.path,
      '.${p.basename(target.path)}.tom-'
      '${DateTime.now().microsecondsSinceEpoch}.tmp',
    ),
  );
  final handle = await temp.open(mode: FileMode.writeOnly);
  try {
    await handle.writeFrom(bytes);
    await handle.flush();
  } finally {
    await handle.close();
  }
  await temp.rename(target.path);
  emitChange(
    uri,
    existed ? TomFileChangeType.modified : TomFileChangeType.created,
  );
  return TomFileRevision.of(bytes, await target.lastModified());
}