generateManifest function

Future<PrebuiltManifest> generateManifest({
  1. required NativePrebuiltConfig config,
  2. required String tag,
  3. required bool allowMissing,
  4. Directory? builtLibraryDir,
  5. Directory? releaseAssetsDir,
  6. bool toleratePartialBuiltLibrary = false,
})

Implementation

Future<PrebuiltManifest> generateManifest({
  required NativePrebuiltConfig config,
  required String tag,
  required bool allowMissing,
  Directory? builtLibraryDir,
  Directory? releaseAssetsDir,
  bool toleratePartialBuiltLibrary = false,
}) async {
  final downloader = HttpDownloader();
  final archiveReader = ArchiveReader();
  final tempDir = await Directory.systemTemp.createTemp(
    'native_prebuilt_manifest_',
  );
  if (releaseAssetsDir != null) {
    releaseAssetsDir.createSync(recursive: true);
  }
  try {
    final payloadHashes = <String, String>{};
    final artifacts = <String, PrebuiltArtifact>{};

    for (final entry in config.artifacts.entries) {
      final platform = entry.key;
      final artifactConfig = entry.value;
      final target = targetFromPlatformLabel(platform);
      final payload = artifactConfig.payload.toArtifactPayload(
        config.libraryStem,
      );
      final canonicalName = canonicalLibraryName(
        target: target,
        libraryStem: config.libraryStem,
        payload: payload,
      );

      final archiveFile = File(
        p.join((releaseAssetsDir ?? tempDir).path, artifactConfig.archive),
      );
      if (builtLibraryDir != null) {
        final builtFileSearch = _findBuiltLibraryFile(
          builtLibraryDir: builtLibraryDir,
          platform: platform,
          canonicalName: canonicalName,
        );

        if (builtFileSearch == null) {
          if (allowMissing || toleratePartialBuiltLibrary) continue;

          throw StateError(
            'Missing built library for $platform. Checked:\n'
            '  ${p.join(builtLibraryDir.path, platform, canonicalName)}\n'
            '  ${p.join(builtLibraryDir.path, canonicalName)}\n'
            '  ${p.join(builtLibraryDir.path, platform)}/**/$canonicalName',
          );
        }

        await packageBuiltLibrary(
          builtFile: builtFileSearch,
          archiveFile: archiveFile,
        );
      } else {
        try {
          await downloader.downloadReleaseArtifact(
            source: config.release.toReleaseSource().withTag(tag),
            archiveName: artifactConfig.archive,
            targetPath: archiveFile,
          );
        } catch (e) {
          if (allowMissing) continue;
          rethrow;
        }
      }

      final archiveHash = await ArchiveReader.sha256Hash(archiveFile);

      final extractedDir = Directory(p.join(tempDir.path, 'extract_$platform'))
        ..createSync(recursive: true);
      final extracted = archiveReader.extractMatchingEntry(
        archiveFile: archiveFile,
        outputDir: extractedDir,
        selection: ArchiveSelectionContext(
          canonicalName: canonicalName,
          acceptVersionedNames: payload is DynamicLibraryPayload,
        ),
      );
      if (extracted == null) {
        if (allowMissing) continue;
        throw StateError('No payload found for $platform');
      }
      payloadHashes[platform] = await ArchiveReader.sha256Hash(extracted);

      artifacts[platform] = PrebuiltArtifact(
        archiveName: artifactConfig.archive,
        archiveSha256: archiveHash,
        payloadSha256: payloadHashes[platform]!,
        payload: payload,
      );
    }

    return PrebuiltManifest(
      schemaVersion: config.schema,
      release: config.release.toReleaseSource().withTag(tag),
      artifacts: artifacts,
    );
  } finally {
    tempDir.deleteSync(recursive: true);
  }
}