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

Unified Diff: utils/pub/package.dart

Issue 10399076: Get codebase ready for actually supporting versioning. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Tiny tweak. Created 8 years, 7 months 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
Index: utils/pub/package.dart
diff --git a/utils/pub/package.dart b/utils/pub/package.dart
index af585ab058af4e73138c987a203d4e6023b1e88a..8b3f047391585c88e7461ef04b6a1054ac6f7ca8 100644
--- a/utils/pub/package.dart
+++ b/utils/pub/package.dart
@@ -5,15 +5,15 @@
/**
* A named, versioned, unit of code and resource reuse.
*/
-class Package implements Hashable {
+class Package {
/**
* Loads the package whose root directory is [packageDir].
*/
- static Future<Package> load(String packageDir, SourceRegistry sources) {
- final pubspecPath = join(packageDir, 'pubspec');
+ static Future<Package> load(String packageDir, SystemCache cache) {
+ var pubspecPath = join(packageDir, 'pubspec');
- return _parsePubspec(pubspecPath, sources).transform((dependencies) {
- return new Package._(packageDir, dependencies);
+ return Pubspec.parse(pubspecPath, cache.sources).transform((pubspec) {
+ return new Package._(packageDir, cache, pubspec);
});
}
@@ -28,179 +28,156 @@ class Package implements Hashable {
final String name;
/**
+ * The package's version.
+ */
+ Version get version() => pubspec.version;
+
+ /**
+ * The parsed pubspec associated with this package.
+ */
+ final Pubspec pubspec;
+
+ /**
+ * The "packages" directory that this package installs its dependencies into.
+ */
+ final PackagesDir packagesDir;
+
+ /**
* The ids of the packages that this package depends on. This is what is
* specified in the pubspec when this package depends on another.
*/
- final Collection<PackageId> dependencies;
+ Collection<PackageRef> get dependencies() => pubspec.dependencies;
/**
* Constructs a package. This should not be called directly. Instead, acquire
* packages from [load()].
*/
- Package._(String dir, this.dependencies)
+ Package._(String dir, SystemCache cache, this.pubspec)
nweiz 2012/05/18 00:08:24 I'm not sure I like Package having a reference to
Bob Nystrom 2012/05/18 20:02:38 Done.
: dir = dir,
- name = basename(dir);
+ name = basename(dir),
+ packagesDir = new PackagesDir(join(dir, 'packages'), cache);
/**
- * Generates a hashcode for the package.
+ * Installs all dependencies of this package to its "packages" directory.
+ * Returns a [Future] that completes when all dependencies are installed.
*/
- // TODO(rnystrom): Do something more sophisticated here once we care about
- // versioning and different package sources.
- int hashCode() => name.hashCode();
+ Future installDependencies() {
+ return packagesDir.installTransitively(this, this.dependencies);
+ }
/**
- * Returns a debug string for the package.
+ * Given [ref], which ambiguously identifies a dependent package, selects an
+ * appropriate precise package to use when this package is the entrypoint.
+ * In other words, given a loose refence like "foo >= 2.0", figures out what
+ * concrete package *this* app wants to use.
*/
- String toString() => '$name ($dir)';
+ Future<PackageId> resolve(PackageRef ref) {
+ // TODO(rnystrom): This should use the lockfile to select the right version
+ // once that's implemented. If the lockfile doesn't exist, it should
+ // generate it. In the meantime, here's a dumb implementation:
+ return new Future.immediate(
+ new PackageId(ref.source, Version.none, ref.description));
+ }
/**
- * Parses the pubspec at the given path and returns the list of package
- * dependencies it exposes.
+ * Returns a debug string for the package.
*/
- static Future<List<PackageId>> _parsePubspec(String path,
- SourceRegistry sources) {
- final completer = new Completer<List<PackageId>>();
-
- // TODO(rnystrom): Handle the directory not existing.
- // TODO(rnystrom): Error-handling.
- final readFuture = readTextFile(path);
- readFuture.handleException((error) {
- // If there is no pubspec, we implicitly treat that as a package with no
- // dependencies.
- // TODO(rnystrom): Distinguish file not found from other real errors.
- completer.complete(<PackageId>[]);
- return true;
- });
-
- readFuture.then((pubspec) {
- if (pubspec.trim() == '') {
- completer.complete(<String>[]);
- return;
- }
-
- var parsedPubspec = loadYaml(pubspec);
- if (parsedPubspec is! Map) {
- completer.completeException('The pubspec must be a YAML mapping.');
- }
-
- if (!parsedPubspec.containsKey('dependencies')) {
- completer.complete(<String>[]);
- return;
- }
-
- var dependencies = parsedPubspec['dependencies'];
- if (dependencies is! Map ||
- dependencies.getKeys().some((e) => e is! String)) {
- completer.completeException(
- 'The pubspec dependencies must be a map of package names.');
- }
-
- var dependencyIds = <PackageId>[];
- dependencies.forEach((name, spec) {
- var fullName, source;
- // TODO(nweiz): parse the version once we have version handling
- if (spec == null || spec is String) {
- fullName = name;
- source = sources.defaultSource;
- } else if (spec is Map) {
- spec.remove('version');
-
- var sourceNames = spec.getKeys();
- if (sourceNames.length > 1) {
- completer.completeException(
- 'Dependency $name may not have multiple sources: '
- '$sourceNames.');
- return;
- }
-
- var sourceName = only(sourceNames);
- if (sourceName is! String) {
- completer.completeException(
- 'Source name $sourceName must be a string.');
- return;
- }
- source = sources[sourceName];
-
- // TODO(nweiz): At some point we want fullName to be able to be an
- // arbitrary object that's parsed by the source.
- fullName = spec[sourceName];
- if (fullName is! String) {
- completer.completeException(
- 'Source identifier $fullName must be a string.');
- return;
- }
- } else {
- completer.completeException(
- 'Dependency specification $spec must be a string or a mapping.');
- return;
- }
-
- var id = new PackageId(fullName, source);
- var nameFromSource = source.packageName(id);
- if (nameFromSource != name) {
- completer.completeException(
- 'Dependency name "$name" doesn\'t match name "$nameFromSource" '
- 'from source "${source.name}".');
- return;
- }
-
- dependencyIds.add(id);
- });
- completer.complete(dependencyIds);
- });
-
- return completer.future;
- }
+ String toString() => '$name ($dir)';
}
/**
- * A unique identifier for a package. A given package id specifies a single
- * chunk of code and resources.
+ * An unambiguous resolved reference to a package. A package ID contains enough
+ * information to correctly install the package.
*
- * Note that it's possible for multiple package ids to point to identical
- * packages. For example, the same package may be available from multiple
- * sources. As far as Pub is concerned, those packages are different.
+ * Note that it's possible for multiple distinct package IDs to point to
+ * different directories that happen to contain identical packages. For example,
+ * the same package may be available from multiple sources. As far as Pub is
+ * concerned, those packages are different.
*/
-// TODO(nweiz, rnystrom): this should include version eventually
-class PackageId implements Hashable, Comparable {
+class PackageId implements Comparable, Hashable {
/**
- * The name used by the [source] to look up the package.
- *
- * Note that this may be distinct from [name], which is the name of the
- * package itself. The [source] uses this name to locate the package and
- * returns the true package name. For example, for a Git source [fullName]
- * might be the URL "git://github.com/dart/uilib.git", while [name] would just
- * be "uilib". It would be up to the source to take the URL and extract the
- * package name.
+ * The [Source] used to look up this package given its [description].
*/
- final String fullName;
+ final Source source;
/**
- * The [Source] used to look up the package given the [fullName].
+ * The package's version.
*/
- final Source source;
+ final Version version;
+
+ /**
+ * The metadata used by the package's [source] to identify and locate it. It
+ * contains whatever [Source]-specific data it needs to be able to install
+ * the package. For example, the description of a git sourced package might
+ * by the URL "git://github.com/dart/uilib.git".
+ */
+ final description;
- PackageId(String this.fullName, Source this.source);
+ PackageId(this.source, this.version, this.description);
/**
- * The name of the package being imported. Not necessarily the same as
- * [fullName].
+ * The name of the package being identified. This will be the human-friendly
+ * name like "uilib".
*/
String get name() => source.packageName(this);
- int hashCode() => fullName.hashCode() ^ source.name.hashCode();
+ int hashCode() => name.hashCode() ^
+ source.name.hashCode() ^
+ version.hashCode();
bool operator ==(other) {
if (other is! PackageId) return false;
- return other.fullName == fullName && other.source.name == source.name;
+ // TODO(rnystrom): We're assuming here the name/version/source tuple is
+ // enough to uniquely identify the package and that we don't need to delve
+ // into the description.
+ return other.name == name &&
+ other.source.name == source.name &&
+ other.version == version;
}
- String toString() => "$fullName from ${source.name}";
+ String toString() => "$name $version from ${source.name}";
int compareTo(Comparable other) {
if (other is! PackageId) throw new IllegalArgumentException(other);
- var sourceComp = this.source.name.compareTo(other.source.name);
+
+ var sourceComp = source.name.compareTo(other.source.name);
if (sourceComp != 0) return sourceComp;
- return this.fullName.compareTo(other.fullName);
+
+ var nameComp = name.compareTo(other.name);
+ if (nameComp != 0) return nameComp;
+
+ return version.compareTo(other.version);
}
}
+
+/**
+ * A reference to a package. Unlike a [PackageId], a PackageRef may not
+ * unambiguously refer to a single package. It may describe a range of allowed
+ * packages.
+ */
+class PackageRef {
nweiz 2012/05/18 00:08:24 What do you think about PackageRange or PackageCon
Bob Nystrom 2012/05/18 20:02:38 I <3 Ref as per our discussion.
+ /**
+ * The name of the package being referenced.
+ */
+ final String name;
+
+ /**
+ * The [Source] used to look up the package.
+ */
+ final Source source;
+
+ /**
+ * The allowed package versions.
+ */
+ final VersionConstraint version;
+
+ /**
+ * The metadata used to identify the package being referenced. The
+ * interpretation of this will vary based on the [source].
+ */
+ final description;
+
+ PackageRef(this.name, this.source, this.version, this.description);
+
+ String toString() => "$name $version from $source ($description)";
+}

Powered by Google App Engine
This is Rietveld 408576698