Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(942)

Unified Diff: lib/src/source.dart

Issue 1528523003: Clean up the semantics of package descriptions. (Closed) Base URL: git@github.com:dart-lang/pub.git@master
Patch Set: Code review changes Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « lib/src/solver/version_solver.dart ('k') | lib/src/source/cached.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/src/source.dart
diff --git a/lib/src/source.dart b/lib/src/source.dart
index 7e5625a2a5b079ca0479afca0a711caa04422f0d..ff590b2404940cbbcd26a8ed027803bec57eab71 100644
--- a/lib/src/source.dart
+++ b/lib/src/source.dart
@@ -11,6 +11,7 @@ import 'package:pub_semver/pub_semver.dart';
import 'package.dart';
import 'pubspec.dart';
import 'system_cache.dart';
+import 'utils.dart';
/// A source from which to get packages.
///
@@ -21,6 +22,28 @@ import 'system_cache.dart';
/// Other sources are *cached* sources. These extend [CachedSource]. When a
/// package needs a dependency from a cached source, it is first installed in
/// the [SystemCache] and then acquired from there.
+///
+/// ## 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:
+///
+/// * User descriptions. These are included in pubspecs and usually written by
+/// hand. They're typically more flexible in the formats they allow to
+/// optimize for ease of authoring.
+///
+/// * Reference descriptions. These are the descriptions in [PackageRef]s and
+/// [PackageDep]. They're parsed directly from user descriptions using
+/// [parseRef], and so add no additional information.
+///
+/// * ID descriptions. These are the descriptions in [PackageId]s, which
+/// uniquely identify and provide the means to locate the concrete code of a
+/// package. They may contain additional expensive-to-compute information
+/// relative to the corresponding reference descriptions. These are the
+/// descriptions stored in lock files.
abstract class Source {
/// The name of the source.
///
@@ -94,10 +117,7 @@ abstract class Source {
///
/// 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)];
- }
+ Future<List<PackageId>> doGetVersions(PackageRef ref);
/// Loads the (possibly remote) pubspec for the package version identified by
/// [id].
@@ -105,6 +125,9 @@ abstract class Source {
/// This may be called for packages that have not yet been downloaded during
/// the version resolution process. Its results are automatically memoized.
///
+ /// Throws a [DataException] if the pubspec's version doesn't match [id]'s
+ /// version.
+ ///
/// 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.");
@@ -117,7 +140,11 @@ abstract class Source {
// Delegate to the overridden one.
pubspec = await doDescribe(id);
- _pubspecs[id.atVersion(pubspec.version)] = pubspec;
+ if (pubspec.version != id.version) {
+ dataError("The pubspec for $id has version ${pubspec.version}.");
+ }
+
+ _pubspecs[id] = pubspec;
return pubspec;
}
@@ -138,31 +165,34 @@ abstract class Source {
/// Returns the directory where this package can (or could) be found locally.
///
/// If the source is cached, this will be a path in the system cache.
- /// Depending on the source, this may throw an [ArgumentError] if [id] isn't
- /// resolved using [resolveId].
String getDirectory(PackageId id);
- /// Gives the source a chance to interpret and validate the description for
- /// a package coming from this source.
+ /// Parses a [PackageRef] from a name and a user-provided [description].
///
- /// When a [Pubspec] or [LockFile] 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.
+ /// 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).
///
- /// It should return if a (possibly modified) valid description, or throw a
- /// [FormatException] if not valid.
+ /// The description in the returned [PackageRef] need bear no resemblance to
+ /// the original user-provided description.
///
- /// [fromLockFile] is true when the description comes from a [LockFile], to
- /// allow the source to use lockfile-specific descriptions via [resolveId].
- dynamic parseDescription(String containingPath, description,
- {bool fromLockFile: false});
+ /// 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.
@@ -187,33 +217,11 @@ abstract class Source {
///
/// This method should be light-weight. It doesn't need to validate that
/// either package exists.
- bool descriptionsEqual(description1, description2);
-
- /// Resolves [id] to a more possibly more precise that will uniquely identify
- /// a package regardless of when the package is requested.
- ///
- /// For some sources, [PackageId]s can point to different chunks of code at
- /// different times. This takes such an [id] and returns a future that
- /// completes to a [PackageId] that will uniquely specify a single chunk of
- /// code forever.
///
- /// For example, [GitSource] might take an [id] with description
- /// `http://github.com/dart-lang/some-lib.git` and return an id with a
- /// description that includes the current commit of the Git repository.
- ///
- /// Pub calls this after getting a package, so the source can use the local
- /// package to determine information about the resolved id.
- ///
- /// The returned [PackageId] may have a description field that's invalid
- /// according to [parseDescription], although it must still be serializable
- /// to JSON and YAML. It must also be equal to [id] according to
- /// [descriptionsEqual].
- ///
- /// By default, this just returns [id].
- Future<PackageId> resolveId(PackageId id) => new Future.value(id);
-
- /// Returns whether [id] is fully-resolved, according to [resolveId].
- bool isResolved(PackageId id) => true;
+ /// 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].
///
« no previous file with comments | « lib/src/solver/version_solver.dart ('k') | lib/src/source/cached.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698