downloadPackage function

Future<void> downloadPackage(
  1. String package,
  2. String? version,
  3. {required String destination,
  4. String? pubHostedUrl}
)

Downloads package and unpacks it into destination

Implementation

Future<void> downloadPackage(
  String package,
  String? version, {
  required String destination,
  String? pubHostedUrl,
}) async {
  pubHostedUrl ??= 'https://pub.dartlang.org';
  final pubHostedUri = Uri.parse(pubHostedUrl);
  final client = http_retry.RetryClient(
    http.Client(),
    when: (rs) => rs.statusCode >= 500,
  );
  try {
    // Find URI for the package archive
    final versionsUri = pubHostedUri.replace(
        path: p.join(pubHostedUri.path, '/api/packages/$package'));
    final versionsRs = await client.get(versionsUri);
    if (versionsRs.statusCode != 200) {
      throw Exception(
          'Unable to access URL: "$versionsUri" (status code: ${versionsRs.statusCode}).');
    }
    final versionsJson = json.decode(versionsRs.body);
    if (version == null) {
      version = versionsJson['latest']['version'] as String;
      log.fine('Latest version is: $version');
    }

    final versions = versionsJson['versions'] as List;
    final data = versions
        .cast<Map<String, dynamic>>()
        .firstWhereOrNull((e) => e['version'] == version);
    if (data == null) {
      log.info(
          'Available versions: ${versions.map((e) => e['version']).join(', ')}');
      throw Exception('Version $version not found in version listing');
    }
    final archiveUrl = data['archive_url'] as String;

    var packageUri = Uri.parse(archiveUrl);
    if (!packageUri.hasScheme) {
      packageUri =
          pubHostedUri.replace(path: p.join(pubHostedUri.path, archiveUrl));
    }
    log.info('Downloading package $package $version from $packageUri');

    final rs = await client.get(packageUri);
    if (rs.statusCode != 200) {
      throw Exception(
          'Unable to access URL: "$packageUri" (status code: ${rs.statusCode}).');
    }
    await _extractTarGz(Stream.value(rs.bodyBytes), destination);
  } catch (e, st) {
    log.warning('Unable to download $package $version', e, st);
    rethrow;
  } finally {
    client.close();
  }
}