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 source; | 5 library source; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 | 8 |
9 import 'package:pathos/path.dart' as path; | 9 import 'package:pathos/path.dart' as path; |
10 | 10 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 /// Installs the package identified by [id] to the system cache. This is only | 106 /// Installs the package identified by [id] to the system cache. This is only |
107 /// called for sources with [shouldCache] set to true. | 107 /// called for sources with [shouldCache] set to true. |
108 /// | 108 /// |
109 /// By default, this uses [systemCacheDirectory] and [install]. | 109 /// By default, this uses [systemCacheDirectory] and [install]. |
110 Future<Package> installToSystemCache(PackageId id) { | 110 Future<Package> installToSystemCache(PackageId id) { |
111 var packageDir; | 111 var packageDir; |
112 return systemCacheDirectory(id).then((p) { | 112 return systemCacheDirectory(id).then((p) { |
113 packageDir = p; | 113 packageDir = p; |
114 | 114 |
115 // See if it's already cached. | 115 // See if it's already cached. |
116 if (!dirExists(packageDir)) return false; | 116 if (dirExists(packageDir)) { |
117 | 117 if (!_isCachedPackageCorrupted(packageDir)) return true; |
118 return _isCachedPackageCorrupted(packageDir).then((isCorrupted) { | |
119 if (!isCorrupted) return true; | |
120 | |
121 // Busted, so wipe out the package and reinstall. | 118 // Busted, so wipe out the package and reinstall. |
122 deleteEntry(packageDir); | 119 deleteEntry(packageDir); |
123 return false; | 120 } |
124 }); | 121 |
125 }).then((isInstalled) { | |
126 if (isInstalled) return true; | |
127 ensureDir(path.dirname(packageDir)); | 122 ensureDir(path.dirname(packageDir)); |
128 return install(id, packageDir); | 123 return install(id, packageDir); |
129 }).then((found) { | 124 }).then((found) { |
130 if (!found) throw 'Package $id not found.'; | 125 if (!found) throw 'Package $id not found.'; |
131 return new Package.load(id.name, packageDir, systemCache.sources); | 126 return new Package.load(id.name, packageDir, systemCache.sources); |
132 }); | 127 }); |
133 } | 128 } |
134 | 129 |
135 /// Since pub generates symlinks that point into the system cache (in | 130 /// Since pub generates symlinks that point into the system cache (in |
136 /// particular, targeting the "lib" directories of cached packages), it's | 131 /// particular, targeting the "lib" directories of cached packages), it's |
137 /// possible to accidentally break cached packages if something traverses | 132 /// possible to accidentally break cached packages if something traverses |
138 /// that symlink. | 133 /// that symlink. |
139 /// | 134 /// |
140 /// This tries to determine if the cached package at [packageDir] has been | 135 /// This tries to determine if the cached package at [packageDir] has been |
141 /// corrupted. The heuristics are it is corrupted if any of the following are | 136 /// corrupted. The heuristics are it is corrupted if any of the following are |
142 /// true: | 137 /// true: |
143 /// | 138 /// |
144 /// * It has an empty "lib" directory. | 139 /// * It has an empty "lib" directory. |
145 /// * It has no pubspec. | 140 /// * It has no pubspec. |
146 Future<bool> _isCachedPackageCorrupted(String packageDir) { | 141 bool _isCachedPackageCorrupted(String packageDir) { |
147 return defer(() { | 142 if (!fileExists(path.join(packageDir, "pubspec.yaml"))) return true; |
148 if (!fileExists(path.join(packageDir, "pubspec.yaml"))) return true; | |
149 | 143 |
150 var libDir = path.join(packageDir, "lib"); | 144 var libDir = path.join(packageDir, "lib"); |
151 if (dirExists(libDir)) { | 145 if (dirExists(libDir)) return listDir(libDir).length == 0; |
152 return listDir(libDir).then((contents) => contents.length == 0); | |
153 } | |
154 | 146 |
155 // If we got here, it's OK. | 147 // If we got here, it's OK. |
156 return false; | 148 return false; |
157 }); | |
158 } | 149 } |
159 | 150 |
160 /// Returns the directory in the system cache that the package identified by | 151 /// Returns the directory in the system cache that the package identified by |
161 /// [id] should be installed to. This should return a path to a subdirectory | 152 /// [id] should be installed to. This should return a path to a subdirectory |
162 /// of [systemCacheRoot]. | 153 /// of [systemCacheRoot]. |
163 /// | 154 /// |
164 /// This doesn't need to be implemented if [shouldCache] is false. | 155 /// This doesn't need to be implemented if [shouldCache] is false. |
165 Future<String> systemCacheDirectory(PackageId id) { | 156 Future<String> systemCacheDirectory(PackageId id) { |
166 return new Future.immediateError( | 157 return new Future.immediateError( |
167 "systemCacheDirectory() must be implemented if shouldCache is true."); | 158 "systemCacheDirectory() must be implemented if shouldCache is true."); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 /// | 202 /// |
212 /// The returned [PackageId] may have a description field that's invalid | 203 /// The returned [PackageId] may have a description field that's invalid |
213 /// according to [parseDescription], although it must still be serializable | 204 /// according to [parseDescription], although it must still be serializable |
214 /// to JSON and YAML. It must also be equal to [id] according to | 205 /// to JSON and YAML. It must also be equal to [id] according to |
215 /// [descriptionsEqual]. | 206 /// [descriptionsEqual]. |
216 /// | 207 /// |
217 /// By default, this just returns [id]. | 208 /// By default, this just returns [id]. |
218 Future<PackageId> resolveId(PackageId id) => new Future.immediate(id); | 209 Future<PackageId> resolveId(PackageId id) => new Future.immediate(id); |
219 | 210 |
220 /// Returns the [Package]s that have been installed in the system cache. | 211 /// Returns the [Package]s that have been installed in the system cache. |
221 Future<List<Package>> getCachedPackages() { | 212 List<Package> getCachedPackages() { |
222 if (shouldCache) throw "Source $name must implement this."; | 213 if (shouldCache) throw "Source $name must implement this."; |
223 } | 214 } |
224 | 215 |
225 /// Returns the source's name. | 216 /// Returns the source's name. |
226 String toString() => name; | 217 String toString() => name; |
227 } | 218 } |
OLD | NEW |