Chromium Code Reviews| Index: lib/src/lock_file.dart |
| diff --git a/lib/src/lock_file.dart b/lib/src/lock_file.dart |
| index 94c574b2ae1de6bbc2e663d6a702e165b93a3c87..9726a105cc14d807b420df22f1e33eb742c50d91 100644 |
| --- a/lib/src/lock_file.dart |
| +++ b/lib/src/lock_file.dart |
| @@ -25,19 +25,29 @@ class LockFile { |
| /// The packages this lockfile pins. |
| final Map<String, PackageId> packages; |
| - /// Creates a new lockfile containing [ids]. |
| - factory LockFile(Iterable<PackageId> ids, SourceRegistry sources) { |
| - var packages = new Map.fromIterable( |
| - ids.where((id) => !id.isRoot), |
| - key: (id) => id.name); |
| - return new LockFile._(packages, sources); |
| - } |
| + /// The intersection of all SDK constraints for all locked packages. |
| + final VersionConstraint sdkConstraint; |
| - LockFile._(Map<String, PackageId> packages, this._sources) |
| + /// Creates a new lockfile containing [ids]. |
| + /// |
| + /// If passed, [sdkConstraint] represents the intersection of all SKD |
| + /// constraints for all locked packages. It defaults to |
| + /// [VersionConstraint.any]. |
| + LockFile(Iterable<PackageId> ids, SourceRegistry sources, |
| + {VersionConstraint sdkConstraint}) |
| + : this._( |
| + new Map.fromIterable( |
| + ids.where((id) => !id.isRoot), |
| + key: (id) => id.name), |
| + sdkConstraint ?? VersionConstraint.any, |
| + sources); |
| + |
| + LockFile._(Map<String, PackageId> packages, this.sdkConstraint, this._sources) |
| : packages = new UnmodifiableMapView(packages); |
| LockFile.empty(this._sources) |
| - : packages = const {}; |
| + : packages = const {}, |
| + sdkConstraint = VersionConstraint.any; |
| /// Loads a lockfile from [filePath]. |
| factory LockFile.load(String filePath, SourceRegistry sources) { |
| @@ -55,8 +65,6 @@ class LockFile { |
| /// `null`. |
| static LockFile _parse(String filePath, String contents, |
| SourceRegistry sources) { |
| - var packages = {}; |
| - |
| if (contents.trim() == '') return new LockFile.empty(sources); |
| var sourceUrl; |
| @@ -65,6 +73,19 @@ class LockFile { |
| _validate(parsed is Map, 'The lockfile must be a YAML mapping.', parsed); |
| + var sdkConstraint = VersionConstraint.any; |
| + var sdkConstraintText = parsed['sdk']; |
| + if (sdkConstraintText != null) { |
| + _validate(sdkConstraintText is String, 'The "sdk" field must be a string.', |
|
Bob Nystrom
2015/12/21 20:55:03
Long line.
nweiz
2016/01/04 23:27:29
Done.
|
| + parsed.nodes['sdk']); |
| + |
| + sdkConstraint = _wrapFormatException( |
| + 'version constraint', |
| + parsed.nodes['sdk'], |
| + () => new VersionConstraint.parse(sdkConstraintText)); |
| + } |
| + |
| + var packages = {}; |
| var packageEntries = parsed['packages']; |
| if (packageEntries != null) { |
| _validate(packageEntries is Map, 'The "packages" field must be a map.', |
| @@ -103,7 +124,22 @@ class LockFile { |
| }); |
| } |
| - return new LockFile._(packages, sources); |
| + return new LockFile._(packages, sdkConstraint, sources); |
| + } |
| + |
| + /// Runs [fn] and wraps any [FormatException] it throws in a |
| + /// [SourceSpanFormatException]. |
| + /// |
| + /// [description] should be a noun phrase that describes whatever's being |
| + /// parsed or processed by [fn]. [span] should be the location of whatever's |
| + /// being processed within the pubspec. |
| + static _wrapFormatException(String description, SourceSpan span, fn()) { |
| + try { |
| + return fn(); |
| + } on FormatException catch (e) { |
| + throw new SourceSpanFormatException( |
| + 'Invalid $description: ${e.message}', span); |
| + } |
| } |
|
Bob Nystrom
2015/12/21 20:55:03
Do we do this elsewhere? Maybe move it into utils?
nweiz
2016/01/04 23:27:29
We do something similar in pubspec.dart, but it th
|
| /// If [condition] is `false` throws a format error with [message] for [node]. |
| @@ -121,7 +157,7 @@ class LockFile { |
| var packages = new Map.from(this.packages); |
| packages[id.name] = id; |
| - return new LockFile._(packages, _sources); |
| + return new LockFile._(packages, sdkConstraint, _sources); |
| } |
| /// Returns a copy of this LockFile with a package named [name] removed. |
| @@ -132,7 +168,7 @@ class LockFile { |
| var packages = new Map.from(this.packages); |
| packages.remove(name); |
| - return new LockFile._(packages, _sources); |
| + return new LockFile._(packages, sdkConstraint, _sources); |
| } |
| /// Returns the contents of the `.packages` file generated from this lockfile. |
| @@ -161,22 +197,23 @@ class LockFile { |
| /// properly serialize package descriptions. |
| String serialize(String packageDir) { |
| // Convert the dependencies to a simple object. |
| - var data = {}; |
| + var packageMap = {}; |
| packages.forEach((name, package) { |
| var description = _sources[package.source] |
| .serializeDescription(packageDir, package.description); |
| - data[name] = { |
| + packageMap[name] = { |
| 'version': package.version.toString(), |
| 'source': package.source, |
| 'description': description |
| }; |
| }); |
| + var data = {'sdk': sdkConstraint.toString(), 'packages': packageMap}; |
| return """ |
| # Generated by pub |
| # See http://pub.dartlang.org/doc/glossary.html#lockfile |
| -${yamlToString({'packages': data})} |
| +${yamlToString(data)} |
| """; |
| } |
| } |