gzipTo method
Compresses the given sessions (all by default) into one GZIP-compressed
JSON Lines file target.
Sessions are concatenated in their given order. Each keeps its own meta
line, so session boundaries remain identifiable after decompression. The
input and output are streamed with bounded memory. An existing target
is overwritten. The target must not be one of the selected session chunks
or an alias to one; an ArgumentError is thrown before writing if it is.
Implementation
Future<void> gzipTo(
File target, {
Iterable<FileLogSession>? sessions,
}) async {
final selected = sessions?.toList() ?? await list();
final normalizedTargetPath = _normalizedAbsolutePath(target.path);
for (final session in selected) {
for (final chunk in session.files) {
if (normalizedTargetPath == _normalizedAbsolutePath(chunk.path)) {
throw ArgumentError.value(
target.path,
'target',
'Must not alias a selected session chunk',
);
}
}
}
final targetType = FileSystemEntity.typeSync(
target.path,
followLinks: false,
);
if (targetType != FileSystemEntityType.notFound) {
final identityPath = targetType == FileSystemEntityType.link
? await Link(target.path).resolveSymbolicLinks()
: target.path;
for (final session in selected) {
for (final chunk in session.files) {
if (!_isRegularFile(chunk)) continue;
if (await FileSystemEntity.identical(identityPath, chunk.path)) {
throw ArgumentError.value(
target.path,
'target',
'Must not alias a selected session chunk',
);
}
}
}
}
await target.parent.create(recursive: true);
final sink = target.openWrite();
Object? primaryError;
StackTrace? primaryStackTrace;
try {
await sink.addStream(_combinedSessions(selected).transform(gzip.encoder));
} on Object catch (error, stackTrace) {
primaryError = error;
primaryStackTrace = stackTrace;
}
try {
await sink.close();
} on Object catch (error, stackTrace) {
if (primaryError == null) {
Error.throwWithStackTrace(error, stackTrace);
}
}
if (primaryError != null) {
Error.throwWithStackTrace(primaryError, primaryStackTrace!);
}
}