archive method

Stream<Es> archive(
  1. File archiveFile,
  2. ArchiveType archiveType, [
  3. bool useRelPath = true
])

archive source path

  • archiveFile: to archive file.
  • archiveType: to archive type.
  • useRelPath: use relative path If true else use deroot absolute path.
final excludes = [r'.**'];
final source = '.';
final action = BasicPathAction(source, excludes:excludes);

final toArchive = File(expandTilde('~/Downloads/ft.tgz'));
action.archive(toArchive, ArchiveType.tgz);

Implementation

Stream<Es> archive(File archiveFile, ArchiveType archiveType,
    [bool useRelPath = true]) {
  final action = PathAction.archive.name, chk = 'validator';
  argErr ??= validator();
  if (argErr!.isNotEmpty) throw ArgumentError.value(argErr, action, chk);
  final srcPath = (type == FileSystemEntityType.directory)
      ? Directory(path).absolute.path
      : path;

  final fields = fieldsFromOptions(fmtFields);
  final fseType = FileSystemEntityType.file;
  final stream = scEntity.stream;
  final fStream =
      stream.where((event) => event.fs.type == fseType).asBroadcastStream();
  final tarEntryController = StreamController<TarEntry>(sync: true);

  late StreamSubscription subs;
  subs = fStream.listen(
    (event) {
      final (entity, stat, extra) = event.asRecord;
      final oldPath = entity.isAbsolute ? entity.path : entity.absolute.path;
      // keep the original,  use useRelPath
      var newPath = oldPath;
      if (useRelPath) {
        if (type == FileSystemEntityType.directory) {
          newPath = oldPath.substring(srcPath.length + 1);
        } else {
          newPath = p.basename(path);
        }
      }
      if (newPath == archiveFile.path) return; // same continue and for...in
      var ok = false;
      newPath = separatorToForwardSlash(newPath);
      try {
        tarEntryController.add(
          TarEntry(
            TarHeader(
                name: newPath,
                modified: stat.modified,
                mode: stat.mode,
                size: stat.size),
            File(entity.path).openRead(),
          ),
        );
        ok = true;
      } catch (e, s) {
        logger.stderr('e, $action, data, secure ${entity.path}');
        scEntity.addError(e, s);
      }

      final line =
          Formatter(entity, stat, extra, action, shows: fields, ok: ok);
      logger.stdout(line.toString());
    },
    cancelOnError: cancelOnError,
    onDone: () {
      logger.trace('d, $action, done.');

      final outputStream = archiveFile.openWrite();
      final tStream = (archiveType == ArchiveType.tgz)
          ? tarEntryController.stream
              .transform(tarWriter)
              .transform(gzip.encoder)
          : tarEntryController.stream;
      final pipe = (archiveType == ArchiveType.tgz)
          ? tStream.pipe(outputStream)
          : tStream.pipe(tarWritingSink(outputStream));

      pipe.then(
        (_) => unawaited(outputStream.close()),
        onError: (e, s) =>
            logger.stderr('e, $action, done, pipe tarwrite, $e\n$s'),
      );
      tarEntryController.close();
    },
    onError: (e, s) {
      if (cancelOnError) {
        tarEntryController.close();

        exitCode = ExitCodeExt.error.code;
        subs.cancel();
      }

      logger
        ..trace('d, $action, cancelOnError:$cancelOnError')
        ..stderr('e, $action, error. $e')
        ..stderr(kIsDebug ? '$s' : '');
    }, // onError
  );
  return fStream;
}