Index: lib/src/source.dart |
diff --git a/lib/src/source.dart b/lib/src/source.dart |
index b2fb08397f8c4403b4adac3fb50b2c3d93d020ce..ff51d5c7c5f0489f11db94531a6a77ce54554794 100644 |
--- a/lib/src/source.dart |
+++ b/lib/src/source.dart |
@@ -21,13 +21,20 @@ import 'utils.dart'; |
/// package needs a dependency from a cached source, it is first installed in |
/// the [SystemCache] and then acquired from there. |
/// |
+/// Each user-visible source has two classes: a [Source] that knows how to do |
+/// filesystem-independent operations like parsing and comparing descriptions, |
+/// and a [BoundSource] that knows how to actually install (and potentially |
+/// download) those packages. Only the [BoundSource] has access to the |
+/// [SystemCache]. |
+/// |
/// ## Subclassing |
/// |
-/// All sources should extend this class. In addition to defining the behavior |
-/// of various methods, sources define the structure of package descriptions |
-/// used in [PackageRef]s, [PackageDep]s, and [PackageId]s. There are three |
-/// distinct types of description, although in practice most sources use the |
-/// same format for one or more of these: |
+/// All [Source]s should extend this class and all [BoundSource]s should extend |
+/// [BoundSource]. In addition to defining the behavior of various methods, |
+/// sources define the structure of package descriptions used in [PackageRef]s, |
+/// [PackageDep]s, and [PackageId]s. There are three distinct types of |
+/// description, although in practice most sources use the same format for one |
+/// or more of these: |
/// |
/// * User descriptions. These are included in pubspecs and usually written by |
/// hand. They're typically more flexible in the formats they allow to |
@@ -55,32 +62,80 @@ abstract class Source { |
/// Defaults to `false`. |
final bool hasMultipleVersions = false; |
- /// Whether or not this source is the default source. |
- bool get isDefault => systemCache.sources.defaultSource == this; |
+ /// Records the system cache to which this source belongs. |
+ /// |
+ /// This should only be called once for each source, by |
+ /// [SystemCache.register]. It should not be overridden by base classes. |
+ BoundSource bind(SystemCache systemCache); |
- /// A cache of pubspecs described by [describe]. |
- final _pubspecs = <PackageId, Pubspec>{}; |
+ /// Parses a [PackageRef] from a name and a user-provided [description]. |
+ /// |
+ /// When a [Pubspec] is parsed, it reads in the description for each |
+ /// dependency. It is up to the dependency's [Source] to determine how that |
+ /// should be interpreted. This will be called during parsing to validate that |
+ /// the given [description] is well-formed according to this source, and to |
+ /// give the source a chance to canonicalize the description. |
+ /// |
+ /// [containingPath] is the path to the local file (pubspec or lockfile) |
+ /// where this description appears. It may be `null` if the description is |
+ /// coming from some in-memory source (such as pulling down a pubspec from |
+ /// pub.dartlang.org). |
+ /// |
+ /// The description in the returned [PackageRef] need bear no resemblance to |
+ /// the original user-provided description. |
+ /// |
+ /// Throws a [FormatException] if the description is not valid. |
+ PackageRef parseRef(String name, description, {String containingPath}); |
- /// The system cache with which this source is registered. |
- SystemCache get systemCache { |
- assert(_systemCache != null); |
- return _systemCache; |
- } |
+ /// Parses a [PackageId] from a name and a serialized description. |
+ /// |
+ /// This only accepts descriptions serialized using [serializeDescription]. It |
+ /// should not be used with user-authored descriptions. |
+ /// |
+ /// Throws a [FormatException] if the description is not valid. |
+ PackageId parseId(String name, Version version, description); |
- /// The system cache variable. |
+ /// When a [LockFile] is serialized, it uses this method to get the |
+ /// [description] in the right format. |
/// |
- /// Set by [_bind]. |
- SystemCache _systemCache; |
+ /// [containingPath] is the containing directory of the root package. |
+ dynamic serializeDescription(String containingPath, description) { |
+ return description; |
+ } |
- /// Records the system cache to which this source belongs. |
+ /// When a package [description] is shown to the user, this is called to |
+ /// convert it into a human-friendly form. |
/// |
- /// This should only be called once for each source, by |
- /// [SystemCache.register]. It should not be overridden by base classes. |
- void bind(SystemCache systemCache) { |
- assert(_systemCache == null); |
- this._systemCache = systemCache; |
+ /// By default, it just converts the description to a string, but sources |
+ /// may customize this. [containingPath] is the containing directory of the |
+ /// root package. |
+ String formatDescription(String containingPath, description) { |
+ return description.toString(); |
} |
+ /// Returns whether or not [description1] describes the same package as |
+ /// [description2] for this source. |
+ /// |
+ /// This method should be light-weight. It doesn't need to validate that |
+ /// either package exists. |
+ /// |
+ /// Note that either description may be a reference description or an ID |
+ /// description; they need not be the same type. ID descriptions should be |
+ /// considered equal to the reference descriptions that produced them. |
+ bool descriptionsEqual(description1, description2); |
+ |
+ /// Returns the source's name. |
+ String toString() => name; |
+} |
+ |
+/// A source bound to a [SystemCache]. |
+abstract class BoundSource { |
+ /// The unbound source that produced [this]. |
+ Source get source; |
+ |
+ /// The system cache to which [this] is bound. |
+ SystemCache get systemCache; |
+ |
/// Get the IDs of all versions that match [ref]. |
/// |
/// Note that this does *not* require the packages to be downloaded locally, |
@@ -96,8 +151,8 @@ abstract class Source { |
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."); |
+ if (ref.source != source.name) { |
+ throw new ArgumentError("Package $ref does not use source ${source.name}."); |
} |
return doGetVersions(ref); |
@@ -117,6 +172,9 @@ abstract class Source { |
/// external code should not call this. Instead, call [getVersions]. |
Future<List<PackageId>> doGetVersions(PackageRef ref); |
+ /// A cache of pubspecs described by [describe]. |
+ final _pubspecs = <PackageId, Pubspec>{}; |
+ |
/// Loads the (possibly remote) pubspec for the package version identified by |
/// [id]. |
/// |
@@ -129,8 +187,8 @@ abstract class Source { |
/// Sources should not override this. Instead, they implement [doDescribe]. |
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."); |
+ if (id.source != source.name) { |
+ throw new ArgumentError("Package $id does not use source ${source.name}."); |
} |
var pubspec = _pubspecs[id]; |
@@ -165,69 +223,10 @@ abstract class Source { |
/// If the source is cached, this will be a path in the system cache. |
String getDirectory(PackageId id); |
- /// Parses a [PackageRef] from a name and a user-provided [description]. |
- /// |
- /// When a [Pubspec] is parsed, it reads in the description for each |
- /// dependency. It is up to the dependency's [Source] to determine how that |
- /// should be interpreted. This will be called during parsing to validate that |
- /// the given [description] is well-formed according to this source, and to |
- /// give the source a chance to canonicalize the description. |
- /// |
- /// [containingPath] is the path to the local file (pubspec or lockfile) |
- /// where this description appears. It may be `null` if the description is |
- /// coming from some in-memory source (such as pulling down a pubspec from |
- /// pub.dartlang.org). |
- /// |
- /// The description in the returned [PackageRef] need bear no resemblance to |
- /// the original user-provided description. |
- /// |
- /// Throws a [FormatException] if the description is not valid. |
- PackageRef parseRef(String name, description, {String containingPath}); |
- |
- /// Parses a [PackageId] from a name and a serialized description. |
- /// |
- /// This only accepts descriptions serialized using [serializeDescription]. It |
- /// should not be used with user-authored descriptions. |
- /// |
- /// Throws a [FormatException] if the description is not valid. |
- PackageId parseId(String name, Version version, description); |
- |
- /// When a [LockFile] is serialized, it uses this method to get the |
- /// [description] in the right format. |
- /// |
- /// [containingPath] is the containing directory of the root package. |
- dynamic serializeDescription(String containingPath, description) { |
- return description; |
- } |
- |
- /// When a package [description] is shown to the user, this is called to |
- /// convert it into a human-friendly form. |
- /// |
- /// By default, it just converts the description to a string, but sources |
- /// may customize this. [containingPath] is the containing directory of the |
- /// root package. |
- String formatDescription(String containingPath, description) { |
- return description.toString(); |
- } |
- |
- /// Returns whether or not [description1] describes the same package as |
- /// [description2] for this source. |
- /// |
- /// This method should be light-weight. It doesn't need to validate that |
- /// either package exists. |
- /// |
- /// Note that either description may be a reference description or an ID |
- /// description; they need not be the same type. ID descriptions should be |
- /// considered equal to the reference descriptions that produced them. |
- bool descriptionsEqual(description1, description2); |
- |
/// 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; |
} |