| Index: utils/pub/entrypoint.dart
|
| diff --git a/utils/pub/entrypoint.dart b/utils/pub/entrypoint.dart
|
| deleted file mode 100644
|
| index e8fa70e49fab60cb311cb120a74d2bace67072cb..0000000000000000000000000000000000000000
|
| --- a/utils/pub/entrypoint.dart
|
| +++ /dev/null
|
| @@ -1,220 +0,0 @@
|
| -// Copyright (c) 2012, 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 entrypoint;
|
| -
|
| -import 'dart:async';
|
| -
|
| -import 'package:pathos/path.dart' as path;
|
| -
|
| -import 'io.dart';
|
| -import 'lock_file.dart';
|
| -import 'log.dart' as log;
|
| -import 'package.dart';
|
| -import 'pubspec.dart';
|
| -import 'sdk.dart' as sdk;
|
| -import 'system_cache.dart';
|
| -import 'utils.dart';
|
| -import 'version.dart';
|
| -import 'solver/version_solver.dart';
|
| -
|
| -/// Pub operates over a directed graph of dependencies that starts at a root
|
| -/// "entrypoint" package. This is typically the package where the current
|
| -/// working directory is located. An entrypoint knows the [root] package it is
|
| -/// associated with and is responsible for managing the "packages" directory
|
| -/// for it.
|
| -///
|
| -/// That directory contains symlinks to all packages used by an app. These links
|
| -/// point either to the [SystemCache] or to some other location on the local
|
| -/// filesystem.
|
| -///
|
| -/// While entrypoints are typically applications, a pure library package may end
|
| -/// up being used as an entrypoint. Also, a single package may be used as an
|
| -/// entrypoint in one context but not in another. For example, a package that
|
| -/// contains a reusable library may not be the entrypoint when used by an app,
|
| -/// but may be the entrypoint when you're running its tests.
|
| -class Entrypoint {
|
| - /// The root package this entrypoint is associated with.
|
| - final Package root;
|
| -
|
| - /// The system-wide cache which caches packages that need to be fetched over
|
| - /// the network.
|
| - final SystemCache cache;
|
| -
|
| - /// Packages which are either currently being asynchronously installed to the
|
| - /// directory, or have already been installed.
|
| - final _installs = new Map<PackageId, Future<PackageId>>();
|
| -
|
| - /// Loads the entrypoint from a package at [rootDir].
|
| - Entrypoint(String rootDir, SystemCache cache)
|
| - : root = new Package.load(null, rootDir, cache.sources),
|
| - cache = cache;
|
| -
|
| - // TODO(rnystrom): Make this path configurable.
|
| - /// The path to the entrypoint's "packages" directory.
|
| - String get packagesDir => path.join(root.dir, 'packages');
|
| -
|
| - /// Ensures that the package identified by [id] is installed to the directory.
|
| - /// Returns the resolved [PackageId].
|
| - ///
|
| - /// If this completes successfully, the package is guaranteed to be importable
|
| - /// using the `package:` scheme.
|
| - ///
|
| - /// This will automatically install the package to the system-wide cache as
|
| - /// well if it requires network access to retrieve (specifically, if
|
| - /// `id.source.shouldCache` is true).
|
| - ///
|
| - /// See also [installDependencies].
|
| - Future<PackageId> install(PackageId id) {
|
| - var pendingOrCompleted = _installs[id];
|
| - if (pendingOrCompleted != null) return pendingOrCompleted;
|
| -
|
| - var packageDir = path.join(packagesDir, id.name);
|
| - var future = new Future.sync(() {
|
| - ensureDir(path.dirname(packageDir));
|
| -
|
| - if (entryExists(packageDir)) {
|
| - // TODO(nweiz): figure out when to actually delete the directory, and
|
| - // when we can just re-use the existing symlink.
|
| - log.fine("Deleting package directory for ${id.name} before install.");
|
| - deleteEntry(packageDir);
|
| - }
|
| -
|
| - if (id.source.shouldCache) {
|
| - return cache.install(id).then(
|
| - (pkg) => createPackageSymlink(id.name, pkg.dir, packageDir));
|
| - } else {
|
| - return id.source.install(id, packageDir).then((found) {
|
| - if (found) return null;
|
| - fail('Package ${id.name} not found in source "${id.source.name}".');
|
| - });
|
| - }
|
| - }).then((_) => id.resolved);
|
| -
|
| - _installs[id] = future;
|
| -
|
| - return future;
|
| - }
|
| -
|
| - /// Installs all dependencies of the [root] package to its "packages"
|
| - /// directory, respecting the [LockFile] if present. Returns a [Future] that
|
| - /// completes when all dependencies are installed.
|
| - Future installDependencies() {
|
| - return new Future.sync(() {
|
| - return resolveVersions(cache.sources, root, lockFile: loadLockFile());
|
| - }).then(_installDependencies);
|
| - }
|
| -
|
| - /// Installs the latest available versions of all dependencies of the [root]
|
| - /// package to its "package" directory, writing a new [LockFile]. Returns a
|
| - /// [Future] that completes when all dependencies are installed.
|
| - Future updateAllDependencies() {
|
| - return resolveVersions(cache.sources, root).then(_installDependencies);
|
| - }
|
| -
|
| - /// Installs the latest available versions of [dependencies], while leaving
|
| - /// other dependencies as specified by the [LockFile] if possible. Returns a
|
| - /// [Future] that completes when all dependencies are installed.
|
| - Future updateDependencies(List<String> dependencies) {
|
| - return new Future.sync(() {
|
| - return resolveVersions(cache.sources, root,
|
| - lockFile: loadLockFile(), useLatest: dependencies);
|
| - }).then(_installDependencies);
|
| - }
|
| -
|
| - /// Removes the old packages directory, installs all dependencies listed in
|
| - /// [result], and writes a [LockFile].
|
| - Future _installDependencies(SolveResult result) {
|
| - return new Future.sync(() {
|
| - if (!result.succeeded) throw result.error;
|
| -
|
| - cleanDir(packagesDir);
|
| - return Future.wait(result.packages.map((id) {
|
| - if (id.isRoot) return new Future.value(id);
|
| - return install(id);
|
| - }).toList());
|
| - }).then((ids) {
|
| - _saveLockFile(ids);
|
| - _installSelfReference();
|
| - _linkSecondaryPackageDirs();
|
| - });
|
| - }
|
| -
|
| - /// Loads the list of concrete package versions from the `pubspec.lock`, if it
|
| - /// exists. If it doesn't, this completes to an empty [LockFile].
|
| - LockFile loadLockFile() {
|
| - var lockFilePath = path.join(root.dir, 'pubspec.lock');
|
| - if (!entryExists(lockFilePath)) return new LockFile.empty();
|
| - return new LockFile.load(lockFilePath, cache.sources);
|
| - }
|
| -
|
| - /// Saves a list of concrete package versions to the `pubspec.lock` file.
|
| - void _saveLockFile(List<PackageId> packageIds) {
|
| - var lockFile = new LockFile.empty();
|
| - for (var id in packageIds) {
|
| - if (!id.isRoot) lockFile.packages[id.name] = id;
|
| - }
|
| -
|
| - var lockFilePath = path.join(root.dir, 'pubspec.lock');
|
| - writeTextFile(lockFilePath, lockFile.serialize());
|
| - }
|
| -
|
| - /// Installs a self-referential symlink in the `packages` directory that will
|
| - /// allow a package to import its own files using `package:`.
|
| - void _installSelfReference() {
|
| - var linkPath = path.join(packagesDir, root.name);
|
| - // Create the symlink if it doesn't exist.
|
| - if (entryExists(linkPath)) return;
|
| - ensureDir(packagesDir);
|
| - createPackageSymlink(root.name, root.dir, linkPath,
|
| - isSelfLink: true, relative: true);
|
| - }
|
| -
|
| - /// If `bin/`, `test/`, or `example/` directories exist, symlink `packages/`
|
| - /// into them so that their entrypoints can be run. Do the same for any
|
| - /// subdirectories of `test/` and `example/`.
|
| - void _linkSecondaryPackageDirs() {
|
| - var binDir = path.join(root.dir, 'bin');
|
| - var exampleDir = path.join(root.dir, 'example');
|
| - var testDir = path.join(root.dir, 'test');
|
| - var toolDir = path.join(root.dir, 'tool');
|
| - var webDir = path.join(root.dir, 'web');
|
| -
|
| - if (dirExists(binDir)) _linkSecondaryPackageDir(binDir);
|
| - for (var dir in ['example', 'test', 'tool', 'web']) {
|
| - _linkSecondaryPackageDirsRecursively(path.join(root.dir, dir));
|
| - }
|
| - }
|
| -
|
| - /// Creates a symlink to the `packages` directory in [dir] and all its
|
| - /// subdirectories.
|
| - void _linkSecondaryPackageDirsRecursively(String dir) {
|
| - if (!dirExists(dir)) return;
|
| - _linkSecondaryPackageDir(dir);
|
| - _listDirWithoutPackages(dir)
|
| - .where(dirExists)
|
| - .forEach(_linkSecondaryPackageDir);
|
| - }
|
| -
|
| - // TODO(nweiz): roll this into [listDir] in io.dart once issue 4775 is fixed.
|
| - /// Recursively lists the contents of [dir], excluding hidden `.DS_Store`
|
| - /// files and `package` files.
|
| - List<String> _listDirWithoutPackages(dir) {
|
| - return flatten(listDir(dir).map((file) {
|
| - if (path.basename(file) == 'packages') return [];
|
| - if (!dirExists(file)) return [];
|
| - var fileAndSubfiles = [file];
|
| - fileAndSubfiles.addAll(_listDirWithoutPackages(file));
|
| - return fileAndSubfiles;
|
| - }));
|
| - }
|
| -
|
| - /// Creates a symlink to the `packages` directory in [dir]. Will replace one
|
| - /// if already there.
|
| - void _linkSecondaryPackageDir(String dir) {
|
| - var symlink = path.join(dir, 'packages');
|
| - if (entryExists(symlink)) deleteEntry(symlink);
|
| - createSymlink(packagesDir, symlink, relative: true);
|
| - }
|
| -}
|
|
|