OLD | NEW |
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 import 'dart:async'; | 5 import 'dart:async'; |
6 | 6 |
7 import 'package:path/path.dart' as path; | 7 import 'package:path/path.dart' as path; |
8 import 'package:pub_semver/pub_semver.dart'; | 8 import 'package:pub_semver/pub_semver.dart'; |
9 | 9 |
10 import '../git.dart' as git; | 10 import '../git.dart' as git; |
(...skipping 10 matching lines...) Expand all Loading... |
21 class GitSource extends Source { | 21 class GitSource extends Source { |
22 final name = "git"; | 22 final name = "git"; |
23 | 23 |
24 BoundGitSource bind(SystemCache systemCache) => | 24 BoundGitSource bind(SystemCache systemCache) => |
25 new BoundGitSource(this, systemCache); | 25 new BoundGitSource(this, systemCache); |
26 | 26 |
27 /// Returns a reference to a git package with the given [name] and [url]. | 27 /// Returns a reference to a git package with the given [name] and [url]. |
28 /// | 28 /// |
29 /// If passed, [reference] is the Git reference. It defaults to `"HEAD"`. | 29 /// If passed, [reference] is the Git reference. It defaults to `"HEAD"`. |
30 PackageRef refFor(String name, String url, {String reference}) => | 30 PackageRef refFor(String name, String url, {String reference}) => |
31 new PackageRef(name, "git", {'url': url, 'ref': reference ?? 'HEAD'}); | 31 new PackageRef(name, this, {'url': url, 'ref': reference ?? 'HEAD'}); |
32 | 32 |
33 /// Given a valid git package description, returns the URL of the repository | 33 /// Given a valid git package description, returns the URL of the repository |
34 /// it pulls from. | 34 /// it pulls from. |
35 String urlFromDescription(description) => description["url"]; | 35 String urlFromDescription(description) => description["url"]; |
36 | 36 |
37 PackageRef parseRef(String name, description, {String containingPath}) { | 37 PackageRef parseRef(String name, description, {String containingPath}) { |
38 // TODO(rnystrom): Handle git URLs that are relative file paths (#8570). | 38 // TODO(rnystrom): Handle git URLs that are relative file paths (#8570). |
39 if (description is String) description = {'url': description}; | 39 if (description is String) description = {'url': description}; |
40 | 40 |
41 if (description is! Map) { | 41 if (description is! Map) { |
42 throw new FormatException("The description must be a Git URL or a map " | 42 throw new FormatException("The description must be a Git URL or a map " |
43 "with a 'url' key."); | 43 "with a 'url' key."); |
44 } | 44 } |
45 | 45 |
46 if (description["url"] is! String) { | 46 if (description["url"] is! String) { |
47 throw new FormatException("The 'url' field of the description must be a " | 47 throw new FormatException("The 'url' field of the description must be a " |
48 "string."); | 48 "string."); |
49 } | 49 } |
50 | 50 |
51 _validateUrl(description["url"]); | 51 _validateUrl(description["url"]); |
52 | 52 |
53 var ref = description["ref"]; | 53 var ref = description["ref"]; |
54 if (ref != null && ref is! String) { | 54 if (ref != null && ref is! String) { |
55 throw new FormatException("The 'ref' field of the description must be a " | 55 throw new FormatException("The 'ref' field of the description must be a " |
56 "string."); | 56 "string."); |
57 } | 57 } |
58 | 58 |
59 return new PackageRef(name, this.name, { | 59 return new PackageRef(name, this, { |
60 "url": description["url"], | 60 "url": description["url"], |
61 "ref": description["ref"] ?? "HEAD" | 61 "ref": description["ref"] ?? "HEAD" |
62 }); | 62 }); |
63 } | 63 } |
64 | 64 |
65 PackageId parseId(String name, Version version, description) { | 65 PackageId parseId(String name, Version version, description) { |
66 if (description is! Map) { | 66 if (description is! Map) { |
67 throw new FormatException("The description must be a map with a 'url' " | 67 throw new FormatException("The description must be a map with a 'url' " |
68 "key."); | 68 "key."); |
69 } | 69 } |
70 | 70 |
71 if (description["url"] is! String) { | 71 if (description["url"] is! String) { |
72 throw new FormatException("The 'url' field of the description must be a " | 72 throw new FormatException("The 'url' field of the description must be a " |
73 "string."); | 73 "string."); |
74 } | 74 } |
75 | 75 |
76 _validateUrl(description["url"]); | 76 _validateUrl(description["url"]); |
77 | 77 |
78 var ref = description["ref"]; | 78 var ref = description["ref"]; |
79 if (ref != null && ref is! String) { | 79 if (ref != null && ref is! String) { |
80 throw new FormatException("The 'ref' field of the description must be a " | 80 throw new FormatException("The 'ref' field of the description must be a " |
81 "string."); | 81 "string."); |
82 } | 82 } |
83 | 83 |
84 if (description["resolved-ref"] is! String) { | 84 if (description["resolved-ref"] is! String) { |
85 throw new FormatException("The 'resolved-ref' field of the description " | 85 throw new FormatException("The 'resolved-ref' field of the description " |
86 "must be a string."); | 86 "must be a string."); |
87 } | 87 } |
88 | 88 |
89 return new PackageId(name, this.name, version, { | 89 return new PackageId(name, this, version, { |
90 "url": description["url"], | 90 "url": description["url"], |
91 "ref": description["ref"] ?? "HEAD", | 91 "ref": description["ref"] ?? "HEAD", |
92 "resolved-ref": description["resolved-ref"] | 92 "resolved-ref": description["resolved-ref"] |
93 }); | 93 }); |
94 } | 94 } |
95 | 95 |
96 /// Throws a [FormatException] if [url] isn't a valid Git URL. | 96 /// Throws a [FormatException] if [url] isn't a valid Git URL. |
97 void _validateUrl(String url) { | 97 void _validateUrl(String url) { |
98 // If the URL contains an @, it's probably an SSH hostname, which we don't | 98 // If the URL contains an @, it's probably an SSH hostname, which we don't |
99 // know how to validate. | 99 // know how to validate. |
(...skipping 25 matching lines...) Expand all Loading... |
125 if (description1['url'] != description2['url']) return false; | 125 if (description1['url'] != description2['url']) return false; |
126 if (description1['ref'] != description2['ref']) return false; | 126 if (description1['ref'] != description2['ref']) return false; |
127 | 127 |
128 if (description1.containsKey('resolved-ref') && | 128 if (description1.containsKey('resolved-ref') && |
129 description2.containsKey('resolved-ref')) { | 129 description2.containsKey('resolved-ref')) { |
130 return description1['resolved-ref'] == description2['resolved-ref']; | 130 return description1['resolved-ref'] == description2['resolved-ref']; |
131 } | 131 } |
132 | 132 |
133 return true; | 133 return true; |
134 } | 134 } |
| 135 |
| 136 int hashDescription(description) { |
| 137 // Don't include the resolved ref in the hash code because we ignore it in |
| 138 // [descriptionsEqual] if only one description defines it. |
| 139 return description['url'].hashCode ^ description['ref'].hashCode; |
| 140 } |
135 } | 141 } |
136 | 142 |
137 /// The [BoundSource] for [GitSource]. | 143 /// The [BoundSource] for [GitSource]. |
138 class BoundGitSource extends CachedSource { | 144 class BoundGitSource extends CachedSource { |
139 final GitSource source; | 145 final GitSource source; |
140 | 146 |
141 final SystemCache systemCache; | 147 final SystemCache systemCache; |
142 | 148 |
143 BoundGitSource(this.source, this.systemCache); | 149 BoundGitSource(this.source, this.systemCache); |
144 | 150 |
(...skipping 13 matching lines...) Expand all Loading... |
158 }); | 164 }); |
159 } | 165 } |
160 | 166 |
161 Future<List<PackageId>> doGetVersions(PackageRef ref) async { | 167 Future<List<PackageId>> doGetVersions(PackageRef ref) async { |
162 await _ensureRepoCache(ref); | 168 await _ensureRepoCache(ref); |
163 var path = _repoCachePath(ref); | 169 var path = _repoCachePath(ref); |
164 var revision = await _firstRevision(path, ref.description['ref']); | 170 var revision = await _firstRevision(path, ref.description['ref']); |
165 var pubspec = await _describeUncached(ref, revision); | 171 var pubspec = await _describeUncached(ref, revision); |
166 | 172 |
167 return [ | 173 return [ |
168 new PackageId(ref.name, source.name, pubspec.version, { | 174 new PackageId(ref.name, source, pubspec.version, { |
169 'url': ref.description['url'], | 175 'url': ref.description['url'], |
170 'ref': ref.description['ref'], | 176 'ref': ref.description['ref'], |
171 'resolved-ref': revision | 177 'resolved-ref': revision |
172 }) | 178 }) |
173 ]; | 179 ]; |
174 } | 180 } |
175 | 181 |
176 /// Since we don't have an easy way to read from a remote Git repo, this | 182 /// Since we don't have an easy way to read from a remote Git repo, this |
177 /// just installs [id] into the system cache, then describes it from there. | 183 /// just installs [id] into the system cache, then describes it from there. |
178 Future<Pubspec> describeUncached(PackageId id) => | 184 Future<Pubspec> describeUncached(PackageId id) => |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
250 .where((entry) => dirExists(path.join(entry, ".git"))) | 256 .where((entry) => dirExists(path.join(entry, ".git"))) |
251 .map((packageDir) => new Package.load( | 257 .map((packageDir) => new Package.load( |
252 null, packageDir, systemCache.sources)) | 258 null, packageDir, systemCache.sources)) |
253 .toList(); | 259 .toList(); |
254 | 260 |
255 // Note that there may be multiple packages with the same name and version | 261 // Note that there may be multiple packages with the same name and version |
256 // (pinned to different commits). The sort order of those is unspecified. | 262 // (pinned to different commits). The sort order of those is unspecified. |
257 packages.sort(Package.orderByNameAndVersion); | 263 packages.sort(Package.orderByNameAndVersion); |
258 | 264 |
259 for (var package in packages) { | 265 for (var package in packages) { |
260 var id = new PackageId(package.name, source.name, package.version, null); | 266 var id = new PackageId(package.name, source, package.version, null); |
261 | 267 |
262 log.message("Resetting Git repository for " | 268 log.message("Resetting Git repository for " |
263 "${log.bold(package.name)} ${package.version}..."); | 269 "${log.bold(package.name)} ${package.version}..."); |
264 | 270 |
265 try { | 271 try { |
266 // Remove all untracked files. | 272 // Remove all untracked files. |
267 await git.run(["clean", "-d", "--force", "-x"], | 273 await git.run(["clean", "-d", "--force", "-x"], |
268 workingDir: package.dir); | 274 workingDir: package.dir); |
269 | 275 |
270 // Discard all changes to tracked files. | 276 // Discard all changes to tracked files. |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
376 (result) => null); | 382 (result) => null); |
377 } | 383 } |
378 | 384 |
379 /// Returns the path to the canonical clone of the repository referred to by | 385 /// Returns the path to the canonical clone of the repository referred to by |
380 /// [id] (the one in `<system cache>/git/cache`). | 386 /// [id] (the one in `<system cache>/git/cache`). |
381 String _repoCachePath(PackageRef ref) { | 387 String _repoCachePath(PackageRef ref) { |
382 var repoCacheName = '${ref.name}-${sha1(ref.description['url'])}'; | 388 var repoCacheName = '${ref.name}-${sha1(ref.description['url'])}'; |
383 return path.join(systemCacheRoot, 'cache', repoCacheName); | 389 return path.join(systemCacheRoot, 'cache', repoCacheName); |
384 } | 390 } |
385 } | 391 } |
OLD | NEW |