| Index: utils/pub/source.dart
|
| diff --git a/utils/pub/source.dart b/utils/pub/source.dart
|
| index 777c1a0222fc8f8ffbd1e4e9229cc5ca77009279..da6b0b72db7d82e7d30d8e00dd5ece569463b7b7 100644
|
| --- a/utils/pub/source.dart
|
| +++ b/utils/pub/source.dart
|
| @@ -108,7 +108,18 @@ abstract class Source {
|
| var path;
|
| return systemCacheDirectory(id).then((p) {
|
| path = p;
|
| - if (dirExists(path)) return true;
|
| +
|
| + // See if it's already cached.
|
| + if (!dirExists(path)) return false;
|
| +
|
| + return _isCachedPackageCorrupted(path).then((isCorrupted) {
|
| + if (!isCorrupted) return true;
|
| +
|
| + // Busted, so wipe out the package and reinstall.
|
| + return deleteDir(path).then((_) => false);
|
| + });
|
| + }).then((isInstalled) {
|
| + if (isInstalled) return true;
|
| ensureDir(dirname(path));
|
| return install(id, path);
|
| }).then((found) {
|
| @@ -117,6 +128,31 @@ abstract class Source {
|
| });
|
| }
|
|
|
| + /// Since pub generates symlinks that point into the system cache (in
|
| + /// particular, targeting the "lib" directories of cached packages), it's
|
| + /// possible to accidentally break cached packages if something traverses
|
| + /// that symlink.
|
| + ///
|
| + /// This tries to determine if the cached package at [packageDir] has been
|
| + /// corrupted. The heuristics are it is corrupted if any of the following are
|
| + /// true:
|
| + ///
|
| + /// * It has an empty "lib" directory.
|
| + /// * It has no pubspec.
|
| + Future<bool> _isCachedPackageCorrupted(String packageDir) {
|
| + return defer(() {
|
| + if (!fileExists(join(packageDir, "pubspec.yaml"))) return true;
|
| +
|
| + var libDir = join(packageDir, "lib");
|
| + if (dirExists(libDir)) {
|
| + return listDir(libDir).then((contents) => contents.length == 0);
|
| + }
|
| +
|
| + // If we got here, it's OK.
|
| + return false;
|
| + });
|
| + }
|
| +
|
| /// Returns the directory in the system cache that the package identified by
|
| /// [id] should be installed to. This should return a path to a subdirectory
|
| /// of [systemCacheRoot].
|
|
|