Stream _checkPackage()

in app/lib/shared/integrity.dart [222:427]


  Stream<String> _checkPackage(Package p) async* {
    if (p.name == null) {
      yield 'Package "${p.id}" has a `name` property which is null.';
    } else if (p.name != p.id) {
      yield 'Package "${p.id}" has a `name` property which is not the same as the id.';
    } else {
      _packages.add(p.name!);
    }
    if (p.replacedBy != null) {
      _packageReplacedBys[p.name!] = p.replacedBy!;

      if (!p.isDiscontinued) {
        yield 'Package "${p.name}" has a `replacedBy` property without being `isDiscontinued`.';
      }
    }
    // empty uploaders
    if (p.uploaders == null || p.uploaders!.isEmpty) {
      // no publisher
      if (p.publisherId == null && !p.isDiscontinued) {
        yield 'Package "${p.name}" has no uploaders, must be marked discontinued.';
      }

      if (p.publisherId != null &&
          _publishersAbandoned.contains(p.publisherId) &&
          !p.isDiscontinued) {
        yield 'Package "${p.name}" has an abandoned publisher, must be marked discontinued.';
      }
    }
    if (p.assignedTags == null || p.assignedTags is! List<String>) {
      yield 'Package "${p.name}" has an `assignedTags` property which is not a list.';
    }
    final assignedTags = p.assignedTags ?? <String>[];
    for (final tag in assignedTags) {
      if (!allowedTagPrefixes.any(tag.startsWith)) {
        yield 'Package "${p.name}" has assigned tag "$tag" in `assignedTags` '
            'property, which is not allowed.';
      }
    }
    if (assignedTags.length != assignedTags.toSet().length) {
      yield 'Package "${p.name}" has an `assignedTags` property which contains duplicates.';
    }
    if (p.likes < 0) {
      yield 'Package "${p.name}" has a `likes` property which is not a non-negative integer.';
    }
    final uploaders = p.uploaders;
    if (uploaders != null) {
      for (final userId in uploaders) {
        yield* _checkUserValid(
          userId,
          entityType: 'Package',
          entityId: p.name,
        );
      }
    }
    if (p.deletedVersions != null) {
      // make sure we store valid versions here
      for (final v in p.deletedVersions!) {
        final c = canonicalizeVersion(v);
        if (c == null) {
          yield 'Package "{p.name}" has invalid deleted version "$v".';
        }
      }
    }
    final versionKeys = <Key>{};
    final qualifiedVersionKeys = <QualifiedVersionKey>{};
    int versionCountUntilLastPublished = 0;
    await for (final pv
        in _db.query<PackageVersion>(ancestorKey: p.key).run()) {
      versionKeys.add(pv.key);
      qualifiedVersionKeys.add(pv.qualifiedVersionKey);
      if (p.deletedVersions != null &&
          p.deletedVersions!.contains(pv.version!)) {
        yield 'PackageVersion "${pv.qualifiedVersionKey}" exists, but is marked as deleted in Package "${p.name}".';
      }
      // Count only the versions that were created before the last published timestamp,
      // to prevent false alarms that could happing if a new version is being published
      // while the integrity check is running.
      if (!pv.created!.isAfter(p.lastVersionPublished!)) {
        versionCountUntilLastPublished++;
      }
    }
    if (p.versionCount != versionCountUntilLastPublished) {
      yield 'Package "${p.name}" has `versionCount` (${p.versionCount}) that differs from the '
          'number of versions until the last published date ($versionCountUntilLastPublished). '
          'Total number of versions: ${versionKeys.length}.';
    }
    if (p.lastVersionPublished == null) {
      yield 'Package "${p.name}" has a `lastVersionPublished` property which is null.';
    }
    if (p.latestPublished == null) {
      yield 'Package "${p.name}" has a `latestPublished` property which is null.';
    }
    if (p.latestPrereleasePublished == null) {
      yield 'Package "${p.name}" has a `latestPrereleasePublished` property which is null.';
    }
    if (p.latestPreviewPublished == null) {
      yield 'Package "${p.name}" has a `latestPreviewPublished` property which is null.';
    }
    if (p.lastVersionPublished != null &&
        p.latestPublished != null &&
        p.lastVersionPublished!.isBefore(p.latestPreviewPublished!)) {
      yield 'Package "${p.name}" has a `lastVersionPublished` property which is before its `latestPublished`.';
    }
    if (p.lastVersionPublished != null &&
        p.latestPrereleasePublished != null &&
        p.lastVersionPublished!.isBefore(p.latestPrereleasePublished!)) {
      yield 'Package "${p.name}" has a `lastVersionPublished` property which is before its `latestPrereleasePublished`. (${p.latestVersion} ${p.latestPrereleaseVersion}, ${p.lastVersionPublished} - ${p.latestPrereleasePublished})';
    }
    if (p.lastVersionPublished != null &&
        p.latestPreviewPublished != null &&
        p.lastVersionPublished!.isBefore(p.latestPreviewPublished!)) {
      yield 'Package "${p.name}" has a `lastVersionPublished` property which is before its `latestPreviewPublished`.';
    }

    if (p.latestVersionKey == null) {
      yield 'Package "${p.name}" has a `latestVersionKey` property which is null.';
    } else if (!versionKeys.contains(p.latestVersionKey)) {
      'Package "${p.name}" has missing `latestVersionKey`: "${p.latestVersionKey!.id}".';
    }
    if (p.latestPrereleaseVersionKey == null) {
      yield 'Package "${p.name}" has a `latestPrereleaseVersionKey` property which is null.';
    } else if (!versionKeys.contains(p.latestPrereleaseVersionKey)) {
      yield 'Package "${p.name}" has missing `latestPrereleaseVersionKey`: "${p.latestPrereleaseVersionKey!.id}".';
    }
    if (p.latestPreviewVersionKey == null) {
      yield 'Package "${p.name}" has a `latestPreviewVersionKey` property which is null.';
    } else if (!versionKeys.contains(p.latestPreviewVersionKey)) {
      yield 'Package "${p.name}" has missing `latestPreviewVersionKey`: "${p.latestPreviewVersionKey!.id}".';
    }

    // Checking if PackageVersionInfo is referenced by a PackageVersion entity.
    final pviQuery = _db.query<PackageVersionInfo>()
      ..filter('package =', p.name);
    final pviKeys = <QualifiedVersionKey>{};
    final referencedAssetIds = <String>[];
    await for (PackageVersionInfo pvi in pviQuery.run()) {
      final key = pvi.qualifiedVersionKey;
      pviKeys.add(key);
      if (!qualifiedVersionKeys.contains(key)) {
        yield 'PackageVersionInfo "$key" has no PackageVersion.';
      }
      if (pvi.versionCreated == null) {
        yield 'PackageVersionInfo "$key" has a `versionCreated` property which is null.';
      }
      if (pvi.updated == null) {
        yield 'PackageVersionInfo "$key" has an `updated` property which is null.';
      }
      if (pvi.libraryCount == null) {
        yield 'PackageVersionInfo "$key" has a `libraryCount` property which is null.';
      }
      for (final kind in pvi.assets) {
        referencedAssetIds.add(key.assetId(kind));
      }
    }
    for (QualifiedVersionKey key in qualifiedVersionKeys) {
      if (!pviKeys.contains(key)) {
        yield 'PackageVersion "$key" has no PackageVersionInfo.';
      }
    }

    // Checking if PackageVersionAsset is referenced by a PackageVersion entity.
    final pvaQuery = _db.query<PackageVersionAsset>()
      ..filter('package =', p.name);
    final foundAssetIds = <String?>{};
    await for (PackageVersionAsset pva in pvaQuery.run()) {
      final key = pva.qualifiedVersionKey;
      if (pva.id !=
          Uri(pathSegments: [pva.package!, pva.version!, pva.kind!]).path) {
        yield 'PackageVersionAsset "${pva.id}" uses old id format.';
        continue;
      }
      if (!qualifiedVersionKeys.contains(key)) {
        yield 'PackageVersionAsset "${pva.id}" has no PackageVersion.';
      }
      foundAssetIds.add(pva.assetId);
      // check if PackageVersionAsset is referenced in PackageVersionInfo
      if (!referencedAssetIds.contains(pva.assetId)) {
        yield 'PackageVersionAsset "${pva.id}" is not referenced from PackageVersionInfo.';
      }
      // check pubspec content
      if (pva.kind == AssetKind.pubspec) {
        try {
          final pubspec = Pubspec.fromYaml(pva.textContent!);
          if (pubspec.hasBadVersionFormat) {
            _badVersionInPubspec
                .putIfAbsent(p.name!, () => <String>{})
                .add(pva.version!);
          }
        } catch (e) {
          yield 'PackageVersionAsset "${pva.id}" "pubspec" has parse error: $e.';
        }
      }
    }

    // check if all of PackageVersionInfo.assets exist
    for (final id in referencedAssetIds) {
      if (!foundAssetIds.contains(id)) {
        yield 'PackageVersionAsset "$id" is referenced from PackageVersionInfo but does not exist.';
      }
    }

    _packageChecked++;
    if (_packageChecked % 200 == 0) {
      _logger.info('  .. $_packageChecked done (${p.name})');
    }
  }