getRootfs method

Future<bool> getRootfs(
  1. String name,
  2. String image,
  3. {String? tag,
  4. required TotalProgressCallback progress,
  5. bool skipDownload = false}
)

Putting layers into single tar file

Implementation

Future<bool> getRootfs(String name, String image,
    {String? tag,
    required TotalProgressCallback progress,
    bool skipDownload = false}) async {
  distroName = name;
  var distroPath = getDistroPath().path;

  // Add library to image name
  if (image.split('/').length == 1) {
    image = 'library/$image';
  }

  // Replace special chars
  final imageName = filename(image, tag);
  final tmpImagePath = (getTmpPath()..cd(imageName)).path;

  // Create distro folder

  var layers = 0;
  bool done = false;

  if (!skipDownload) {
    await _download(image, tmpImagePath,
        (current, total, currentStep, totalStep) {
      layers = total;
      if (kDebugMode) {
        print('${current + 1}/$total');
      }
      progress(current, total, currentStep, totalStep);
      if (current + 1 == total && currentStep == totalStep) {
        done = true;
      }
    }, tag: tag);
  }

  // Wait for download to finish
  while (!done && !skipDownload) {
    await Future.delayed(const Duration(milliseconds: 500));
  }

  Notify.message('Extracting layers ...');

  // Extract layers
  // Write the compressed tar file to disk.
  int retry = 0;

  String outArchive = SafePath(distroPath).file('$imageName.tar.gz');
  while (retry < 2) {
    try {
      Archive archive = Archive();

      // More than one layer
      if (layers != 1) {
        for (var i = 0; i < layers; i++) {
          // Read archives layers
          if (kDebugMode) {
            print('Extracting layer $i of $layers');
          }
          // progress(i, layers, -1, -1);
          Notify.message('Extracting layer $i of $layers');

          // In memory
          final tarfile = GZipDecoder().decodeBytes(
              File(SafePath(tmpImagePath).file('layer_$i.tar.gz'))
                  .readAsBytesSync());
          final subArchive = TarDecoder().decodeBytes(tarfile);

          // Add files to archive
          for (final file in subArchive) {
            archive.addFile(file);
            if (kDebugMode && !file.name.contains('/')) {
              if (kDebugMode) {
                print('Adding root file ${file.name}');
              }
            }
          }
        }

        // Archive as tar then gzip to disk
        final tarfile = TarEncoder().encode(archive);
        final gzData = GZipEncoder().encode(tarfile);
        final fp = File(outArchive);

        Notify.message('writingtodisk-text'.i18n());
        fp.writeAsBytesSync(gzData!);
      } else if (layers == 1) {
        // Just copy the file
        File(SafePath(tmpImagePath).file('layer_0.tar.gz'))
            .copySync(outArchive);
      }

      retry = 2;
      break;
    } catch (e, stackTrace) {
      retry++;
      if (retry == 2) {
        logDebug(e, stackTrace, null);
      }
      await Future.delayed(const Duration(seconds: 1));
      if (kDebugMode) {
        print('Retrying $retry');
      }
    }
  }

  Notify.message('creatinginstance-text'.i18n());

  // Check if tar file is created
  if (!File(outArchive).existsSync()) {
    throw Exception('Tar file is not created');
  }
  // Wait for tar file to be created
  await Future.delayed(const Duration(seconds: 1));
  // Cleanup
  await Directory(tmpImagePath).delete(recursive: true);
  return true;
}