| 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 import 'dart:collection'; | 5 import 'dart:collection'; |
| 6 | 6 |
| 7 import 'package:path/path.dart' as p; | 7 import 'package:path/path.dart' as p; |
| 8 import 'package:package_config/packages_file.dart' as packages_file; | 8 import 'package:package_config/packages_file.dart' as packages_file; |
| 9 import 'package:pub_semver/pub_semver.dart'; | 9 import 'package:pub_semver/pub_semver.dart'; |
| 10 import 'package:source_span/source_span.dart'; | 10 import 'package:source_span/source_span.dart'; |
| 11 import 'package:yaml/yaml.dart'; | 11 import 'package:yaml/yaml.dart'; |
| 12 | 12 |
| 13 import 'io.dart'; | 13 import 'io.dart'; |
| 14 import 'package.dart'; | 14 import 'package.dart'; |
| 15 import 'source_registry.dart'; | 15 import 'source_registry.dart'; |
| 16 import 'system_cache.dart'; | 16 import 'system_cache.dart'; |
| 17 import 'utils.dart'; | 17 import 'utils.dart'; |
| 18 | 18 |
| 19 /// A parsed and validated `pubspec.lock` file. | 19 /// A parsed and validated `pubspec.lock` file. |
| 20 class LockFile { | 20 class LockFile { |
| 21 /// The source registry with which the lock file's IDs are interpreted. | |
| 22 final SourceRegistry _sources; | |
| 23 | |
| 24 /// The packages this lockfile pins. | 21 /// The packages this lockfile pins. |
| 25 final Map<String, PackageId> packages; | 22 final Map<String, PackageId> packages; |
| 26 | 23 |
| 27 /// The intersection of all SDK constraints for all locked packages. | 24 /// The intersection of all SDK constraints for all locked packages. |
| 28 final VersionConstraint sdkConstraint; | 25 final VersionConstraint sdkConstraint; |
| 29 | 26 |
| 30 /// Creates a new lockfile containing [ids]. | 27 /// Creates a new lockfile containing [ids]. |
| 31 /// | 28 /// |
| 32 /// If passed, [sdkConstraint] represents the intersection of all SKD | 29 /// If passed, [sdkConstraint] represents the intersection of all SKD |
| 33 /// constraints for all locked packages. It defaults to | 30 /// constraints for all locked packages. It defaults to |
| 34 /// [VersionConstraint.any]. | 31 /// [VersionConstraint.any]. |
| 35 LockFile(Iterable<PackageId> ids, SourceRegistry sources, | 32 LockFile(Iterable<PackageId> ids, {VersionConstraint sdkConstraint}) |
| 36 {VersionConstraint sdkConstraint}) | |
| 37 : this._( | 33 : this._( |
| 38 new Map.fromIterable( | 34 new Map.fromIterable( |
| 39 ids.where((id) => !id.isRoot), | 35 ids.where((id) => !id.isRoot), |
| 40 key: (id) => id.name), | 36 key: (id) => id.name), |
| 41 sdkConstraint ?? VersionConstraint.any, | 37 sdkConstraint ?? VersionConstraint.any); |
| 42 sources); | |
| 43 | 38 |
| 44 LockFile._(Map<String, PackageId> packages, this.sdkConstraint, this._sources) | 39 LockFile._(Map<String, PackageId> packages, this.sdkConstraint) |
| 45 : packages = new UnmodifiableMapView(packages); | 40 : packages = new UnmodifiableMapView(packages); |
| 46 | 41 |
| 47 LockFile.empty(this._sources) | 42 LockFile.empty() |
| 48 : packages = const {}, | 43 : packages = const {}, |
| 49 sdkConstraint = VersionConstraint.any; | 44 sdkConstraint = VersionConstraint.any; |
| 50 | 45 |
| 51 /// Loads a lockfile from [filePath]. | 46 /// Loads a lockfile from [filePath]. |
| 52 factory LockFile.load(String filePath, SourceRegistry sources) { | 47 factory LockFile.load(String filePath, SourceRegistry sources) { |
| 53 return LockFile._parse(filePath, readTextFile(filePath), sources); | 48 return LockFile._parse(filePath, readTextFile(filePath), sources); |
| 54 } | 49 } |
| 55 | 50 |
| 56 /// Parses a lockfile whose text is [contents]. | 51 /// Parses a lockfile whose text is [contents]. |
| 57 factory LockFile.parse(String contents, SourceRegistry sources) { | 52 factory LockFile.parse(String contents, SourceRegistry sources) { |
| 58 return LockFile._parse(null, contents, sources); | 53 return LockFile._parse(null, contents, sources); |
| 59 } | 54 } |
| 60 | 55 |
| 61 /// Parses the lockfile whose text is [contents]. | 56 /// Parses the lockfile whose text is [contents]. |
| 62 /// | 57 /// |
| 63 /// [filePath] is the system-native path to the lockfile on disc. It may be | 58 /// [filePath] is the system-native path to the lockfile on disc. It may be |
| 64 /// `null`. | 59 /// `null`. |
| 65 static LockFile _parse(String filePath, String contents, | 60 static LockFile _parse(String filePath, String contents, |
| 66 SourceRegistry sources) { | 61 SourceRegistry sources) { |
| 67 if (contents.trim() == '') return new LockFile.empty(sources); | 62 if (contents.trim() == '') return new LockFile.empty(); |
| 68 | 63 |
| 69 var sourceUrl; | 64 var sourceUrl; |
| 70 if (filePath != null) sourceUrl = p.toUri(filePath); | 65 if (filePath != null) sourceUrl = p.toUri(filePath); |
| 71 var parsed = loadYamlNode(contents, sourceUrl: sourceUrl); | 66 var parsed = loadYamlNode(contents, sourceUrl: sourceUrl); |
| 72 | 67 |
| 73 _validate(parsed is Map, 'The lockfile must be a YAML mapping.', parsed); | 68 _validate(parsed is Map, 'The lockfile must be a YAML mapping.', parsed); |
| 74 | 69 |
| 75 var sdkConstraint = VersionConstraint.any; | 70 var sdkConstraint = VersionConstraint.any; |
| 76 var sdkConstraintText = parsed['sdk']; | 71 var sdkConstraintText = parsed['sdk']; |
| 77 if (sdkConstraintText != null) { | 72 if (sdkConstraintText != null) { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 } | 113 } |
| 119 | 114 |
| 120 // Validate the name. | 115 // Validate the name. |
| 121 _validate(name == id.name, | 116 _validate(name == id.name, |
| 122 "Package name $name doesn't match ${id.name}.", spec); | 117 "Package name $name doesn't match ${id.name}.", spec); |
| 123 | 118 |
| 124 packages[name] = id; | 119 packages[name] = id; |
| 125 }); | 120 }); |
| 126 } | 121 } |
| 127 | 122 |
| 128 return new LockFile._(packages, sdkConstraint, sources); | 123 return new LockFile._(packages, sdkConstraint); |
| 129 } | 124 } |
| 130 | 125 |
| 131 /// Runs [fn] and wraps any [FormatException] it throws in a | 126 /// Runs [fn] and wraps any [FormatException] it throws in a |
| 132 /// [SourceSpanFormatException]. | 127 /// [SourceSpanFormatException]. |
| 133 /// | 128 /// |
| 134 /// [description] should be a noun phrase that describes whatever's being | 129 /// [description] should be a noun phrase that describes whatever's being |
| 135 /// parsed or processed by [fn]. [span] should be the location of whatever's | 130 /// parsed or processed by [fn]. [span] should be the location of whatever's |
| 136 /// being processed within the pubspec. | 131 /// being processed within the pubspec. |
| 137 static _wrapFormatException(String description, SourceSpan span, fn()) { | 132 static _wrapFormatException(String description, SourceSpan span, fn()) { |
| 138 try { | 133 try { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 151 | 146 |
| 152 /// Returns a copy of this LockFile with [id] added. | 147 /// Returns a copy of this LockFile with [id] added. |
| 153 /// | 148 /// |
| 154 /// If there's already an ID with the same name as [id] in the LockFile, it's | 149 /// If there's already an ID with the same name as [id] in the LockFile, it's |
| 155 /// overwritten. | 150 /// overwritten. |
| 156 LockFile setPackage(PackageId id) { | 151 LockFile setPackage(PackageId id) { |
| 157 if (id.isRoot) return this; | 152 if (id.isRoot) return this; |
| 158 | 153 |
| 159 var packages = new Map.from(this.packages); | 154 var packages = new Map.from(this.packages); |
| 160 packages[id.name] = id; | 155 packages[id.name] = id; |
| 161 return new LockFile._(packages, sdkConstraint, _sources); | 156 return new LockFile._(packages, sdkConstraint); |
| 162 } | 157 } |
| 163 | 158 |
| 164 /// Returns a copy of this LockFile with a package named [name] removed. | 159 /// Returns a copy of this LockFile with a package named [name] removed. |
| 165 /// | 160 /// |
| 166 /// Returns an identical [LockFile] if there's no package named [name]. | 161 /// Returns an identical [LockFile] if there's no package named [name]. |
| 167 LockFile removePackage(String name) { | 162 LockFile removePackage(String name) { |
| 168 if (!this.packages.containsKey(name)) return this; | 163 if (!this.packages.containsKey(name)) return this; |
| 169 | 164 |
| 170 var packages = new Map.from(this.packages); | 165 var packages = new Map.from(this.packages); |
| 171 packages.remove(name); | 166 packages.remove(name); |
| 172 return new LockFile._(packages, sdkConstraint, _sources); | 167 return new LockFile._(packages, sdkConstraint); |
| 173 } | 168 } |
| 174 | 169 |
| 175 /// Returns the contents of the `.packages` file generated from this lockfile. | 170 /// Returns the contents of the `.packages` file generated from this lockfile. |
| 176 /// | 171 /// |
| 177 /// If [entrypoint] is passed, a relative entry is added for its "lib/" | 172 /// If [entrypoint] is passed, a relative entry is added for its "lib/" |
| 178 /// directory. | 173 /// directory. |
| 179 String packagesFile(SystemCache cache, [String entrypoint]) { | 174 String packagesFile(SystemCache cache, [String entrypoint]) { |
| 180 var header = "Generated by pub on ${new DateTime.now()}."; | 175 var header = "Generated by pub on ${new DateTime.now()}."; |
| 181 | 176 |
| 182 var map = new Map.fromIterable(ordered(packages.keys), value: (name) { | 177 var map = new Map.fromIterable(ordered(packages.keys), value: (name) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 193 } | 188 } |
| 194 | 189 |
| 195 /// Returns the serialized YAML text of the lock file. | 190 /// Returns the serialized YAML text of the lock file. |
| 196 /// | 191 /// |
| 197 /// [packageDir] is the containing directory of the root package, used to | 192 /// [packageDir] is the containing directory of the root package, used to |
| 198 /// properly serialize package descriptions. | 193 /// properly serialize package descriptions. |
| 199 String serialize(String packageDir) { | 194 String serialize(String packageDir) { |
| 200 // Convert the dependencies to a simple object. | 195 // Convert the dependencies to a simple object. |
| 201 var packageMap = {}; | 196 var packageMap = {}; |
| 202 packages.forEach((name, package) { | 197 packages.forEach((name, package) { |
| 203 var description = _sources[package.source] | 198 var description = package.source |
| 204 .serializeDescription(packageDir, package.description); | 199 .serializeDescription(packageDir, package.description); |
| 205 | 200 |
| 206 packageMap[name] = { | 201 packageMap[name] = { |
| 207 'version': package.version.toString(), | 202 'version': package.version.toString(), |
| 208 'source': package.source, | 203 'source': package.source.name, |
| 209 'description': description | 204 'description': description |
| 210 }; | 205 }; |
| 211 }); | 206 }); |
| 212 | 207 |
| 213 var data = {'sdk': sdkConstraint.toString(), 'packages': packageMap}; | 208 var data = {'sdk': sdkConstraint.toString(), 'packages': packageMap}; |
| 214 return """ | 209 return """ |
| 215 # Generated by pub | 210 # Generated by pub |
| 216 # See http://pub.dartlang.org/doc/glossary.html#lockfile | 211 # See http://pub.dartlang.org/doc/glossary.html#lockfile |
| 217 ${yamlToString(data)} | 212 ${yamlToString(data)} |
| 218 """; | 213 """; |
| 219 } | 214 } |
| 220 } | 215 } |
| OLD | NEW |