| 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
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..99f15f55c7560a3c4e45ae6f0e9d369b9d87a5e0
 | 
| --- /dev/null
 | 
| +++ b/sdk/lib/_internal/pub_generated/lib/src/barback/asset_environment.dart
 | 
| @@ -0,0 +1,460 @@
 | 
| +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 '../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';
 | 
| +class AssetEnvironment {
 | 
| +  static Future<AssetEnvironment> create(Entrypoint entrypoint,
 | 
| +      BarbackMode mode, {WatcherType watcherType, String hostname, int basePort,
 | 
| +      Iterable<String> packages, bool useDart2JS: true}) {
 | 
| +    if (watcherType == null) watcherType = WatcherType.NONE;
 | 
| +    if (hostname == null) hostname = "localhost";
 | 
| +    if (basePort == null) basePort = 0;
 | 
| +    return entrypoint.loadPackageGraph().then((graph) {
 | 
| +      log.fine("Loaded package graph.");
 | 
| +      var barback = new Barback(new PubPackageProvider(graph, packages));
 | 
| +      barback.log.listen(_log);
 | 
| +      var environment = new AssetEnvironment._(
 | 
| +          graph,
 | 
| +          barback,
 | 
| +          mode,
 | 
| +          watcherType,
 | 
| +          hostname,
 | 
| +          basePort,
 | 
| +          packages);
 | 
| +      return environment._load(useDart2JS: useDart2JS).then((_) => environment);
 | 
| +    });
 | 
| +  }
 | 
| +  AdminServer _adminServer;
 | 
| +  final _directories = new Map<String, SourceDirectory>();
 | 
| +  final Barback barback;
 | 
| +  Package get rootPackage => graph.entrypoint.root;
 | 
| +  final PackageGraph graph;
 | 
| +  final BarbackMode mode;
 | 
| +  final _builtInTransformers = <Transformer>[];
 | 
| +  final WatcherType _watcherType;
 | 
| +  final String _hostname;
 | 
| +  final int _basePort;
 | 
| +  final Set<String> packages;
 | 
| +  Set<AssetId> _modifiedSources;
 | 
| +  AssetEnvironment._(PackageGraph graph, this.barback, this.mode,
 | 
| +      this._watcherType, this._hostname, this._basePort, Iterable<String> packages)
 | 
| +      : graph = graph,
 | 
| +        packages = packages == null ?
 | 
| +          graph.packages.keys.toSet() :
 | 
| +          packages.toSet();
 | 
| +  Iterable<Transformer> getBuiltInTransformers(Package package) {
 | 
| +    if (package.name != rootPackage.name) return null;
 | 
| +    if (_builtInTransformers.isEmpty) return null;
 | 
| +    return _builtInTransformers;
 | 
| +  }
 | 
| +  Future<AdminServer> startAdminServer([int port]) {
 | 
| +    assert(_adminServer == null);
 | 
| +    if (port == null) port = _basePort == 0 ? 0 : _basePort - 1;
 | 
| +    return AdminServer.bind(this, _hostname, port).then((server) => _adminServer =
 | 
| +        server);
 | 
| +  }
 | 
| +  Future<BarbackServer> serveDirectory(String rootDirectory) {
 | 
| +    var directory = _directories[rootDirectory];
 | 
| +    if (directory != null) {
 | 
| +      return directory.server.then((server) {
 | 
| +        log.fine('Already serving $rootDirectory on ${server.url}.');
 | 
| +        return server;
 | 
| +      });
 | 
| +    }
 | 
| +    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 (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();
 | 
| +    });
 | 
| +  }
 | 
| +  Future<BarbackServer> servePackageBinDirectory(String package) {
 | 
| +    return _provideDirectorySources(
 | 
| +        graph.packages[package],
 | 
| +        "bin").then(
 | 
| +            (_) =>
 | 
| +                BarbackServer.bind(this, _hostname, 0, package: package, rootDirectory: "bin"));
 | 
| +  }
 | 
