diff --git a/bin/async_compile.dart b/bin/async_compile.dart
index a6f27c0fc6795230196037da8f7959ae68ed29cf..c8d56813a7cebb806ec3e0389745c85d1b377a9c 100644
--- a/bin/async_compile.dart
+++ b/bin/async_compile.dart
@@ -13,7 +13,7 @@ import 'package:path/path.dart' as p;
 /// Increment this whenever a meaningful change in the async/await compiler
 /// itself is landed. Bumping this will force all previously compiled files
 /// that were compiled against an older compiler to be recompiled.
-const COMPILER_VERSION = "1";
+const COMPILER_VERSION = "2";
 
 /// The path to pub's root directory (sdk/lib/_internal/pub) in the Dart repo.
 ///
@@ -172,4 +172,4 @@ void _writeFile(String path, String contents) {
   } on IOException catch (ex) {
     // Do nothing.
   }
-}
\ No newline at end of file
+}
diff --git a/bin/pub.dart b/bin/pub.dart
index 8f7fa4e32ddb192e82476c190c4953617b49973d..67cefeb189a5d5967ce539e8d71974987a9478d5 100644
--- a/bin/pub.dart
+++ b/bin/pub.dart
@@ -129,7 +129,7 @@ int chooseExitCode(exception) {
 }
 
 /// Walks the command tree and runs the selected pub command.
-Future invokeCommand(String cacheDir, ArgResults mainOptions) {
+Future invokeCommand(String cacheDir, ArgResults mainOptions) async {
   var commands = PubCommand.mainCommands;
   var command;
   var commandString = "pub";
@@ -174,26 +174,25 @@ Future invokeCommand(String cacheDir, ArgResults mainOptions) {
         'Command "${options.name}" does not take any arguments.');
   }
 
-  return syncFuture(() {
+  try {
+    // TODO(rnystrom): Use await here when this is fixed:
+    // https://github.com/dart-lang/async_await/issues/40.
     return command.run(cacheDir, mainOptions, options);
-  }).whenComplete(() {
+  } finally {
     command.cache.deleteTempDir();
-  });
+  }
 }
 
 /// Checks that pub is running on a supported platform.
 ///
 /// If it isn't, it prints an error message and exits. Completes when the
 /// validation is done.
