| Index: utils/pub/git_source.dart
|
| diff --git a/utils/pub/git_source.dart b/utils/pub/git_source.dart
|
| index 90f619bb500e26dd166af3e997f6cd4b4898bc2d..e5775df734c36eb2f00fa21b81825a30a0af0ffa 100644
|
| --- a/utils/pub/git_source.dart
|
| +++ b/utils/pub/git_source.dart
|
| @@ -40,19 +40,23 @@ class GitSource extends Source {
|
| return isGitInstalled.chain((installed) {
|
| if (!installed) {
|
| throw new Exception(
|
| - "Cannot install '${id.name}' from Git (${id.description}).\n"
|
| + "Cannot install '${id.name}' from Git (${_getUrl(id)}).\n"
|
| "Please ensure Git is correctly installed.");
|
| }
|
|
|
| return ensureDir(join(systemCacheRoot, 'cache'));
|
| }).chain((_) => _ensureRepoCache(id))
|
| - .chain((_) => _revisionCachePath(id, "HEAD"))
|
| + .chain((_) => _revisionCachePath(id))
|
| .chain((path) {
|
| revisionCachePath = path;
|
| return exists(revisionCachePath);
|
| }).chain((exists) {
|
| if (exists) return new Future.immediate(null);
|
| return _clone(_repoCachePath(id), revisionCachePath);
|
| + }).chain((_) {
|
| + var ref = _getRef(id);
|
| + if (ref == null) return new Future.immediate(null);
|
| + return _checkOut(revisionCachePath, ref);
|
| }).chain((_) => Package.load(revisionCachePath, systemCache.sources));
|
| }
|
|
|
| @@ -61,14 +65,26 @@ class GitSource extends Source {
|
| * it'll be cloned.
|
| */
|
| String packageName(description) =>
|
| - basename(description).replaceFirst(const RegExp("\.git\$"), "");
|
| + basename(_getUrl(description)).replaceFirst(const RegExp("\.git\$"), "");
|
|
|
| /**
|
| * Ensures [description] is a Git URL.
|
| */
|
| void validateDescription(description) {
|
| - if (description is! String) {
|
| - throw new FormatException("The description must be a git URL.");
|
| + // A single string is assumed to be a Git URL.
|
| + if (description is String) return;
|
| + if (description is! Map || !description.containsKey('url')) {
|
| + throw new FormatException("The description must be a Git URL or a map "
|
| + "with a 'url' key.");
|
| + }
|
| + description = new Map.from(description);
|
| + description.remove('url');
|
| + description.remove('ref');
|
| +
|
| + if (!description.isEmpty()) {
|
| + var plural = description.length > 1;
|
| + var keys = Strings.join(description.keys, ', ');
|
| + throw new FormatException("Invalid key${plural ? 's' : ''}: $keys.");
|
| }
|
| }
|
|
|
| @@ -81,7 +97,7 @@ class GitSource extends Source {
|
| Future _ensureRepoCache(PackageId id) {
|
| var path = _repoCachePath(id);
|
| return exists(path).chain((exists) {
|
| - if (!exists) return _clone(id.description, path);
|
| + if (!exists) return _clone(_getUrl(id), path);
|
|
|
| return runProcess("git", ["pull", "--force"], workingDir: path,
|
| pipeStdout: true, pipeStderr: true).transform((result) {
|
| @@ -107,7 +123,9 @@ class GitSource extends Source {
|
| * Returns the path to the revision-specific cache of [id] at [ref], which can
|
| * be any Git ref.
|
| */
|
| - Future<String> _revisionCachePath(PackageId id, String ref) {
|
| + Future<String> _revisionCachePath(PackageId id) {
|
| + var ref = _getRef(id);
|
| + if (ref == null) ref = 'HEAD';
|
| return _revisionAt(id, ref).transform((rev) {
|
| var revisionCacheName = '${id.name}-$rev';
|
| return join(systemCacheRoot, revisionCacheName);
|
| @@ -126,11 +144,53 @@ class GitSource extends Source {
|
| }
|
|
|
| /**
|
| + * Checks out the reference [ref] in [repoPath].
|
| + */
|
| + Future _checkOut(String repoPath, String ref) {
|
| + return runProcess("git", ["checkout", ref], pipeStdout: true,
|
| + pipeStderr: true, workingDir: repoPath).transform((result) {
|
| + if (!result.success) throw 'Git failed.';
|
| + return null;
|
| + });
|
| + }
|
| +
|
| + /**
|
| * Returns the path to the canonical clone of the repository referred to by
|
| * [id] (the one in `<system cache>/git/cache`).
|
| */
|
| String _repoCachePath(PackageId id) {
|
| - var repoCacheName = '${id.name}-${sha1(id.description)}';
|
| + var repoCacheName = '${id.name}-${sha1(_getUrl(id))}';
|
| return join(systemCacheRoot, 'cache', repoCacheName);
|
| }
|
| +
|
| + /**
|
| + * Returns the repository URL for [id].
|
| + *
|
| + * [description] may be a description or a [PackageId].
|
| + */
|
| + String _getUrl(description) {
|
| + description = _getDescription(description);
|
| + if (description is String) return description;
|
| + return description['url'];
|
| + }
|
| +
|
| + /**
|
| + * Returns the commit ref for [id], or null if none is given.
|
| + *
|
| + * [description] may be a description or a [PackageId].
|
| + */
|
| + String _getRef(description) {
|
| + description = _getDescription(description);
|
| + if (description is String) return null;
|
| + return description['ref'];
|
| + }
|
| +
|
| + /**
|
| + * Returns [description] if it's a description, or [PackageId.description] if
|
| + * it's a [PackageId].
|
| + */
|
| + _getDescription(description) {
|
| + if (description is PackageId) return description.description;
|
| + return description;
|
| + }
|
| }
|
|
|