| +  Future precompileExecutables(String packageName, String directory,
 | 
| +      {Iterable<AssetId> executableIds}) {
 | 
| +    if (executableIds == null) {
 | 
| +      executableIds = graph.packages[packageName].executableIds;
 | 
| +    }
 | 
| +    log.fine("executables for $packageName: $executableIds");
 | 
| +    if (executableIds.isEmpty) return null;
 | 
| +    var package = graph.packages[packageName];
 | 
| +    return servePackageBinDirectory(packageName).then((server) {
 | 
| +      return waitAndPrintErrors(executableIds.map((id) {
 | 
| +        var basename = path.url.basename(id.path);
 | 
| +        var snapshotPath = path.join(directory, "$basename.snapshot");
 | 
| +        return runProcess(
 | 
| +            Platform.executable,
 | 
| +            [
 | 
| +                '--snapshot=$snapshotPath',
 | 
| +                server.url.resolve(basename).toString()]).then((result) {
 | 
| +          if (result.success) {
 | 
| +            log.message("Precompiled ${_formatExecutable(id)}.");
 | 
| +          } else {
 | 
| +            deleteEntry(snapshotPath);
 | 
| +            throw new ApplicationException(
 | 
| +                log.yellow("Failed to precompile " "${_formatExecutable(id)}:\n") +
 | 
| +                    result.stderr.join('\n'));
 | 
| +          }
 | 
| +        });
 | 
| +      })).whenComplete(() {
 | 
| +        server.close();
 | 
| +      });
 | 
| +    });
 | 
| +  }
 | 
| +  String _formatExecutable(AssetId id) =>
 | 
| +      log.bold("${id.package}:${path.basenameWithoutExtension(id.path)}");
 | 
| +  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;
 | 
| +      });
 | 
| +    });
 | 
| +  }
 | 
| +  String getSourceDirectoryContaining(String assetPath) =>
 | 
| +      _directories.values.firstWhere(
 | 
| +          (dir) => path.isWithin(dir.directory, assetPath)).directory;
 | 
| +  Future<List<Uri>> getUrlsForAssetPath(String assetPath) {
 | 
| +    return _lookUpPathInServerRoot(assetPath).then((urls) {
 | 
| +      if (urls.isNotEmpty) return urls;
 | 
| +      return _lookUpPathInPackagesDirectory(assetPath);
 | 
| +    }).then((urls) {
 | 
| +      if (urls.isNotEmpty) return urls;
 | 
| +      return _lookUpPathInDependency(assetPath);
 | 
| +    });
 | 
| +  }
 | 
| +  Future<List<Uri>> _lookUpPathInServerRoot(String assetPath) {
 | 
| +    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)));
 | 
| +    }));
 | 
| +  }
 | 
| +  Future<List<Uri>> _lookUpPathInPackagesDirectory(String assetPath) {
 | 
| +    var components = path.split(path.relative(assetPath));
 | 
| +    if (components.first != "packages") return new Future.value([]);
 | 
| +    if (!packages.contains(components[1])) return new Future.value([]);
 | 
| +    return Future.wait(_directories.values.map((dir) {
 | 
| +      return dir.server.then(
 | 
| +          (server) => server.url.resolveUri(path.toUri(assetPath)));
 | 
| +    }));
 | 
| +  }
 | 
| +  Future<List<Uri>> _lookUpPathInDependency(String assetPath) {
 | 
| +    for (var packageName in packages) {
 | 
| +      var package = graph.packages[packageName];
 | 
| +      var libDir = path.join(package.dir, 'lib');
 | 
| +      var assetDir = path.join(package.dir, '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([]);
 | 
| +  }
 | 
| +  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);
 | 
| +    });
 | 
| +  }
 | 
| +  bool containsPath(String sourcePath) {
 | 
| +    var directories = ["lib"];
 | 
| +    directories.addAll(_directories.keys);
 | 
| +    return directories.any((dir) => path.isWithin(dir, sourcePath));
 | 
| +  }
 | 