-Future validatePlatform() {
-  return syncFuture(() {
-    if (Platform.operatingSystem != 'windows') return null;
-
-    return runProcess('ver', []).then((result) {
-      if (result.stdout.join('\n').contains('XP')) {
-        log.error('Sorry, but pub is not supported on Windows XP.');
-        return flushThenExit(exit_codes.USAGE);
-      }
-    });
-  });
+Future validatePlatform() async {
+  if (Platform.operatingSystem != 'windows') return;
+
+  var result = await runProcess('ver', []);
+  if (result.stdout.join('\n').contains('XP')) {
+    log.error('Sorry, but pub is not supported on Windows XP.');
+    await flushThenExit(exit_codes.USAGE);
+  }
 }
diff --git a/lib/src/command/cache_repair.dart b/lib/src/command/cache_repair.dart
index b16efe2f77bae181b151a9b8818fc534a14874b8..dfeab5eaa55f085668d51f093b5ed140db28f3ef 100644
--- a/lib/src/command/cache_repair.dart
+++ b/lib/src/command/cache_repair.dart
@@ -19,33 +19,33 @@ class CacheRepairCommand extends PubCommand {
   String get usage => "pub cache repair";
   String get docUrl => "http://dartlang.org/tools/pub/cmd/pub-cache.html";
 
-  Future onRun() {
+  Future onRun() async {
     var successes = 0;
     var failures = 0;
 
     // Repair every cached source.
-    return Future.forEach(cache.sources.where(
-        (source) => source is CachedSource), (source) {
-      return source.repairCachedPackages().then((results) {
-        successes += results.first;
-        failures += results.last;
-      });
-    }).then((_) {
-      if (successes > 0) {
-        var packages = pluralize("package", successes);
-        log.message("Reinstalled ${log.green(successes)} $packages.");
-      }
-
-      if (failures > 0) {
-        var packages = pluralize("package", failures);
-        log.message("Failed to reinstall ${log.red(failures)} $packages.");
-      }
-
-      if (successes == 0 && failures == 0) {
-        log.message("No packages in cache, so nothing to repair.");
-      }
-
-      if (failures > 0) return flushThenExit(exit_codes.UNAVAILABLE);
-    });
+    for (var source in cache.sources) {
+      if (source is! CachedSource) continue;
+
+      var results = await source.repairCachedPackages();
+      successes += results.first;
+      failures += results.last;
+    }
+
+    if (successes > 0) {
+      var packages = pluralize("package", successes);
+      log.message("Reinstalled ${log.green(successes)} $packages.");
+    }
+
+    if (failures > 0) {
+      var packages = pluralize("package", failures);
+      log.message("Failed to reinstall ${log.red(failures)} $packages.");
+    }
+
+    if (successes == 0 && failures == 0) {
+      log.message("No packages in cache, so nothing to repair.");
+    }
+
+    if (failures > 0) await flushThenExit(exit_codes.UNAVAILABLE);
   }
 }
diff --git a/lib/src/command/downgrade.dart b/lib/src/command/downgrade.dart
index 94e8fc6c056d3442c6937f47857e9d648ae559a8..d3313a49b104dfedef48800d70473cad762811f7 100644
--- a/lib/src/command/downgrade.dart
+++ b/lib/src/command/downgrade.dart
@@ -28,14 +28,13 @@ class DowngradeCommand extends PubCommand {
         help: "Report what dependencies would change but don't change any.");
   }
 
-  Future onRun() {
+  Future onRun() async {
     var dryRun = commandOptions['dry-run'];
-    return entrypoint.acquireDependencies(SolveType.DOWNGRADE,
-        useLatest: commandOptions.rest, dryRun: dryRun).then((_) {
-      if (isOffline) {
-        log.warning("Warning: Downgrading when offline may not update you to "
-            "the oldest versions of your dependencies.");
-      }
-    });
+    await entrypoint.acquireDependencies(SolveType.DOWNGRADE,
+        useLatest: commandOptions.rest, dryRun: dryRun);
+    if (isOffline) {
+      log.warning("Warning: Downgrading when offline may not update you to "
+          "the oldest versions of your dependencies.");
+    }
   }
 }
diff --git a/lib/src/command/serve.dart b/lib/src/command/serve.dart
index 0d6a84d24a802ba82dcaab95d74ae5c166b6353e..1d7db1562df5e226494c9c45b9920f8d0eec1719 100644
--- a/lib/src/command/serve.dart
+++ b/lib/src/command/serve.dart
@@ -79,7 +79,7 @@ class ServeCommand extends BarbackCommand {
         help: 'Force the use of a polling filesystem watcher.');
   }
 
