Support advisories with several affected packages with 'pub' a… (#4176)
diff --git a/lib/src/source/hosted.dart b/lib/src/source/hosted.dart
index 0439faf..7a2c9de 100644
--- a/lib/src/source/hosted.dart
+++ b/lib/src/source/hosted.dart
@@ -665,55 +665,60 @@
throw FormatException('affectedPackages must be a list');
}
- final affectedPkg = affectedPackages.firstWhereOrNull((element) {
- if (element is! Map) {
+ bool matchesNameAndEcosystem(
+ dynamic affectedPackage,
+ String name,
+ String ecosystem,
+ ) {
+ if (affectedPackage is! Map) {
throw FormatException('affectedPackage must be a map');
}
- final pkg = element['package'];
- if (pkg is! Map) {
+ final package = affectedPackage['package'];
+ if (package is! Map) {
throw FormatException('package must be a map');
}
- final name = pkg['name'];
- if (name is! String) {
+ final affectedName = package['name'];
+ if (affectedName is! String) {
throw FormatException('package name must be a String');
}
- if (name == packageName) {
- final ecosystem = pkg['ecosystem'];
- if (ecosystem is! String) {
+ if (affectedName == name) {
+ final affectedEcosystem = package['ecosystem'];
+ if (affectedEcosystem is! String) {
throw FormatException('ecosystem must be a String');
}
- return ecosystem.toLowerCase() == 'pub';
+ return affectedEcosystem.toLowerCase() == ecosystem;
}
return false;
- }) as Map?;
-
- if (affectedPkg == null) {
- throw FormatException(
- 'Advisory $id does not contain $packageName among its affected packages.',
- );
- }
- final affectedVersions = <String>{};
- final versions = affectedPkg['versions'];
- if (versions is! List) {
- throw FormatException('package versions must be a list');
}
- for (final v in versions) {
- if (v is! String) {
- throw FormatException('package version elements must be a string');
+ for (final affectedPackage in affectedPackages) {
+ if (matchesNameAndEcosystem(affectedPackage, packageName, 'pub')) {
+ final affectedVersions = <String>{};
+ final versions = affectedPackage['versions'];
+ if (versions is! List) {
+ throw FormatException('package versions must be a list');
+ }
+
+ for (final v in versions) {
+ if (v is! String) {
+ throw FormatException(
+ 'package version elements must be a string',
+ );
+ }
+ affectedVersions.add(v);
+ }
+
+ advisoriesList.add(
+ Advisory(
+ id: id,
+ affectedVersions: affectedVersions,
+ aliases: aliasIDs,
+ summary: summary,
+ pubDisplayUrl: pubDisplayUrl,
+ ),
+ );
}
- affectedVersions.add(v);
}
-
- advisoriesList.add(
- Advisory(
- id: id,
- affectedVersions: affectedVersions,
- aliases: aliasIDs,
- summary: summary,
- pubDisplayUrl: pubDisplayUrl,
- ),
- );
}
return advisoriesList;
diff --git a/test/get/hosted/advisory_test.dart b/test/get/hosted/advisory_test.dart
index df50293..0392168 100644
--- a/test/get/hosted/advisory_test.dart
+++ b/test/get/hosted/advisory_test.dart
@@ -190,6 +190,35 @@
await ctx.run(['get']);
});
+ testWithGolden('show advisory - same package mentioned twice', (ctx) async {
+ final server = await servePackages();
+ server
+ ..serve('foo', '1.0.0')
+ ..serve('foo', '1.2.3')
+ ..serve('baz', '1.0.0');
+
+ await d.dir(appPath, [
+ d.pubspec({
+ 'name': 'app',
+ 'dependencies': {
+ 'foo': '^1.0.0',
+ 'baz': '^1.0.0',
+ },
+ }),
+ ]).create();
+
+ server.addAdvisory(
+ advisoryId: '123',
+ displayUrl: 'https://github.com/advisories/123',
+ affectedPackages: [
+ AffectedPackage(name: 'foo', versions: ['1.0.0']),
+ AffectedPackage(name: 'foo', versions: ['1.2.3']),
+ ],
+ );
+
+ await ctx.run(['get']);
+ });
+
testWithGolden('show id if no display url is present', (ctx) async {
final server = await servePackages();
server
diff --git a/test/package_server.dart b/test/package_server.dart
index bbaf2a6..1b142b2 100644
--- a/test/package_server.dart
+++ b/test/package_server.dart
@@ -143,7 +143,7 @@
jsonEncode({
'advisoriesUpdated': defaultAdvisoriesUpdated.toIso8601String(),
'advisories': [
- for (final advisory in package.advisories)
+ for (final advisory in package.advisories.values)
{
'id': advisory.id,
'summary': 'Example',
@@ -345,8 +345,14 @@
for (final package in affectedPackages) {
_packages[package.name]!.advisoriesUpdated =
advisoriesUpdated ?? defaultAdvisoriesUpdated;
- _packages[package.name]!.advisories.add(
- _ServedAdvisory(advisoryId, affectedPackages, aliases, displayUrl),
+ _packages[package.name]!.advisories.putIfAbsent(
+ advisoryId,
+ () => _ServedAdvisory(
+ advisoryId,
+ affectedPackages,
+ aliases,
+ displayUrl,
+ ),
);
}
}
@@ -409,7 +415,7 @@
bool isDiscontinued = false;
String? discontinuedReplacementText;
DateTime? advisoriesUpdated;
- final advisories = <_ServedAdvisory>[];
+ final advisories = <String, _ServedAdvisory>{};
}
/// A package that's intended to be served.
diff --git a/test/testdata/goldens/get/hosted/advisory_test/show advisory - same package mentioned twice.txt b/test/testdata/goldens/get/hosted/advisory_test/show advisory - same package mentioned twice.txt
new file mode 100644
index 0000000..d8eda1a
--- /dev/null
+++ b/test/testdata/goldens/get/hosted/advisory_test/show advisory - same package mentioned twice.txt
@@ -0,0 +1,12 @@
+# GENERATED BY: test/get/hosted/advisory_test.dart
+
+## Section 0
+$ pub get
+Resolving dependencies...
+Downloading packages...
++ baz 1.0.0
++ foo 1.2.3 (affected by advisory: [^0])
+Changed 2 dependencies!
+Dependencies are affected by security advisories:
+ [^0]: https://github.com/advisories/123
+