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})');
}
}