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'; | |
8 | |
7 import 'package:path/path.dart' as p; | 9 import 'package:path/path.dart' as p; |
8 import 'package:pub_semver/pub_semver.dart'; | 10 import 'package:pub_semver/pub_semver.dart'; |
9 import 'package:source_span/source_span.dart'; | 11 import 'package:source_span/source_span.dart'; |
10 import 'package:yaml/yaml.dart'; | 12 import 'package:yaml/yaml.dart'; |
11 | 13 |
12 import 'io.dart'; | 14 import 'io.dart'; |
13 import 'package.dart'; | 15 import 'package.dart'; |
14 import 'source_registry.dart'; | 16 import 'source_registry.dart'; |
15 import 'utils.dart'; | 17 import 'utils.dart'; |
16 | 18 |
17 /// A parsed and validated `pubspec.lock` file. | 19 /// A parsed and validated `pubspec.lock` file. |
18 class LockFile { | 20 class LockFile { |
21 /// The source registry with which the lock file's IDs are interpreted. | |
22 /// | |
23 /// This is `null` for an empty lock file, since there are no IDs to | |
24 /// interpret. | |
25 final SourceRegistry _sources; | |
26 | |
19 /// The packages this lockfile pins. | 27 /// The packages this lockfile pins. |
20 Map<String, PackageId> packages; | 28 final Map<String, PackageId> packages; |
21 | 29 |
22 /// Creates a new lockfile containing [ids]. | 30 /// Creates a new lockfile containing [ids]. |
23 factory LockFile(List<PackageId> ids) { | 31 /// |
24 var lockFile = new LockFile.empty(); | 32 /// Throws an [ArgumentError] if any package has an undefined source according |
33 /// to [sources] or an unresolved ID according to [Source.isResolved]. | |
34 factory LockFile(Iterable<PackageId> ids, SourceRegistry sources) { | |
35 var packages = {}; | |
25 for (var id in ids) { | 36 for (var id in ids) { |
26 if (!id.isRoot) lockFile.packages[id.name] = id; | 37 if (id.isRoot) continue; |
38 | |
39 var source = sources[id.source]; | |
40 if (source == null) { | |
41 throw new ArgumentError('Undefined source "$source" for package "$id".') ; | |
Bob Nystrom
2015/08/07 21:50:56
Long line.
Also, does this do the right thing on
nweiz
2015/08/07 22:16:07
Done.
| |
42 } | |
43 | |
44 if (!source.isResolved(id)) { | |
45 throw new ArgumentError('ID "$id" is not resolved.'); | |
46 } | |
47 | |
48 packages[id.name] = id; | |
27 } | 49 } |
28 | 50 |
29 return lockFile; | 51 return new LockFile._(packages, sources); |
30 } | 52 } |
31 | 53 |
32 LockFile._(this.packages); | 54 LockFile._(Map<String, PackageId> packages, this._sources) |
55 : packages = new UnmodifiableMapView(packages); | |
33 | 56 |
34 LockFile.empty() | 57 LockFile.empty() |
35 : packages = <String, PackageId>{}; | 58 : packages = const {}, |
59 _sources = null; | |
36 | 60 |
37 /// Loads a lockfile from [filePath]. | 61 /// Loads a lockfile from [filePath]. |
38 factory LockFile.load(String filePath, SourceRegistry sources) { | 62 factory LockFile.load(String filePath, SourceRegistry sources) { |
39 return LockFile._parse(filePath, readTextFile(filePath), sources); | 63 return LockFile._parse(filePath, readTextFile(filePath), sources); |
40 } | 64 } |
41 | 65 |
42 /// Parses a lockfile whose text is [contents]. | 66 /// Parses a lockfile whose text is [contents]. |
43 factory LockFile.parse(String contents, SourceRegistry sources) { | 67 factory LockFile.parse(String contents, SourceRegistry sources) { |
44 return LockFile._parse(null, contents, sources); | 68 return LockFile._parse(null, contents, sources); |
45 } | 69 } |
46 | 70 |
47 /// Parses the lockfile whose text is [contents]. | 71 /// Parses the lockfile whose text is [contents]. |
48 /// | 72 /// |
49 /// [filePath] is the system-native path to the lockfile on disc. It may be | 73 /// [filePath] is the system-native path to the lockfile on disc. It may be |
50 /// `null`. | 74 /// `null`. |
51 static LockFile _parse(String filePath, String contents, | 75 static LockFile _parse(String filePath, String contents, |
52 SourceRegistry sources) { | 76 SourceRegistry sources) { |
53 var packages = <String, PackageId>{}; | 77 var packages = {}; |
54 | 78 |
55 if (contents.trim() == '') return new LockFile.empty(); | 79 if (contents.trim() == '') return new LockFile.empty(); |
56 | 80 |
57 var sourceUrl; | 81 var sourceUrl; |
58 if (filePath != null) sourceUrl = p.toUri(filePath); | 82 if (filePath != null) sourceUrl = p.toUri(filePath); |
59 var parsed = loadYamlNode(contents, sourceUrl: sourceUrl); | 83 var parsed = loadYamlNode(contents, sourceUrl: sourceUrl); |
60 | 84 |
61 _validate(parsed is Map, 'The lockfile must be a YAML mapping.', parsed); | 85 _validate(parsed is Map, 'The lockfile must be a YAML mapping.', parsed); |
62 | 86 |
63 var packageEntries = parsed['packages']; | 87 var packageEntries = parsed['packages']; |
(...skipping 29 matching lines...) Expand all Loading... | |
93 var id = new PackageId(name, sourceName, version, description); | 117 var id = new PackageId(name, sourceName, version, description); |
94 | 118 |
95 // Validate the name. | 119 // Validate the name. |
96 _validate(name == id.name, | 120 _validate(name == id.name, |
97 "Package name $name doesn't match ${id.name}.", spec); | 121 "Package name $name doesn't match ${id.name}.", spec); |
98 | 122 |
99 packages[name] = id; | 123 packages[name] = id; |
100 }); | 124 }); |
101 } | 125 } |
102 | 126 |
103 return new LockFile._(packages); | 127 return new LockFile._(packages, sources); |
104 } | 128 } |
105 | 129 |
106 /// If [condition] is `false` throws a format error with [message] for [node]. | 130 /// If [condition] is `false` throws a format error with [message] for [node]. |
107 static void _validate(bool condition, String message, YamlNode node) { | 131 static void _validate(bool condition, String message, YamlNode node) { |
108 if (condition) return; | 132 if (condition) return; |
109 throw new SourceSpanFormatException(message, node.span); | 133 throw new SourceSpanFormatException(message, node.span); |
110 } | 134 } |
111 | 135 |
112 /// Returns the serialized YAML text of the lock file. | 136 /// Returns the serialized YAML text of the lock file. |
113 /// | 137 /// |
114 /// [packageDir] is the containing directory of the root package, used to | 138 /// [packageDir] is the containing directory of the root package, used to |
115 /// properly serialize package descriptions. | 139 /// properly serialize package descriptions. |
116 String serialize(String packageDir, SourceRegistry sources) { | 140 String serialize(String packageDir) { |
117 // Convert the dependencies to a simple object. | 141 // Convert the dependencies to a simple object. |
118 var data = {}; | 142 var data = {}; |
119 packages.forEach((name, package) { | 143 packages.forEach((name, package) { |
120 var description = sources[package.source].serializeDescription(packageDir, | 144 var description = _sources[package.source] |
121 package.description); | 145 .serializeDescription(packageDir, package.description); |
122 | 146 |
123 data[name] = { | 147 data[name] = { |
124 'version': package.version.toString(), | 148 'version': package.version.toString(), |
125 'source': package.source, | 149 'source': package.source, |
126 'description': description | 150 'description': description |
127 }; | 151 }; |
128 }); | 152 }); |
129 | 153 |
130 return """ | 154 return """ |
131 # Generated by pub | 155 # Generated by pub |
132 # See http://pub.dartlang.org/doc/glossary.html#lockfile | 156 # See http://pub.dartlang.org/doc/glossary.html#lockfile |
133 ${yamlToString({'packages': data})} | 157 ${yamlToString({'packages': data})} |
134 """; | 158 """; |
135 } | 159 } |
136 } | 160 } |
OLD | NEW |