-  Future onRunTransformerCommand() {
+  Future onRunTransformerCommand() async {
     var port = parseInt(commandOptions['port'], 'port');
     var adminPort = commandOptions['admin-port'] == null ? null :
         parseInt(commandOptions['admin-port'], 'admin port');
@@ -87,91 +87,87 @@ class ServeCommand extends BarbackCommand {
     var watcherType = commandOptions['force-poll'] ?
         WatcherType.POLLING : WatcherType.AUTO;
 
-    return AssetEnvironment.create(entrypoint, mode, watcherType: watcherType,
-        hostname: hostname, basePort: port, useDart2JS: useDart2JS)
-        .then((environment) {
-
-      var directoryLength = sourceDirectories.map((dir) => dir.length)
-          .reduce(math.max);
-
-      return environment.startAdminServer(adminPort).then((server) {
-        server.results.listen((_) {
-          // The admin server produces no result values.
-          assert(false);
-        }, onError: _fatalError);
-
-        if (logAdminUrl) {
-          log.message("Running admin server on "
-              "${log.bold('http://$hostname:${server.port}')}");
-        }
-
-        // Start up the servers. We pause updates while this is happening so
-        // that we don't log spurious build results in the middle of listing
-        // out the bound servers.
-        environment.pauseUpdates();
-        return Future.forEach(sourceDirectories, (directory) {
-          return _startServer(environment, directory, directoryLength);
-        });
-      }).then((_) {
-        // Now that the servers are up and logged, send them to barback.
-        environment.barback.errors.listen((error) {
-          log.error(log.red("Build error:\n$error"));
-        });
-
-        environment.barback.results.listen((result) {
-          if (result.succeeded) {
-            // TODO(rnystrom): Report using growl/inotify-send where available.
-            log.message("Build completed ${log.green('successfully')}");
-          } else {
-            log.message("Build completed with "
-                "${log.red(result.errors.length)} errors.");
-          }
-        }, onError: _fatalError);
-
-        environment.resumeUpdates();
-        return _completer.future;
-      });
+    var environment = await AssetEnvironment.create(entrypoint, mode,
+        watcherType: watcherType, hostname: hostname, basePort: port,
+        useDart2JS: useDart2JS);
+    var directoryLength = sourceDirectories.map((dir) => dir.length)
+        .reduce(math.max);
+
+    var server = await environment.startAdminServer(adminPort);
+    server.results.listen((_) {
+      // The admin server produces no result values.
+      assert(false);
+    }, onError: _fatalError);
+
+    if (logAdminUrl) {
+      log.message("Running admin server on "
+          "${log.bold('http://$hostname:${server.port}')}");
+    }
+
+    // Start up the servers. We pause updates while this is happening so
+    // that we don't log spurious build results in the middle of listing
+    // out the bound servers.
+    environment.pauseUpdates();
+    for (var directory in sourceDirectories) {
+      await _startServer(environment, directory, directoryLength);
+    }
+
+    // Now that the servers are up and logged, send them to barback.
+    environment.barback.errors.listen((error) {
+      log.error(log.red("Build error:\n$error"));
     });
-  }
 
-  Future _startServer(AssetEnvironment environment, String rootDirectory,
-      int directoryLength) {
-    return environment.serveDirectory(rootDirectory).then((server) {
-      // In release mode, strip out .dart files since all relevant ones have
-      // been compiled to JavaScript already.
-      if (mode == BarbackMode.RELEASE) {
-        server.allowAsset = (url) => !url.path.endsWith(".dart");
+    environment.barback.results.listen((result) {
+      if (result.succeeded) {
+        // TODO(rnystrom): Report using growl/inotify-send where available.
+        log.message("Build completed ${log.green('successfully')}");
+      } else {
+        log.message("Build completed with "
+            "${log.red(result.errors.length)} errors.");
       }
+    }, onError: _fatalError);
 
-      // Add two characters to account for "[" and "]".
-      var prefix = log.gray(
-          padRight("[${server.rootDirectory}]", directoryLength + 2));
-
-      server.results.listen((result) {
-        var buffer = new StringBuffer();
-        buffer.write("$prefix ");
+    environment.resumeUpdates();
+    await _completer.future;
+  }
 
-        if (result.isSuccess) {
-          buffer.write(
-              "${log.green('GET')} ${result.url.path} $_arrow ${result.id}");
+  Future _startServer(AssetEnvironment environment, String rootDirectory,
+      int directoryLength) async {
+    var server = await environment.serveDirectory(rootDirectory);
+    // In release mode, strip out .dart files since all relevant ones have
+    // been compiled to JavaScript already.
+    if (mode == BarbackMode.RELEASE) {
+      server.allowAsset = (url) => !url.path.endsWith(".dart");
+    }
+
+    // Add two characters to account for "[" and "]".
+    var prefix = log.gray(
+        padRight("[${server.rootDirectory}]", directoryLength + 2));
+
+    server.results.listen((result) {
+      var buffer = new StringBuffer();
+      buffer.write("$prefix ");
+
+      if (result.isSuccess) {
+        buffer.write(
+            "${log.green('GET')} ${result.url.path} $_arrow ${result.id}");
+      } else {
+        buffer.write("${log.red('GET')} ${result.url.path} $_arrow");
+
+        var error = result.error.toString();
+        if (error.contains("\n")) {
+          buffer.write("\n${prefixLines(error)}");
         } else {
-          buffer.write("${log.red('GET')} ${result.url.path} $_arrow");
-
-          var error = result.error.toString();
-          if (error.contains("\n")) {
-            buffer.write("\n${prefixLines(error)}");
-          } else {
-            buffer.write(" $error");
-          }
+          buffer.write(" $error");
         }
+      }
 
-        log.message(buffer);
-      }, onError: _fatalError);
+      log.message(buffer);
+    }, onError: _fatalError);
 
-      log.message("Serving ${entrypoint.root.name} "
-          "${padRight(server.rootDirectory, directoryLength)} "
-          "on ${log.bold('http://$hostname:${server.port}')}");
-    });
+    log.message("Serving ${entrypoint.root.name} "
+        "${padRight(server.rootDirectory, directoryLength)} "
+        "on ${log.bold('http://$hostname:${server.port}')}");
   }
 
   /// Reports [error] and exits the server.
diff --git a/lib/src/command/upgrade.dart b/lib/src/command/upgrade.dart
index c42c33b385b4df610dad2dd9fd01999158681274..841a3ef6d79894c16bac2e49f1f07a61b83adeca 100644
--- a/lib/src/command/upgrade.dart
+++ b/lib/src/command/upgrade.dart
@@ -29,14 +29,13 @@ class UpgradeCommand extends PubCommand {
         help: "Report what dependencies would change but don't change any.");
   }
 
-  Future onRun() {
+  Future onRun() async {
     var dryRun = commandOptions['dry-run'];
-    return entrypoint.acquireDependencies(SolveType.UPGRADE,
-        useLatest: commandOptions.rest, dryRun: dryRun).then((_) {
-      if (isOffline) {
-        log.warning("Warning: Upgrading when offline may not update you to the "
-                    "latest versions of your dependencies.");
-      }
-    });
+    await entrypoint.acquireDependencies(SolveType.UPGRADE,
+        useLatest: commandOptions.rest, dryRun: dryRun);
+    if (isOffline) {
+      log.warning("Warning: Upgrading when offline may not update you to the "
+                  "latest versions of your dependencies.");
+    }
   }
 }
diff --git a/lib/src/executable.dart b/lib/src/executable.dart
index 795139230b5f2ce36b8df38e57599edd38b57bea..3976d0d5256a561c7831bd9d50a3e7c389c3506a 100644
--- a/lib/src/executable.dart
+++ b/lib/src/executable.dart
@@ -30,7 +30,7 @@ import 'utils.dart';
 ///
 /// Returns the exit code of the spawned app.
 Future<int> runExecutable(Entrypoint entrypoint, String package,
-    String executable, Iterable<String> args, {bool isGlobal: false}) {
+    String executable, Iterable<String> args, {bool isGlobal: false}) async {
   // Unless the user overrides the verbosity, we want to filter out the
   // normal pub output shown while loading the environment.
   if (log.verbosity == log.Verbosity.NORMAL) {
@@ -55,24 +55,21 @@ Future<int> runExecutable(Entrypoint entrypoint, String package,
     executable = p.join("bin", executable);
   }
 
-  var environment;
   // TODO(nweiz): Use [packages] to only load assets from packages that the
   // executable might load.
-  return AssetEnvironment.create(entrypoint, BarbackMode.RELEASE,
-      useDart2JS: false).then((_environment) {
-    environment = _environment;
-
-    environment.barback.errors.listen((error) {
-      log.error(log.red("Build error:\n$error"));
-    });
-
-    if (package == entrypoint.root.name) {
-      // Serve the entire root-most directory containing the entrypoint. That
-      // ensures that, for example, things like `import '../../utils.dart';`
-      // will work from within some deeply nested script.
-      return environment.serveDirectory(rootDir);
-    }
+  var environment = await AssetEnvironment.create(entrypoint,
+      BarbackMode.RELEASE, useDart2JS: false);
+  environment.barback.errors.listen((error) {
+    log.error(log.red("Build error:\n$error"));
+  });
 
+  var server;
+  if (package == entrypoint.root.name) {
+    // Serve the entire root-most directory containing the entrypoint. That
+    // ensures that, for example, things like `import '../../utils.dart';`
+    // will work from within some deeply nested script.
+    server = await environment.serveDirectory(rootDir);
+  } else {
     // Make sure the dependency exists.
     var dep = entrypoint.root.immediateDependencies.firstWhere(
         (dep) => dep.name == package, orElse: () => null);
@@ -87,46 +84,47 @@ Future<int> runExecutable(Entrypoint entrypoint, String package,
     }
 
     // For other packages, always use the "bin" directory.
-    return environment.servePackageBinDirectory(package);
-  }).then((server) {
-    // Try to make sure the entrypoint script exists (or is generated) before
-    // we spawn the process to run it.
-    var assetPath = "${p.url.joinAll(p.split(executable))}.dart";
-    var id = new AssetId(server.package, assetPath);
-    return environment.barback.getAssetById(id).then((_) {
-      var vmArgs = [];
-
-      // Run in checked mode.
-      // TODO(rnystrom): Make this configurable.
-      vmArgs.add("--checked");
-
-      // Get the URL of the executable, relative to the server's root directory.
-      var relativePath = p.url.relative(assetPath,
-          from: p.url.joinAll(p.split(server.rootDirectory)));
-      vmArgs.add(server.url.resolve(relativePath).toString());
-      vmArgs.addAll(args);
-
-      return Process.start(Platform.executable, vmArgs).then((process) {
-        // Note: we're not using process.std___.pipe(std___) here because
-        // that prevents pub from also writing to the output streams.
-        process.stderr.listen(stderr.add);
-        process.stdout.listen(stdout.add);
-        stdin.listen(process.stdin.add);
-
-        return process.exitCode;
-      });
-    }).catchError((error, stackTrace) {
-      if (error is! AssetNotFoundException) throw error;
-
-      var message = "Could not find ${log.bold(executable + ".dart")}";
-      if (package != entrypoint.root.name) {
-        message += " in package ${log.bold(server.package)}";
-      }
+    server = await environment.servePackageBinDirectory(package);
+  }
+
+  // Try to make sure the entrypoint script exists (or is generated) before
+  // we spawn the process to run it.
+  var assetPath = "${p.url.joinAll(p.split(executable))}.dart";
+  var id = new AssetId(server.package, assetPath);
+  // TODO(rnystrom): Use try/catch here when
+  // https://github.com/dart-lang/async_await/issues/4 is fixed.
+  return environment.barback.getAssetById(id).then((_) async {
+    var vmArgs = [];
+
+    // Run in checked mode.
+    // TODO(rnystrom): Make this configurable.
+    vmArgs.add("--checked");
+
+    // Get the URL of the executable, relative to the server's root directory.
+    var relativePath = p.url.relative(assetPath,
+        from: p.url.joinAll(p.split(server.rootDirectory)));
+    vmArgs.add(server.url.resolve(relativePath).toString());
+    vmArgs.addAll(args);
+
+    var process = await Process.start(Platform.executable, vmArgs);
+    // Note: we're not using process.std___.pipe(std___) here because
+    // that prevents pub from also writing to the output streams.
+    process.stderr.listen(stderr.add);
+    process.stdout.listen(stdout.add);
+    stdin.listen(process.stdin.add);
+
+    return process.exitCode;
+  }).catchError((error, stackTrace) {
+    if (error is! AssetNotFoundException) throw error;
+
+    var message = "Could not find ${log.bold(executable + ".dart")}";
+    if (package != entrypoint.root.name) {
+      message += " in package ${log.bold(server.package)}";
+    }
 
-      log.error("$message.");
-      log.fine(new Chain.forTrace(stackTrace));
-      return exit_codes.NO_INPUT;
-    });
+    log.error("$message.");
+    log.fine(new Chain.forTrace(stackTrace));
+    return exit_codes.NO_INPUT;
   });
 }
 
@@ -136,45 +134,42 @@ Future<int> runExecutable(Entrypoint entrypoint, String package,
 /// Returns the snapshot's exit code.
 ///
 /// This doesn't do any validation of the snapshot's SDK version.
-Future<int> runSnapshot(String path, Iterable<String> args) {
+Future<int> runSnapshot(String path, Iterable<String> args) async {
   var vmArgs = [path]..addAll(args);
 
-  return Process.start(Platform.executable, vmArgs).then((process) {
-    // Note: we're not using process.std___.pipe(std___) here because
-    // that prevents pub from also writing to the output streams.
-    process.stderr.listen(stderr.add);
-    process.stdout.listen(stdout.add);
-    stdin.listen(process.stdin.add);
+  var process = await Process.start(Platform.executable, vmArgs);
+  // Note: we're not using process.std___.pipe(std___) here because
+  // that prevents pub from also writing to the output streams.
+  process.stderr.listen(stderr.add);
+  process.stdout.listen(stdout.add);
+  stdin.listen(process.stdin.add);
 
-    return process.exitCode;
-  });
+  return process.exitCode;
 }
 
 /// Runs the executable snapshot at [snapshotPath].
-Future _runCachedExecutable(Entrypoint entrypoint, String snapshotPath,
-    List<String> args) {
-  return syncFuture(() {
-    // If the snapshot was compiled with a different SDK version, we need to
-    // recompile it.
-    var sdkVersionPath = p.join(".pub", "bin", "sdk-version");
-    if (fileExists(sdkVersionPath) &&
-        readTextFile(sdkVersionPath) == "${sdk.version}\n") {
-      return null;
-    }
-
+Future<int> _runCachedExecutable(Entrypoint entrypoint, String snapshotPath,
+    List<String> args) async {
+  // If the snapshot was compiled with a different SDK version, we need to
+  // recompile it.
+  var sdkVersionPath = p.join(".pub", "bin", "sdk-version");
+  if (!fileExists(sdkVersionPath) ||
+      readTextFile(sdkVersionPath) != "${sdk.version}\n") {
     log.fine("Precompiled executables are out of date.");
-    return entrypoint.precompileExecutables();
-  }).then((_) {
-    var vmArgs = ["--checked", snapshotPath]..addAll(args);
-
-    return Process.start(Platform.executable, vmArgs).then((process) {
-      // Note: we're not using process.std___.pipe(std___) here because
-      // that prevents pub from also writing to the output streams.
-      process.stderr.listen(stderr.add);
-      process.stdout.listen(stdout.add);
-      stdin.listen(process.stdin.add);
-
-      return process.exitCode;
-    });
-  });
+    await entrypoint.precompileExecutables();
+  }
+
+  // TODO(rnystrom): Use cascade here when async_await compiler supports it.
+  // See: https://github.com/dart-lang/async_await/issues/26.
+  var vmArgs = ["--checked", snapshotPath];
+  vmArgs.addAll(args);
+
+  var process = await Process.start(Platform.executable, vmArgs);
+  // Note: we're not using process.std___.pipe(std___) here because
+  // that prevents pub from also writing to the output streams.
+  process.stderr.listen(stderr.add);
+  process.stdout.listen(stdout.add);
+  stdin.listen(process.stdin.add);
+
+  return process.exitCode;
 }
diff --git a/lib/src/global_packages.dart b/lib/src/global_packages.dart
index 08f9fb1a544e57b55396aa90669b740c8950313b..be8614801fb980f1959bc1c54ecccaeb934b0381 100644
--- a/lib/src/global_packages.dart
+++ b/lib/src/global_packages.dart
@@ -68,19 +68,18 @@ class GlobalPackages {
 
   /// Caches the package located in the Git repository [repo] and makes it the
   /// active global version.
-  Future activateGit(String repo) {
+  Future activateGit(String repo) async {
     var source = cache.sources["git"] as GitSource;
-    return source.getPackageNameFromRepo(repo).then((name) {
-      // Call this just to log what the current active package is, if any.
-      _describeActive(name);
-
-      // TODO(nweiz): Add some special handling for git repos that contain path
-      // dependencies. Their executables shouldn't be cached, and there should
-      // be a mechanism for redoing dependency resolution if a path pubspec has
-      // changed (see also issue 20499).
-      return _installInCache(
-          new PackageDep(name, "git", VersionConstraint.any, repo));
-    });
+    var name = await source.getPackageNameFromRepo(repo);
+    // Call this just to log what the current active package is, if any.
+    _describeActive(name);
+
+    // TODO(nweiz): Add some special handling for git repos that contain path
+    // dependencies. Their executables shouldn't be cached, and there should
+    // be a mechanism for redoing dependency resolution if a path pubspec has
+    // changed (see also issue 20499).
+    await _installInCache(
+        new PackageDep(name, "git", VersionConstraint.any, repo));
   }
 
   /// Finds the latest version of the hosted package with [name] that matches
@@ -91,32 +90,31 @@ class GlobalPackages {
   }
 
   /// Makes the local package at [path] globally active.
-  Future activatePath(String path) {
+  Future activatePath(String path) async {
     var entrypoint = new Entrypoint(path, cache);
 
     // Get the package's dependencies.
-    return entrypoint.ensureLockFileIsUpToDate().then((_) {
-      var name = entrypoint.root.name;
+    await entrypoint.ensureLockFileIsUpToDate();
+    var name = entrypoint.root.name;
 
-      // Call this just to log what the current active package is, if any.
-      _describeActive(name);
+    // Call this just to log what the current active package is, if any.
+    _describeActive(name);
 
-      // Write a lockfile that points to the local package.
-      var fullPath = canonicalize(entrypoint.root.dir);
-      var id = new PackageId(name, "path", entrypoint.root.version,
-          PathSource.describePath(fullPath));
+    // Write a lockfile that points to the local package.
+    var fullPath = canonicalize(entrypoint.root.dir);
+    var id = new PackageId(name, "path", entrypoint.root.version,
+        PathSource.describePath(fullPath));
 
-      // TODO(rnystrom): Look in "bin" and display list of binaries that
-      // user can run.
-      _writeLockFile(name, new LockFile([id]));
+    // TODO(rnystrom): Look in "bin" and display list of binaries that
+    // user can run.
+    _writeLockFile(name, new LockFile([id]));
 
-      var binDir = p.join(_directory, name, 'bin');
-      if (dirExists(binDir)) deleteEntry(binDir);
-    });
+    var binDir = p.join(_directory, name, 'bin');
+    if (dirExists(binDir)) deleteEntry(binDir);
   }
 
   /// Installs the package [dep] and its dependencies into the system cache.
-  Future _installInCache(PackageDep dep) {
+  Future _installInCache(PackageDep dep) async {
     var source = cache.sources[dep.source];
 
     // Create a dummy package with just [dep] so we can do resolution on it.
@@ -124,28 +122,26 @@ class GlobalPackages {
         dependencies: [dep], sources: cache.sources));
 
     // Resolve it and download its dependencies.
-    return resolveVersions(SolveType.GET, cache.sources, root).then((result) {
-      if (!result.succeeded) {
-        // If the package specified by the user doesn't exist, we want to
-        // surface that as a [DataError] with the associated exit code.
-        if (result.error.package != dep.name) throw result.error;
-        if (result.error is NoVersionException) dataError(result.error.message);
-        throw result.error;
-      }
-      result.showReport(SolveType.GET);
-
-      // Make sure all of the dependencies are locally installed.
-      return Future.wait(result.packages.map(_cacheDependency)).then((ids) {
-        var lockFile = new LockFile(ids);
-
-        // Load the package graph from [result] so we don't need to re-parse all
-        // the pubspecs.
-        return new Entrypoint.inMemory(root, lockFile, cache)
-            .loadPackageGraph(result)
-            .then((graph) => _precompileExecutables(graph.entrypoint, dep.name))
-            .then((_) => _writeLockFile(dep.name, lockFile));
-      });
-    });
+    var result = await resolveVersions(SolveType.GET, cache.sources, root);
+    if (!result.succeeded) {
+      // If the package specified by the user doesn't exist, we want to
+      // surface that as a [DataError] with the associated exit code.
+      if (result.error.package != dep.name) throw result.error;
+      if (result.error is NoVersionException) dataError(result.error.message);
+      throw result.error;
+    }
+    result.showReport(SolveType.GET);
+
+    // Make sure all of the dependencies are locally installed.
+    var ids = await Future.wait(result.packages.map(_cacheDependency));
+    var lockFile = new LockFile(ids);
+
+    // Load the package graph from [result] so we don't need to re-parse all
+    // the pubspecs.
+    var graph = await new Entrypoint.inMemory(root, lockFile, cache)
+        .loadPackageGraph(result);
+    await _precompileExecutables(graph.entrypoint, dep.name);
+    _writeLockFile(dep.name, lockFile);
   }
 
   /// Precompiles the executables for [package] and saves them in the global
@@ -171,15 +167,14 @@ class GlobalPackages {
   /// Downloads [id] into the system cache if it's a cached package.
   ///
   /// Returns the resolved [PackageId] for [id].
-  Future<PackageId> _cacheDependency(PackageId id) {
+  Future<PackageId> _cacheDependency(PackageId id) async {
     var source = cache.sources[id.source];
 
-    return syncFuture(() {
-      if (id.isRoot) return null;
-      if (source is! CachedSource) return null;
+    if (!id.isRoot && source is CachedSource) {
+      await source.downloadToSystemCache(id);
+    }
 
-      return source.downloadToSystemCache(id);
-    }).then((_) => source.resolveId(id));
+    return source.resolveId(id);
   }
 
   /// Finishes activating package [package] by saving [lockFile] in the cache.
@@ -249,6 +244,8 @@ class GlobalPackages {
   ///
   /// Returns an [Entrypoint] loaded with the active package if found.
   Future<Entrypoint> find(String name) {
+    // TODO(rnystrom): Use async/await here when on __ catch is supported.
+    // See: https://github.com/dart-lang/async_await/issues/27
     return syncFuture(() {
       var lockFilePath = _getLockFilePath(name);
       var lockFile;