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.source; | 5 library pub.source; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 | 8 |
9 import 'package:pub_semver/pub_semver.dart'; | 9 import 'package:pub_semver/pub_semver.dart'; |
10 | 10 |
(...skipping 19 matching lines...) Expand all Loading... |
30 | 30 |
31 /// Whether this source can choose between multiple versions of the same | 31 /// Whether this source can choose between multiple versions of the same |
32 /// package during version solving. | 32 /// package during version solving. |
33 /// | 33 /// |
34 /// Defaults to `false`. | 34 /// Defaults to `false`. |
35 final bool hasMultipleVersions = false; | 35 final bool hasMultipleVersions = false; |
36 | 36 |
37 /// Whether or not this source is the default source. | 37 /// Whether or not this source is the default source. |
38 bool get isDefault => systemCache.sources.defaultSource == this; | 38 bool get isDefault => systemCache.sources.defaultSource == this; |
39 | 39 |
| 40 /// A cache of pubspecs described by [describe]. |
| 41 final _pubspecs = <PackageId, Pubspec>{}; |
| 42 |
40 /// The system cache with which this source is registered. | 43 /// The system cache with which this source is registered. |
41 SystemCache get systemCache { | 44 SystemCache get systemCache { |
42 assert(_systemCache != null); | 45 assert(_systemCache != null); |
43 return _systemCache; | 46 return _systemCache; |
44 } | 47 } |
45 | 48 |
46 /// The system cache variable. | 49 /// The system cache variable. |
47 /// | 50 /// |
48 /// Set by [_bind]. | 51 /// Set by [_bind]. |
49 SystemCache _systemCache; | 52 SystemCache _systemCache; |
50 | 53 |
51 /// Records the system cache to which this source belongs. | 54 /// Records the system cache to which this source belongs. |
52 /// | 55 /// |
53 /// This should only be called once for each source, by | 56 /// This should only be called once for each source, by |
54 /// [SystemCache.register]. It should not be overridden by base classes. | 57 /// [SystemCache.register]. It should not be overridden by base classes. |
55 void bind(SystemCache systemCache) { | 58 void bind(SystemCache systemCache) { |
56 assert(_systemCache == null); | 59 assert(_systemCache == null); |
57 this._systemCache = systemCache; | 60 this._systemCache = systemCache; |
58 } | 61 } |
59 | 62 |
60 /// Get the pubspecs of all versions that exist for the package described by | 63 /// Get the IDs of all versions that match [ref]. |
61 /// [description]. | |
62 /// | |
63 /// [name] is the expected name of the package. | |
64 /// | 64 /// |
65 /// Note that this does *not* require the packages to be downloaded locally, | 65 /// Note that this does *not* require the packages to be downloaded locally, |
66 /// which is the point. This is used during version resolution to determine | 66 /// which is the point. This is used during version resolution to determine |
| 67 /// which package versions are available to be downloaded (or already |
| 68 /// downloaded). |
| 69 /// |
| 70 /// By default, this assumes that each description has a single version and |
| 71 /// uses [describe] to get that version. |
| 72 /// |
| 73 /// Sources should not override this. Instead, they implement [doGetVersions]. |
| 74 Future<List<PackageId>> getVersions(PackageRef ref) { |
| 75 if (ref.isRoot) { |
| 76 throw new ArgumentError("Cannot get versions for the root package."); |
| 77 } |
| 78 if (ref.source != name) { |
| 79 throw new ArgumentError("Package $ref does not use source $name."); |
| 80 } |
| 81 |
| 82 return doGetVersions(ref); |
| 83 } |
| 84 |
| 85 /// Get the IDs of all versions that match [ref]. |
| 86 /// |
| 87 /// Note that this does *not* require the packages to be downloaded locally, |
| 88 /// which is the point. This is used during version resolution to determine |
67 /// which package versions are available to be downloaded (or already | 89 /// which package versions are available to be downloaded (or already |
68 /// downloaded). | 90 /// downloaded). |
69 /// | 91 /// |
70 /// By default, this assumes that each description has a single version and | 92 /// By default, this assumes that each description has a single version and |
71 /// uses [describe] to get that version. | 93 /// uses [describe] to get that version. |
72 Future<List<Pubspec>> getVersions(String name, description) async { | 94 /// |
73 var id = new PackageId(name, this.name, Version.none, description); | 95 /// This method is effectively protected: subclasses must implement it, but |
74 return [await describe(id)]; | 96 /// external code should not call this. Instead, call [getVersions]. |
| 97 Future<List<PackageId>> doGetVersions(PackageRef ref) async { |
| 98 var pubspec = await describe(ref.atVersion(Version.none)); |
| 99 return [ref.atVersion(pubspec.version)]; |
75 } | 100 } |
76 | 101 |
77 /// Loads the (possibly remote) pubspec for the package version identified by | 102 /// Loads the (possibly remote) pubspec for the package version identified by |
78 /// [id]. | 103 /// [id]. |
79 /// | 104 /// |
80 /// This may be called for packages that have not yet been downloaded during | 105 /// This may be called for packages that have not yet been downloaded during |
81 /// the version resolution process. | 106 /// the version resolution process. Its results are automatically memoized. |
82 /// | 107 /// |
83 /// Sources should not override this. Instead, they implement [doDescribe]. | 108 /// Sources should not override this. Instead, they implement [doDescribe]. |
84 Future<Pubspec> describe(PackageId id) { | 109 Future<Pubspec> describe(PackageId id) async { |
85 if (id.isRoot) throw new ArgumentError("Cannot describe the root package."); | 110 if (id.isRoot) throw new ArgumentError("Cannot describe the root package."); |
86 if (id.source != name) { | 111 if (id.source != name) { |
87 throw new ArgumentError("Package $id does not use source $name."); | 112 throw new ArgumentError("Package $id does not use source $name."); |
88 } | 113 } |
89 | 114 |
| 115 var pubspec = _pubspecs[id]; |
| 116 if (pubspec != null) return pubspec; |
| 117 |
90 // Delegate to the overridden one. | 118 // Delegate to the overridden one. |
91 return doDescribe(id); | 119 pubspec = await doDescribe(id); |
| 120 _pubspecs[id.atVersion(pubspec.version)] = pubspec; |
| 121 return pubspec; |
92 } | 122 } |
93 | 123 |
94 /// Loads the (possibly remote) pubspec for the package version identified by | 124 /// Loads the (possibly remote) pubspec for the package version identified by |
95 /// [id]. | 125 /// [id]. |
96 /// | 126 /// |
97 /// This may be called for packages that have not yet been downloaded during | 127 /// This may be called for packages that have not yet been downloaded during |
98 /// the version resolution process. | 128 /// the version resolution process. |
99 /// | 129 /// |
100 /// This method is effectively protected: subclasses must implement it, but | 130 /// This method is effectively protected: subclasses must implement it, but |
101 /// external code should not call this. Instead, call [describe]. | 131 /// external code should not call this. Instead, call [describe]. |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 /// according to [parseDescription], although it must still be serializable | 208 /// according to [parseDescription], although it must still be serializable |
179 /// to JSON and YAML. It must also be equal to [id] according to | 209 /// to JSON and YAML. It must also be equal to [id] according to |
180 /// [descriptionsEqual]. | 210 /// [descriptionsEqual]. |
181 /// | 211 /// |
182 /// By default, this just returns [id]. | 212 /// By default, this just returns [id]. |
183 Future<PackageId> resolveId(PackageId id) => new Future.value(id); | 213 Future<PackageId> resolveId(PackageId id) => new Future.value(id); |
184 | 214 |
185 /// Returns whether [id] is fully-resolved, according to [resolveId]. | 215 /// Returns whether [id] is fully-resolved, according to [resolveId]. |
186 bool isResolved(PackageId id) => true; | 216 bool isResolved(PackageId id) => true; |
187 | 217 |
| 218 /// Stores [pubspec] so it's returned when [describe] is called with [id]. |
| 219 /// |
| 220 /// This is notionally protected; it should only be called by subclasses. |
| 221 void memoizePubspec(PackageId id, Pubspec pubspec) { |
| 222 _pubspecs[id] = pubspec; |
| 223 } |
| 224 |
188 /// Returns the source's name. | 225 /// Returns the source's name. |
189 String toString() => name; | 226 String toString() => name; |
190 } | 227 } |
OLD | NEW |