| +  void pauseUpdates() {
 | 
| +    assert(_modifiedSources == null);
 | 
| +    _modifiedSources = new Set<AssetId>();
 | 
| +  }
 | 
| +  void resumeUpdates() {
 | 
| +    assert(_modifiedSources != null);
 | 
| +    barback.updateSources(_modifiedSources);
 | 
| +    _modifiedSources = null;
 | 
| +  }
 | 
| +  Future _load({bool useDart2JS}) {
 | 
| +    return log.progress("Initializing barback", () {
 | 
| +      var containsDart2JS = graph.entrypoint.root.pubspec.transformers.any(
 | 
| +          (transformers) =>
 | 
| +              transformers.any((config) => config.id.package == '\$dart2js'));
 | 
| +      if (!containsDart2JS && useDart2JS) {
 | 
| +        _builtInTransformers.addAll(
 | 
| +            [new Dart2JSTransformer(this, mode), new DartForwardingTransformer(mode)]);
 | 
| +      }
 | 
| +      var dartPath = assetPath('dart');
 | 
| +      var pubSources = listDir(
 | 
| +          dartPath,
 | 
| +          recursive: true).where(
 | 
| +              (file) => path.extension(file) == ".dart").map((library) {
 | 
| +        var idPath = path.join('lib', path.relative(library, from: dartPath));
 | 
| +        return new AssetId('\$pub', path.toUri(idPath).toString());
 | 
| +      });
 | 
| +      var libPath = path.join(sdk.rootDirectory, "lib");
 | 
| +      var sdkSources = listDir(
 | 
| +          libPath,
 | 
| +          recursive: true).where((file) => path.extension(file) == ".dart").map((file) {
 | 
| +        var idPath =
 | 
| +            path.join("lib", path.relative(file, from: sdk.rootDirectory));
 | 
| +        return new AssetId('\$sdk', path.toUri(idPath).toString());
 | 
| +      });
 | 
| +      var transformerServer;
 | 
| +      return BarbackServer.bind(this, _hostname, 0).then((server) {
 | 
| +        transformerServer = server;
 | 
| +        var errorStream = barback.errors.map((error) {
 | 
| +          if (error is! AssetLoadException) throw error;
 | 
| +          log.error(log.red(error.message));
 | 
| +          log.fine(error.stackTrace.terse);
 | 
| +        });
 | 
| +        return _withStreamErrors(() {
 | 
| +          return log.progress("Loading source assets", () {
 | 
| +            barback.updateSources(pubSources);
 | 
| +            barback.updateSources(sdkSources);
 | 
| +            return _provideSources();
 | 
| +          });
 | 
| +        }, [errorStream, barback.results]);
 | 
| +      }).then((_) {
 | 
| +        log.fine("Provided sources.");
 | 
| +        var completer = new Completer();
 | 
| +        var 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));
 | 
| +        });
 | 
| +        return _withStreamErrors(() {
 | 
| +          return log.progress("Loading transformers", () {
 | 
| +            return loadAllTransformers(
 | 
| +                this,
 | 
| +                transformerServer).then((_) => transformerServer.close());
 | 
| +          }, fine: true);
 | 
| +        }, [errorStream, barback.results, transformerServer.results]);
 | 
| +      }).then((_) => barback.removeSources(pubSources));
 | 
| +    }, fine: true);
 | 
| +  }
 | 
| +  Future _provideSources() {
 | 
| +    return Future.wait(packages.map((package) {
 | 
| +      return _provideDirectorySources(graph.packages[package], "lib");
 | 
| +    }));
 | 
| +  }
 | 
| +  Future<StreamSubscription<WatchEvent>>
 | 
| +      _provideDirectorySources(Package package, String dir) {
 | 
| +    log.fine("Providing sources for ${package.name}|$dir.");
 | 
| +    if (_watcherType == WatcherType.NONE) {
 | 
| +      _updateDirectorySources(package, dir);
 | 
| +      return new Future.value();
 | 
| +    }
 | 
| +    return _watchDirectorySources(package, dir).then((_) {
 | 
| +      _updateDirectorySources(package, dir);
 | 
| +    });
 | 
| +  }
 | 
