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 |