7b72bd1b8d
This fixes a race condition in r9767 caused by issue 4155. Review URL: https://chromiumcodereview.appspot.com//10790079 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@9824 260f80e4-7a28-3924-810f-c04153c831b5
198 lines
5.4 KiB
Dart
198 lines
5.4 KiB
Dart
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
#library('package');
|
|
|
|
#import('io.dart');
|
|
#import('pubspec.dart');
|
|
#import('source.dart');
|
|
#import('source_registry.dart');
|
|
#import('version.dart');
|
|
|
|
/**
|
|
* A named, versioned, unit of code and resource reuse.
|
|
*/
|
|
class Package {
|
|
/**
|
|
* Loads the package whose root directory is [packageDir].
|
|
*/
|
|
static Future<Package> load(String packageDir, SourceRegistry sources) {
|
|
var pubspecPath = join(packageDir, 'pubspec.yaml');
|
|
|
|
return fileExists(pubspecPath).chain((exists) {
|
|
if (exists) {
|
|
return readTextFile(pubspecPath).transform((contents) {
|
|
return new Pubspec.parse(contents, sources);
|
|
});
|
|
} else {
|
|
// If there is no pubspec, we implicitly treat that as a package with
|
|
// no dependencies.
|
|
return new Future.immediate(new Pubspec.empty());
|
|
}
|
|
}).transform((pubspec) {
|
|
return new Package._(packageDir, pubspec);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* The path to the directory containing the package.
|
|
*/
|
|
final String dir;
|
|
|
|
/**
|
|
* The name of the package.
|
|
*/
|
|
final String name;
|
|
|
|
/**
|
|
* The package's version.
|
|
*/
|
|
Version get version() => pubspec.version;
|
|
|
|
/**
|
|
* The parsed pubspec associated with this package.
|
|
*/
|
|
final Pubspec pubspec;
|
|
|
|
/**
|
|
* The ids of the packages that this package depends on. This is what is
|
|
* specified in the pubspec when this package depends on another.
|
|
*/
|
|
Collection<PackageRef> get dependencies() => pubspec.dependencies;
|
|
|
|
/**
|
|
* Constructs a package with the given name and pubspec. The package will
|
|
* no directory associated with it.
|
|
*/
|
|
Package.inMemory(this.name, this.pubspec)
|
|
: dir = null;
|
|
|
|
/**
|
|
* Constructs a package. This should not be called directly. Instead, acquire
|
|
* packages from [load()].
|
|
*/
|
|
Package._(String dir, this.pubspec)
|
|
: dir = dir,
|
|
name = basename(dir);
|
|
|
|
/**
|
|
* Returns a debug string for the package.
|
|
*/
|
|
String toString() => '$name $version ($dir)';
|
|
}
|
|
|
|
/**
|
|
* 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 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.
|
|
*/
|
|
class PackageId implements Comparable, Hashable {
|
|
/**
|
|
* The [Source] used to look up this package given its [description].
|
|
*/
|
|
final Source source;
|
|
|
|
/**
|
|
* The package's version.
|
|
*/
|
|
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(this.source, this.version, this.description);
|
|
|
|
/**
|
|
* The name of the package being identified. This will be the human-friendly
|
|
* name like "uilib".
|
|
*/
|
|
String get name() => source.packageName(description);
|
|
|
|
int hashCode() => name.hashCode() ^
|
|
source.name.hashCode() ^
|
|
version.hashCode();
|
|
|
|
bool operator ==(other) {
|
|
if (other is! PackageId) return false;
|
|
// 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() => "$name $version from ${source.name}";
|
|
|
|
int compareTo(Comparable other) {
|
|
if (other is! PackageId) throw new IllegalArgumentException(other);
|
|
|
|
var sourceComp = source.name.compareTo(other.source.name);
|
|
if (sourceComp != 0) return sourceComp;
|
|
|
|
var nameComp = name.compareTo(other.name);
|
|
if (nameComp != 0) return nameComp;
|
|
|
|
return version.compareTo(other.version);
|
|
}
|
|
|
|
/**
|
|
* Returns the pubspec for this package.
|
|
*/
|
|
Future<Pubspec> describe() => source.describe(this);
|
|
|
|
/**
|
|
* Returns a future that completes to the resovled [PackageId] for this id.
|
|
*/
|
|
Future<PackageId> get resolved() => source.resolveId(this);
|
|
}
|
|
|
|
/**
|
|
* 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 {
|
|
/**
|
|
* The [Source] used to look up the package.
|
|
*/
|
|
final Source source;
|
|
|
|
/**
|
|
* The allowed package versions.
|
|
*/
|
|
final VersionConstraint constraint;
|
|
|
|
/**
|
|
* The metadata used to identify the package being referenced. The
|
|
* interpretation of this will vary based on the [source].
|
|
*/
|
|
final description;
|
|
|
|
/**
|
|
* The name of the package being referenced.
|
|
*/
|
|
String get name() => source.packageName(description);
|
|
|
|
PackageRef(this.source, this.constraint, this.description);
|
|
|
|
String toString() => "$name $constraint from $source ($description)";
|
|
|
|
/**
|
|
* Returns a [PackageId] generated from this [PackageRef] with the given
|
|
* concrete version.
|
|
*/
|
|
PackageId atVersion(Version version) =>
|
|
new PackageId(source, version, description);
|
|
}
|