| +  void _updateDirectorySources(Package package, String dir) {
 | 
| +    var ids = _listDirectorySources(package, dir);
 | 
| +    if (_modifiedSources == null) {
 | 
| +      barback.updateSources(ids);
 | 
| +    } else {
 | 
| +      _modifiedSources.addAll(ids);
 | 
| +    }
 | 
| +  }
 | 
| +  void _removeDirectorySources(String dir) {
 | 
| +    var ids = _listDirectorySources(rootPackage, dir);
 | 
| +    if (_modifiedSources == null) {
 | 
| +      barback.removeSources(ids);
 | 
| +    } else {
 | 
| +      _modifiedSources.removeAll(ids);
 | 
| +    }
 | 
| +  }
 | 
| +  Iterable<AssetId> _listDirectorySources(Package package, String dir) {
 | 
| +    var subdirectory = path.join(package.dir, dir);
 | 
| +    if (!dirExists(subdirectory)) return [];
 | 
| +    return package.listFiles(beneath: subdirectory).map((file) {
 | 
| +      var relative = path.relative(file, from: package.dir);
 | 
| +      if (Platform.operatingSystem == 'windows') {
 | 
| +        relative = relative.replaceAll("\\", "/");
 | 
| +      }
 | 
| +      var uri = new Uri(pathSegments: relative.split("/"));
 | 
| +      return new AssetId(package.name, uri.toString());
 | 
| +    });
 | 
| +  }
 | 
| +  Future<StreamSubscription<WatchEvent>> _watchDirectorySources(Package package,
 | 
| +      String dir) {
 | 
| +    var packageId = graph.lockFile.packages[package.name];
 | 
| +    if (packageId != null &&
 | 
| +        graph.entrypoint.cache.sources[packageId.source] is CachedSource) {
 | 
| +      return new Future.value();
 | 
| +    }
 | 
| +    var subdirectory = path.join(package.dir, dir);
 | 
| +    if (!dirExists(subdirectory)) return new Future.value();
 | 
| +    var watcher = _watcherType.create(subdirectory);
 | 
| +    var subscription = watcher.events.listen((event) {
 | 
| +      var parts = path.split(event.path);
 | 
| +      if (parts.contains("packages")) return;
 | 
| +      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 = path.relative(event.path, from: package.dir);
 | 
| +      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);
 | 
| +  }
 | 
| +  Future _withStreamErrors(Future futureCallback(), List<Stream> streams) {
 | 
| +    var completer = new Completer.sync();
 | 
| +    var subscriptions = streams.map(
 | 
| +        (stream) => stream.listen((_) {}, onError: completer.complete)).toList();
 | 
| +    syncFuture(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();
 | 
| +      }
 | 
| +    });
 | 
| +  }
 | 
| +}
 | 
| +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 = [];
 | 
| +  if (!messageMentions(entry.level.name)) {
 | 
| +    prefixParts.add("${entry.level} from");
 | 
| +  }
 | 
| +  prefixParts.add(entry.transform.transformer);
 | 
| +  if (!messageMentionsAsset(entry.transform.primaryId)) {
 | 
| +    prefixParts.add("on ${entry.transform.primaryId}");
 | 
| +  }
 | 
| +  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;
 | 
| +  }
 | 
| +}
 | 
| +class OverlappingSourceDirectoryException implements Exception {
 | 
| +  final List<String> overlappingDirectories;
 | 
| +  OverlappingSourceDirectoryException(this.overlappingDirectories);
 | 
| +}
 | 
| +abstract class WatcherType {
 | 
| +  static const AUTO = const _AutoWatcherType();
 | 
| +  static const POLLING = const _PollingWatcherType();
 | 
| +  static const NONE = const _NoneWatcherType();
 | 
| +  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";
 | 
| +}
 | 
| 
 |