gzipTo method

Future<void> gzipTo(
  1. File target, {
  2. Iterable<FileLogSession>? sessions,
})

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!);
  }
}