Skip to content

Commit

Permalink
Forbid unknown description keys (after 3.7) (#4458)
Browse files Browse the repository at this point in the history
  • Loading branch information
sigurdm authored Dec 3, 2024
1 parent 30bfc43 commit b3b6b87
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 1 deletion.
2 changes: 2 additions & 0 deletions lib/src/global_packages.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import 'entrypoint.dart';
import 'exceptions.dart';
import 'executable.dart' as exec;
import 'io.dart';
import 'language_version.dart';
import 'lock_file.dart';
import 'log.dart' as log;
import 'package.dart';
Expand Down Expand Up @@ -114,6 +115,7 @@ class GlobalPackages {
if (ref != null) 'ref': ref,
},
containingDescription: RootDescription(p.current),
languageVersion: LanguageVersion.fromVersion(sdk.version),
);
} on FormatException catch (e) {
throw ApplicationException(e.message);
Expand Down
5 changes: 5 additions & 0 deletions lib/src/language_version.dart
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ class LanguageVersion implements Comparable<LanguageVersion> {

bool get supportsWorkspaces => this >= firstVersionWithWorkspaces;

bool get forbidsUnknownDescriptionKeys =>
this >= firstVersionForbidingUnknownDescriptionKeys;

/// Minimum language version at which short hosted syntax is supported.
///
/// This allows `hosted` dependencies to be expressed as:
Expand Down Expand Up @@ -109,6 +112,8 @@ class LanguageVersion implements Comparable<LanguageVersion> {
static const firstVersionWithNullSafety = LanguageVersion(2, 12);
static const firstVersionWithShorterHostedSyntax = LanguageVersion(2, 15);
static const firstVersionWithWorkspaces = LanguageVersion(3, 5);
static const firstVersionForbidingUnknownDescriptionKeys =
LanguageVersion(3, 7);

/// Transform language version to string that can be parsed with
/// [LanguageVersion.parse].
Expand Down
12 changes: 11 additions & 1 deletion lib/src/source/git.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class GitSource extends CachedSource {
String name,
Object? description, {
Description? containingDescription,
LanguageVersion? languageVersion,
required LanguageVersion languageVersion,
}) {
String url;
String? ref;
Expand Down Expand Up @@ -72,6 +72,16 @@ class GitSource extends CachedSource {
'string.');
}
path = descriptionPath;

if (languageVersion.forbidsUnknownDescriptionKeys) {
for (final key in description.keys) {
if (!['url', 'ref', 'path'].contains(key)) {
throw FormatException(
'Unknown key "$key" in description.',
);
}
}
}
}

final containingDir = switch (containingDescription) {
Expand Down
9 changes: 9 additions & 0 deletions lib/src/source/hosted.dart
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,15 @@ class HostedSource extends CachedSource {
}
final url = u ?? defaultUrl;

if (languageVersion.forbidsUnknownDescriptionKeys) {
for (final key in description.keys) {
if (!['url', 'name'].contains(key)) {
throw FormatException(
'Unknown key "$key" in description.',
);
}
}
}
return HostedDescription(name, url as String);
}

Expand Down
34 changes: 34 additions & 0 deletions test/pubspec_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1133,5 +1133,39 @@ name: 'foo'
);
});
});
test(
'Throws after language 3.7 '
'if using unknown keys in dependency description', () {
expectPubspecException(
'''
environment:
sdk: 3.7.0
dependencies:
foo:
hosted:
name: 'foo'
url: https://pub.dev/
someOtherProperty: 'smile'
''',
(pubspec) => pubspec.dependencies,
expectedContains: 'Unknown key "someOtherProperty" in description.',
);

expectPubspecException(
'''
environment:
sdk: 3.7.0
dependencies:
test:
git:
ref: 'v1.0.0'
url: https://github.com/dart-lang/test
path: 'pkgs/test'
someOtherProperty: 'smile'
''',
(pubspec) => pubspec.dependencies,
expectedContains: 'Unknown key "someOtherProperty" in description.',
);
});
});
}
104 changes: 104 additions & 0 deletions test/unknown_properties_in_description_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:pub/src/exit_codes.dart';
import 'package:test/test.dart';

import 'descriptor.dart' as d;
import 'test_pub.dart';

void main() {
test('Ignores additional properties in descriptions before 3.7', () async {
final server = await servePackages();
server.serve(
'foo',
'1.0.0',
sdk: '^3.6.0',
deps: {
'bar': {
'hosted': {'url': server.url, 'unknown': 11},
},
},
);
server.serve('bar', '1.0.0');
await d.appDir(
pubspec: {
'environment': {'sdk': '^3.6.0'},
},
dependencies: {
'foo': {
'hosted': {'url': server.url, 'unknown': 11},
'version': '^1.0.0',
},
},
).create();
await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '3.7.0'});
});

test('Detects unknown attributes in descriptions in root project after 3.7',
() async {
final server = await servePackages();
server.serve(
'foo',
'1.0.0',
sdk: '^3.6.0',
deps: {
'bar': {
'hosted': {'url': server.url, 'unknown': 11},
},
},
);
server.serve('bar', '1.0.0');
await d.appDir(
pubspec: {
'environment': {'sdk': '^3.7.0'},
},
dependencies: {
'foo': {
'hosted': {'url': server.url, 'unknown': 11},
'version': '^1.0.0',
},
},
).create();
await pubGet(
environment: {'_PUB_TEST_SDK_VERSION': '3.7.0'},
error: contains('Invalid description in the "myapp" pubspec '
'on the "foo" dependency: Unknown key "unknown" in description.'),
exitCode: DATA,
);
});

test('Detects unknown attributes in descriptions in dependency after 3.7',
() async {
final server = await servePackages();
server.serve(
'foo',
'1.0.0',
sdk: '^3.7.0',
deps: {
'bar': {
'hosted': {'url': server.url, 'unknown': 11},
},
},
);
server.serve('bar', '1.0.0');
await d.appDir(
pubspec: {
'environment': {'sdk': '^3.6.0'},
},
dependencies: {
'foo': {
'hosted': {'url': server.url, 'unknown': 11},
'version': '^1.0.0',
},
},
).create();
await pubGet(
environment: {'_PUB_TEST_SDK_VERSION': '3.7.0'},
error: contains('Invalid description in the "foo" pubspec '
'on the "bar" dependency: Unknown key "unknown" in description.'),
exitCode: DATA,
);
});
}

0 comments on commit b3b6b87

Please sign in to comment.