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

Unified Diff: utils/pub/git_source.dart

Issue 10736015: Make the Git source install to the system cache. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Minor fixes Created 8 years, 5 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
« no previous file with comments | « no previous file | utils/pub/source.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: utils/pub/git_source.dart
diff --git a/utils/pub/git_source.dart b/utils/pub/git_source.dart
index ae7f53b1a2489d61a1cf4f9c7fefc5ba08121597..4eb7c01d483f88412285f0211ecb0f9cffaea555 100644
--- a/utils/pub/git_source.dart
+++ b/utils/pub/git_source.dart
@@ -7,6 +7,7 @@
#import('io.dart');
#import('package.dart');
#import('source.dart');
+#import('source_registry.dart');
#import('utils.dart');
/**
@@ -15,32 +16,44 @@
class GitSource extends Source {
final String name = "git";
- // TODO(rnystrom): Git packages could in theory be cached, but that adds a
- // lot of complexity. When you install a git package, you are installing
- // and pinning to a specific commit. That means different installs of the
- // same git path but at different commits need to be disambiguated in the
- // system cache. It may also lead to a lot of garbage in the system cache.
- // For now, we are punting and simply not caching them.
- final bool shouldCache = false;
+ final bool shouldCache = true;
GitSource();
/**
* Clones a Git repo to the local filesystem.
+ *
+ * The Git cache directory is a little idiosyncratic. At the top level, it
+ * contains a directory for each commit of each repository, named `<package
+ * name>-<commit hash>`. These are the canonical package directories that are
+ * linked to from the `packages/` directory.
+ *
+ * In addition, the Git system cache contains a subdirectory named `cache/`
+ * which contains a directory for each separate repository URL, named
+ * `<package name>-<url hash>`. These are used to check out the repository
+ * itself; each of the commit-specific directories are clones of a directory
+ * in `cache/`.
Bob Nystrom 2012/07/10 21:29:33 Nice comment!
*/
- Future<bool> install(PackageId id, String destPath) {
+ Future<Package> installToSystemCache(PackageId id) {
+ var revisionCachePath;
+
return isGitInstalled.chain((installed) {
- if (installed) {
- return runProcess("git",
- ["clone", "--progress", id.description, destPath],
- pipeStdout: true, pipeStderr: true).
- transform((result) => result.success);
- } else {
+ if (!installed) {
throw new Exception(
"Cannot install '${id.name}' from Git (${id.description}).\n"
"Please ensure Git is correctly installed.");
}
- });
+
+ return ensureDir(join(systemCacheRoot, 'cache'));
+ }).chain((_) => _ensureRepoCache(id))
+ .chain((_) => _revisionCachePath(id, "HEAD"))
+ .chain((path) {
+ revisionCachePath = path;
+ return exists(revisionCachePath);
+ }).chain((exists) {
+ if (exists) return new Future.immediate(null);
+ return _clone(_repoCachePath(id), revisionCachePath);
+ }).chain((_) => Package.load(revisionCachePath, systemCache.sources));
}
/**
@@ -58,4 +71,67 @@ class GitSource extends Source {
throw new FormatException("The description must be a git URL.");
}
}
+
+ /**
+ * Ensure that the canonical clone of the repository referred to by [id] (the
+ * one in `<system cache>/git/cache`) exists and is up-to-date. Returns a
+ * future that completes once this is finished and throws an exception if it
+ * fails.
+ */
+ Future _ensureRepoCache(PackageId id) {
+ var path = _repoCachePath(id);
+ return exists(path).chain((exists) {
+ if (!exists) return _clone(id.description, path);
+
+ return runProcess("git", ["pull", "--force", "--progress"],
+ workingDir: path, pipeStdout: true,
+ pipeStderr: true).transform((result) {
+ if (!result.success) throw 'Git failed.';
+ return null;
+ });
+ });
+ }
+
+ /**
+ * Returns a future that completes to the revision hash of the repository for
+ * [id] at [ref], which can be any Git ref.
+ */
+ Future<String> _revisionAt(PackageId id, String ref) {
+ return runProcess("git", ["rev-parse", ref],
+ workingDir: _repoCachePath(id), pipeStderr: true).transform((result) {
+ if (!result.success) throw 'Git failed.';
+ return result.stdout[0];
+ });
+ }
+
+ /**
+ * 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) {
+ return _revisionAt(id, ref).transform((rev) {
+ var revisionCacheName = '${id.name}-$rev';
+ return join(systemCacheRoot, revisionCacheName);
+ });
+ }
+
+ /**
+ * Clones the repo at the URI [from] to the path [to] on the local filesystem.
+ */
+ Future _clone(String from, String to) {
+ return runProcess("git", ["clone", "--progress", from, to],
+ pipeStdout: true, pipeStderr: true).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)}';
+ return join(systemCacheRoot, 'cache', repoCacheName);
+ }
}
« no previous file with comments | « no previous file | utils/pub/source.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698