unArchive static method

void unArchive(
  1. UnArchiveOptions options
)

Unarchives file to targetDir. Symmetric to archive method.

Implementation

static void unArchive(UnArchiveOptions options) {
  _log(options.logBuffer,
      '--- Unarchive Started: ${p.basename(options.file.path)} ---');

  final extName = p.extension(options.file.path);
  final isCompressed = extName.endsWith('.gz') || extName.endsWith('.tgz');

  final inputStream = options.file.openRead();
  final input =
      isCompressed ? inputStream.transform(gzip.decoder) : inputStream;

  TarReader.forEach(input, (tarEntry) async {
    final location =
        p.normalize(p.join(options.targetDir.path, tarEntry.name));

    if (!p.isWithin(options.targetDir.path, location)) {
      _log(options.logBuffer,
          'Warning: Skipping insecure entry: ${tarEntry.name}');
      return;
    }

    if (tarEntry.type == TypeFlag.dir) {
      _log(options.logBuffer, 'Creating dir: ${tarEntry.name}');
      Directory(location).createSync(recursive: true);
      return;
    }

    if (tarEntry.type == TypeFlag.reg) {
      final targetFile = File(location);
      targetFile.parent.createSync(recursive: true);
      _log(options.logBuffer, 'Extracting file: ${tarEntry.name}');
      try {
        await tarEntry.contents.pipe(targetFile.openWrite());
        targetFile.setLastModifiedSync(tarEntry.modified);
        options.onFileExtracted?.call(targetFile);
      } catch (e) {
        _log(options.logBuffer, 'Pipe failed for ${tarEntry.name}: $e');
        rethrow;
      }
    }
  }).then((_) {
    _log(options.logBuffer, '--- Unarchive Completed Successfully ---');
    options.onSuccess?.call();
  }).catchError((e, st) {
    _log(options.logBuffer, '!!! Unarchive Failed: $e');
    options.onError?.call(e, st);
  });
}