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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | utils/pub/source.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #library('git_source'); 5 #library('git_source');
6 6
7 #import('io.dart'); 7 #import('io.dart');
8 #import('package.dart'); 8 #import('package.dart');
9 #import('source.dart'); 9 #import('source.dart');
10 #import('source_registry.dart');
10 #import('utils.dart'); 11 #import('utils.dart');
11 12
12 /** 13 /**
13 * A package source that installs packages from Git repos. 14 * A package source that installs packages from Git repos.
14 */ 15 */
15 class GitSource extends Source { 16 class GitSource extends Source {
16 final String name = "git"; 17 final String name = "git";
17 18
18 // TODO(rnystrom): Git packages could in theory be cached, but that adds a 19 final bool shouldCache = true;
19 // lot of complexity. When you install a git package, you are installing
20 // and pinning to a specific commit. That means different installs of the
21 // same git path but at different commits need to be disambiguated in the
22 // system cache. It may also lead to a lot of garbage in the system cache.
23 // For now, we are punting and simply not caching them.
24 final bool shouldCache = false;
25 20
26 GitSource(); 21 GitSource();
27 22
28 /** 23 /**
29 * Clones a Git repo to the local filesystem. 24 * Clones a Git repo to the local filesystem.
25 *
26 * The Git cache directory is a little idiosyncratic. At the top level, it
27 * contains a directory for each commit of each repository, named `<package
28 * name>-<commit hash>`. These are the canonical package directories that are
29 * linked to from the `packages/` directory.
30 *
31 * In addition, the Git system cache contains a subdirectory named `cache/`
32 * which contains a directory for each separate repository URL, named
33 * `<package name>-<url hash>`. These are used to check out the repository
34 * itself; each of the commit-specific directories are clones of a directory
35 * in `cache/`.
Bob Nystrom 2012/07/10 21:29:33 Nice comment!
30 */ 36 */
31 Future<bool> install(PackageId id, String destPath) { 37 Future<Package> installToSystemCache(PackageId id) {
38 var revisionCachePath;
39
32 return isGitInstalled.chain((installed) { 40 return isGitInstalled.chain((installed) {
33 if (installed) { 41 if (!installed) {
34 return runProcess("git",
35 ["clone", "--progress", id.description, destPath],
36 pipeStdout: true, pipeStderr: true).
37 transform((result) => result.success);
38 } else {
39 throw new Exception( 42 throw new Exception(
40 "Cannot install '${id.name}' from Git (${id.description}).\n" 43 "Cannot install '${id.name}' from Git (${id.description}).\n"
41 "Please ensure Git is correctly installed."); 44 "Please ensure Git is correctly installed.");
42 } 45 }
43 }); 46
47 return ensureDir(join(systemCacheRoot, 'cache'));
48 }).chain((_) => _ensureRepoCache(id))
49 .chain((_) => _revisionCachePath(id, "HEAD"))
50 .chain((path) {
51 revisionCachePath = path;
52 return exists(revisionCachePath);
53 }).chain((exists) {
54 if (exists) return new Future.immediate(null);
55 return _clone(_repoCachePath(id), revisionCachePath);
56 }).chain((_) => Package.load(revisionCachePath, systemCache.sources));
44 } 57 }
45 58
46 /** 59 /**
47 * The package name of a Git repo is the name of the directory into which 60 * The package name of a Git repo is the name of the directory into which
48 * it'll be cloned. 61 * it'll be cloned.
49 */ 62 */
50 String packageName(description) => 63 String packageName(description) =>
51 basename(description).replaceFirst(const RegExp("\.git\$"), ""); 64 basename(description).replaceFirst(const RegExp("\.git\$"), "");
52 65
53 /** 66 /**
54 * Ensures [description] is a Git URL. 67 * Ensures [description] is a Git URL.
55 */ 68 */
56 void validateDescription(description) { 69 void validateDescription(description) {
57 if (description is! String) { 70 if (description is! String) {
58 throw new FormatException("The description must be a git URL."); 71 throw new FormatException("The description must be a git URL.");
59 } 72 }
60 } 73 }
74
75 /**
76 * Ensure that the canonical clone of the repository referred to by [id] (the
77 * one in `<system cache>/git/cache`) exists and is up-to-date. Returns a
78 * future that completes once this is finished and throws an exception if it
79 * fails.
80 */
81 Future _ensureRepoCache(PackageId id) {
82 var path = _repoCachePath(id);
83 return exists(path).chain((exists) {
84 if (!exists) return _clone(id.description, path);
85
86 return runProcess("git", ["pull", "--force", "--progress"],
87 workingDir: path, pipeStdout: true,
88 pipeStderr: true).transform((result) {
89 if (!result.success) throw 'Git failed.';
90 return null;
91 });
92 });
93 }
94
95 /**
96 * Returns a future that completes to the revision hash of the repository for
97 * [id] at [ref], which can be any Git ref.
98 */
99 Future<String> _revisionAt(PackageId id, String ref) {
100 return runProcess("git", ["rev-parse", ref],
101 workingDir: _repoCachePath(id), pipeStderr: true).transform((result) {
102 if (!result.success) throw 'Git failed.';
103 return result.stdout[0];
104 });
105 }
106
107 /**
108 * Returns the path to the revision-specific cache of [id] at [ref], which can
109 * be any Git ref.
110 */
111 Future<String> _revisionCachePath(PackageId id, String ref) {
112 return _revisionAt(id, ref).transform((rev) {
113 var revisionCacheName = '${id.name}-$rev';
114 return join(systemCacheRoot, revisionCacheName);
115 });
116 }
117
118 /**
119 * Clones the repo at the URI [from] to the path [to] on the local filesystem.
120 */
121 Future _clone(String from, String to) {
122 return runProcess("git", ["clone", "--progress", from, to],
123 pipeStdout: true, pipeStderr: true).transform((result) {
124 if (!result.success) throw 'Git failed.';
125 return null;
126 });
127 }
128
129 /**
130 * Returns the path to the canonical clone of the repository referred to by
131 * [id] (the one in `<system cache>/git/cache`).
132 */
133 String _repoCachePath(PackageId id) {
134 var repoCacheName = '${id.name}-${sha1(id.description)}';
135 return join(systemCacheRoot, 'cache', repoCacheName);
136 }
61 } 137 }
OLDNEW
« 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