diff --git a/lib/src/command_lish.dart b/lib/src/command_lish.dart
index 1e5673da28f9b82319315a44d9776cff89cd891e..4a370d7d67a1815dce0c76525bb35b7b3c167b9e 100644
--- a/lib/src/command_lish.dart
+++ b/lib/src/command_lish.dart
@@ -109,7 +109,7 @@ class LishCommand extends PubCommand {
 
   /// The basenames of directories that are automatically excluded from
   /// archives.
-  final _BLACKLISTED_DIRECTORIES = const ['packages'];
+  final _BLACKLISTED_DIRS = const ['packages'];
 
   /// Returns a list of files that should be included in the published package.
   /// If this is a Git repository, this will respect .gitignore; otherwise, it
@@ -117,11 +117,8 @@ class LishCommand extends PubCommand {
   Future<List<String>> get _filesToPublish {
     var rootDir = entrypoint.root.dir;
 
-    return Future.wait([
-      dirExists(join(rootDir, '.git')),
-      git.isInstalled
-    ]).then((results) {
-      if (results[0] && results[1]) {
+    return git.isInstalled.then((gitInstalled) {
+      if (dirExists(join(rootDir, '.git')) && gitInstalled) {
         // List all files that aren't gitignored, including those not checked
         // in to Git.
         return git.run(["ls-files", "--cached", "--others",
@@ -129,27 +126,17 @@ class LishCommand extends PubCommand {
       }
 
       return listDir(rootDir, recursive: true).then((entries) {
-        return Future.wait(entries.map((entry) {
-          return fileExists(entry).then((isFile) {
-            // Skip directories.
-            if (!isFile) return null;
-
-            // TODO(rnystrom): Making these relative will break archive
-            // creation if the cwd is ever *not* the package root directory.
-            // Should instead only make these relative right before generating
-            // the tree display (which is what really needs them to be).
-            // Make it relative to the package root.
-            return relativeTo(entry, rootDir);
-          });
-        }));
+        return entries
+            .where(fileExists) // Skip directories.
+            .map((entry) => relativeTo(entry, rootDir));
       });
-    }).then((files) => files.where((file) {
-      if (file == null || _BLACKLISTED_FILES.contains(basename(file))) {
-        return false;
-      }
+    }).then((files) => files.where(_shouldPublish).toList());
+  }
 
-      return !splitPath(file).any(_BLACKLISTED_DIRECTORIES.contains);
-    }).toList());
+  /// Returns `true` if [file] should be published.
+  bool _shouldPublish(String file) {
+    if (_BLACKLISTED_FILES.contains(basename(file))) return false;
+    return !splitPath(file).any(_BLACKLISTED_DIRS.contains);
   }
 
   /// Returns the value associated with [key] in [map]. Throws a user-friendly
diff --git a/lib/src/command_uploader.dart b/lib/src/command_uploader.dart
index 445b61e58a921a08037465a085b296ced9f0ee03..a8c2100647518f3241258eb42d21441a91f02bad 100644
--- a/lib/src/command_uploader.dart
+++ b/lib/src/command_uploader.dart
@@ -58,11 +58,10 @@ class UploaderCommand extends PubCommand {
       exit(exit_codes.USAGE);
     }
 
-    return new Future.immediate(null).then((_) {
+    return defer(() {
       var package = commandOptions['package'];
       if (package != null) return package;
-      return Entrypoint.load(path.current, cache)
-          .then((entrypoint) => entrypoint.root.name);
+      return new Entrypoint(path.current, cache).root.name;
     }).then((package) {
       var uploader = commandOptions.rest[0];
       return oauth2.withClient(cache, (client) {
diff --git a/lib/src/entrypoint.dart b/lib/src/entrypoint.dart
index 7a940d41ceb4a3b7cdd2ade8f6560b3fa318c820..973081a29223ffeb0aea021bd450b156e801ed61 100644
--- a/lib/src/entrypoint.dart
+++ b/lib/src/entrypoint.dart
@@ -40,16 +40,12 @@ class Entrypoint {
 
   /// Packages which are either currently being asynchronously installed to the
   /// directory, or have already been installed.
-  final Map<PackageId, Future<PackageId>> _installs;
-
-  Entrypoint(this.root, this.cache)
-  : _installs = new Map<PackageId, Future<PackageId>>();
+  final _installs = new Map<PackageId, Future<PackageId>>();
 
   /// Loads the entrypoint from a package at [rootDir].
-  static Future<Entrypoint> load(String rootDir, SystemCache cache) {
-    return Package.load(null, rootDir, cache.sources).then((package) =>
-        new Entrypoint(package, cache));
-  }
+  Entrypoint(String rootDir, SystemCache cache)
+      : root = new Package(null, rootDir, cache.sources),
+        cache = cache;
 
   // TODO(rnystrom): Make this path configurable.
   /// The path to this "packages" directory.
@@ -71,10 +67,10 @@ class Entrypoint {
     if (pendingOrCompleted != null) return pendingOrCompleted;
 
     var packageDir = join(path, id.name);
-    var future = ensureDir(dirname(packageDir)).then((_) {
-      return exists(packageDir);
-    }).then((exists) {
-      if (!exists) return;
+    var future = defer(() {
+      ensureDir(dirname(packageDir));
+      if (!dirExists(packageDir)) return;
+
       // 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.");
@@ -101,9 +97,9 @@ class Entrypoint {
   /// directory, respecting the [LockFile] if present. Returns a [Future] that
   /// completes when all dependencies are installed.
   Future installDependencies() {
-    return loadLockFile()
-      .then((lockFile) => resolveVersions(cache.sources, root, lockFile))
-      .then(_installDependencies);
+    return defer(() {
+      return resolveVersions(cache.sources, root, loadLockFile());
+    }).then(_installDependencies);
   }
 
   /// Installs the latest available versions of all dependencies of the [root]
@@ -111,19 +107,19 @@ class Entrypoint {
   /// [Future] that completes when all dependencies are installed.
   Future updateAllDependencies() {
     return resolveVersions(cache.sources, root, new LockFile.empty())
-      .then(_installDependencies);
+        .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 loadLockFile().then((lockFile) {
-      var versionSolver = new VersionSolver(cache.sources, root, lockFile);
+    return defer(() {
+      var solver = new VersionSolver(cache.sources, root, loadLockFile());
       for (var dependency in dependencies) {
-        versionSolver.useLatestVersion(dependency);
+        solver.useLatestVersion(dependency);
       }
-      return versionSolver.solve();
+      return solver.solve();
     }).then(_installDependencies);
   }
 
@@ -144,7 +140,8 @@ class Entrypoint {
   /// reached packages. This should only be called after the lockfile has been
   /// successfully generated.
   Future<List<Package>> walkDependencies() {
-    return loadLockFile().then((lockFile) {
+    return defer(() {
+      var lockFile = loadLockFile();
       var group = new FutureGroup<Package>();
       var visited = new Set<String>();
 
@@ -199,43 +196,33 @@ class Entrypoint {
 
   /// Loads the list of concrete package versions from the `pubspec.lock`, if it
   /// exists. If it doesn't, this completes to an empty [LockFile].
-  Future<LockFile> loadLockFile() {
+  LockFile loadLockFile() {
     var lockFilePath = join(root.dir, 'pubspec.lock');
-
-    log.fine("Loading lockfile.");
-    return fileExists(lockFilePath).then((exists) {
-      if (!exists) {
-        log.fine("No lock file at $lockFilePath, creating empty one.");
-        return new LockFile.empty();
-      }
-
-      return readTextFile(lockFilePath).then((text) =>
-          new LockFile.parse(text, cache.sources));
-    });
+    if (!fileExists(lockFilePath)) return new LockFile.empty();
+    return new LockFile.parse(readTextFile(lockFilePath), cache.sources);
   }
 
   /// Saves a list of concrete package versions to the `pubspec.lock` file.
-  Future _saveLockFile(List<PackageId> packageIds) {
+  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 = join(root.dir, 'pubspec.lock');
-    log.fine("Saving lockfile.");
-    return writeTextFile(lockFilePath, lockFile.serialize());
+    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:`.
   Future _installSelfReference(_) {
-    var linkPath = join(path, root.name);
-    return exists(linkPath).then((exists) {
+    return defer(() {
+      var linkPath = join(path, root.name);
       // Create the symlink if it doesn't exist.
-      if (exists) return;
-      return ensureDir(path).then(
-          (_) => createPackageSymlink(root.name, root.dir, linkPath,
-              isSelfLink: true));
+      if (entryExists(linkPath)) return;
+      ensureDir(path);
+      return createPackageSymlink(root.name, root.dir, linkPath,
+          isSelfLink: true);
     });
   }
 
@@ -248,8 +235,8 @@ class Entrypoint {
     var testDir = join(root.dir, 'test');
     var toolDir = join(root.dir, 'tool');
     var webDir = join(root.dir, 'web');
-    return dirExists(binDir).then((exists) {
-      if (!exists) return;
+    return defer(() {
+      if (!dirExists(binDir)) return;
       return _linkSecondaryPackageDir(binDir);
     }).then((_) => _linkSecondaryPackageDirsRecursively(exampleDir))
       .then((_) => _linkSecondaryPackageDirsRecursively(testDir))
@@ -260,14 +247,14 @@ class Entrypoint {
   /// Creates a symlink to the `packages` directory in [dir] and all its
   /// subdirectories.
   Future _linkSecondaryPackageDirsRecursively(String dir) {
-    return dirExists(dir).then((exists) {
-      if (!exists) return;
+    return defer(() {
+      if (!dirExists(dir)) return;
       return _linkSecondaryPackageDir(dir)
-        .then((_) => _listDirWithoutPackages(dir))
-        .then((files) {
+          .then((_) => _listDirWithoutPackages(dir))
+          .then((files) {
         return Future.wait(files.map((file) {
-          return dirExists(file).then((isDir) {
-            if (!isDir) return;
+          return defer(() {
+            if (!dirExists(file)) return;
             return _linkSecondaryPackageDir(file);
           });
         }));
@@ -282,8 +269,8 @@ class Entrypoint {
     return listDir(dir).then((files) {
       return Future.wait(files.map((file) {
         if (basename(file) == 'packages') return new Future.immediate([]);
-        return dirExists(file).then((isDir) {
-          if (!isDir) return [];
+        return defer(() {
+          if (!dirExists(file)) return [];
           return _listDirWithoutPackages(file);
         }).then((subfiles) {
           var fileAndSubfiles = [file];
@@ -296,9 +283,9 @@ class Entrypoint {
 
   /// Creates a symlink to the `packages` directory in [dir] if none exists.
   Future _linkSecondaryPackageDir(String dir) {
-    var to = join(dir, 'packages');
-    return exists(to).then((exists) {
-      if (exists) return;
+    return defer(() {
+      var to = join(dir, 'packages');
+      if (entryExists(to)) return;
       return createSymlink(path, to);
     });
   }
diff --git a/lib/src/error_group.dart b/lib/src/error_group.dart
index 0bdf5e5568d6b9e4d3a8a3d79feceba921170b6e..90edfa5179678e276142788b61472519e1f06280 100644
--- a/lib/src/error_group.dart
+++ b/lib/src/error_group.dart
@@ -6,6 +6,8 @@ library error_group;
 
 import 'dart:async';
 
+import 'utils.dart';
+
 /// An [ErrorGroup] entangles the errors of multiple [Future]s and [Stream]s
 /// with one another. This allows APIs to expose multiple [Future]s and
 /// [Stream]s that have identical error conditions without forcing API consumers
@@ -260,7 +262,7 @@ class _ErrorGroupStream extends Stream {
     if (_isDone) return;
     _subscription.cancel();
     // Call these asynchronously to work around issue 7913.
-    new Future.immediate(null).then((_) {
+    defer(() {
       _controller.signalError(e.error, e.stackTrace);
       _controller.close();
     });
diff --git a/lib/src/git_source.dart b/lib/src/git_source.dart
index 2b46706c8a8b168187fa463610ade1b2dddad1dd..b53c7257ad6d78431ffcd11a9807f3d478cef8c4 100644
--- a/lib/src/git_source.dart
+++ b/lib/src/git_source.dart
@@ -42,21 +42,19 @@ class GitSource extends Source {
             "Please ensure Git is correctly installed.");
       }
 
-      return ensureDir(join(systemCacheRoot, 'cache'));
-    }).then((_) => _ensureRepoCache(id))
-      .then((_) => _revisionCachePath(id))
+      ensureDir(join(systemCacheRoot, 'cache'));
+      return _ensureRepoCache(id);
+    }).then((_) => _revisionCachePath(id))
       .then((path) {
       revisionCachePath = path;
-      return exists(revisionCachePath);
-    }).then((exists) {
-      if (exists) return;
+      if (entryExists(revisionCachePath)) return;
       return _clone(_repoCachePath(id), revisionCachePath, mirror: false);
     }).then((_) {
       var ref = _getEffectiveRef(id);
       if (ref == 'HEAD') return;
       return _checkOut(revisionCachePath, ref);
     }).then((_) {
-      return Package.load(id.name, revisionCachePath, systemCache.sources);
+      return new Package(id.name, revisionCachePath, systemCache.sources);
     });
   }
 
@@ -106,10 +104,9 @@ class GitSource extends Source {
   /// future that completes once this is finished and throws an exception if it
   /// fails.
   Future _ensureRepoCache(PackageId id) {
-    var path = _repoCachePath(id);
-    return exists(path).then((exists) {
-      if (!exists) return _clone(_getUrl(id), path, mirror: true);
-
+    return defer(() {
+      var path = _repoCachePath(id);
+      if (!entryExists(path)) return _clone(_getUrl(id), path, mirror: true);
       return git.run(["fetch"], workingDir: path).then((result) => null);
     });
   }
@@ -135,9 +132,10 @@ class GitSource extends Source {
   /// the working tree, but instead makes the repository a local mirror of the
   /// remote repository. See the manpage for `git clone` for more information.
   Future _clone(String from, String to, {bool mirror: false}) {
-    // Git on Windows does not seem to automatically create the destination
-    // directory.
-    return ensureDir(to).then((_) {
+    return defer(() {
+      // Git on Windows does not seem to automatically create the destination
+      // directory.
+      ensureDir(to);
       var args = ["clone", from, to];
       if (mirror) args.insertRange(1, 1, "--mirror");
       return git.run(args);
diff --git a/lib/src/io.dart b/lib/src/io.dart
index 88697bb12381a782e56df4aa0660a22e89aa4eb4..c81da000b73e479d9366db42cbd8b9770f14138c 100644
--- a/lib/src/io.dart
+++ b/lib/src/io.dart
@@ -54,59 +54,17 @@ bool isBeneath(entry, dir) {
 /// Returns the path to [target] from [base].
 String relativeTo(target, base) => path.relative(target, from: base);
 
-/// Asynchronously determines if [path], which can be a [String] file path, a
-/// [File], or a [Directory] exists on the file system. Returns a [Future] that
-/// completes with the result.
-Future<bool> exists(path) {
-  path = _getPath(path);
-  return Future.wait([fileExists(path), dirExists(path)]).then((results) {
-    return results[0] || results[1];
-  });
-}
-
-/// Asynchronously determines if [file], which can be a [String] file path or a
-/// [File], exists on the file system. Returns a [Future] that completes with
-/// the result.
-Future<bool> fileExists(file) {
-  var path = _getPath(file);
-  return log.ioAsync("Seeing if file $path exists.",
-      new File(path).exists(),
-      (exists) => "File $path ${exists ? 'exists' : 'does not exist'}.");
-}
+/// Determines if [path], which can be a [String] file path, a [File], or a
+/// [Directory] exists on the file system.
+bool entryExists(path) => fileExists(path) || dirExists(path);
 
-// TODO(rnystrom): Get rid of this and only use sync.
-/// Reads the contents of the text file [file], which can either be a [String]
-/// or a [File].
-Future<String> readTextFile(file) {
-  var path = _getPath(file);
-  return log.ioAsync("Reading text file $path.",
-      new File(path).readAsString(Encoding.UTF_8),
-      (contents) {
-        // Sanity check: don't spew a huge file.
-        if (contents.length < 1024 * 1024) {
-          return "Read $path. Contents:\n$contents";
-        } else {
-          return "Read ${contents.length} characters from $path.";
-        }
-      });
-}
+/// Determines if [file], which can be a [String] file path or a [File], exists
+/// on the file system.
+bool fileExists(file) => _getFile(file).existsSync();
 
 /// Reads the contents of the text file [file], which can either be a [String]
 /// or a [File].
-String readTextFileSync(file) {
-  var path = _getPath(file);
-  log.io("Reading text file $path.");
-  var contents = new File(path).readAsStringSync(Encoding.UTF_8);
-
-  // Sanity check: don't spew a huge file.
-  if (contents.length < 1024 * 1024) {
-    log.fine("Read $path. Contents:\n$contents");
-  } else {
-    log.fine("Read ${contents.length} characters from $path.");
-  }
-
-  return contents;
-}
+String readTextFile(file) => _getFile(file).readAsStringSync(Encoding.UTF_8);
 
 /// Reads the contents of the binary file [file], which can either be a [String]
 /// or a [File].
@@ -119,10 +77,10 @@ List<int> readBinaryFile(file) {
 }
 
 /// Creates [file] (which can either be a [String] or a [File]), and writes
-/// [contents] to it. Completes when the file is written and closed.
+/// [contents] to it.
 ///
 /// If [dontLogContents] is true, the contents of the file will never be logged.
-Future<File> writeTextFile(file, String contents, {dontLogContents: false}) {
+File writeTextFile(file, String contents, {dontLogContents: false}) {
   var path = _getPath(file);
   file = new File(path);
 
@@ -132,16 +90,13 @@ Future<File> writeTextFile(file, String contents, {dontLogContents: false}) {
     log.fine("Contents:\n$contents");
   }
 
-  return file.open(FileMode.WRITE).then((opened) {
-    return opened.writeString(contents).then((ignore) {
-        return opened.close().then((_) {
-          log.fine("Wrote text file $path.");
-          return file;
-        });
-    });
-  });
+  return file..writeAsStringSync(contents);
 }
 
+/// Deletes [file], which can be a [String] or a [File]. Returns a [Future]
+/// that completes when the deletion is done.
+File deleteFile(file) => _getFile(file)..delete();
+
 /// Creates [file] (which can either be a [String] or a [File]), and writes
 /// [contents] to it.
 File writeBinaryFile(file, List<int> contents) {
@@ -156,14 +111,6 @@ File writeBinaryFile(file, List<int> contents) {
   return file;
 }
 
-/// Asynchronously deletes [file], which can be a [String] or a [File]. Returns
-/// a [Future] that completes when the deletion is done.
-Future<File> deleteFile(file) {
-  var path = _getPath(file);
-  return log.ioAsync("delete file $path",
-      new File(path).delete());
-}
-
 /// Writes [stream] to a new file at [path], which may be a [String] or a
 /// [File]. Will replace any file already at that path. Completes when the file
 /// is done being written.
@@ -178,42 +125,32 @@ Future<File> createFileFromStream(Stream<List<int>> stream, path) {
   });
 }
 
-/// Creates a directory [dir]. Returns a [Future] that completes when the
-/// directory is created.
-Future<Directory> createDir(dir) {
-  dir = _getDirectory(dir);
-  return log.ioAsync("create directory ${dir.path}",
-      dir.create());
-}
+/// Creates a directory [dir].
+Directory createDir(dir) => _getDirectory(dir)..createSync();
 
 /// Ensures that [path] and all its parent directories exist. If they don't
-/// exist, creates them. Returns a [Future] that completes once all the
-/// directories are created.
-Future<Directory> ensureDir(path) {
+/// exist, creates them.
+Directory ensureDir(path) {
   path = _getPath(path);
+
   log.fine("Ensuring directory $path exists.");
-  if (path == '.') return new Future.immediate(new Directory('.'));
+  var dir = new Directory(path);
+  if (path == '.' || dirExists(path)) return dir;
 
-  return dirExists(path).then((exists) {
-    if (exists) {
-      log.fine("Directory $path already exists.");
-      return new Directory(path);
-    }
+  ensureDir(dirname(path));
 
-    return ensureDir(dirname(path)).then((_) {
-      return createDir(path).catchError((asyncError) {
-        if (asyncError.error is! DirectoryIOException) throw asyncError;
-        // Error 17 means the directory already exists (or 183 on Windows).
-        if (asyncError.error.osError.errorCode == 17 ||
-            asyncError.error.osError.errorCode == 183) {
-          log.fine("Got 'already exists' error when creating directory.");
-          return _getDirectory(path);
-        }
+  try {
+    createDir(dir);
+  } on DirectoryIOException catch (ex) {
+    // Error 17 means the directory already exists (or 183 on Windows).
+    if (ex.osError.errorCode == 17 || ex.osError.errorCode == 183) {
+      log.fine("Got 'already exists' error when creating directory.");
+    } else {
+      throw ex;
+    }
+  }
 
-        throw asyncError;
-      });
-    });
-  });
+  return dir;
 }
 
 /// Creates a temp directory whose name will be based on [dir] with a unique
@@ -307,29 +244,16 @@ Future<List<String>> listDir(dir,
   return doList(_getDirectory(dir), new Set<String>());
 }
 
-// TODO(rnystrom): Migrate everything over to the sync one and get rid of this.
-/// Asynchronously determines if [dir], which can be a [String] directory path
-/// or a [Directory], exists on the file system. Returns a [Future] that
-/// completes with the result.
-Future<bool> dirExists(dir) {
-  dir = _getDirectory(dir);
-  return log.ioAsync("Seeing if directory ${dir.path} exists.",
-      dir.exists(),
-      (exists) => "Directory ${dir.path} "
-                  "${exists ? 'exists' : 'does not exist'}.");
-}
-
 /// Determines if [dir], which can be a [String] directory path or a
-/// [Directory], exists on the file system. Returns a [Future] that completes
-/// with the result.
-bool dirExistsSync(dir) => _getDirectory(dir).existsSync();
+/// [Directory], exists on the file system.
+bool dirExists(dir) => _getDirectory(dir).existsSync();
 
 /// "Cleans" [dir]. If that directory already exists, it will be deleted. Then a
 /// new empty directory will be created. Returns a [Future] that completes when
 /// the new clean directory is created.
 Future<Directory> cleanDir(dir) {
-  return dirExists(dir).then((exists) {
-    if (exists) {
+  return defer(() {
+    if (dirExists(dir)) {
       // Delete it first.
       return deleteDir(dir).then((_) => createDir(dir));
     } else {
@@ -416,11 +340,11 @@ Future<File> createSymlink(from, to) {
 /// appropriate and then does nothing.
 Future<File> createPackageSymlink(String name, from, to,
     {bool isSelfLink: false}) {
-  // See if the package has a "lib" directory.
-  from = join(from, 'lib');
-  return dirExists(from).then((exists) {
+  return defer(() {
+    // See if the package has a "lib" directory.
+    from = join(from, 'lib');
     log.fine("Creating ${isSelfLink ? "self" : ""}link for package '$name'.");
-    if (exists) return createSymlink(from, to);
+    if (dirExists(from)) return createSymlink(from, to);
 
     // It's OK for the self link (i.e. the root package) to not have a lib
     // directory since it may just be a leaf application that only has
@@ -430,7 +354,7 @@ Future<File> createPackageSymlink(String name, from, to,
                   'you will not be able to import any libraries from it.');
     }
 
-    return to;
+    return _getFile(to);
   });
 }
 
@@ -982,6 +906,14 @@ class PubProcessResult {
   bool get success => exitCode == 0;
 }
 
+/// Gets a dart:io [File] for [entry], which can either already be a File or be
+/// a path string.
+File _getFile(entry) {
+  if (entry is File) return entry;
+  if (entry is String) return new File(entry);
+  throw 'Entry $entry is not a supported type.';
+}
+
 /// Gets the path string for [entry], which can either already be a path string,
 /// or be a [File] or [Directory]. Allows working generically with "file-like"
 /// objects.
diff --git a/lib/src/oauth2.dart b/lib/src/oauth2.dart
index b9aa38ed42d42903e628c7ac4226f76ac3883276..616b63891ea8a9b0d21f4eae64454555a9307d20 100644
--- a/lib/src/oauth2.dart
+++ b/lib/src/oauth2.dart
@@ -51,12 +51,12 @@ final _scopes = ['https://www.googleapis.com/auth/userinfo.email'];
 Credentials _credentials;
 
 /// Delete the cached credentials, if they exist.
-Future clearCredentials(SystemCache cache) {
+void clearCredentials(SystemCache cache) {
   _credentials = null;
   var credentialsFile = _credentialsFile(cache);
-  return fileExists(credentialsFile).then((exists) {
-    if (exists) return deleteFile(credentialsFile);
-  });
+  if (!fileExists(credentialsFile)) return;
+
+  deleteFile(credentialsFile);
 }
 
 /// Asynchronously passes an OAuth2 [Client] to [fn], and closes the client when
@@ -71,7 +71,7 @@ Future withClient(SystemCache cache, Future fn(Client client)) {
     return fn(client).whenComplete(() {
       client.close();
       // Be sure to save the credentials even when an error happens.
-      return _saveCredentials(cache, client.credentials);
+      _saveCredentials(cache, client.credentials);
     });
   }).catchError((asyncError) {
     if (asyncError.error is ExpirationException) {
@@ -84,7 +84,8 @@ Future withClient(SystemCache cache, Future fn(Client client)) {
         message = "$message (${asyncError.error.description})";
       }
       log.error("$message.");
-      return clearCredentials(cache).then((_) => withClient(cache, fn));
+      clearCredentials(cache);
+      return withClient(cache, fn);
     } else {
       throw asyncError;
     }
@@ -94,58 +95,52 @@ Future withClient(SystemCache cache, Future fn(Client client)) {
 /// Gets a new OAuth2 client. If saved credentials are available, those are
 /// used; otherwise, the user is prompted to authorize the pub client.
 Future<Client> _getClient(SystemCache cache) {
-  return _loadCredentials(cache).then((credentials) {
+  return defer(() {
+    var credentials = _loadCredentials(cache);
     if (credentials == null) return _authorize();
-    return new Client(_identifier, _secret, credentials,
-        httpClient: httpClient);
-  }).then((client) {
-    return _saveCredentials(cache, client.credentials).then((_) => client);
+
+    var client = new Client(_identifier, _secret, credentials,
+        httpClient: curlClient);
+    _saveCredentials(cache, client.credentials);
+    return client;
   });
 }
 
 /// Loads the user's OAuth2 credentials from the in-memory cache or the
 /// filesystem if possible. If the credentials can't be loaded for any reason,
 /// the returned [Future] will complete to null.
-Future<Credentials> _loadCredentials(SystemCache cache) {
+Credentials _loadCredentials(SystemCache cache) {
   log.fine('Loading OAuth2 credentials.');
 
-  if (_credentials != null) {
-    log.fine('Using already-loaded credentials.');
-    return new Future.immediate(_credentials);
-  }
+  try {
+    if (_credentials != null) return _credentials;
 
-  var path = _credentialsFile(cache);
-  return fileExists(path).then((credentialsExist) {
-    if (!credentialsExist) {
-      log.fine('No credentials found at $path.');
-      return;
-    }
+    var path = _credentialsFile(cache);
+    if (!fileExists(path)) return;
 
-    return readTextFile(_credentialsFile(cache)).then((credentialsJson) {
-      var credentials = new Credentials.fromJson(credentialsJson);
-      if (credentials.isExpired && !credentials.canRefresh) {
-        log.error("Pub's authorization to upload packages has expired and "
-            "can't be automatically refreshed.");
-        return null; // null means re-authorize
-      }
+    var credentials = new Credentials.fromJson(readTextFile(path));
+    if (credentials.isExpired && !credentials.canRefresh) {
+      log.error("Pub's authorization to upload packages has expired and "
+          "can't be automatically refreshed.");
+      return null; // null means re-authorize.
+    }
 
-      return credentials;
-    });
-  }).catchError((e) {
+    return credentials;
+  } catch (e) {
     log.error('Warning: could not load the saved OAuth2 credentials: $e\n'
         'Obtaining new credentials...');
-    return null; // null means re-authorize
-  });
+    return null; // null means re-authorize.
+  }
 }
 
 /// Save the user's OAuth2 credentials to the in-memory cache and the
 /// filesystem.
-Future _saveCredentials(SystemCache cache, Credentials credentials) {
+void _saveCredentials(SystemCache cache, Credentials credentials) {
   log.fine('Saving OAuth2 credentials.');
   _credentials = credentials;
   var path = _credentialsFile(cache);
-  return ensureDir(dirname(path)).then((_) =>
-      writeTextFile(path, credentials.toJson(), dontLogContents: true));
+  ensureDir(dirname(path));
+  writeTextFile(path, credentials.toJson(), dontLogContents: true);
 }
 
 /// The path to the file in which the user's OAuth2 credentials are stored.
@@ -177,7 +172,7 @@ Future<Client> _authorize() {
   var server = new HttpServer();
   server.addRequestHandler((request) => request.path == "/",
       (request, response) {
-    chainToCompleter(new Future.immediate(null).then((_) {
+    chainToCompleter(defer(() {
       log.message('Authorization received, processing...');
       var queryString = request.queryString;
       if (queryString == null) queryString = '';
diff --git a/lib/src/package.dart b/lib/src/package.dart
index 72c5c0e19c77476b616d4bcb8a48ed9034e95100..ac9cc39703353a377d922bc8d4dbcf6a23772981 100644
--- a/lib/src/package.dart
+++ b/lib/src/package.dart
@@ -15,31 +15,6 @@ final _README_REGEXP = new RegExp(r"^README($|\.)", caseSensitive: false);
 
 /// A named, versioned, unit of code and resource reuse.
 class Package {
-  /// Loads the package whose root directory is [packageDir]. [name] is the
-  /// expected name of that package (e.g. the name given in the dependency), or
-  /// null if the package being loaded is the entrypoint package.
-  static Future<Package> load(String name, String packageDir,
-      SourceRegistry sources) {
-    var pubspecPath = join(packageDir, 'pubspec.yaml');
-
-    return fileExists(pubspecPath).then((exists) {
-      if (!exists) throw new PubspecNotFoundException(name);
-      return readTextFile(pubspecPath);
-    }).then((contents) {
-      try {
-        var pubspec = new Pubspec.parse(contents, sources);
-
-        if (pubspec.name == null) throw new PubspecHasNoNameException(name);
-        if (name != null && pubspec.name != name) {
-          throw new PubspecNameMismatchException(name, pubspec.name);
-        }
-        return new Package._(packageDir, pubspec);
-      } on FormatException catch (ex) {
-        throw 'Could not parse $pubspecPath:\n${ex.message}';
-      }
-    });
-  }
-
   /// The path to the directory containing the package.
   final String dir;
 
@@ -80,6 +55,30 @@ class Package {
     });
   }
 
+  /// Loads the package whose root directory is [packageDir]. [name] is the
+  /// expected name of that package (e.g. the name given in the dependency), or
+  /// `null` if the package being loaded is the entrypoint package.
+  factory Package(String name, String packageDir, SourceRegistry sources) {
+    var pubspecPath = join(packageDir, 'pubspec.yaml');
+    if (!fileExists(pubspecPath)) throw new PubspecNotFoundException(name);
+
+    try {
+      var pubspec = new Pubspec.parse(readTextFile(pubspecPath), sources);
+
+      if (pubspec.name == null) {
+        throw new PubspecHasNoNameException(name);
+      }
+
+      if (name != null && pubspec.name != name) {
+        throw new PubspecNameMismatchException(name, pubspec.name);
+      }
+
+      return new Package._(packageDir, pubspec);
+    } on FormatException catch (ex) {
+      throw 'Could not parse $pubspecPath:\n${ex.message}';
+    }
+  }
+
   /// Constructs a package with the given pubspec. The package will have no
   /// directory associated with it.
   Package.inMemory(this.pubspec)
diff --git a/lib/src/pub.dart b/lib/src/pub.dart
index dcd76c68c4d8895399ab7c5702362109e6c6775f..db628d03157cdb811e2d28078b7397952053c0fa 100644
--- a/lib/src/pub.dart
+++ b/lib/src/pub.dart
@@ -235,43 +235,34 @@ abstract class PubCommand {
       exit(_chooseExitCode(error));
     }
 
-    var future = new Future.immediate(null);
-    if (requiresEntrypoint) {
-      // TODO(rnystrom): Will eventually need better logic to walk up
-      // subdirectories until we hit one that looks package-like. For now, just
-      // assume the cwd is it.
-      future = Entrypoint.load(path.current, cache);
-    }
-
-    future = future.then((entrypoint) {
-      this.entrypoint = entrypoint;
-      try {
-        var commandFuture = onRun();
-        if (commandFuture == null) return true;
+    defer(() {
+      if (requiresEntrypoint) {
+        // TODO(rnystrom): Will eventually need better logic to walk up
+        // subdirectories until we hit one that looks package-like. For now,
+        // just assume the cwd is it.
+        entrypoint = new Entrypoint(path.current, cache);
+      }
 
-        return commandFuture;
-      } catch (error, trace) {
-        handleError(error, trace);
+      var commandFuture = onRun();
+      if (commandFuture == null) return true;
+
+      return commandFuture;
+    }).whenComplete(() => cache_.deleteTempDir()).catchError((asyncError) {
+      var e = asyncError.error;
+      if (e is PubspecNotFoundException && e.name == null) {
+        e = 'Could not find a file named "pubspec.yaml" in the directory '
+          '${path.current}.';
+      } else if (e is PubspecHasNoNameException && e.name == null) {
+        e = 'pubspec.yaml is missing the required "name" field (e.g. "name: '
+          '${basename(path.current)}").';
       }
-    });
 
-    future
-      .then((_) => cache_.deleteTempDir())
-      .catchError((asyncError) {
-        var e = asyncError.error;
-        if (e is PubspecNotFoundException && e.name == null) {
-          e = 'Could not find a file named "pubspec.yaml" in the directory '
-            '${path.current}.';
-        } else if (e is PubspecHasNoNameException && e.name == null) {
-          e = 'pubspec.yaml is missing the required "name" field (e.g. "name: '
-            '${basename(path.current)}").';
-        }
-
-        handleError(e, asyncError.stackTrace);
-      })
+      handleError(e, asyncError.stackTrace);
+    }).then((_) {
       // Explicitly exit on success to ensure that any dangling dart:io handles
       // don't cause the process to never terminate.
-      .then((_) => exit(0));
+      exit(0);
+    });
   }
 
   /// Override this to perform the specific command. Return a future that
diff --git a/lib/src/sdk_source.dart b/lib/src/sdk_source.dart
index e0782b08cc3d0494c96f2d9c8b2d4b89c70ddeeb..124d2651bb1cd76d066ac412e0ff67a05bcd133a 100644
--- a/lib/src/sdk_source.dart
+++ b/lib/src/sdk_source.dart
@@ -10,6 +10,7 @@ import 'package.dart';
 import 'pubspec.dart';
 import 'sdk.dart' as sdk;
 import 'source.dart';
+import 'utils.dart';
 import 'version.dart';
 
 /// A package source that uses libraries from the Dart SDK.
@@ -20,10 +21,10 @@ class SdkSource extends Source {
   /// SDK packages are not individually versioned. Instead, their version is
   /// inferred from the revision number of the SDK itself.
   Future<Pubspec> describe(PackageId id) {
-    return _getPackagePath(id).then((packageDir) {
+    return defer(() {
+      var packageDir = _getPackagePath(id);
       // TODO(rnystrom): What if packageDir is null?
-      return Package.load(id.name, packageDir, systemCache.sources);
-    }).then((package) {
+      var package = new Package(id.name, packageDir, systemCache.sources);
       // Ignore the pubspec's version, and use the SDK's.
       return new Pubspec(id.name, sdk.version, package.pubspec.dependencies,
           package.pubspec.environment);
@@ -33,18 +34,18 @@ class SdkSource extends Source {
   /// Since all the SDK files are already available locally, installation just
   /// involves symlinking the SDK library into the packages directory.
   Future<bool> install(PackageId id, String destPath) {
-    return _getPackagePath(id).then((path) {
-      if (path == null) return new Future<bool>.immediate(false);
+    return defer(() {
+      var path = _getPackagePath(id);
+      if (path == null) return false;
 
-      return createPackageSymlink(id.name, path, destPath).then(
-          (_) => true);
+      return createPackageSymlink(id.name, path, destPath).then((_) => true);
     });
   }
 
   /// Gets the path in the SDK's "pkg" directory to the directory containing
   /// package [id]. Returns `null` if the package could not be found.
-  Future<String> _getPackagePath(PackageId id) {
+  String _getPackagePath(PackageId id) {
     var pkgPath = join(sdk.rootDirectory, "pkg", id.description);
-    return dirExists(pkgPath).then((found) => found ? pkgPath : null);
+    return dirExists(pkgPath) ? pkgPath : null;
   }
 }
diff --git a/lib/src/source.dart b/lib/src/source.dart
index d086374f3bffcde40dd21c2b202bcdd582bfbc80..977efad3a59c73e369039d1216d5952bbf6fd26d 100644
--- a/lib/src/source.dart
+++ b/lib/src/source.dart
@@ -9,6 +9,7 @@ import 'io.dart';
 import 'package.dart';
 import 'pubspec.dart';
 import 'system_cache.dart';
+import 'utils.dart';
 import 'version.dart';
 
 /// A source from which to install packages.
@@ -104,14 +105,15 @@ abstract class Source {
   ///
   /// By default, this uses [systemCacheDirectory] and [install].
   Future<Package> installToSystemCache(PackageId id) {
-    return systemCacheDirectory(id).then((path) {
-      return exists(path).then((exists) {
-        if (exists) return new Future<bool>.immediate(true);
-        return ensureDir(dirname(path)).then((_) => install(id, path));
-      }).then((found) {
-        if (!found) throw 'Package $id not found.';
-        return Package.load(id.name, path, systemCache.sources);
-      });
+    var path;
+    return systemCacheDirectory(id).then((p) {
+      path = p;
+      if (dirExists(path)) return true;
+      ensureDir(dirname(path));
+      return install(id, path);
+    }).then((found) {
+      if (!found) throw 'Package $id not found.';
+      return new Package(id.name, path, systemCache.sources);
     });
   }
 
diff --git a/lib/src/system_cache.dart b/lib/src/system_cache.dart
index 634dc173257b0e9742a549f86e6903fae9b855be..2fec00262e77ce2ee2baa039a81240b1ed755fa1 100644
--- a/lib/src/system_cache.dart
+++ b/lib/src/system_cache.dart
@@ -71,8 +71,8 @@ class SystemCache {
     // Try to get it from the system cache first.
     if (id.source.shouldCache) {
       return id.systemCacheDirectory.then((packageDir) {
-        if (!dirExistsSync(packageDir)) return getUncached();
-        return Package.load(id.name, packageDir, sources);
+        if (!dirExists(packageDir)) return getUncached();
+        return new Package(id.name, packageDir, sources);
       });
     }
 
@@ -105,7 +105,8 @@ class SystemCache {
   /// temp directory to ensure that it's on the same volume as the pub system
   /// cache so that it can move the directory from it.
   Future<Directory> createTempDir() {
-    return ensureDir(tempDir).then((temp) {
+    return defer(() {
+      var temp = ensureDir(tempDir);
       return io.createTempDir(join(temp, 'dir'));
     });
   }
@@ -113,8 +114,8 @@ class SystemCache {
   /// Delete's the system cache's internal temp directory.
   Future deleteTempDir() {
     log.fine('Clean up system cache temp directory $tempDir.');
-    return dirExists(tempDir).then((exists) {
-      if (!exists) return;
+    return defer(() {
+      if (!dirExists(tempDir)) return;
       return deleteDir(tempDir);
     });
   }
diff --git a/lib/src/utils.dart b/lib/src/utils.dart
index 1b41a4e1a055d36db417a53c2663a54847b65ab3..7a257d4e16df187fbdfd7b97bc3a18269a109c99 100644
--- a/lib/src/utils.dart
+++ b/lib/src/utils.dart
@@ -145,6 +145,16 @@ String sha1(String source) {
   return CryptoUtils.bytesToHex(sha.close());
 }
 
+/// Invokes the given callback asynchronously. Returns a [Future] that completes
+/// to the result of [callback].
+///
+/// This is also used to wrap synchronous code that may thrown an exception to
+/// ensure that methods that have both sync and async code only report errors
+/// asynchronously.
+Future defer(callback()) {
+  return new Future.immediate(null).then((_) => callback());
+}
+
 /// Returns a [Future] that completes in [milliseconds].
 Future sleep(int milliseconds) {
   var completer = new Completer();
diff --git a/lib/src/validator/compiled_dartdoc.dart b/lib/src/validator/compiled_dartdoc.dart
index c2c93f3a8708610624d1abdfce09a95813c4ce47..e5a7353d9927f2c20d1d1519ca6370bdf507ec73 100644
--- a/lib/src/validator/compiled_dartdoc.dart
+++ b/lib/src/validator/compiled_dartdoc.dart
@@ -21,27 +21,26 @@ class CompiledDartdocValidator extends Validator {
 
   Future validate() {
     return listDir(entrypoint.root.dir, recursive: true).then((entries) {
-      return futureWhere(entries, (entry) {
+      for (var entry in entries) {
         if (basename(entry) != "nav.json") return false;
         var dir = dirname(entry);
 
         // Look for tell-tale Dartdoc output files all in the same directory.
-        return Future.wait([
-          fileExists(entry),
-          fileExists(join(dir, "index.html")),
-          fileExists(join(dir, "styles.css")),
-          fileExists(join(dir, "dart-logo-small.png")),
-          fileExists(join(dir, "client-live-nav.js"))
-        ]).then((results) => results.every((val) => val));
-      }).then((files) {
-        for (var dartdocDir in files.mappedBy(dirname)) {
-          var relativePath = path.relative(dartdocDir);
+        var files = [
+          entry,
+          join(dir, "index.html"),
+          join(dir, "styles.css"),
+          join(dir, "dart-logo-small.png"),
+          join(dir, "client-live-nav.js")
+        ];
+
+        if (files.every((val) => fileExists(val))) {
           warnings.add("Avoid putting generated documentation in "
-                  "$relativePath.\n"
+                  "${path.relative(dir)}.\n"
               "Generated documentation bloats the package with redundant "
                   "data.");
         }
-      });
+      }
     });
   }
 }
diff --git a/lib/src/validator/dependency.dart b/lib/src/validator/dependency.dart
index 18cff6624b013321e2dc78b7713349f05f89e5f1..a848c545574db233111e1e1e698822e96915c8c1 100644
--- a/lib/src/validator/dependency.dart
+++ b/lib/src/validator/dependency.dart
@@ -38,7 +38,7 @@ class DependencyValidator extends Validator {
           // should warn about unittest. Until then, it's reasonable not to put
           // a constraint on it.
           dependency.name != 'unittest') {
-        return _warnAboutConstraint(dependency);
+        _warnAboutConstraint(dependency);
       }
 
       return new Future.immediate(null);
@@ -74,21 +74,20 @@ class DependencyValidator extends Validator {
   }
 
   /// Warn that dependencies should have version constraints.
-  Future _warnAboutConstraint(PackageRef ref) {
-    return entrypoint.loadLockFile().then((lockFile) {
-      var message = 'Your dependency on "${ref.name}" should have a version '
-          'constraint.';
-      var locked = lockFile.packages[ref.name];
-      if (locked != null) {
-        message = '$message For example:\n'
-          '\n'
-          'dependencies:\n'
-          '  ${ref.name}: ${_constraintForVersion(locked.version)}\n';
-      }
-      warnings.add("$message\n"
-          "Without a constraint, you're promising to support all future "
-          "versions of ${ref.name}.");
-    });
+  void _warnAboutConstraint(PackageRef ref) {
+    var lockFile = entrypoint.loadLockFile();
+    var message = 'Your dependency on "${ref.name}" should have a version '
+        'constraint.';
+    var locked = lockFile.packages[ref.name];
+    if (locked != null) {
+      message = '$message For example:\n'
+        '\n'
+        'dependencies:\n'
+        '  ${ref.name}: ${_constraintForVersion(locked.version)}\n';
+    }
+    warnings.add("$message\n"
+        "Without a constraint, you're promising to support all future "
+        "versions of ${ref.name}.");
   }
 
   /// Returns the suggested version constraint for a dependency that was tested
diff --git a/lib/src/validator/directory.dart b/lib/src/validator/directory.dart
index 09a6c7e952b713e94a8f5e103bdf59530693437c..6ab932ca64224ac591826a9de4c575231545093c 100644
--- a/lib/src/validator/directory.dart
+++ b/lib/src/validator/directory.dart
@@ -8,6 +8,7 @@ import 'dart:async';
 
 import '../entrypoint.dart';
 import '../io.dart';
+import '../utils.dart';
 import '../validator.dart';
 
 /// A validator that validates a package's top-level directories.
@@ -19,29 +20,27 @@ class DirectoryValidator extends Validator {
 
   Future validate() {
     return listDir(entrypoint.root.dir).then((dirs) {
-      return Future.wait(dirs.map((dir) {
-        return dirExists(dir).then((exists) {
-          if (!exists) return;
-
-          dir = basename(dir);
-          if (_PLURAL_NAMES.contains(dir)) {
-            // Cut off the "s"
-            var singularName = dir.substring(0, dir.length - 1);
-            warnings.add('Rename the top-level "$dir" directory to '
-                    '"$singularName".\n'
-                'The Pub layout convention is to use singular directory '
-                    'names.\n'
-                'Plural names won\'t be correctly identified by Pub and other '
-                    'tools.');
-          }
-
-          if (dir.contains(new RegExp(r"^samples?$"))) {
-            warnings.add('Rename the top-level "$dir" directory to "example".\n'
-                'This allows Pub to find your examples and create "packages" '
-                    'directories for them.\n');
-          }
-        });
-      }));
+      for (var dir in dirs) {
+        if (!dirExists(dir)) continue;
+
+        dir = basename(dir);
+        if (_PLURAL_NAMES.contains(dir)) {
+          // Cut off the "s"
+          var singularName = dir.substring(0, dir.length - 1);
+          warnings.add('Rename the top-level "$dir" directory to '
+                  '"$singularName".\n'
+              'The Pub layout convention is to use singular directory '
+                  'names.\n'
+              'Plural names won\'t be correctly identified by Pub and other '
+                  'tools.');
+        }
+
+        if (dir.contains(new RegExp(r"^samples?$"))) {
+          warnings.add('Rename the top-level "$dir" directory to "example".\n'
+              'This allows Pub to find your examples and create "packages" '
+                  'directories for them.\n');
+        }
+      }
     });
   }
 }
diff --git a/lib/src/validator/lib.dart b/lib/src/validator/lib.dart
index faee7290231abda4caa52fa2be39bc1ab66c36b0..7346223ebaf27a68231d6330af382a763bfcf87f 100644
--- a/lib/src/validator/lib.dart
+++ b/lib/src/validator/lib.dart
@@ -23,8 +23,8 @@ class LibValidator extends Validator {
   Future validate() {
     var libDir = join(entrypoint.root.dir, "lib");
 
-    return dirExists(libDir).then((libDirExists) {
-      if (!libDirExists) {
+    return defer(() {
+      if (!dirExists(libDir)) {
         errors.add('You must have a "lib" directory.\n'
             "Without that, users cannot import any code from your package.");
         return;
diff --git a/lib/src/validator/name.dart b/lib/src/validator/name.dart
index 7c4778c8af4604b849c9b16b4e9a4c6587d4a7c9..0386089c9821fa9c226cec98ed0338037159c4ba 100644
--- a/lib/src/validator/name.dart
+++ b/lib/src/validator/name.dart
@@ -10,6 +10,7 @@ import 'dart:io';
 import '../../../pkg/path/lib/path.dart' as path;
 import '../entrypoint.dart';
 import '../io.dart';
+import '../utils.dart';
 import '../validator.dart';
 
 /// Dart reserved words, from the Dart spec.
@@ -47,8 +48,8 @@ class NameValidator extends Validator {
   /// to the package's root directory.
   Future<List<String>> get _libraries {
     var libDir = join(entrypoint.root.dir, "lib");
-    return dirExists(libDir).then((libDirExists) {
-      if (!libDirExists) return [];
+    return defer(() {
+      if (!dirExists(libDir)) return [];
       return listDir(libDir, recursive: true);
     }).then((files) {
       return files
diff --git a/test/io_test.dart b/test/io_test.dart
index 94e8a52d871ee15d5e15d0a276b48c4e4199f868..29e970982d0e47a1b12d25f5a1a1348333e424f7 100644
--- a/test/io_test.dart
+++ b/test/io_test.dart
@@ -6,16 +6,19 @@ library io_test;
 
 import '../../../pkg/unittest/lib/unittest.dart';
 import '../../pub/io.dart';
+import '../../pub/utils.dart';
 
 main() {
   group('listDir', () {
     test('lists a simple directory non-recursively', () {
       expect(withTempDir((path) {
-        var future = writeTextFile(join(path, 'file1.txt'), '')
-            .then((_) => writeTextFile(join(path, 'file2.txt'), ''))
-            .then((_) => createDir(join(path, 'subdir')))
-            .then((_) => writeTextFile(join(path, 'subdir', 'file3.txt'), ''))
-            .then((_) => listDir(path));
+        var future = defer(() {
+          writeTextFile(join(path, 'file1.txt'), '');
+          writeTextFile(join(path, 'file2.txt'), '');
+          createDir(join(path, 'subdir'));
+          writeTextFile(join(path, 'subdir', 'file3.txt'), '');
+          return listDir(path);
+        });
         expect(future, completion(unorderedEquals([
           join(path, 'file1.txt'),
           join(path, 'file2.txt'),
@@ -27,11 +30,13 @@ main() {
 
     test('lists a simple directory recursively', () {
       expect(withTempDir((path) {
-        var future = writeTextFile(join(path, 'file1.txt'), '')
-            .then((_) => writeTextFile(join(path, 'file2.txt'), ''))
-            .then((_) => createDir(join(path, 'subdir')))
-            .then((_) => writeTextFile(join(path, 'subdir', 'file3.txt'), ''))
-            .then((_) => listDir(path, recursive: true));
+        var future = defer(() {
+          writeTextFile(join(path, 'file1.txt'), '');
+          writeTextFile(join(path, 'file2.txt'), '');
+          createDir(join(path, 'subdir'));
+          writeTextFile(join(path, 'subdir', 'file3.txt'), '');
+          return listDir(path, recursive: true);
+        });
         expect(future, completion(unorderedEquals([
           join(path, 'file1.txt'),
           join(path, 'file2.txt'),
@@ -44,12 +49,14 @@ main() {
 
     test('ignores hidden files by default', () {
       expect(withTempDir((path) {
-        var future = writeTextFile(join(path, 'file1.txt'), '')
-            .then((_) => writeTextFile(join(path, 'file2.txt'), ''))
-            .then((_) => writeTextFile(join(path, '.file3.txt'), ''))
-            .then((_) => createDir(join(path, '.subdir')))
-            .then((_) => writeTextFile(join(path, '.subdir', 'file3.txt'), ''))
-            .then((_) => listDir(path, recursive: true));
+        var future = defer(() {
+          writeTextFile(join(path, 'file1.txt'), '');
+          writeTextFile(join(path, 'file2.txt'), '');
+          writeTextFile(join(path, '.file3.txt'), '');
+          createDir(join(path, '.subdir'));
+          writeTextFile(join(path, '.subdir', 'file3.txt'), '');
+          return listDir(path, recursive: true);
+        });
         expect(future, completion(unorderedEquals([
           join(path, 'file1.txt'),
           join(path, 'file2.txt')
@@ -60,14 +67,14 @@ main() {
 
     test('includes hidden files when told to', () {
       expect(withTempDir((path) {
-        var future = writeTextFile(join(path, 'file1.txt'), '')
-            .then((_) => writeTextFile(join(path, 'file2.txt'), ''))
-            .then((_) => writeTextFile(join(path, '.file3.txt'), ''))
-            .then((_) => createDir(join(path, '.subdir')))
-            .then((_) => writeTextFile(join(path, '.subdir', 'file3.txt'), ''))
-            .then((_) {
-              return listDir(path, recursive: true, includeHiddenFiles: true);
-            });
+        var future = defer(() {
+          writeTextFile(join(path, 'file1.txt'), '');
+          writeTextFile(join(path, 'file2.txt'), '');
+          writeTextFile(join(path, '.file3.txt'), '');
+          createDir(join(path, '.subdir'));
+          writeTextFile(join(path, '.subdir', 'file3.txt'), '');
+          return listDir(path, recursive: true, includeHiddenFiles: true);
+        });
         expect(future, completion(unorderedEquals([
           join(path, 'file1.txt'),
           join(path, 'file2.txt'),
@@ -82,19 +89,18 @@ main() {
     test('returns the unresolved paths for symlinks', () {
       expect(withTempDir((path) {
         var dirToList = join(path, 'dir-to-list');
-        var future = writeTextFile(join(path, 'file1.txt'), '')
-            .then((_) => writeTextFile(join(path, 'file2.txt'), ''))
-            .then((_) => createDir(dirToList))
-            .then((_) {
-              return createSymlink(
-                  join(path, 'file1.txt'),
-                  join(dirToList, 'link1'));
-            }).then((_) => createDir(join(dirToList, 'subdir')))
-            .then((_) {
-              return createSymlink(
+        var future = defer(() {
+          writeTextFile(join(path, 'file1.txt'), '');
+          writeTextFile(join(path, 'file2.txt'), '');
+          createDir(dirToList);
+          return createSymlink(join(path, 'file1.txt'),
+                               join(dirToList, 'link1'));
+        }).then((_) {
+          createDir(join(dirToList, 'subdir'));
+          return createSymlink(
                   join(path, 'file2.txt'),
                   join(dirToList, 'subdir', 'link2'));
-            }).then((_) => listDir(dirToList, recursive: true));
+        }).then((_) => listDir(dirToList, recursive: true));
         expect(future, completion(unorderedEquals([
           join(dirToList, 'link1'),
           join(dirToList, 'subdir'),
@@ -106,9 +112,10 @@ main() {
 
     test('works with recursive symlinks', () {
       expect(withTempDir((path) {
-        var future = writeTextFile(join(path, 'file1.txt'), '')
-            .then((_) => createSymlink(path, join(path, 'linkdir')))
-            .then((_) => listDir(path, recursive: true));
+        var future = defer(() {
+          writeTextFile(join(path, 'file1.txt'), '');
+          return createSymlink(path, join(path, 'linkdir'));
+        }).then((_) => listDir(path, recursive: true));
         expect(future, completion(unorderedEquals([
           join(path, 'file1.txt'),
           join(path, 'linkdir')
diff --git a/test/test_pub.dart b/test/test_pub.dart
index e8c4e5cf14a363716ecd752dddb1b75f2717f1c5..3b9bc20e793df2aca43e1c859a45e99c9fb15a5f 100644
--- a/test/test_pub.dart
+++ b/test/test_pub.dart
@@ -604,14 +604,15 @@ void confirmPublish(ScheduledProcess pub) {
 /// [Future] may have a type other than [Process].
 Future _doPub(Function fn, sandboxDir, List args, Future<Uri> tokenEndpoint) {
   String pathInSandbox(path) => join(getFullPath(sandboxDir), path);
-
-  return Future.wait([
-    ensureDir(pathInSandbox(appPath)),
-    _awaitObject(args),
-    tokenEndpoint == null ? new Future.immediate(null) : tokenEndpoint
-  ]).then((results) {
-    var args = results[1];
-    var tokenEndpoint = results[2];
+  return defer(() {
+    ensureDir(pathInSandbox(appPath));
+    return Future.wait([
+      _awaitObject(args),
+      tokenEndpoint == null ? new Future.immediate(null) : tokenEndpoint
+    ]);
+  }).then((results) {
+    var args = results[0];
+    var tokenEndpoint = results[1];
     // Find a Dart executable we can use to spawn. Use the same one that was
     // used to run this script itself.
     var dartBin = new Options().executable;
@@ -819,14 +820,14 @@ abstract class Descriptor {
   }
 
   /// Validates that at least one file in [dir] matching [name] is valid
-  /// according to [validate]. [validate] should complete to an exception if
-  /// the input path is invalid.
+  /// according to [validate]. [validate] should throw or complete to an
+  /// exception if the input path is invalid.
   Future _validateOneMatch(String dir, Future validate(String path)) {
     // Special-case strings to support multi-level names like "myapp/packages".
     if (name is String) {
       var path = join(dir, name);
-      return exists(path).then((exists) {
-        if (!exists) {
+      return defer(() {
+        if (!entryExists(path)) {
           throw new ExpectException('File $name in $dir not found.');
         }
         return validate(path);
@@ -897,25 +898,23 @@ class FileDescriptor extends Descriptor {
 
   /// Creates the file within [dir]. Returns a [Future] that is completed after
   /// the creation is done.
-  Future<File> create(dir) => new Future.immediate(null).then((_) =>
-      writeBinaryFile(join(dir, _stringName), contents));
+  Future<File> create(dir) =>
+      defer(() => writeBinaryFile(join(dir, _stringName), contents));
 
   /// Deletes the file within [dir]. Returns a [Future] that is completed after
   /// the deletion is done.
-  Future delete(dir) {
-    return deleteFile(join(dir, _stringName));
-  }
+  Future delete(dir) =>
+      defer(() => deleteFile(join(dir, _stringName)));
 
   /// Validates that this file correctly matches the actual file at [path].
   Future validate(String path) {
     return _validateOneMatch(path, (file) {
-      return readTextFile(file).then((text) {
-        if (text == textContents) return null;
+      var text = readTextFile(file);
+      if (text == textContents) return null;
 
-        throw new ExpectException(
-            'File $file should contain:\n\n$textContents\n\n'
-            'but contained:\n\n$text');
-      });
+      throw new ExpectException(
+          'File $file should contain:\n\n$textContents\n\n'
+          'but contained:\n\n$text');
     });
   }
 
@@ -944,13 +943,13 @@ class DirectoryDescriptor extends Descriptor {
   /// Creates the file within [dir]. Returns a [Future] that is completed after
   /// the creation is done.
   Future<Directory> create(parentDir) {
-    // Create the directory.
-    return ensureDir(join(parentDir, _stringName)).then((dir) {
-      if (contents == null) return new Future<Directory>.immediate(dir);
+    return defer(() {
+      // Create the directory.
+      var dir = ensureDir(join(parentDir, _stringName));
+      if (contents == null) return dir;
 
       // Recursively create all of its children.
-      final childFutures =
-          contents.map((child) => child.create(dir)).toList();
+      var childFutures = contents.map((child) => child.create(dir)).toList();
       // Only complete once all of the children have been created too.
       return Future.wait(childFutures).then((_) => dir);
     });
@@ -1154,8 +1153,8 @@ class NothingDescriptor extends Descriptor {
   Future delete(dir) => new Future.immediate(null);
 
   Future validate(String dir) {
-    return exists(join(dir, name)).then((exists) {
-      if (exists) {
+    return defer(() {
+      if (entryExists(join(dir, name))) {
         throw new ExpectException('File $name in $dir should not exist.');
       }
     });
@@ -1179,12 +1178,10 @@ typedef Validator ValidatorCreator(Entrypoint entrypoint);
 Future<Pair<List<String>, List<String>>> schedulePackageValidation(
     ValidatorCreator fn) {
   return _scheduleValue((sandboxDir) {
-    var cache = new SystemCache.withSources(
-        join(sandboxDir, cachePath));
+    var cache = new SystemCache.withSources(join(sandboxDir, cachePath));
 
-    return Entrypoint.load(join(sandboxDir, appPath), cache)
-        .then((entrypoint) {
-      var validator = fn(entrypoint);
+    return defer(() {
+      var validator = fn(new Entrypoint(join(sandboxDir, appPath), cache));
       return validator.validate().then((_) {
         return new Pair(validator.errors, validator.warnings);
       });
@@ -1529,7 +1526,7 @@ class ScheduledServer {
   /// Raises an error complaining of an unexpected request.
   void _awaitHandle(HttpRequest request, HttpResponse response) {
     if (_ignored.contains(new Pair(request.method, request.path))) return;
-    var future = timeout(new Future.immediate(null).then((_) {
+    var future = timeout(defer(() {
       if (_handlers.isEmpty) {
         fail('Unexpected ${request.method} request to ${request.path}.');
       }