| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library pub.lock_file; | 5 library pub.lock_file; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import 'package:path/path.dart' as p; | 9 import 'package:path/path.dart' as p; |
| 10 import 'package:package_config/packages_file.dart' as packages_file; | 10 import 'package:package_config/packages_file.dart' as packages_file; |
| 11 import 'package:pub_semver/pub_semver.dart'; | 11 import 'package:pub_semver/pub_semver.dart'; |
| 12 import 'package:source_span/source_span.dart'; | 12 import 'package:source_span/source_span.dart'; |
| 13 import 'package:yaml/yaml.dart'; | 13 import 'package:yaml/yaml.dart'; |
| 14 | 14 |
| 15 import 'io.dart'; | 15 import 'io.dart'; |
| 16 import 'package.dart'; | 16 import 'package.dart'; |
| 17 import 'source_registry.dart'; | 17 import 'source_registry.dart'; |
| 18 import 'utils.dart'; | 18 import 'utils.dart'; |
| 19 | 19 |
| 20 /// A parsed and validated `pubspec.lock` file. | 20 /// A parsed and validated `pubspec.lock` file. |
| 21 class LockFile { | 21 class LockFile { |
| 22 /// The source registry with which the lock file's IDs are interpreted. | 22 /// The source registry with which the lock file's IDs are interpreted. |
| 23 final SourceRegistry _sources; | 23 final SourceRegistry _sources; |
| 24 | 24 |
| 25 /// The packages this lockfile pins. | 25 /// The packages this lockfile pins. |
| 26 final Map<String, PackageId> packages; | 26 final Map<String, PackageId> packages; |
| 27 | 27 |
| 28 /// Creates a new lockfile containing [ids]. | 28 /// Creates a new lockfile containing [ids]. |
| 29 /// | |
| 30 /// Throws an [ArgumentError] if any package has an unresolved ID according to | |
| 31 /// [Source.isResolved]. | |
| 32 factory LockFile(Iterable<PackageId> ids, SourceRegistry sources) { | 29 factory LockFile(Iterable<PackageId> ids, SourceRegistry sources) { |
| 33 var packages = {}; | 30 var packages = new Map.fromIterable( |
| 34 for (var id in ids) { | 31 ids.where((id) => !id.isRoot), |
| 35 if (id.isRoot) continue; | 32 key: (id) => id.name); |
| 36 | |
| 37 if (!sources[id.source].isResolved(id)) { | |
| 38 throw new ArgumentError('ID "$id" is not resolved.'); | |
| 39 } | |
| 40 | |
| 41 packages[id.name] = id; | |
| 42 } | |
| 43 | |
| 44 return new LockFile._(packages, sources); | 33 return new LockFile._(packages, sources); |
| 45 } | 34 } |
| 46 | 35 |
| 47 LockFile._(Map<String, PackageId> packages, this._sources) | 36 LockFile._(Map<String, PackageId> packages, this._sources) |
| 48 : packages = new UnmodifiableMapView(packages); | 37 : packages = new UnmodifiableMapView(packages); |
| 49 | 38 |
| 50 LockFile.empty(this._sources) | 39 LockFile.empty(this._sources) |
| 51 : packages = const {}; | 40 : packages = const {}; |
| 52 | 41 |
| 53 /// Loads a lockfile from [filePath]. | 42 /// Loads a lockfile from [filePath]. |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 _validate(spec.containsKey('source'), | 80 _validate(spec.containsKey('source'), |
| 92 'Package $name is missing a source.', spec); | 81 'Package $name is missing a source.', spec); |
| 93 var sourceName = spec['source']; | 82 var sourceName = spec['source']; |
| 94 | 83 |
| 95 _validate(spec.containsKey('description'), | 84 _validate(spec.containsKey('description'), |
| 96 'Package $name is missing a description.', spec); | 85 'Package $name is missing a description.', spec); |
| 97 var description = spec['description']; | 86 var description = spec['description']; |
| 98 | 87 |
| 99 // Let the source parse the description. | 88 // Let the source parse the description. |
| 100 var source = sources[sourceName]; | 89 var source = sources[sourceName]; |
| 90 var id; |
| 101 try { | 91 try { |
| 102 description = source.parseDescription(filePath, description, | 92 id = source.parseId(name, version, description); |
| 103 fromLockFile: true); | |
| 104 } on FormatException catch (ex) { | 93 } on FormatException catch (ex) { |
| 105 throw new SourceSpanFormatException(ex.message, | 94 throw new SourceSpanFormatException(ex.message, |
| 106 spec.nodes['source'].span); | 95 spec.nodes['description'].span); |
| 107 } | 96 } |
| 108 | 97 |
| 109 var id = new PackageId(name, sourceName, version, description); | |
| 110 | |
| 111 // Validate the name. | 98 // Validate the name. |
| 112 _validate(name == id.name, | 99 _validate(name == id.name, |
| 113 "Package name $name doesn't match ${id.name}.", spec); | 100 "Package name $name doesn't match ${id.name}.", spec); |
| 114 | 101 |
| 115 packages[name] = id; | 102 packages[name] = id; |
| 116 }); | 103 }); |
| 117 } | 104 } |
| 118 | 105 |
| 119 return new LockFile._(packages, sources); | 106 return new LockFile._(packages, sources); |
| 120 } | 107 } |
| 121 | 108 |
| 122 /// If [condition] is `false` throws a format error with [message] for [node]. | 109 /// If [condition] is `false` throws a format error with [message] for [node]. |
| 123 static void _validate(bool condition, String message, YamlNode node) { | 110 static void _validate(bool condition, String message, YamlNode node) { |
| 124 if (condition) return; | 111 if (condition) return; |
| 125 throw new SourceSpanFormatException(message, node.span); | 112 throw new SourceSpanFormatException(message, node.span); |
| 126 } | 113 } |
| 127 | 114 |
| 128 /// Returns a copy of this LockFile with [id] added. | 115 /// Returns a copy of this LockFile with [id] added. |
| 129 /// | 116 /// |
| 130 /// Throws an [ArgumentError] if [id] isn't resolved according to | 117 /// If there's already an ID with the same name as [id] in the LockFile, it's |
| 131 /// [Source.isResolved]. If there's already an ID with the same name as [id] | 118 /// overwritten. |
| 132 /// in the LockFile, it's overwritten. | |
| 133 LockFile setPackage(PackageId id) { | 119 LockFile setPackage(PackageId id) { |
| 134 if (id.isRoot) return this; | 120 if (id.isRoot) return this; |
| 135 | 121 |
| 136 if (!_sources[id.source].isResolved(id)) { | |
| 137 throw new ArgumentError('ID "$id" is not resolved.'); | |
| 138 } | |
| 139 | |
| 140 var packages = new Map.from(this.packages); | 122 var packages = new Map.from(this.packages); |
| 141 packages[id.name] = id; | 123 packages[id.name] = id; |
| 142 return new LockFile._(packages, _sources); | 124 return new LockFile._(packages, _sources); |
| 143 } | 125 } |
| 144 | 126 |
| 145 /// Returns a copy of this LockFile with a package named [name] removed. | 127 /// Returns a copy of this LockFile with a package named [name] removed. |
| 146 /// | 128 /// |
| 147 /// Returns an identical [LockFile] if there's no package named [name]. | 129 /// Returns an identical [LockFile] if there's no package named [name]. |
| 148 LockFile removePackage(String name) { | 130 LockFile removePackage(String name) { |
| 149 if (!this.packages.containsKey(name)) return this; | 131 if (!this.packages.containsKey(name)) return this; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 191 }; | 173 }; |
| 192 }); | 174 }); |
| 193 | 175 |
| 194 return """ | 176 return """ |
| 195 # Generated by pub | 177 # Generated by pub |
| 196 # See http://pub.dartlang.org/doc/glossary.html#lockfile | 178 # See http://pub.dartlang.org/doc/glossary.html#lockfile |
| 197 ${yamlToString({'packages': data})} | 179 ${yamlToString({'packages': data})} |
| 198 """; | 180 """; |
| 199 } | 181 } |
| 200 } | 182 } |
| OLD | NEW |