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 library pub.source.git; | 5 library pub.source.git; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 | 8 |
9 import 'package:path/path.dart' as path; | 9 import 'package:path/path.dart' as path; |
10 | 10 |
11 import '../git.dart' as git; | 11 import '../git.dart' as git; |
12 import '../io.dart'; | 12 import '../io.dart'; |
13 import '../log.dart' as log; | 13 import '../log.dart' as log; |
14 import '../package.dart'; | 14 import '../package.dart'; |
15 import '../source.dart'; | 15 import '../pubspec.dart'; |
16 import '../utils.dart'; | 16 import '../utils.dart'; |
| 17 import 'cached.dart'; |
17 | 18 |
18 /// A package source that gets packages from Git repos. | 19 /// A package source that gets packages from Git repos. |
19 class GitSource extends Source { | 20 class GitSource extends CachedSource { |
20 final String name = "git"; | 21 final name = "git"; |
21 | |
22 final bool shouldCache = true; | |
23 | 22 |
24 /// The paths to the canonical clones of repositories for which "git fetch" | 23 /// The paths to the canonical clones of repositories for which "git fetch" |
25 /// has already been run during this run of pub. | 24 /// has already been run during this run of pub. |
26 final _updatedRepos = new Set<String>(); | 25 final _updatedRepos = new Set<String>(); |
27 | 26 |
28 GitSource(); | 27 GitSource(); |
29 | 28 |
| 29 /// Since we don't have an easy way to read from a remote Git repo, this |
| 30 /// just installs [id] into the system cache, then describes it from there. |
| 31 Future<Pubspec> describeUncached(PackageId id) { |
| 32 return downloadToSystemCache(id).then((package) => package.pubspec); |
| 33 } |
| 34 |
30 /// Clones a Git repo to the local filesystem. | 35 /// Clones a Git repo to the local filesystem. |
31 /// | 36 /// |
32 /// The Git cache directory is a little idiosyncratic. At the top level, it | 37 /// The Git cache directory is a little idiosyncratic. At the top level, it |
33 /// contains a directory for each commit of each repository, named `<package | 38 /// contains a directory for each commit of each repository, named `<package |
34 /// name>-<commit hash>`. These are the canonical package directories that are | 39 /// name>-<commit hash>`. These are the canonical package directories that are |
35 /// linked to from the `packages/` directory. | 40 /// linked to from the `packages/` directory. |
36 /// | 41 /// |
37 /// In addition, the Git system cache contains a subdirectory named `cache/` | 42 /// In addition, the Git system cache contains a subdirectory named `cache/` |
38 /// which contains a directory for each separate repository URL, named | 43 /// which contains a directory for each separate repository URL, named |
39 /// `<package name>-<url hash>`. These are used to check out the repository | 44 /// `<package name>-<url hash>`. These are used to check out the repository |
40 /// itself; each of the commit-specific directories are clones of a directory | 45 /// itself; each of the commit-specific directories are clones of a directory |
41 /// in `cache/`. | 46 /// in `cache/`. |
42 Future<Package> downloadToSystemCache(PackageId id, {bool force}) { | 47 Future<Package> downloadToSystemCache(PackageId id, {bool force}) { |
43 // Force is not supported because the cache repair command doesn't need it. | 48 // Force is not supported because the cache repair command doesn't need it. |
44 // Instead, it uses [resetCachedPackages]. | 49 // Instead, it uses [resetCachedPackages]. |
45 assert(force != true); | 50 assert(force != true); |
46 | 51 |
47 var revisionCachePath; | 52 var revisionCachePath; |
48 | 53 |
49 return git.isInstalled.then((installed) { | 54 return git.isInstalled.then((installed) { |
50 if (!installed) { | 55 if (!installed) { |
51 throw new Exception( | 56 throw new Exception( |
52 "Cannot get ${id.name} from Git (${_getUrl(id)}).\n" | 57 "Cannot get ${id.name} from Git (${_getUrl(id)}).\n" |
53 "Please ensure Git is correctly installed."); | 58 "Please ensure Git is correctly installed."); |
54 } | 59 } |
55 | 60 |
56 ensureDir(path.join(systemCacheRoot, 'cache')); | 61 ensureDir(path.join(systemCacheRoot, 'cache')); |
57 return _ensureRevision(id); | 62 return _ensureRevision(id); |
58 }).then((_) => systemCacheDirectory(id)).then((path) { | 63 }).then((_) => getDirectory(id)).then((path) { |
59 revisionCachePath = path; | 64 revisionCachePath = path; |
60 if (entryExists(revisionCachePath)) return null; | 65 if (entryExists(revisionCachePath)) return null; |
61 return _clone(_repoCachePath(id), revisionCachePath, mirror: false); | 66 return _clone(_repoCachePath(id), revisionCachePath, mirror: false); |
62 }).then((_) { | 67 }).then((_) { |
63 var ref = _getEffectiveRef(id); | 68 var ref = _getEffectiveRef(id); |
64 if (ref == 'HEAD') return null; | 69 if (ref == 'HEAD') return null; |
65 return _checkOut(revisionCachePath, ref); | 70 return _checkOut(revisionCachePath, ref); |
66 }).then((_) { | 71 }).then((_) { |
67 return new Package.load(id.name, revisionCachePath, systemCache.sources); | 72 return new Package.load(id.name, revisionCachePath, systemCache.sources); |
68 }); | 73 }); |
69 } | 74 } |
70 | 75 |
71 /// Returns the path to the revision-specific cache of [id]. | 76 /// Returns the path to the revision-specific cache of [id]. |
72 Future<String> systemCacheDirectory(PackageId id) { | 77 Future<String> getDirectory(PackageId id) { |
73 return _ensureRevision(id).then((rev) { | 78 return _ensureRevision(id).then((rev) { |
74 var revisionCacheName = '${id.name}-$rev'; | 79 var revisionCacheName = '${id.name}-$rev'; |
75 return path.join(systemCacheRoot, revisionCacheName); | 80 return path.join(systemCacheRoot, revisionCacheName); |
76 }); | 81 }); |
77 } | 82 } |
78 | 83 |
79 /// Ensures [description] is a Git URL. | 84 /// Ensures [description] is a Git URL. |
80 dynamic parseDescription(String containingPath, description, | 85 dynamic parseDescription(String containingPath, description, |
81 {bool fromLockFile: false}) { | 86 {bool fromLockFile: false}) { |
82 // TODO(rnystrom): Handle git URLs that are relative file paths (#8570). | 87 // TODO(rnystrom): Handle git URLs that are relative file paths (#8570). |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 | 121 |
117 /// Attaches a specific commit to [id] to disambiguate it. | 122 /// Attaches a specific commit to [id] to disambiguate it. |
118 Future<PackageId> resolveId(PackageId id) { | 123 Future<PackageId> resolveId(PackageId id) { |
119 return _ensureRevision(id).then((revision) { | 124 return _ensureRevision(id).then((revision) { |
120 var description = {'url': _getUrl(id), 'ref': _getRef(id)}; | 125 var description = {'url': _getUrl(id), 'ref': _getRef(id)}; |
121 description['resolved-ref'] = revision; | 126 description['resolved-ref'] = revision; |
122 return new PackageId(id.name, name, id.version, description); | 127 return new PackageId(id.name, name, id.version, description); |
123 }); | 128 }); |
124 } | 129 } |
125 | 130 |
| 131 List<Package> getCachedPackages() { |
| 132 // TODO(keertip): Implement getCachedPackages(). |
| 133 throw new UnimplementedError( |
| 134 "The git source doesn't support listing its cached packages yet."); |
| 135 } |
| 136 |
126 /// Resets all cached packages back to the pristine state of the Git | 137 /// Resets all cached packages back to the pristine state of the Git |
127 /// repository at the revision they are pinned to. | 138 /// repository at the revision they are pinned to. |
128 Future<Pair<int, int>> repairCachedPackages() { | 139 Future<Pair<int, int>> repairCachedPackages() { |
129 if (!dirExists(systemCacheRoot)) return new Future.value(new Pair(0, 0)); | 140 if (!dirExists(systemCacheRoot)) return new Future.value(new Pair(0, 0)); |
130 | 141 |
131 var successes = 0; | 142 var successes = 0; |
132 var failures = 0; | 143 var failures = 0; |
133 | 144 |
134 var packages = listDir(systemCacheRoot) | 145 var packages = listDir(systemCacheRoot) |
135 .where((entry) => dirExists(path.join(entry, ".git"))) | 146 .where((entry) => dirExists(path.join(entry, ".git"))) |
(...skipping 19 matching lines...) Expand all Loading... |
155 }).catchError((error, stackTrace) { | 166 }).catchError((error, stackTrace) { |
156 failures++; | 167 failures++; |
157 log.error("Failed to reset ${log.bold(package.name)} " | 168 log.error("Failed to reset ${log.bold(package.name)} " |
158 "${package.version}. Error:\n$error"); | 169 "${package.version}. Error:\n$error"); |
159 log.fine(stackTrace); | 170 log.fine(stackTrace); |
160 failures++; | 171 failures++; |
161 }, test: (error) => error is git.GitException); | 172 }, test: (error) => error is git.GitException); |
162 })).then((_) => new Pair(successes, failures)); | 173 })).then((_) => new Pair(successes, failures)); |
163 } | 174 } |
164 | 175 |
165 // TODO(keertip): Implement getCachedPackages(). | |
166 | |
167 /// Ensure that the canonical clone of the repository referred to by [id] (the | 176 /// Ensure that the canonical clone of the repository referred to by [id] (the |
168 /// one in `<system cache>/git/cache`) exists and contains the revision | 177 /// one in `<system cache>/git/cache`) exists and contains the revision |
169 /// referred to by [id]. | 178 /// referred to by [id]. |
170 /// | 179 /// |
171 /// Returns a future that completes to the hash of the revision identified by | 180 /// Returns a future that completes to the hash of the revision identified by |
172 /// [id]. | 181 /// [id]. |
173 Future<String> _ensureRevision(PackageId id) { | 182 Future<String> _ensureRevision(PackageId id) { |
174 return syncFuture(() { | 183 return syncFuture(() { |
175 var path = _repoCachePath(id); | 184 var path = _repoCachePath(id); |
176 if (!entryExists(path)) { | 185 if (!entryExists(path)) { |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 return description['ref']; | 291 return description['ref']; |
283 } | 292 } |
284 | 293 |
285 /// Returns [description] if it's a description, or [PackageId.description] if | 294 /// Returns [description] if it's a description, or [PackageId.description] if |
286 /// it's a [PackageId]. | 295 /// it's a [PackageId]. |
287 _getDescription(description) { | 296 _getDescription(description) { |
288 if (description is PackageId) return description.description; | 297 if (description is PackageId) return description.description; |
289 return description; | 298 return description; |
290 } | 299 } |
291 } | 300 } |
OLD | NEW |