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

Side by Side Diff: utils/pub/git_source.dart

Issue 11638010: Convert /** comments to /// in pub. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Respond to review. Created 8 years 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 | « utils/pub/git.dart ('k') | utils/pub/hosted_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 'git.dart' as git; 7 import 'git.dart' as git;
8 import 'io.dart'; 8 import 'io.dart';
9 import 'package.dart'; 9 import 'package.dart';
10 import 'source.dart'; 10 import 'source.dart';
11 import 'source_registry.dart'; 11 import 'source_registry.dart';
12 import 'utils.dart'; 12 import 'utils.dart';
13 13
14 /** 14 /// A package source that installs packages from Git repos.
15 * A package source that installs packages from Git repos.
16 */
17 class GitSource extends Source { 15 class GitSource extends Source {
18 final String name = "git"; 16 final String name = "git";
19 17
20 final bool shouldCache = true; 18 final bool shouldCache = true;
21 19
22 GitSource(); 20 GitSource();
23 21
24 /** 22 /// Clones a Git repo to the local filesystem.
25 * Clones a Git repo to the local filesystem. 23 ///
26 * 24 /// The Git cache directory is a little idiosyncratic. At the top level, it
27 * The Git cache directory is a little idiosyncratic. At the top level, it 25 /// contains a directory for each commit of each repository, named `<package
28 * contains a directory for each commit of each repository, named `<package 26 /// name>-<commit hash>`. These are the canonical package directories that are
29 * name>-<commit hash>`. These are the canonical package directories that are 27 /// linked to from the `packages/` directory.
30 * linked to from the `packages/` directory. 28 ///
31 * 29 /// In addition, the Git system cache contains a subdirectory named `cache/`
32 * In addition, the Git system cache contains a subdirectory named `cache/` 30 /// which contains a directory for each separate repository URL, named
33 * which contains a directory for each separate repository URL, named 31 /// `<package name>-<url hash>`. These are used to check out the repository
34 * `<package name>-<url hash>`. These are used to check out the repository 32 /// itself; each of the commit-specific directories are clones of a directory
35 * itself; each of the commit-specific directories are clones of a directory 33 /// in `cache/`.
36 * in `cache/`.
37 */
38 Future<Package> installToSystemCache(PackageId id) { 34 Future<Package> installToSystemCache(PackageId id) {
39 var revisionCachePath; 35 var revisionCachePath;
40 36
41 return git.isInstalled.chain((installed) { 37 return git.isInstalled.chain((installed) {
42 if (!installed) { 38 if (!installed) {
43 throw new Exception( 39 throw new Exception(
44 "Cannot install '${id.name}' from Git (${_getUrl(id)}).\n" 40 "Cannot install '${id.name}' from Git (${_getUrl(id)}).\n"
45 "Please ensure Git is correctly installed."); 41 "Please ensure Git is correctly installed.");
46 } 42 }
47 43
48 return ensureDir(join(systemCacheRoot, 'cache')); 44 return ensureDir(join(systemCacheRoot, 'cache'));
49 }).chain((_) => _ensureRepoCache(id)) 45 }).chain((_) => _ensureRepoCache(id))
50 .chain((_) => _revisionCachePath(id)) 46 .chain((_) => _revisionCachePath(id))
51 .chain((path) { 47 .chain((path) {
52 revisionCachePath = path; 48 revisionCachePath = path;
53 return exists(revisionCachePath); 49 return exists(revisionCachePath);
54 }).chain((exists) { 50 }).chain((exists) {
55 if (exists) return new Future.immediate(null); 51 if (exists) return new Future.immediate(null);
56 return _clone(_repoCachePath(id), revisionCachePath, mirror: false); 52 return _clone(_repoCachePath(id), revisionCachePath, mirror: false);
57 }).chain((_) { 53 }).chain((_) {
58 var ref = _getEffectiveRef(id); 54 var ref = _getEffectiveRef(id);
59 if (ref == 'HEAD') return new Future.immediate(null); 55 if (ref == 'HEAD') return new Future.immediate(null);
60 return _checkOut(revisionCachePath, ref); 56 return _checkOut(revisionCachePath, ref);
61 }).chain((_) { 57 }).chain((_) {
62 return Package.load(id.name, revisionCachePath, systemCache.sources); 58 return Package.load(id.name, revisionCachePath, systemCache.sources);
63 }); 59 });
64 } 60 }
65 61
66 /** 62 /// Ensures [description] is a Git URL.
67 * Ensures [description] is a Git URL.
68 */
69 void validateDescription(description, {bool fromLockFile: false}) { 63 void validateDescription(description, {bool fromLockFile: false}) {
70 // A single string is assumed to be a Git URL. 64 // A single string is assumed to be a Git URL.
71 if (description is String) return; 65 if (description is String) return;
72 if (description is! Map || !description.containsKey('url')) { 66 if (description is! Map || !description.containsKey('url')) {
73 throw new FormatException("The description must be a Git URL or a map " 67 throw new FormatException("The description must be a Git URL or a map "
74 "with a 'url' key."); 68 "with a 'url' key.");
75 } 69 }
76 description = new Map.from(description); 70 description = new Map.from(description);
77 description.remove('url'); 71 description.remove('url');
78 description.remove('ref'); 72 description.remove('ref');
79 if (fromLockFile) description.remove('resolved-ref'); 73 if (fromLockFile) description.remove('resolved-ref');
80 74
81 if (!description.isEmpty) { 75 if (!description.isEmpty) {
82 var plural = description.length > 1; 76 var plural = description.length > 1;
83 var keys = Strings.join(description.keys, ', '); 77 var keys = Strings.join(description.keys, ', ');
84 throw new FormatException("Invalid key${plural ? 's' : ''}: $keys."); 78 throw new FormatException("Invalid key${plural ? 's' : ''}: $keys.");
85 } 79 }
86 } 80 }
87 81
88 /** 82 /// Two Git descriptions are equal if both their URLs and their refs are
89 * Two Git descriptions are equal if both their URLs and their refs are equal. 83 /// equal.
90 */
91 bool descriptionsEqual(description1, description2) { 84 bool descriptionsEqual(description1, description2) {
92 // TODO(nweiz): Do we really want to throw an error if you have two 85 // TODO(nweiz): Do we really want to throw an error if you have two
93 // dependencies on some repo, one of which specifies a ref and one of which 86 // dependencies on some repo, one of which specifies a ref and one of which
94 // doesn't? If not, how do we handle that case in the version solver? 87 // doesn't? If not, how do we handle that case in the version solver?
95 return _getUrl(description1) == _getUrl(description2) && 88 return _getUrl(description1) == _getUrl(description2) &&
96 _getRef(description1) == _getRef(description2); 89 _getRef(description1) == _getRef(description2);
97 } 90 }
98 91
99 /** 92 /// Attaches a specific commit to [id] to disambiguate it.
100 * Attaches a specific commit to [id] to disambiguate it.
101 */
102 Future<PackageId> resolveId(PackageId id) { 93 Future<PackageId> resolveId(PackageId id) {
103 return _revisionAt(id).transform((revision) { 94 return _revisionAt(id).transform((revision) {
104 var description = {'url': _getUrl(id), 'ref': _getRef(id)}; 95 var description = {'url': _getUrl(id), 'ref': _getRef(id)};
105 description['resolved-ref'] = revision; 96 description['resolved-ref'] = revision;
106 return new PackageId(id.name, this, id.version, description); 97 return new PackageId(id.name, this, id.version, description);
107 }); 98 });
108 } 99 }
109 100
110 /** 101 /// Ensure that the canonical clone of the repository referred to by [id] (the
111 * Ensure that the canonical clone of the repository referred to by [id] (the 102 /// one in `<system cache>/git/cache`) exists and is up-to-date. Returns a
112 * one in `<system cache>/git/cache`) exists and is up-to-date. Returns a 103 /// future that completes once this is finished and throws an exception if it
113 * future that completes once this is finished and throws an exception if it 104 /// fails.
114 * fails.
115 */
116 Future _ensureRepoCache(PackageId id) { 105 Future _ensureRepoCache(PackageId id) {
117 var path = _repoCachePath(id); 106 var path = _repoCachePath(id);
118 return exists(path).chain((exists) { 107 return exists(path).chain((exists) {
119 if (!exists) return _clone(_getUrl(id), path, mirror: true); 108 if (!exists) return _clone(_getUrl(id), path, mirror: true);
120 109
121 return git.run(["fetch"], workingDir: path).transform((result) => null); 110 return git.run(["fetch"], workingDir: path).transform((result) => null);
122 }); 111 });
123 } 112 }
124 113
125 /** 114 /// Returns a future that completes to the revision hash of [id].
126 * Returns a future that completes to the revision hash of [id].
127 */
128 Future<String> _revisionAt(PackageId id) { 115 Future<String> _revisionAt(PackageId id) {
129 return git.run(["rev-parse", _getEffectiveRef(id)], 116 return git.run(["rev-parse", _getEffectiveRef(id)],
130 workingDir: _repoCachePath(id)).transform((result) => result[0]); 117 workingDir: _repoCachePath(id)).transform((result) => result[0]);
131 } 118 }
132 119
133 /** 120 /// Returns the path to the revision-specific cache of [id].
134 * Returns the path to the revision-specific cache of [id].
135 */
136 Future<String> _revisionCachePath(PackageId id) { 121 Future<String> _revisionCachePath(PackageId id) {
137 return _revisionAt(id).transform((rev) { 122 return _revisionAt(id).transform((rev) {
138 var revisionCacheName = '${id.name}-$rev'; 123 var revisionCacheName = '${id.name}-$rev';
139 return join(systemCacheRoot, revisionCacheName); 124 return join(systemCacheRoot, revisionCacheName);
140 }); 125 });
141 } 126 }
142 127
143 /** 128 /// Clones the repo at the URI [from] to the path [to] on the local
144 * Clones the repo at the URI [from] to the path [to] on the local filesystem. 129 /// filesystem.
145 * 130 ///
146 * If [mirror] is true, create a bare, mirrored clone. This doesn't check out 131 /// If [mirror] is true, create a bare, mirrored clone. This doesn't check out
147 * the working tree, but instead makes the repository a local mirror of the 132 /// the working tree, but instead makes the repository a local mirror of the
148 * remote repository. See the manpage for `git clone` for more information. 133 /// remote repository. See the manpage for `git clone` for more information.
149 */
150 Future _clone(String from, String to, {bool mirror: false}) { 134 Future _clone(String from, String to, {bool mirror: false}) {
151 // Git on Windows does not seem to automatically create the destination 135 // Git on Windows does not seem to automatically create the destination
152 // directory. 136 // directory.
153 return ensureDir(to).chain((_) { 137 return ensureDir(to).chain((_) {
154 var args = ["clone", from, to]; 138 var args = ["clone", from, to];
155 if (mirror) args.insertRange(1, 1, "--mirror"); 139 if (mirror) args.insertRange(1, 1, "--mirror");
156 return git.run(args); 140 return git.run(args);
157 }).transform((result) => null); 141 }).transform((result) => null);
158 } 142 }
159 143
160 /** 144 /// Checks out the reference [ref] in [repoPath].
161 * Checks out the reference [ref] in [repoPath].
162 */
163 Future _checkOut(String repoPath, String ref) { 145 Future _checkOut(String repoPath, String ref) {
164 return git.run(["checkout", ref], workingDir: repoPath).transform( 146 return git.run(["checkout", ref], workingDir: repoPath).transform(
165 (result) => null); 147 (result) => null);
166 } 148 }
167 149
168 /** 150 /// Returns the path to the canonical clone of the repository referred to by
169 * Returns the path to the canonical clone of the repository referred to by 151 /// [id] (the one in `<system cache>/git/cache`).
170 * [id] (the one in `<system cache>/git/cache`).
171 */
172 String _repoCachePath(PackageId id) { 152 String _repoCachePath(PackageId id) {
173 var repoCacheName = '${id.name}-${sha1(_getUrl(id))}'; 153 var repoCacheName = '${id.name}-${sha1(_getUrl(id))}';
174 return join(systemCacheRoot, 'cache', repoCacheName); 154 return join(systemCacheRoot, 'cache', repoCacheName);
175 } 155 }
176 156
177 /** 157 /// Returns the repository URL for [id].
178 * Returns the repository URL for [id]. 158 ///
179 * 159 /// [description] may be a description or a [PackageId].
180 * [description] may be a description or a [PackageId].
181 */
182 String _getUrl(description) { 160 String _getUrl(description) {
183 description = _getDescription(description); 161 description = _getDescription(description);
184 if (description is String) return description; 162 if (description is String) return description;
185 return description['url']; 163 return description['url'];
186 } 164 }
187 165
188 /** 166 /// Returns the commit ref that should be checked out for [description].
189 * Returns the commit ref that should be checked out for [description]. 167 ///
190 * 168 /// This differs from [_getRef] in that it doesn't just return the ref in
191 * This differs from [_getRef] in that it doesn't just return the ref in 169 /// [description]. It will return a sensible default if that ref doesn't
192 * [description]. It will return a sensible default if that ref doesn't exist, 170 /// exist, and it will respect the "resolved-ref" parameter set by
193 * and it will respect the "resolved-ref" parameter set by [resolveId]. 171 /// [resolveId].
194 * 172 ///
195 * [description] may be a description or a [PackageId]. 173 /// [description] may be a description or a [PackageId].
196 */
197 String _getEffectiveRef(description) { 174 String _getEffectiveRef(description) {
198 description = _getDescription(description); 175 description = _getDescription(description);
199 if (description is Map && description.containsKey('resolved-ref')) { 176 if (description is Map && description.containsKey('resolved-ref')) {
200 return description['resolved-ref']; 177 return description['resolved-ref'];
201 } 178 }
202 179
203 var ref = _getRef(description); 180 var ref = _getRef(description);
204 return ref == null ? 'HEAD' : ref; 181 return ref == null ? 'HEAD' : ref;
205 } 182 }
206 183
207 /** 184 /// Returns the commit ref for [description], or null if none is given.
208 * Returns the commit ref for [description], or null if none is given. 185 ///
209 * 186 /// [description] may be a description or a [PackageId].
210 * [description] may be a description or a [PackageId].
211 */
212 String _getRef(description) { 187 String _getRef(description) {
213 description = _getDescription(description); 188 description = _getDescription(description);
214 if (description is String) return null; 189 if (description is String) return null;
215 return description['ref']; 190 return description['ref'];
216 } 191 }
217 192
218 /** 193 /// Returns [description] if it's a description, or [PackageId.description] if
219 * Returns [description] if it's a description, or [PackageId.description] if 194 /// it's a [PackageId].
220 * it's a [PackageId].
221 */
222 _getDescription(description) { 195 _getDescription(description) {
223 if (description is PackageId) return description.description; 196 if (description is PackageId) return description.description;
224 return description; 197 return description;
225 } 198 }
226 } 199 }
OLDNEW
« no previous file with comments | « utils/pub/git.dart ('k') | utils/pub/hosted_source.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698