| Index: lib/src/source.dart
|
| diff --git a/lib/src/source.dart b/lib/src/source.dart
|
| index e49b17f737a4cfda1ef444b231f2bb912751e47f..7e5625a2a5b079ca0479afca0a711caa04422f0d 100644
|
| --- a/lib/src/source.dart
|
| +++ b/lib/src/source.dart
|
| @@ -37,6 +37,9 @@ abstract class Source {
|
| /// Whether or not this source is the default source.
|
| bool get isDefault => systemCache.sources.defaultSource == this;
|
|
|
| + /// A cache of pubspecs described by [describe].
|
| + final _pubspecs = <PackageId, Pubspec>{};
|
| +
|
| /// The system cache with which this source is registered.
|
| SystemCache get systemCache {
|
| assert(_systemCache != null);
|
| @@ -57,10 +60,29 @@ abstract class Source {
|
| this._systemCache = systemCache;
|
| }
|
|
|
| - /// Get the pubspecs of all versions that exist for the package described by
|
| - /// [description].
|
| + /// Get the IDs of all versions that match [ref].
|
| ///
|
| - /// [name] is the expected name of the package.
|
| + /// Note that this does *not* require the packages to be downloaded locally,
|
| + /// which is the point. This is used during version resolution to determine
|
| + /// which package versions are available to be downloaded (or already
|
| + /// downloaded).
|
| + ///
|
| + /// By default, this assumes that each description has a single version and
|
| + /// uses [describe] to get that version.
|
| + ///
|
| + /// Sources should not override this. Instead, they implement [doGetVersions].
|
| + Future<List<PackageId>> getVersions(PackageRef ref) {
|
| + if (ref.isRoot) {
|
| + throw new ArgumentError("Cannot get versions for the root package.");
|
| + }
|
| + if (ref.source != name) {
|
| + throw new ArgumentError("Package $ref does not use source $name.");
|
| + }
|
| +
|
| + return doGetVersions(ref);
|
| + }
|
| +
|
| + /// Get the IDs of all versions that match [ref].
|
| ///
|
| /// Note that this does *not* require the packages to be downloaded locally,
|
| /// which is the point. This is used during version resolution to determine
|
| @@ -69,26 +91,34 @@ abstract class Source {
|
| ///
|
| /// By default, this assumes that each description has a single version and
|
| /// uses [describe] to get that version.
|
| - Future<List<Pubspec>> getVersions(String name, description) async {
|
| - var id = new PackageId(name, this.name, Version.none, description);
|
| - return [await describe(id)];
|
| + ///
|
| + /// This method is effectively protected: subclasses must implement it, but
|
| + /// external code should not call this. Instead, call [getVersions].
|
| + Future<List<PackageId>> doGetVersions(PackageRef ref) async {
|
| + var pubspec = await describe(ref.atVersion(Version.none));
|
| + return [ref.atVersion(pubspec.version)];
|
| }
|
|
|
| /// Loads the (possibly remote) pubspec for the package version identified by
|
| /// [id].
|
| ///
|
| /// This may be called for packages that have not yet been downloaded during
|
| - /// the version resolution process.
|
| + /// the version resolution process. Its results are automatically memoized.
|
| ///
|
| /// Sources should not override this. Instead, they implement [doDescribe].
|
| - Future<Pubspec> describe(PackageId id) {
|
| + Future<Pubspec> describe(PackageId id) async {
|
| if (id.isRoot) throw new ArgumentError("Cannot describe the root package.");
|
| if (id.source != name) {
|
| throw new ArgumentError("Package $id does not use source $name.");
|
| }
|
|
|
| + var pubspec = _pubspecs[id];
|
| + if (pubspec != null) return pubspec;
|
| +
|
| // Delegate to the overridden one.
|
| - return doDescribe(id);
|
| + pubspec = await doDescribe(id);
|
| + _pubspecs[id.atVersion(pubspec.version)] = pubspec;
|
| + return pubspec;
|
| }
|
|
|
| /// Loads the (possibly remote) pubspec for the package version identified by
|
| @@ -185,6 +215,13 @@ abstract class Source {
|
| /// Returns whether [id] is fully-resolved, according to [resolveId].
|
| bool isResolved(PackageId id) => true;
|
|
|
| + /// Stores [pubspec] so it's returned when [describe] is called with [id].
|
| + ///
|
| + /// This is notionally protected; it should only be called by subclasses.
|
| + void memoizePubspec(PackageId id, Pubspec pubspec) {
|
| + _pubspecs[id] = pubspec;
|
| + }
|
| +
|
| /// Returns the source's name.
|
| String toString() => name;
|
| }
|
|
|