| Index: sdk/lib/_internal/pub/lib/src/source/cached.dart
|
| diff --git a/sdk/lib/_internal/pub/lib/src/source/cached.dart b/sdk/lib/_internal/pub/lib/src/source/cached.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..2be69be42ffc34e79abae1cbb6552582c8951b35
|
| --- /dev/null
|
| +++ b/sdk/lib/_internal/pub/lib/src/source/cached.dart
|
| @@ -0,0 +1,101 @@
|
| +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
|
| +// for details. All rights reserved. Use of this source code is governed by a
|
| +// BSD-style license that can be found in the LICENSE file.
|
| +
|
| +library pub.source.cached;
|
| +
|
| +import 'dart:async';
|
| +
|
| +import 'package:path/path.dart' as path;
|
| +
|
| +import '../io.dart';
|
| +import '../package.dart';
|
| +import '../pubspec.dart';
|
| +import '../source.dart';
|
| +import '../utils.dart';
|
| +
|
| +/// Base class for a [Source] that installs packages into pub's [SystemCache].
|
| +///
|
| +/// A source should be cached if it requires network access to retrieve
|
| +/// packages or the package needs to be "frozen" at the point in time that it's
|
| +/// installed. (For example, Git packages are cached because installing from
|
| +/// the same repo over time may yield different commits.)
|
| +abstract class CachedSource extends Source {
|
| + /// The root directory of this source's cache within the system cache.
|
| + ///
|
| + /// This shouldn't be overridden by subclasses.
|
| + String get systemCacheRoot => path.join(systemCache.rootDir, name);
|
| +
|
| + /// If [id] is already in the system cache, just loads it from there.
|
| + ///
|
| + /// Otherwise, defers to the subclass.
|
| + Future<Pubspec> onDescribe(PackageId id) {
|
| + return getDirectory(id).then((packageDir) {
|
| + if (fileExists(path.join(packageDir, "pubspec.yaml"))) {
|
| + return new Pubspec.load(packageDir, systemCache.sources,
|
| + expectedName: id.name);
|
| + }
|
| +
|
| + return describeUncached(id);
|
| + });
|
| + }
|
| +
|
| + /// Loads the (possibly remote) pubspec for the package version identified by
|
| + /// [id].
|
| + ///
|
| + /// This will only be called for packages that have not yet been installed in
|
| + /// the system cache.
|
| + Future<Pubspec> describeUncached(PackageId id);
|
| +
|
| + Future get(PackageId id, String packageDir) {
|
| + return downloadToSystemCache(id).then(
|
| + (pkg) => createPackageSymlink(id.name, pkg.dir, packageDir));
|
| + }
|
| +
|
| + /// Determines if the package with [id] is already downloaded to the system
|
| + /// cache.
|
| + ///
|
| + /// Completes to true if the package is in the cache and appears to be
|
| + /// uncorrupted.
|
| + Future<bool> isInSystemCache(PackageId id) {
|
| + // Let the system cache initiate the download so that it can handle
|
| + // multiple concurrent downloads of the same package.
|
| + return getDirectory(id).then((packageDir) {
|
| + return dirExists(packageDir) && !isCachedPackageCorrupted(packageDir);
|
| + });
|
| + }
|
| +
|
| + /// Downloads the package identified by [id] to the system cache.
|
| + Future<Package> downloadToSystemCache(PackageId id);
|
| +
|
| + /// Returns the [Package]s that have been downloaded to the system cache.
|
| + List<Package> getCachedPackages();
|
| +
|
| + /// Reinstalls all packages that have been previously installed into the
|
| + /// system cache by this source.
|
| + ///
|
| + /// Returns a [Pair] whose first element is the number of packages
|
| + /// successfully repaired and the second is the number of failures.
|
| + Future<Pair<int, int>> repairCachedPackages();
|
| +
|
| + /// 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.
|
| + bool isCachedPackageCorrupted(String packageDir) {
|
| + if (!fileExists(path.join(packageDir, "pubspec.yaml"))) return true;
|
| +
|
| + var libDir = path.join(packageDir, "lib");
|
| + if (dirExists(libDir)) return listDir(libDir).length == 0;
|
| +
|
| + // If we got here, it's OK.
|
| + return false;
|
| + }
|
| +}
|
|
|