Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(125)

Unified Diff: sdk/lib/_internal/pub_generated/lib/src/barback/asset_environment.dart

Issue 937243002: Revert "Revert "Use native async/await support in pub."" (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: sdk/lib/_internal/pub_generated/lib/src/barback/asset_environment.dart
diff --git a/sdk/lib/_internal/pub_generated/lib/src/barback/asset_environment.dart b/sdk/lib/_internal/pub_generated/lib/src/barback/asset_environment.dart
deleted file mode 100644
index 8316d4e4e03c93f3c52c574755708e3c5216ae8d..0000000000000000000000000000000000000000
--- a/sdk/lib/_internal/pub_generated/lib/src/barback/asset_environment.dart
+++ /dev/null
@@ -1,960 +0,0 @@
-// 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.barback.asset_environment;
-
-import 'dart:async';
-import 'dart:io';
-
-import 'package:barback/barback.dart';
-import 'package:path/path.dart' as path;
-import 'package:watcher/watcher.dart';
-
-import '../cached_package.dart';
-import '../entrypoint.dart';
-import '../exceptions.dart';
-import '../io.dart';
-import '../log.dart' as log;
-import '../package.dart';
-import '../package_graph.dart';
-import '../sdk.dart' as sdk;
-import '../source/cached.dart';
-import '../utils.dart';
-import 'admin_server.dart';
-import 'barback_server.dart';
-import 'dart_forwarding_transformer.dart';
-import 'dart2js_transformer.dart';
-import 'load_all_transformers.dart';
-import 'pub_package_provider.dart';
-import 'source_directory.dart';
-
-/// The entire "visible" state of the assets of a package and all of its
-/// dependencies, taking into account the user's configuration when running pub.
-///
-/// Where [PackageGraph] just describes the entrypoint's dependencies as
-/// specified by pubspecs, this includes "transient" information like the mode
-/// that the user is running pub in, or which directories they want to
-/// transform.
-class AssetEnvironment {
- /// Creates a new build environment for working with the assets used by
- /// [entrypoint] and its dependencies.
- ///
- /// HTTP servers that serve directories from this environment will be bound
- /// to [hostname] and have ports based on [basePort]. If omitted, they
- /// default to "localhost" and "0" (use ephemeral ports), respectively.
- ///
- /// Loads all used transformers using [mode] (including dart2js if
- /// [useDart2JS] is true).
- ///
- /// This will only add the root package's "lib" directory to the environment.
- /// Other directories can be added to the environment using [serveDirectory].
- ///
- /// If [watcherType] is not [WatcherType.NONE] (the default), watches source
- /// assets for modification.
- ///
- /// If [packages] is passed, only those packages' assets are loaded and
- /// served.
- ///
- /// If [entrypoints] is passed, only transformers necessary to run those
- /// entrypoints are loaded. Each entrypoint is expected to refer to a Dart
- /// library.
- ///
- /// Returns a [Future] that completes to the environment once the inputs,
- /// transformers, and server are loaded and ready.
- static Future<AssetEnvironment> create(Entrypoint entrypoint,
- BarbackMode mode, {WatcherType watcherType, String hostname, int basePort,
- Iterable<String> packages, Iterable<AssetId> entrypoints, bool useDart2JS:
- true}) {
- if (watcherType == null) watcherType = WatcherType.NONE;
- if (hostname == null) hostname = "localhost";
- if (basePort == null) basePort = 0;
-
- return log.progress("Loading asset environment", () {
- final completer0 = new Completer();
- scheduleMicrotask(() {
- try {
- new Future.value(entrypoint.loadPackageGraph()).then((x0) {
- try {
- var graph = x0;
- graph = _adjustPackageGraph(graph, mode, packages);
- var barback = new Barback(new PubPackageProvider(graph));
- barback.log.listen(_log);
- var environment =
- new AssetEnvironment._(graph, barback, mode, watcherType, hostname, basePort);
- new Future.value(
- environment._load(entrypoints: entrypoints, useDart2JS: useDart2JS)).then((x1) {
- try {
- x1;
- completer0.complete(environment);
- } catch (e0, s0) {
- completer0.completeError(e0, s0);
- }
- }, onError: completer0.completeError);
- } catch (e1, s1) {
- completer0.completeError(e1, s1);
- }
- }, onError: completer0.completeError);
- } catch (e, s) {
- completer0.completeError(e, s);
- }
- });
- return completer0.future;
- }, fine: true);
- }
-
- /// Return a version of [graph] that's restricted to [packages] (if passed)
- /// and loads cached packages (if [mode] is [BarbackMode.DEBUG]).
- static PackageGraph _adjustPackageGraph(PackageGraph graph, BarbackMode mode,
- Iterable<String> packages) {
- if (mode != BarbackMode.DEBUG && packages == null) return graph;
- packages = (packages == null ? graph.packages.keys : packages).toSet();
-
- return new PackageGraph(
- graph.entrypoint,
- graph.lockFile,
- new Map.fromIterable(packages, value: (packageName) {
- var package = graph.packages[packageName];
- if (mode != BarbackMode.DEBUG) return package;
- var cache = path.join('.pub/deps/debug', packageName);
- if (!dirExists(cache)) return package;
- return new CachedPackage(package, cache);
- }));
- }
-
- /// The server for the Web Socket API and admin interface.
- AdminServer _adminServer;
-
- /// The public directories in the root package that are included in the asset
- /// environment, keyed by their root directory.
- final _directories = new Map<String, SourceDirectory>();
-
- /// The [Barback] instance used to process assets in this environment.
- final Barback barback;
-
- /// The root package being built.
- Package get rootPackage => graph.entrypoint.root;
-
- /// The graph of packages whose assets and transformers are loaded in this
- /// environment.
- ///
- /// This isn't necessarily identical to the graph that's passed in to the
- /// environment. It may expose fewer packages if some packages' assets don't
- /// need to be loaded, and it may expose some [CachedPackage]s.
- final PackageGraph graph;
-
- /// The mode to run the transformers in.
- final BarbackMode mode;
-
- /// The [Transformer]s that should be appended by default to the root
- /// package's transformer cascade. Will be empty if there are none.
- final _builtInTransformers = <Transformer>[];
-
- /// How source files should be watched.
- final WatcherType _watcherType;
-
- /// The hostname that servers are bound to.
- final String _hostname;
-
- /// The starting number for ports that servers will be bound to.
- ///
- /// Servers will be bound to ports starting at this number and then
- /// incrementing from there. However, if this is zero, then ephemeral port
- /// numbers will be selected for each server.
- final int _basePort;
-
- /// The modified source assets that have not been sent to barback yet.
- ///
- /// The build environment can be paused (by calling [pauseUpdates]) and
- /// resumed ([resumeUpdates]). While paused, all source asset updates that
- /// come from watching or adding new directories are not sent to barback.
- /// When resumed, all pending source updates are sent to barback.
- ///
- /// This lets pub serve and pub build create an environment and bind several
- /// servers before barback starts building and producing results
- /// asynchronously.
- ///
- /// If this is `null`, then the environment is "live" and all updates will
- /// go to barback immediately.
- Set<AssetId> _modifiedSources;
-
- AssetEnvironment._(this.graph, this.barback, this.mode, this._watcherType,
- this._hostname, this._basePort);
-
- /// Gets the built-in [Transformer]s that should be added to [package].
- ///
- /// Returns `null` if there are none.
- Iterable<Transformer> getBuiltInTransformers(Package package) {
- // Built-in transformers only apply to the root package.
- if (package.name != rootPackage.name) return null;
-
- // The built-in transformers are for dart2js and forwarding assets around
- // dart2js.
- if (_builtInTransformers.isEmpty) return null;
-
- return _builtInTransformers;
- }
-
- /// Starts up the admin server on an appropriate port and returns it.
- ///
- /// This may only be called once on the build environment.
- Future<AdminServer> startAdminServer([int port]) {
- // Can only start once.
- assert(_adminServer == null);
-
- // The admin server is bound to one before the base port by default, unless
- // it's ephemeral in which case the admin port is too.
- if (port == null) port = _basePort == 0 ? 0 : _basePort - 1;
-
- return AdminServer.bind(this, _hostname, port).then((server) => _adminServer =
- server);
- }
-
- /// Binds a new port to serve assets from within [rootDirectory] in the
- /// entrypoint package.
- ///
- /// Adds and watches the sources within that directory. Returns a [Future]
- /// that completes to the bound server.
- ///
- /// If [rootDirectory] is already being served, returns that existing server.
- Future<BarbackServer> serveDirectory(String rootDirectory) {
- // See if there is already a server bound to the directory.
- var directory = _directories[rootDirectory];
- if (directory != null) {
- return directory.server.then((server) {
- log.fine('Already serving $rootDirectory on ${server.url}.');
- return server;
- });
- }
-
- // See if the new directory overlaps any existing servers.
- var overlapping = _directories.keys.where(
- (directory) =>
- path.isWithin(directory, rootDirectory) ||
- path.isWithin(rootDirectory, directory)).toList();
-
- if (overlapping.isNotEmpty) {
- return new Future.error(
- new OverlappingSourceDirectoryException(overlapping));
- }
-
- var port = _basePort;
-
- // If not using an ephemeral port, find the lowest-numbered available one.
- if (port != 0) {
- var boundPorts =
- _directories.values.map((directory) => directory.port).toSet();
- while (boundPorts.contains(port)) {
- port++;
- }
- }
-
- var sourceDirectory =
- new SourceDirectory(this, rootDirectory, _hostname, port);
- _directories[rootDirectory] = sourceDirectory;
-
- return _provideDirectorySources(
- rootPackage,
- rootDirectory).then((subscription) {
- sourceDirectory.watchSubscription = subscription;
- return sourceDirectory.serve();
- });
- }
-
- /// Binds a new port to serve assets from within the "bin" directory of
- /// [package].
- ///
- /// Adds the sources within that directory and then binds a server to it.
- /// Unlike [serveDirectory], this works with packages that are not the
- /// entrypoint.
- ///
- /// Returns a [Future] that completes to the bound server.
- Future<BarbackServer> servePackageBinDirectory(String package) {
- return _provideDirectorySources(
- graph.packages[package],
- "bin").then(
- (_) =>
- BarbackServer.bind(this, _hostname, 0, package: package, rootDirectory: "bin"));
- }
-
- /// Precompiles all of [packageName]'s executables to snapshots in
- /// [directory].
- ///
- /// If [executableIds] is passed, only those executables are precompiled.
- ///
- /// Returns a map from executable name to path for the snapshots that were
- /// successfully precompiled.
- Future<Map<String, String>> precompileExecutables(String packageName,
- String directory, {Iterable<AssetId> executableIds}) {
- final completer0 = new Completer();
- scheduleMicrotask(() {
- try {
- join0() {
- log.fine("Executables for ${packageName}: ${executableIds}");
- join1() {
- var package = graph.packages[packageName];
- new Future.value(servePackageBinDirectory(packageName)).then((x0) {
- try {
- var server = x0;
- join2() {
- completer0.complete();
- }
- finally0(cont0) {
- server.close();
- cont0();
- }
- catch0(e1, s1) {
- finally0(() => completer0.completeError(e1, s1));
- }
- try {
- var precompiled = {};
- new Future.value(waitAndPrintErrors(executableIds.map(((id) {
- final completer0 = new Completer();
- scheduleMicrotask(() {
- try {
- var basename = path.url.basename(id.path);
- var snapshotPath =
- path.join(directory, "${basename}.snapshot");
- new Future.value(
- runProcess(
- Platform.executable,
- [
- '--snapshot=${snapshotPath}',
- server.url.resolve(basename).toString()])).then((x0) {
- try {
- var result = x0;
- join0() {
- completer0.complete();
- }
- if (result.success) {
- log.message(
- "Precompiled ${_formatExecutable(id)}.");
- precompiled[path.withoutExtension(basename)] =
- snapshotPath;
- join0();
- } else {
- throw new ApplicationException(
- log.yellow("Failed to precompile ${_formatExecutable(id)}:\n") +
- result.stderr.join('\n'));
- join0();
- }
- } catch (e0, s0) {
- completer0.completeError(e0, s0);
- }
- }, onError: completer0.completeError);
- } catch (e, s) {
- completer0.completeError(e, s);
- }
- });
- return completer0.future;
- })))).then((x1) {
- try {
- x1;
- final v0 = precompiled;
- finally0(() {
- completer0.complete(v0);
- });
- } catch (e2, s2) {
- catch0(e2, s2);
- }
- }, onError: catch0);
- } catch (e3, s3) {
- catch0(e3, s3);
- }
- } catch (e4, s4) {
- completer0.completeError(e4, s4);
- }
- }, onError: completer0.completeError);
- }
- if (executableIds.isEmpty) {
- completer0.complete([]);
- } else {
- join1();
- }
- }
- if (executableIds == null) {
- executableIds = graph.packages[packageName].executableIds;
- join0();
- } else {
- join0();
- }
- } catch (e, s) {
- completer0.completeError(e, s);
- }
- });
- return completer0.future;
- }
-
- /// Returns the executable name for [id].
- ///
- /// [id] is assumed to be an executable in a bin directory. The return value
- /// is intended for log output and may contain formatting.
- String _formatExecutable(AssetId id) =>
- log.bold("${id.package}:${path.basenameWithoutExtension(id.path)}");
-
- /// Stops the server bound to [rootDirectory].
- ///
- /// Also removes any source files within that directory from barback. Returns
- /// the URL of the unbound server, of `null` if [rootDirectory] was not
- /// bound to a server.
- Future<Uri> unserveDirectory(String rootDirectory) {
- log.fine("Unserving $rootDirectory.");
- var directory = _directories.remove(rootDirectory);
- if (directory == null) return new Future.value();
-
- return directory.server.then((server) {
- var url = server.url;
- return directory.close().then((_) {
- _removeDirectorySources(rootDirectory);
- return url;
- });
- });
- }
-
- /// Gets the source directory that contains [assetPath] within the entrypoint
- /// package.
- ///
- /// If [assetPath] is not contained within a source directory, this throws
- /// an exception.
- String getSourceDirectoryContaining(String assetPath) =>
- _directories.values.firstWhere(
- (dir) => path.isWithin(dir.directory, assetPath)).directory;
-
- /// Return all URLs serving [assetPath] in this environment.
- Future<List<Uri>> getUrlsForAssetPath(String assetPath) {
- // Check the three (mutually-exclusive) places the path could be pointing.
- return _lookUpPathInServerRoot(assetPath).then((urls) {
- if (urls.isNotEmpty) return urls;
- return _lookUpPathInPackagesDirectory(assetPath);
- }).then((urls) {
- if (urls.isNotEmpty) return urls;
- return _lookUpPathInDependency(assetPath);
- });
- }
-
- /// Look up [assetPath] in the root directories of servers running in the
- /// entrypoint package.
- Future<List<Uri>> _lookUpPathInServerRoot(String assetPath) {
- // Find all of the servers whose root directories contain the asset and
- // generate appropriate URLs for each.
- return Future.wait(
- _directories.values.where(
- (dir) => path.isWithin(dir.directory, assetPath)).map((dir) {
- var relativePath = path.relative(assetPath, from: dir.directory);
- return dir.server.then(
- (server) => server.url.resolveUri(path.toUri(relativePath)));
- }));
- }
-
- /// Look up [assetPath] in the "packages" directory in the entrypoint package.
- Future<List<Uri>> _lookUpPathInPackagesDirectory(String assetPath) {
- var components = path.split(path.relative(assetPath));
- if (components.first != "packages") return new Future.value([]);
- if (!graph.packages.containsKey(components[1])) return new Future.value([]);
- return Future.wait(_directories.values.map((dir) {
- return dir.server.then(
- (server) => server.url.resolveUri(path.toUri(assetPath)));
- }));
- }
-
- /// Look up [assetPath] in the "lib" or "asset" directory of a dependency
- /// package.
- Future<List<Uri>> _lookUpPathInDependency(String assetPath) {
- for (var packageName in graph.packages.keys) {
- var package = graph.packages[packageName];
- var libDir = package.path('lib');
- var assetDir = package.path('asset');
-
- var uri;
- if (path.isWithin(libDir, assetPath)) {
- uri = path.toUri(
- path.join('packages', package.name, path.relative(assetPath, from: libDir)));
- } else if (path.isWithin(assetDir, assetPath)) {
- uri = path.toUri(
- path.join('assets', package.name, path.relative(assetPath, from: assetDir)));
- } else {
- continue;
- }
-
- return Future.wait(_directories.values.map((dir) {
- return dir.server.then((server) => server.url.resolveUri(uri));
- }));
- }
-
- return new Future.value([]);
- }
-
- /// Given a URL to an asset served by this environment, returns the ID of the
- /// asset that would be accessed by that URL.
- ///
- /// If no server can serve [url], completes to `null`.
- Future<AssetId> getAssetIdForUrl(Uri url) {
- return Future.wait(
- _directories.values.map((dir) => dir.server)).then((servers) {
- var server = servers.firstWhere((server) {
- if (server.port != url.port) return false;
- return isLoopback(server.address.host) == isLoopback(url.host) ||
- server.address.host == url.host;
- }, orElse: () => null);
- if (server == null) return null;
- return server.urlToId(url);
- });
- }
-
- /// Determines if [sourcePath] is contained within any of the directories in
- /// the root package that are visible to this build environment.
- bool containsPath(String sourcePath) {
- var directories = ["lib"];
- directories.addAll(_directories.keys);
- return directories.any((dir) => path.isWithin(dir, sourcePath));
- }
-
- /// Pauses sending source asset updates to barback.
- void pauseUpdates() {
- // Cannot pause while already paused.
- assert(_modifiedSources == null);
-
- _modifiedSources = new Set<AssetId>();
- }
-
- /// Sends any pending source updates to barback and begins the asynchronous
- /// build process.
- void resumeUpdates() {
- // Cannot resume while not paused.
- assert(_modifiedSources != null);
-
- barback.updateSources(_modifiedSources);
- _modifiedSources = null;
- }
-
- /// Loads the assets and transformers for this environment.
- ///
- /// This transforms and serves all library and asset files in all packages in
- /// the environment's package graph. It loads any transformer plugins defined
- /// in packages in [graph] and re-runs them as necessary when any input files
- /// change.
- ///
- /// If [useDart2JS] is `true`, then the [Dart2JSTransformer] is implicitly
- /// added to end of the root package's transformer phases.
- ///
- /// If [entrypoints] is passed, only transformers necessary to run those
- /// entrypoints will be loaded.
- ///
- /// Returns a [Future] that completes once all inputs and transformers are
- /// loaded.
- Future _load({Iterable<AssetId> entrypoints, bool useDart2JS}) {
- return log.progress("Initializing barback", () {
- final completer0 = new Completer();
- scheduleMicrotask(() {
- try {
- var containsDart2JS =
- graph.entrypoint.root.pubspec.transformers.any(((transformers) {
- return transformers.any(
- (config) => config.id.package == '\$dart2js');
- }));
- join0() {
- new Future.value(BarbackServer.bind(this, _hostname, 0)).then((x0) {
- try {
- var transformerServer = x0;
- var errorStream = barback.errors.map(((error) {
- if (error is! AssetLoadException) throw error;
- log.error(log.red(error.message));
- log.fine(error.stackTrace.terse);
- }));
- new Future.value(_withStreamErrors((() {
- return log.progress("Loading source assets", _provideSources);
- }), [errorStream, barback.results])).then((x1) {
- try {
- x1;
- log.fine("Provided sources.");
- errorStream = barback.errors.map(((error) {
- if (error is! TransformerException) throw error;
- var message = error.error.toString();
- if (error.stackTrace != null) {
- message += "\n" + error.stackTrace.terse.toString();
- }
- _log(
- new LogEntry(
- error.transform,
- error.transform.primaryId,
- LogLevel.ERROR,
- message,
- null));
- }));
- new Future.value(_withStreamErrors((() {
- final completer0 = new Completer();
- scheduleMicrotask(() {
- try {
- completer0.complete(
- log.progress("Loading transformers", (() {
- final completer0 = new Completer();
- scheduleMicrotask(() {
- try {
- new Future.value(
- loadAllTransformers(
- this,
- transformerServer,
- entrypoints: entrypoints)).then((x0) {
- try {
- x0;
- transformerServer.close();
- completer0.complete();
- } catch (e0, s0) {
- completer0.completeError(e0, s0);
- }
- }, onError: completer0.completeError);
- } catch (e, s) {
- completer0.completeError(e, s);
- }
- });
- return completer0.future;
- }), fine: true));
- } catch (e, s) {
- completer0.completeError(e, s);
- }
- });
- return completer0.future;
- }),
- [errorStream, barback.results, transformerServer.results])).then((x2) {
- try {
- x2;
- completer0.complete();
- } catch (e0, s0) {
- completer0.completeError(e0, s0);
- }
- }, onError: completer0.completeError);
- } catch (e1, s1) {
- completer0.completeError(e1, s1);
- }
- }, onError: completer0.completeError);
- } catch (e2, s2) {
- completer0.completeError(e2, s2);
- }
- }, onError: completer0.completeError);
- }
- if (!containsDart2JS && useDart2JS) {
- _builtInTransformers.addAll(
- [new Dart2JSTransformer(this, mode), new DartForwardingTransformer(mode)]);
- join0();
- } else {
- join0();
- }
- } catch (e, s) {
- completer0.completeError(e, s);
- }
- });
- return completer0.future;
- }, fine: true);
- }
-
- /// Provides the public source assets in the environment to barback.
- ///
- /// If [watcherType] is not [WatcherType.NONE], enables watching on them.
- Future _provideSources() {
- final completer0 = new Completer();
- scheduleMicrotask(() {
- try {
- new Future.value(Future.wait(graph.packages.values.map(((package) {
- final completer0 = new Completer();
- scheduleMicrotask(() {
- try {
- join0() {
- new Future.value(
- _provideDirectorySources(package, "lib")).then((x0) {
- try {
- x0;
- completer0.complete();
- } catch (e0, s0) {
- completer0.completeError(e0, s0);
- }
- }, onError: completer0.completeError);
- }
- if (graph.isPackageStatic(package.name)) {
- completer0.complete(null);
- } else {
- join0();
- }
- } catch (e, s) {
- completer0.completeError(e, s);
- }
- });
- return completer0.future;
- })))).then((x0) {
- try {
- x0;
- completer0.complete();
- } catch (e0, s0) {
- completer0.completeError(e0, s0);
- }
- }, onError: completer0.completeError);
- } catch (e, s) {
- completer0.completeError(e, s);
- }
- });
- return completer0.future;
- }
-
- /// Provides all of the source assets within [dir] in [package] to barback.
- ///
- /// If [watcherType] is not [WatcherType.NONE], enables watching on them.
- /// Returns the subscription to the watcher, or `null` if none was created.
- Future<StreamSubscription<WatchEvent>>
- _provideDirectorySources(Package package, String dir) {
- log.fine("Providing sources for ${package.name}|$dir.");
- // TODO(rnystrom): Handle overlapping directories. If two served
- // directories overlap like so:
- //
- // $ pub serve example example/subdir
- //
- // Then the sources of the subdirectory will be updated and watched twice.
- // See: #17454
- if (_watcherType == WatcherType.NONE) {
- _updateDirectorySources(package, dir);
- return new Future.value();
- }
-
- // Watch the directory before listing is so we don't miss files that
- // are added between the initial list and registering the watcher.
- return _watchDirectorySources(package, dir).then((_) {
- _updateDirectorySources(package, dir);
- });
- }
-
- /// Updates barback with all of the files in [dir] inside [package].
- void _updateDirectorySources(Package package, String dir) {
- var ids = _listDirectorySources(package, dir);
- if (_modifiedSources == null) {
- barback.updateSources(ids);
- } else {
- _modifiedSources.addAll(ids);
- }
- }
-
- /// Removes all of the files in [dir] in the root package from barback.
- void _removeDirectorySources(String dir) {
- var ids = _listDirectorySources(rootPackage, dir);
- if (_modifiedSources == null) {
- barback.removeSources(ids);
- } else {
- _modifiedSources.removeAll(ids);
- }
- }
-
- /// Lists all of the source assets in [dir] inside [package].
- ///
- /// For large packages, listing the contents is a performance bottleneck, so
- /// this is optimized for our needs in here instead of using the more general
- /// but slower [listDir].
- Iterable<AssetId> _listDirectorySources(Package package, String dir) {
- // This is used in some performance-sensitive paths and can list many, many
- // files. As such, it leans more havily towards optimization as opposed to
- // readability than most code in pub. In particular, it avoids using the
- // path package, since re-parsing a path is very expensive relative to
- // string operations.
- return package.listFiles(beneath: dir).map((file) {
- // From profiling, path.relative here is just as fast as a raw substring
- // and is correct in the case where package.dir has a trailing slash.
- var relative = package.relative(file);
-
- if (Platform.operatingSystem == 'windows') {
- relative = relative.replaceAll("\\", "/");
- }
-
- var uri = new Uri(pathSegments: relative.split("/"));
- return new AssetId(package.name, uri.toString());
- });
- }
-
- /// Adds a file watcher for [dir] within [package], if the directory exists
- /// and the package needs watching.
- Future<StreamSubscription<WatchEvent>> _watchDirectorySources(Package package,
- String dir) {
- // If this package comes from a cached source, its contents won't change so
- // we don't need to monitor it. `packageId` will be null for the
- // application package, since that's not locked.
- var packageId = graph.lockFile.packages[package.name];
- if (packageId != null &&
- graph.entrypoint.cache.sources[packageId.source] is CachedSource) {
- return new Future.value();
- }
-
- var subdirectory = package.path(dir);
- if (!dirExists(subdirectory)) return new Future.value();
-
- // TODO(nweiz): close this watcher when [barback] is closed.
- var watcher = _watcherType.create(subdirectory);
- var subscription = watcher.events.listen((event) {
- // Don't watch files symlinked into these directories.
- // TODO(rnystrom): If pub gets rid of symlinks, remove this.
- var parts = path.split(event.path);
- if (parts.contains("packages")) return;
-
- // Skip files that were (most likely) compiled from nearby ".dart"
- // files. These are created by the Editor's "Run as JavaScript"
- // command and are written directly into the package's directory.
- // When pub's dart2js transformer then tries to create the same file
- // name, we get a build error. To avoid that, just don't consider
- // that file to be a source.
- // TODO(rnystrom): Remove these when the Editor no longer generates
- // .js files and users have had enough time that they no longer have
- // these files laying around. See #15859.
- if (event.path.endsWith(".dart.js")) return;
- if (event.path.endsWith(".dart.js.map")) return;
- if (event.path.endsWith(".dart.precompiled.js")) return;
-
- var idPath = package.relative(event.path);
- var id = new AssetId(package.name, path.toUri(idPath).toString());
- if (event.type == ChangeType.REMOVE) {
- if (_modifiedSources != null) {
- _modifiedSources.remove(id);
- } else {
- barback.removeSources([id]);
- }
- } else if (_modifiedSources != null) {
- _modifiedSources.add(id);
- } else {
- barback.updateSources([id]);
- }
- });
-
- return watcher.ready.then((_) => subscription);
- }
-
- /// Returns the result of [futureCallback] unless any stream in [streams]
- /// emits an error before it's done.
- ///
- /// If a stream does emit an error, that error is thrown instead.
- /// [futureCallback] is a callback rather than a plain future to ensure that
- /// [streams] are listened to before any code that might cause an error starts
- /// running.
- Future _withStreamErrors(Future futureCallback(), List<Stream> streams) {
- var completer = new Completer.sync();
- var subscriptions = streams.map(
- (stream) => stream.listen((_) {}, onError: completer.completeError)).toList();
-
- new Future.sync(futureCallback).then((_) {
- if (!completer.isCompleted) completer.complete();
- }).catchError((error, stackTrace) {
- if (!completer.isCompleted) completer.completeError(error, stackTrace);
- });
-
- return completer.future.whenComplete(() {
- for (var subscription in subscriptions) {
- subscription.cancel();
- }
- });
- }
-}
-
-/// Log [entry] using Pub's logging infrastructure.
-///
-/// Since both [LogEntry] objects and the message itself often redundantly
-/// show the same context like the file where an error occurred, this tries
-/// to avoid showing redundant data in the entry.
-void _log(LogEntry entry) {
- messageMentions(text) =>
- entry.message.toLowerCase().contains(text.toLowerCase());
-
- messageMentionsAsset(id) =>
- messageMentions(id.toString()) ||
- messageMentions(path.fromUri(entry.assetId.path));
-
- var prefixParts = [];
-
- // Show the level (unless the message mentions it).
- if (!messageMentions(entry.level.name)) {
- prefixParts.add("${entry.level} from");
- }
-
- // Show the transformer.
- prefixParts.add(entry.transform.transformer);
-
- // Mention the primary input of the transform unless the message seems to.
- if (!messageMentionsAsset(entry.transform.primaryId)) {
- prefixParts.add("on ${entry.transform.primaryId}");
- }
-
- // If the relevant asset isn't the primary input, mention it unless the
- // message already does.
- if (entry.assetId != entry.transform.primaryId &&
- !messageMentionsAsset(entry.assetId)) {
- prefixParts.add("with input ${entry.assetId}");
- }
-
- var prefix = "[${prefixParts.join(' ')}]:";
- var message = entry.message;
- if (entry.span != null) {
- message = entry.span.message(entry.message);
- }
-
- switch (entry.level) {
- case LogLevel.ERROR:
- log.error("${log.red(prefix)}\n$message");
- break;
-
- case LogLevel.WARNING:
- log.warning("${log.yellow(prefix)}\n$message");
- break;
-
- case LogLevel.INFO:
- log.message("${log.cyan(prefix)}\n$message");
- break;
-
- case LogLevel.FINE:
- log.fine("${log.gray(prefix)}\n$message");
- break;
- }
-}
-
-/// Exception thrown when trying to serve a new directory that overlaps one or
-/// more directories already being served.
-class OverlappingSourceDirectoryException implements Exception {
- /// The relative paths of the directories that overlap the one that could not
- /// be served.
- final List<String> overlappingDirectories;
-
- OverlappingSourceDirectoryException(this.overlappingDirectories);
-}
-
-/// An enum describing different modes of constructing a [DirectoryWatcher].
-abstract class WatcherType {
- /// A watcher that automatically chooses its type based on the operating
- /// system.
- static const AUTO = const _AutoWatcherType();
-
- /// A watcher that always polls the filesystem for changes.
- static const POLLING = const _PollingWatcherType();
-
- /// No directory watcher at all.
- static const NONE = const _NoneWatcherType();
-
- /// Creates a new DirectoryWatcher.
- DirectoryWatcher create(String directory);
-
- String toString();
-}
-
-class _AutoWatcherType implements WatcherType {
- const _AutoWatcherType();
-
- DirectoryWatcher create(String directory) => new DirectoryWatcher(directory);
-
- String toString() => "auto";
-}
-
-class _PollingWatcherType implements WatcherType {
- const _PollingWatcherType();
-
- DirectoryWatcher create(String directory) =>
- new PollingDirectoryWatcher(directory);
-
- String toString() => "polling";
-}
-
-class _NoneWatcherType implements WatcherType {
- const _NoneWatcherType();
-
- DirectoryWatcher create(String directory) => null;
-
- String toString() => "none";
-}

Powered by Google App Engine
This is Rietveld 408576698