From bbc3f1e33342e9a3ea4719ecba8401d4dcd341cc Mon Sep 17 00:00:00 2001
From: "nweiz@google.com" <nweiz@google.com>
Date: Thu, 21 Aug 2014 18:45:57 +0000
Subject: [PATCH] Make servePackages's contents argument saner.

R=rnystrom@google.com

Review URL: https://codereview.chromium.org//488323002

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge@39469 260f80e4-7a28-3924-810f-c04153c831b5
---
 .../copies_non_dart_files_to_build_test.dart  |   2 +-
 .../adds_latest_matching_version_test.dart    |  12 +-
 test/cache/add/adds_latest_version_test.dart  |  10 +-
 .../all_adds_all_matching_versions_test.dart  |  12 +-
 .../all_with_some_versions_present_test.dart  |  12 +-
 test/cache/add/already_cached_test.dart       |   6 +-
 test/cache/add/no_matching_version_test.dart  |   8 +-
 test/cache/add/package_not_found_test.dart    |   2 +-
 test/cache/repair/handles_failure_test.dart   |   8 +-
 .../reinstalls_hosted_packages_test.dart      |  14 +-
 test/dependency_override_test.dart            |  38 ++--
 test/deps_test.dart                           |  36 ++--
 .../does_not_show_other_versions_test.dart    |  10 +-
 .../dry_run_does_not_apply_changes_test.dart  |   8 +-
 test/downgrade/unlock_dependers_test.dart     |  16 +-
 test/downgrade/unlock_if_necessary_test.dart  |  16 +-
 .../dry_run_does_not_apply_changes_test.dart  |   6 +-
 .../hosted/avoid_network_requests_test.dart   |  16 +-
 test/get/hosted/cached_pubspec_test.dart      |   2 +-
 ...t_upgrade_on_removed_constraints_test.dart |  12 +-
 ...o_network_requests_when_possible_test.dart |  10 +-
 test/get/hosted/get_test.dart                 |   4 +-
 test/get/hosted/get_transitive_test.dart      |  12 +-
 test/get/hosted/resolve_constraints_test.dart |  14 +-
 .../stay_locked_if_compatible_test.dart       |   4 +-
 .../stay_locked_if_new_is_satisfied_test.dart |  22 +-
 test/get/hosted/stay_locked_test.dart         |   4 +-
 .../hosted/unlock_if_incompatible_test.dart   |   4 +-
 .../unlock_if_new_is_unsatisfied_test.dart    |  26 +--
 .../unlock_if_version_doesnt_exist_test.dart  |   4 +-
 test/get/switch_source_test.dart              |   2 +-
 .../activate_git_after_hosted_test.dart       |  14 +-
 .../activate_hosted_after_git_test.dart       |  14 +-
 .../activate_hosted_after_path_test.dart      |  14 +-
 .../activate_path_after_hosted_test.dart      |  14 +-
 test/global/activate/cached_package_test.dart |   6 +-
 test/global/activate/constraint_test.dart     |  12 +-
 .../activate/different_version_test.dart      |   8 +-
 .../activate/empty_constraint_test.dart       |   8 +-
 .../activate/ignores_active_version_test.dart |   8 +-
 .../installs_dependencies_for_git_test.dart   |   8 +-
 .../installs_dependencies_for_path_test.dart  |   8 +-
 .../activate/installs_dependencies_test.dart  |  10 +-
 ...orts_version_solver_backtracking_test.dart |  12 +-
 .../activate/uncached_package_test.dart       |  10 +-
 .../global/activate/unknown_package_test.dart |   2 +-
 ...eactivate_and_reactivate_package_test.dart |   8 +-
 .../deactivate/hosted_package_test.dart       |   4 +-
 .../deactivate/unknown_package_test.dart      |   2 +-
 test/global/list_test.dart                    |  16 +-
 .../run/errors_if_outside_bin_test.dart       |  14 +-
 .../run/implicit_executable_name_test.dart    |  14 +-
 test/global/run/nonexistent_script_test.dart  |   2 +-
 test/global/run/runs_script_test.dart         |  14 +-
 test/global/run/unknown_package_test.dart     |   2 +-
 ...il_gracefully_on_missing_package_test.dart |   2 +-
 test/hosted/offline_test.dart                 |   6 +-
 .../remove_removed_dependency_test.dart       |   8 +-
 ...ve_removed_transitive_dependency_test.dart |  16 +-
 test/implicit_barback_dependency_test.dart    |  74 +++----
 test/implicit_dependency_test.dart            |  52 ++---
 .../lists_dependency_directories_test.dart    |   2 +-
 test/no_package_symlinks_test.dart            |   8 +-
 ...t_if_dependency_is_not_installed_test.dart |   2 +-
 ...tive_dependency_is_not_installed_test.dart |   2 +-
 test/serve_packages.dart                      | 195 ++++++++++++++++++
 ...for_immediate_and_transitive_dep_test.dart |  24 +--
 test/snapshot/creates_a_snapshot_test.dart    |  20 +-
 ...t_when_a_dependency_is_unchanged_test.dart |  12 +-
 ...napshot_an_entrypoint_dependency_test.dart |  12 +-
 ...snapshot_transitive_dependencies_test.dart |  12 +-
 ...ints_errors_for_broken_snapshots_test.dart |  23 ++-
 ...mpiles_if_the_sdk_is_out_of_date_test.dart |   8 +-
 .../snapshots_transformed_code_test.dart      |  22 +-
 ...upgrades_snapshot_for_dependency_test.dart |  32 +--
 test/snapshot/upgrades_snapshot_test.dart     |  24 ++-
 test/test_pub.dart                            | 138 +------------
 .../dry_run_does_not_apply_changes_test.dart  |   8 +-
 .../upgrade/hosted/unlock_dependers_test.dart |  16 +-
 .../hosted/unlock_if_necessary_test.dart      |  16 +-
 .../upgrade_removed_constraints_test.dart     |  12 +-
 .../upgrade/report/describes_change_test.dart |  12 +-
 ...wer_versions_for_locked_packages_test.dart |  16 +-
 .../report/highlights_overrides_test.dart     |   4 +-
 .../leading_character_shows_change_test.dart  |  22 +-
 .../shows_newer_available_versions_test.dart  |  34 +--
 ...s_number_of_changed_dependencies_test.dart |  10 +-
 87 files changed, 746 insertions(+), 674 deletions(-)
 create mode 100644 test/serve_packages.dart

diff --git a/test/build/copies_non_dart_files_to_build_test.dart b/test/build/copies_non_dart_files_to_build_test.dart
index fecee29e..443143f5 100644
--- a/test/build/copies_non_dart_files_to_build_test.dart
+++ b/test/build/copies_non_dart_files_to_build_test.dart
@@ -9,7 +9,7 @@ main() {
   initConfig();
 
   integration("copies non-Dart files to build/", () {
-    servePackages([packageMap("browser", "1.0.0")]);
+    servePackages((builder) => builder.serve("browser", "1.0.0"));
 
     d.dir(appPath, [
       // A browser dependency with no entrypoints shouldn't cause dart.js to be
diff --git a/test/cache/add/adds_latest_matching_version_test.dart b/test/cache/add/adds_latest_matching_version_test.dart
index 5d6701bb..f602a31c 100644
--- a/test/cache/add/adds_latest_matching_version_test.dart
+++ b/test/cache/add/adds_latest_matching_version_test.dart
@@ -11,12 +11,12 @@ main() {
   initConfig();
   integration('adds the latest version of the package matching the '
               'version constraint', () {
-    servePackages([
-      packageMap("foo", "1.2.2"),
-      packageMap("foo", "1.2.3"),
-      packageMap("foo", "2.0.0-dev"),
-      packageMap("foo", "2.0.0")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.2.2");
+      builder.serve("foo", "1.2.3");
+      builder.serve("foo", "2.0.0-dev");
+      builder.serve("foo", "2.0.0");
+    });
 
     schedulePub(args: ["cache", "add", "foo", "-v", ">=1.0.0 <2.0.0"],
         output: 'Downloading foo 1.2.3...');
diff --git a/test/cache/add/adds_latest_version_test.dart b/test/cache/add/adds_latest_version_test.dart
index 5aae1ddc..a9385762 100644
--- a/test/cache/add/adds_latest_version_test.dart
+++ b/test/cache/add/adds_latest_version_test.dart
@@ -10,11 +10,11 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('adds the latest stable version of the package', () {
-    servePackages([
-      packageMap("foo", "1.2.2"),
-      packageMap("foo", "1.2.3"),
-      packageMap("foo", "1.2.4-dev")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.2.2");
+      builder.serve("foo", "1.2.3");
+      builder.serve("foo", "1.2.4-dev");
+    });
 
     schedulePub(args: ["cache", "add", "foo"],
         output: 'Downloading foo 1.2.3...');
diff --git a/test/cache/add/all_adds_all_matching_versions_test.dart b/test/cache/add/all_adds_all_matching_versions_test.dart
index 3939f5bf..79b8555b 100644
--- a/test/cache/add/all_adds_all_matching_versions_test.dart
+++ b/test/cache/add/all_adds_all_matching_versions_test.dart
@@ -10,12 +10,12 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('"--all" adds all matching versions of the package', () {
-    servePackages([
-      packageMap("foo", "1.2.2"),
-      packageMap("foo", "1.2.3-dev"),
-      packageMap("foo", "1.2.3"),
-      packageMap("foo", "2.0.0")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.2.2");
+      builder.serve("foo", "1.2.3-dev");
+      builder.serve("foo", "1.2.3");
+      builder.serve("foo", "2.0.0");
+    });
 
     schedulePub(args: ["cache", "add", "foo", "-v", ">=1.0.0 <2.0.0", "--all"],
         output: '''
diff --git a/test/cache/add/all_with_some_versions_present_test.dart b/test/cache/add/all_with_some_versions_present_test.dart
index 3a900772..3faa1c5a 100644
--- a/test/cache/add/all_with_some_versions_present_test.dart
+++ b/test/cache/add/all_with_some_versions_present_test.dart
@@ -10,12 +10,12 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('"--all" adds all non-installed versions of the package', () {
-    servePackages([
-      packageMap("foo", "1.2.1"),
-      packageMap("foo", "1.2.2"),
-      packageMap("foo", "1.2.3"),
-      packageMap("foo", "2.0.0")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.2.1");
+      builder.serve("foo", "1.2.2");
+      builder.serve("foo", "1.2.3");
+      builder.serve("foo", "2.0.0");
+    });
 
     // Install a couple of versions first.
     schedulePub(args: ["cache", "add", "foo", "-v", "1.2.1"],
diff --git a/test/cache/add/already_cached_test.dart b/test/cache/add/already_cached_test.dart
index ad68f6c7..f6aaa921 100644
--- a/test/cache/add/already_cached_test.dart
+++ b/test/cache/add/already_cached_test.dart
@@ -10,9 +10,9 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('does nothing if the package is already cached', () {
-    servePackages([
-      packageMap("foo", "1.2.3")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.2.3");
+    });
 
     // Run once to put it in the cache.
     schedulePub(args: ["cache", "add", "foo"],
diff --git a/test/cache/add/no_matching_version_test.dart b/test/cache/add/no_matching_version_test.dart
index 2f8cc353..53fd3c57 100644
--- a/test/cache/add/no_matching_version_test.dart
+++ b/test/cache/add/no_matching_version_test.dart
@@ -9,10 +9,10 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('fails if no version matches the version constraint', () {
-    servePackages([
-      packageMap("foo", "1.2.2"),
-      packageMap("foo", "1.2.3")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.2.2");
+      builder.serve("foo", "1.2.3");
+    });
 
     schedulePub(args: ["cache", "add", "foo", "-v", ">2.0.0"],
         error: 'Package foo has no versions that match >2.0.0.',
diff --git a/test/cache/add/package_not_found_test.dart b/test/cache/add/package_not_found_test.dart
index d1bacfcf..1ee9daff 100644
--- a/test/cache/add/package_not_found_test.dart
+++ b/test/cache/add/package_not_found_test.dart
@@ -10,7 +10,7 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('fails if the package cound not be found on the source', () {
-    servePackages([]);
+    serveNoPackages();
 
     schedulePub(args: ["cache", "add", "foo"],
         error: new RegExp(r"Could not find package foo at http://.*"),
diff --git a/test/cache/repair/handles_failure_test.dart b/test/cache/repair/handles_failure_test.dart
index 54d2e946..6f9e009b 100644
--- a/test/cache/repair/handles_failure_test.dart
+++ b/test/cache/repair/handles_failure_test.dart
@@ -14,10 +14,10 @@ main() {
   initConfig();
   integration('handles failure to reinstall some packages', () {
     // Only serve two packages so repairing will have a failure.
-    servePackages([
-      packageMap("foo", "1.2.3"),
-      packageMap("foo", "1.2.5")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.2.3");
+      builder.serve("foo", "1.2.5");
+    });
 
     // Set up a cache with some packages.
     d.dir(cachePath, [
diff --git a/test/cache/repair/reinstalls_hosted_packages_test.dart b/test/cache/repair/reinstalls_hosted_packages_test.dart
index eee64d54..cb813209 100644
--- a/test/cache/repair/reinstalls_hosted_packages_test.dart
+++ b/test/cache/repair/reinstalls_hosted_packages_test.dart
@@ -10,13 +10,13 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('reinstalls previously cached hosted packages', () {
-    servePackages([
-      packageMap("foo", "1.2.3"),
-      packageMap("foo", "1.2.4"),
-      packageMap("foo", "1.2.5"),
-      packageMap("bar", "1.2.3"),
-      packageMap("bar", "1.2.4")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.2.3");
+      builder.serve("foo", "1.2.4");
+      builder.serve("foo", "1.2.5");
+      builder.serve("bar", "1.2.3");
+      builder.serve("bar", "1.2.4");
+    });
 
     // Set up a cache with some broken packages.
     d.dir(cachePath, [
diff --git a/test/dependency_override_test.dart b/test/dependency_override_test.dart
index fcbb3bc2..4e47e24f 100644
--- a/test/dependency_override_test.dart
+++ b/test/dependency_override_test.dart
@@ -11,11 +11,11 @@ main() {
   initConfig();
   forBothPubGetAndUpgrade((command) {
     integration("chooses best version matching override constraint", () {
-      servePackages([
-        packageMap("foo", "1.0.0"),
-        packageMap("foo", "2.0.0"),
-        packageMap("foo", "3.0.0")
-      ]);
+      servePackages((builder) {
+        builder.serve("foo", "1.0.0");
+        builder.serve("foo", "2.0.0");
+        builder.serve("foo", "3.0.0");
+      });
 
       d.dir(appPath, [
         d.pubspec({
@@ -37,9 +37,9 @@ main() {
     });
 
     integration("treats override as implicit dependency", () {
-      servePackages([
-        packageMap("foo", "1.0.0")
-      ]);
+      servePackages((builder) {
+        builder.serve("foo", "1.0.0");
+      });
 
       d.dir(appPath, [
         d.pubspec({
@@ -58,12 +58,14 @@ main() {
     });
 
     integration("ignores other constraints on overridden package", () {
-      servePackages([
-        packageMap("foo", "1.0.0"),
-        packageMap("foo", "2.0.0"),
-        packageMap("foo", "3.0.0"),
-        packageMap("bar", "1.0.0", {"foo": "5.0.0-nonexistent"})
-      ]);
+      servePackages((builder) {
+        builder.serve("foo", "1.0.0");
+        builder.serve("foo", "2.0.0");
+        builder.serve("foo", "3.0.0");
+        builder.serve("bar", "1.0.0", pubspec: {
+          "dependencies": {"foo": "5.0.0-nonexistent"}
+        });
+      });
 
       d.dir(appPath, [
         d.pubspec({
@@ -86,10 +88,10 @@ main() {
     });
 
     integration("warns about overridden dependencies", () {
-      servePackages([
-        packageMap("foo", "1.0.0"),
-        packageMap("bar", "1.0.0")
-      ]);
+      servePackages((builder) {
+        builder.serve("foo", "1.0.0");
+        builder.serve("bar", "1.0.0");
+      });
 
       d.dir("baz", [
         d.libDir("baz"),
diff --git a/test/deps_test.dart b/test/deps_test.dart
index 0241d66e..7c520064 100644
--- a/test/deps_test.dart
+++ b/test/deps_test.dart
@@ -11,31 +11,21 @@ main() {
   initConfig();
 
   setUp(() {
-    servePackages([
-      packageMap("normal", "1.2.3", {
+    servePackages((builder) {
+      builder.serve("normal", "1.2.3", deps: {
         "transitive": "any",
         "circular_a": "any"
-      }),
-      packageMap("transitive", "1.2.3", {
-        "shared": "any"
-      }),
-      packageMap("shared", "1.2.3", {
-        "other": "any"
-      }),
-      packageMap("unittest", "1.2.3", {
-        "shared": "any"
-      }),
-      packageMap("other", "1.0.0"),
-      packageMap("overridden", "1.0.0"),
-      packageMap("overridden", "2.0.0"),
-      packageMap("override_only", "1.2.3"),
-      packageMap("circular_a", "1.2.3", {
-        "circular_b": "any"
-      }),
-      packageMap("circular_b", "1.2.3", {
-        "circular_a": "any"
-      })
-    ]);
+      });
+      builder.serve("transitive", "1.2.3", deps: {"shared": "any"});
+      builder.serve("shared", "1.2.3", deps: {"other": "any"});
+      builder.serve("unittest", "1.2.3", deps: {"shared": "any"});
+      builder.serve("other", "1.0.0");
+      builder.serve("overridden", "1.0.0");
+      builder.serve("overridden", "2.0.0");
+      builder.serve("override_only", "1.2.3");
+      builder.serve("circular_a", "1.2.3", deps: {"circular_b": "any"});
+      builder.serve("circular_b", "1.2.3", deps: {"circular_a": "any"});
+    });
 
     d.dir("from_path", [
       d.libDir("from_path"),
diff --git a/test/downgrade/does_not_show_other_versions_test.dart b/test/downgrade/does_not_show_other_versions_test.dart
index e62bff04..2c49d31e 100644
--- a/test/downgrade/does_not_show_other_versions_test.dart
+++ b/test/downgrade/does_not_show_other_versions_test.dart
@@ -12,11 +12,11 @@ import '../test_pub.dart';
 main() {
   initConfig();
   integration("does not show how many other versions are available", () {
-    servePackages([
-      packageMap("downgraded", "1.0.0"),
-      packageMap("downgraded", "2.0.0"),
-      packageMap("downgraded", "3.0.0-dev")
-    ]);
+    servePackages((builder) {
+      builder.serve("downgraded", "1.0.0");
+      builder.serve("downgraded", "2.0.0");
+      builder.serve("downgraded", "3.0.0-dev");
+    });
 
     d.appDir({
       "downgraded": "3.0.0-dev"
diff --git a/test/downgrade/dry_run_does_not_apply_changes_test.dart b/test/downgrade/dry_run_does_not_apply_changes_test.dart
index 4bae7635..c1f8335c 100644
--- a/test/downgrade/dry_run_does_not_apply_changes_test.dart
+++ b/test/downgrade/dry_run_does_not_apply_changes_test.dart
@@ -12,10 +12,10 @@ import '../test_pub.dart';
 main() {
   initConfig();
   integration("--dry-run shows report but does not apply changes", () {
-    servePackages([
-      packageMap("foo", "1.0.0"),
-      packageMap("foo", "2.0.0"),
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.0.0");
+      builder.serve("foo", "2.0.0");
+    });
 
     // Create the first lockfile.
     d.appDir({
diff --git a/test/downgrade/unlock_dependers_test.dart b/test/downgrade/unlock_dependers_test.dart
index 93a376c0..c329bdb2 100644
--- a/test/downgrade/unlock_dependers_test.dart
+++ b/test/downgrade/unlock_dependers_test.dart
@@ -11,10 +11,10 @@ main() {
   initConfig();
   integration("downgrades a locked package's dependers in order to get it to "
       "min version", () {
-    servePackages([
-      packageMap("foo", "2.0.0", {"bar": ">1.0.0"}),
-      packageMap("bar", "2.0.0")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "2.0.0", deps: {"bar": ">1.0.0"});
+      builder.serve("bar", "2.0.0");
+    });
 
     d.appDir({"foo": "any", "bar": "any"}).create();
 
@@ -25,10 +25,10 @@ main() {
       "bar": "2.0.0"
     }).validate();
 
-    servePackages([
-      packageMap("foo", "1.0.0", {"bar": "any"}),
-      packageMap("bar", "1.0.0")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.0.0", deps: {"bar": "any"});
+      builder.serve("bar", "1.0.0");
+    });
 
     pubDowngrade(args: ['bar']);
 
diff --git a/test/downgrade/unlock_if_necessary_test.dart b/test/downgrade/unlock_if_necessary_test.dart
index 48c7bd86..8561bb48 100644
--- a/test/downgrade/unlock_if_necessary_test.dart
+++ b/test/downgrade/unlock_if_necessary_test.dart
@@ -11,10 +11,10 @@ main() {
   initConfig();
   integration("downgrades one locked hosted package's dependencies if it's "
       "necessary", () {
-    servePackages([
-      packageMap("foo", "2.0.0", {"foo_dep": "any"}),
-      packageMap("foo_dep", "2.0.0")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "2.0.0", deps: {"foo_dep": "any"});
+      builder.serve("foo_dep", "2.0.0");
+    });
 
     d.appDir({"foo": "any"}).create();
 
@@ -25,10 +25,10 @@ main() {
       "foo_dep": "2.0.0"
     }).validate();
 
-    servePackages([
-      packageMap("foo", "1.0.0", {"foo_dep": "<2.0.0"}),
-      packageMap("foo_dep", "1.0.0")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.0.0", deps: {"foo_dep": "<2.0.0"});
+      builder.serve("foo_dep", "1.0.0");
+    });
 
     pubDowngrade(args: ['foo']);
 
diff --git a/test/get/dry_run_does_not_apply_changes_test.dart b/test/get/dry_run_does_not_apply_changes_test.dart
index add71d22..7a07d25a 100644
--- a/test/get/dry_run_does_not_apply_changes_test.dart
+++ b/test/get/dry_run_does_not_apply_changes_test.dart
@@ -10,9 +10,9 @@ import '../test_pub.dart';
 main() {
   initConfig();
   integration("--dry-run shows but does not apply changes", () {
-    servePackages([
-      packageMap("foo", "1.0.0")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.0.0");
+    });
 
     d.appDir({
       "foo": "1.0.0"
diff --git a/test/get/hosted/avoid_network_requests_test.dart b/test/get/hosted/avoid_network_requests_test.dart
index cd66d84a..27ccca32 100644
--- a/test/get/hosted/avoid_network_requests_test.dart
+++ b/test/get/hosted/avoid_network_requests_test.dart
@@ -13,14 +13,14 @@ main() {
   initConfig();
 
   integration('only requests versions that are needed during solving', () {
-    servePackages([
-      packageMap("foo", "1.0.0"),
-      packageMap("foo", "1.1.0"),
-      packageMap("foo", "1.2.0"),
-      packageMap("bar", "1.0.0"),
-      packageMap("bar", "1.1.0"),
-      packageMap("bar", "1.2.0")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.0.0");
+      builder.serve("foo", "1.1.0");
+      builder.serve("foo", "1.2.0");
+      builder.serve("bar", "1.0.0");
+      builder.serve("bar", "1.1.0");
+      builder.serve("bar", "1.2.0");
+    });
 
     d.appDir({
       "foo": "any"
diff --git a/test/get/hosted/cached_pubspec_test.dart b/test/get/hosted/cached_pubspec_test.dart
index 30243369..77a3a3f4 100644
--- a/test/get/hosted/cached_pubspec_test.dart
+++ b/test/get/hosted/cached_pubspec_test.dart
@@ -13,7 +13,7 @@ main() {
   initConfig();
 
   integration('does not request a pubspec for a cached package', () {
-    servePackages([packageMap("foo", "1.2.3")]);
+    servePackages((builder) => builder.serve("foo", "1.2.3"));
 
     d.appDir({"foo": "1.2.3"}).create();
 
diff --git a/test/get/hosted/do_not_upgrade_on_removed_constraints_test.dart b/test/get/hosted/do_not_upgrade_on_removed_constraints_test.dart
index 45808d55..9c65587d 100644
--- a/test/get/hosted/do_not_upgrade_on_removed_constraints_test.dart
+++ b/test/get/hosted/do_not_upgrade_on_removed_constraints_test.dart
@@ -11,12 +11,12 @@ main() {
   initConfig();
   integration("doesn't upgrade dependencies whose constraints have been "
       "removed", () {
-    servePackages([
-      packageMap("foo", "1.0.0", {"shared-dep": "any"}),
-      packageMap("bar", "1.0.0", {"shared-dep": "<2.0.0"}),
-      packageMap("shared-dep", "1.0.0"),
-      packageMap("shared-dep", "2.0.0")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.0.0", deps: {"shared-dep": "any"});
+      builder.serve("bar", "1.0.0", deps: {"shared-dep": "<2.0.0"});
+      builder.serve("shared-dep", "1.0.0");
+      builder.serve("shared-dep", "2.0.0");
+    });
 
     d.appDir({"foo": "any", "bar": "any"}).create();
 
diff --git a/test/get/hosted/does_no_network_requests_when_possible_test.dart b/test/get/hosted/does_no_network_requests_when_possible_test.dart
index 44532fd0..bb7f1bec 100644
--- a/test/get/hosted/does_no_network_requests_when_possible_test.dart
+++ b/test/get/hosted/does_no_network_requests_when_possible_test.dart
@@ -13,11 +13,11 @@ main() {
   initConfig();
 
   integration('does not request versions if the lockfile is up to date', () {
-    servePackages([
-      packageMap("foo", "1.0.0"),
-      packageMap("foo", "1.1.0"),
-      packageMap("foo", "1.2.0")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.0.0");
+      builder.serve("foo", "1.1.0");
+      builder.serve("foo", "1.2.0");
+    });
 
     d.appDir({
       "foo": "any"
diff --git a/test/get/hosted/get_test.dart b/test/get/hosted/get_test.dart
index fa2ffe43..58890c81 100644
--- a/test/get/hosted/get_test.dart
+++ b/test/get/hosted/get_test.dart
@@ -11,7 +11,7 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('gets a package from a pub server', () {
-    servePackages([packageMap("foo", "1.2.3")]);
+    servePackages((builder) => builder.serve("foo", "1.2.3"));
 
     d.appDir({"foo": "1.2.3"}).create();
 
@@ -22,7 +22,7 @@ main() {
   });
 
   integration('URL encodes the package name', () {
-    servePackages([]);
+    serveNoPackages();
 
     d.appDir({"bad name!": "1.2.3"}).create();
 
diff --git a/test/get/hosted/get_transitive_test.dart b/test/get/hosted/get_transitive_test.dart
index 60a9b1e9..7dedb6db 100644
--- a/test/get/hosted/get_transitive_test.dart
+++ b/test/get/hosted/get_transitive_test.dart
@@ -10,12 +10,12 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('gets packages transitively from a pub server', () {
-    servePackages([
-      packageMap("foo", "1.2.3", {"bar": "2.0.4"}),
-      packageMap("bar", "2.0.3"),
-      packageMap("bar", "2.0.4"),
-      packageMap("bar", "2.0.5")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.2.3", deps: {"bar": "2.0.4"});
+      builder.serve("bar", "2.0.3");
+      builder.serve("bar", "2.0.4");
+      builder.serve("bar", "2.0.5");
+    });
 
     d.appDir({"foo": "1.2.3"}).create();
 
diff --git a/test/get/hosted/resolve_constraints_test.dart b/test/get/hosted/resolve_constraints_test.dart
index 47cdba66..ca7c7410 100644
--- a/test/get/hosted/resolve_constraints_test.dart
+++ b/test/get/hosted/resolve_constraints_test.dart
@@ -10,13 +10,13 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('resolves version constraints from a pub server', () {
-    servePackages([
-      packageMap("foo", "1.2.3", {"baz": ">=2.0.0"}),
-      packageMap("bar", "2.3.4", {"baz": "<3.0.0"}),
-      packageMap("baz", "2.0.3"),
-      packageMap("baz", "2.0.4"),
-      packageMap("baz", "3.0.1")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.2.3", deps: {"baz": ">=2.0.0"});
+      builder.serve("bar", "2.3.4", deps: {"baz": "<3.0.0"});
+      builder.serve("baz", "2.0.3");
+      builder.serve("baz", "2.0.4");
+      builder.serve("baz", "3.0.1");
+    });
 
     d.appDir({"foo": "any", "bar": "any"}).create();
 
diff --git a/test/get/hosted/stay_locked_if_compatible_test.dart b/test/get/hosted/stay_locked_if_compatible_test.dart
index 23660e0d..d8c29a41 100644
--- a/test/get/hosted/stay_locked_if_compatible_test.dart
+++ b/test/get/hosted/stay_locked_if_compatible_test.dart
@@ -11,7 +11,7 @@ main() {
   initConfig();
   integration("doesn't upgrade a locked pub server package with a new "
       "compatible constraint", () {
-    servePackages([packageMap("foo", "1.0.0")]);
+    servePackages((builder) => builder.serve("foo", "1.0.0"));
 
     d.appDir({"foo": "any"}).create();
 
@@ -19,7 +19,7 @@ main() {
 
     d.packagesDir({"foo": "1.0.0"}).validate();
 
-    servePackages([packageMap("foo", "1.0.1")]);
+    servePackages((builder) => builder.serve("foo", "1.0.1"));
 
     d.appDir({"foo": ">=1.0.0"}).create();
 
diff --git a/test/get/hosted/stay_locked_if_new_is_satisfied_test.dart b/test/get/hosted/stay_locked_if_new_is_satisfied_test.dart
index c3aa7f4f..868f8583 100644
--- a/test/get/hosted/stay_locked_if_new_is_satisfied_test.dart
+++ b/test/get/hosted/stay_locked_if_new_is_satisfied_test.dart
@@ -11,11 +11,11 @@ main() {
   initConfig();
   integration("doesn't unlock dependencies if a new dependency is already "
       "satisfied", () {
-    servePackages([
-      packageMap("foo", "1.0.0", {"bar": "<2.0.0"}),
-      packageMap("bar", "1.0.0", {"baz": "<2.0.0"}),
-      packageMap("baz", "1.0.0")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.0.0", deps: {"bar": "<2.0.0"});
+      builder.serve("bar", "1.0.0", deps: {"baz": "<2.0.0"});
+      builder.serve("baz", "1.0.0");
+    });
 
     d.appDir({"foo": "any"}).create();
 
@@ -27,12 +27,12 @@ main() {
       "baz": "1.0.0"
     }).validate();
 
-    servePackages([
-      packageMap("foo", "2.0.0", {"bar": "<3.0.0"}),
-      packageMap("bar", "2.0.0", {"baz": "<3.0.0"}),
-      packageMap("baz", "2.0.0"),
-      packageMap("newdep", "2.0.0", {"baz": ">=1.0.0"})
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "2.0.0", deps: {"bar": "<3.0.0"});
+      builder.serve("bar", "2.0.0", deps: {"baz": "<3.0.0"});
+      builder.serve("baz", "2.0.0");
+      builder.serve("newdep", "2.0.0", deps: {"baz": ">=1.0.0"});
+    });
 
     d.appDir({"foo": "any", "newdep": "any"}).create();
 
diff --git a/test/get/hosted/stay_locked_test.dart b/test/get/hosted/stay_locked_test.dart
index 66a2a6b0..a43ad2e0 100644
--- a/test/get/hosted/stay_locked_test.dart
+++ b/test/get/hosted/stay_locked_test.dart
@@ -15,7 +15,7 @@ main() {
   initConfig();
   integration('keeps a pub server package locked to the version in the '
       'lockfile', () {
-    servePackages([packageMap("foo", "1.0.0")]);
+    servePackages((builder) => builder.serve("foo", "1.0.0"));
 
     d.appDir({"foo": "any"}).create();
 
@@ -28,7 +28,7 @@ main() {
     schedule(() => deleteEntry(path.join(sandboxDir, packagesPath)));
 
     // Start serving a newer package as well.
-    servePackages([packageMap("foo", "1.0.1")]);
+    servePackages((builder) => builder.serve("foo", "1.0.1"));
 
     // This shouldn't upgrade the foo dependency due to the lockfile.
     pubGet();
diff --git a/test/get/hosted/unlock_if_incompatible_test.dart b/test/get/hosted/unlock_if_incompatible_test.dart
index 4621703c..77eeca60 100644
--- a/test/get/hosted/unlock_if_incompatible_test.dart
+++ b/test/get/hosted/unlock_if_incompatible_test.dart
@@ -11,14 +11,14 @@ main() {
   initConfig();
   integration('upgrades a locked pub server package with a new incompatible '
       'constraint', () {
-    servePackages([packageMap("foo", "1.0.0")]);
+    servePackages((builder) => builder.serve("foo", "1.0.0"));
 
     d.appDir({"foo": "any"}).create();
 
     pubGet();
 
     d.packagesDir({"foo": "1.0.0"}).validate();
-    servePackages([packageMap("foo", "1.0.1")]);
+    servePackages((builder) => builder.serve("foo", "1.0.1"));
     d.appDir({"foo": ">1.0.0"}).create();
 
     pubGet();
diff --git a/test/get/hosted/unlock_if_new_is_unsatisfied_test.dart b/test/get/hosted/unlock_if_new_is_unsatisfied_test.dart
index d8ceb425..c3f1793b 100644
--- a/test/get/hosted/unlock_if_new_is_unsatisfied_test.dart
+++ b/test/get/hosted/unlock_if_new_is_unsatisfied_test.dart
@@ -11,12 +11,12 @@ main() {
   initConfig();
   integration("unlocks dependencies if necessary to ensure that a new "
       "dependency is satisfied", () {
-    servePackages([
-      packageMap("foo", "1.0.0", {"bar": "<2.0.0"}),
-      packageMap("bar", "1.0.0", {"baz": "<2.0.0"}),
-      packageMap("baz", "1.0.0", {"qux": "<2.0.0"}),
-      packageMap("qux", "1.0.0")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.0.0", deps: {"bar": "<2.0.0"});
+      builder.serve("bar", "1.0.0", deps: {"baz": "<2.0.0"});
+      builder.serve("baz", "1.0.0", deps: {"qux": "<2.0.0"});
+      builder.serve("qux", "1.0.0");
+    });
 
     d.appDir({"foo": "any"}).create();
 
@@ -29,13 +29,13 @@ main() {
       "qux": "1.0.0"
     }).validate();
 
-    servePackages([
-      packageMap("foo", "2.0.0", {"bar": "<3.0.0"}),
-      packageMap("bar", "2.0.0", {"baz": "<3.0.0"}),
-      packageMap("baz", "2.0.0", {"qux": "<3.0.0"}),
-      packageMap("qux", "2.0.0"),
-      packageMap("newdep", "2.0.0", {"baz": ">=1.5.0"})
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "2.0.0", deps: {"bar": "<3.0.0"});
+      builder.serve("bar", "2.0.0", deps: {"baz": "<3.0.0"});
+      builder.serve("baz", "2.0.0", deps: {"qux": "<3.0.0"});
+      builder.serve("qux", "2.0.0");
+      builder.serve("newdep", "2.0.0", deps: {"baz": ">=1.5.0"});
+    });
 
     d.appDir({"foo": "any", "newdep": "any"}).create();
 
diff --git a/test/get/hosted/unlock_if_version_doesnt_exist_test.dart b/test/get/hosted/unlock_if_version_doesnt_exist_test.dart
index 2b662e66..a3f57ff8 100644
--- a/test/get/hosted/unlock_if_version_doesnt_exist_test.dart
+++ b/test/get/hosted/unlock_if_version_doesnt_exist_test.dart
@@ -15,7 +15,7 @@ main() {
   initConfig();
   integration('upgrades a locked pub server package with a nonexistent version',
       () {
-    servePackages([packageMap("foo", "1.0.0")]);
+    servePackages((builder) => builder.serve("foo", "1.0.0"));
 
     d.appDir({"foo": "any"}).create();
     pubGet();
@@ -23,7 +23,7 @@ main() {
 
     schedule(() => deleteEntry(p.join(sandboxDir, cachePath)));
 
-    servePackages([packageMap("foo", "1.0.1")], replace: true);
+    servePackages((builder) => builder.serve("foo", "1.0.1"), replace: true);
     pubGet();
     d.packagesDir({"foo": "1.0.1"}).validate();
   });
diff --git a/test/get/switch_source_test.dart b/test/get/switch_source_test.dart
index 978dee82..4b8ad777 100644
--- a/test/get/switch_source_test.dart
+++ b/test/get/switch_source_test.dart
@@ -10,7 +10,7 @@ import '../test_pub.dart';
 main() {
   initConfig();
   integration('re-gets a package if its source has changed', () {
-    servePackages([packageMap("foo", "1.2.3")]);
+    servePackages((builder) => builder.serve("foo", "1.2.3"));
 
     d.dir('foo', [
       d.libDir('foo', 'foo 0.0.1'),
diff --git a/test/global/activate/activate_git_after_hosted_test.dart b/test/global/activate/activate_git_after_hosted_test.dart
index 9aea6fdb..30082928 100644
--- a/test/global/activate/activate_git_after_hosted_test.dart
+++ b/test/global/activate/activate_git_after_hosted_test.dart
@@ -10,13 +10,13 @@ main() {
   integration('activating a Git package deactivates the hosted one', () {
     ensureGit();
 
-    servePackages([
-      packageMap("foo", "1.0.0")
-    ], contents: [
-      d.dir("bin", [
-        d.file("foo.dart", "main(args) => print('hosted');")
-      ])
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.0.0", contents: [
+        d.dir("bin", [
+          d.file("foo.dart", "main(args) => print('hosted');")
+        ])
+      ]);
+    });
 
     d.git('foo.git', [
       d.libPubspec("foo", "1.0.0"),
diff --git a/test/global/activate/activate_hosted_after_git_test.dart b/test/global/activate/activate_hosted_after_git_test.dart
index 296490ff..09ac4151 100644
--- a/test/global/activate/activate_hosted_after_git_test.dart
+++ b/test/global/activate/activate_hosted_after_git_test.dart
@@ -11,13 +11,13 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('activating a hosted package deactivates the Git one', () {
-    servePackages([
-      packageMap("foo", "2.0.0")
-    ], contents: [
-      d.dir("bin", [
-        d.file("foo.dart", "main(args) => print('hosted');")
-      ])
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "2.0.0", contents: [
+        d.dir("bin", [
+          d.file("foo.dart", "main(args) => print('hosted');")
+        ])
+      ]);
+    });
 
     d.git('foo.git', [
       d.libPubspec("foo", "1.0.0"),
diff --git a/test/global/activate/activate_hosted_after_path_test.dart b/test/global/activate/activate_hosted_after_path_test.dart
index 6cd26d00..3115695c 100644
--- a/test/global/activate/activate_hosted_after_path_test.dart
+++ b/test/global/activate/activate_hosted_after_path_test.dart
@@ -11,13 +11,13 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('activating a hosted package deactivates the path one', () {
-    servePackages([
-      packageMap("foo", "2.0.0")
-    ], contents: [
-      d.dir("bin", [
-        d.file("foo.dart", "main(args) => print('hosted');")
-      ])
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "2.0.0", contents: [
+        d.dir("bin", [
+          d.file("foo.dart", "main(args) => print('hosted');")
+        ])
+      ]);
+    });
 
     d.dir("foo", [
       d.libPubspec("foo", "1.0.0"),
diff --git a/test/global/activate/activate_path_after_hosted_test.dart b/test/global/activate/activate_path_after_hosted_test.dart
index fa744878..30bfbd7c 100644
--- a/test/global/activate/activate_path_after_hosted_test.dart
+++ b/test/global/activate/activate_path_after_hosted_test.dart
@@ -11,13 +11,13 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('activating a hosted package deactivates the path one', () {
-    servePackages([
-      packageMap("foo", "1.0.0")
-    ], contents: [
-      d.dir("bin", [
-        d.file("foo.dart", "main(args) => print('hosted');")
-      ])
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.0.0", contents: [
+        d.dir("bin", [
+          d.file("foo.dart", "main(args) => print('hosted');")
+        ])
+      ]);
+    });
 
     d.dir("foo", [
       d.libPubspec("foo", "2.0.0"),
diff --git a/test/global/activate/cached_package_test.dart b/test/global/activate/cached_package_test.dart
index c9071c75..348e7677 100644
--- a/test/global/activate/cached_package_test.dart
+++ b/test/global/activate/cached_package_test.dart
@@ -10,9 +10,9 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('can activate an already cached package', () {
-    servePackages([
-      packageMap("foo", "1.0.0")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.0.0");
+    });
 
     schedulePub(args: ["cache", "add", "foo"]);
 
diff --git a/test/global/activate/constraint_test.dart b/test/global/activate/constraint_test.dart
index b5073b18..714e06c5 100644
--- a/test/global/activate/constraint_test.dart
+++ b/test/global/activate/constraint_test.dart
@@ -10,12 +10,12 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('chooses the highest version that matches the constraint', () {
-    servePackages([
-      packageMap("foo", "1.0.0"),
-      packageMap("foo", "1.0.1"),
-      packageMap("foo", "1.1.0"),
-      packageMap("foo", "1.2.3")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.0.0");
+      builder.serve("foo", "1.0.1");
+      builder.serve("foo", "1.1.0");
+      builder.serve("foo", "1.2.3");
+    });
 
     schedulePub(args: ["global", "activate", "foo", "<1.1.0"]);
 
diff --git a/test/global/activate/different_version_test.dart b/test/global/activate/different_version_test.dart
index d9542f73..a21387cb 100644
--- a/test/global/activate/different_version_test.dart
+++ b/test/global/activate/different_version_test.dart
@@ -8,10 +8,10 @@ main() {
   initConfig();
   integration("discards the previous active version if it doesn't match the "
       "constraint", () {
-    servePackages([
-      packageMap("foo", "1.0.0"),
-      packageMap("foo", "2.0.0")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.0.0");
+      builder.serve("foo", "2.0.0");
+    });
 
     // Activate 1.0.0.
     schedulePub(args: ["global", "activate", "foo", "1.0.0"]);
diff --git a/test/global/activate/empty_constraint_test.dart b/test/global/activate/empty_constraint_test.dart
index 4d29194d..c1f6f026 100644
--- a/test/global/activate/empty_constraint_test.dart
+++ b/test/global/activate/empty_constraint_test.dart
@@ -8,10 +8,10 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('errors if the constraint matches no versions', () {
-    servePackages([
-      packageMap("foo", "1.0.0"),
-      packageMap("foo", "1.0.1")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.0.0");
+      builder.serve("foo", "1.0.1");
+    });
 
     schedulePub(args: ["global", "activate", "foo", ">1.1.0"],
         error: """
diff --git a/test/global/activate/ignores_active_version_test.dart b/test/global/activate/ignores_active_version_test.dart
index e578b81d..a34e0c68 100644
--- a/test/global/activate/ignores_active_version_test.dart
+++ b/test/global/activate/ignores_active_version_test.dart
@@ -8,10 +8,10 @@ main() {
   initConfig();
   integration('ignores previously activated version',
         () {
-    servePackages([
-      packageMap("foo", "1.2.3"),
-      packageMap("foo", "1.3.0")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.2.3");
+      builder.serve("foo", "1.3.0");
+    });
 
     // Activate 1.2.3.
     schedulePub(args: ["global", "activate", "foo", "1.2.3"]);
diff --git a/test/global/activate/installs_dependencies_for_git_test.dart b/test/global/activate/installs_dependencies_for_git_test.dart
index b50c1f1f..f716c91d 100644
--- a/test/global/activate/installs_dependencies_for_git_test.dart
+++ b/test/global/activate/installs_dependencies_for_git_test.dart
@@ -10,10 +10,10 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('activating a Git package installs its dependencies', () {
-    servePackages([
-      packageMap("bar", "1.0.0", {"baz": "any"}),
-      packageMap("baz", "1.0.0")
-    ]);
+    servePackages((builder) {
+      builder.serve("bar", "1.0.0", deps: {"baz": "any"});
+      builder.serve("baz", "1.0.0");
+    });
 
     d.git('foo.git', [
       d.libPubspec("foo", "1.0.0", deps: {
diff --git a/test/global/activate/installs_dependencies_for_path_test.dart b/test/global/activate/installs_dependencies_for_path_test.dart
index 3480de12..ad987351 100644
--- a/test/global/activate/installs_dependencies_for_path_test.dart
+++ b/test/global/activate/installs_dependencies_for_path_test.dart
@@ -11,10 +11,10 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('activating a path package installs dependencies', () {
-    servePackages([
-      packageMap("bar", "1.0.0", {"baz": "any"}),
-      packageMap("baz", "2.0.0")
-    ]);
+    servePackages((builder) {
+      builder.serve("bar", "1.0.0", deps: {"baz": "any"});
+      builder.serve("baz", "2.0.0");
+    });
 
     d.dir("foo", [
       d.libPubspec("foo", "0.0.0", deps: {
diff --git a/test/global/activate/installs_dependencies_test.dart b/test/global/activate/installs_dependencies_test.dart
index 7918bfdf..add1b82f 100644
--- a/test/global/activate/installs_dependencies_test.dart
+++ b/test/global/activate/installs_dependencies_test.dart
@@ -9,11 +9,11 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('activating a package installs its dependencies', () {
-    servePackages([
-      packageMap("foo", "1.0.0", {"bar": "any"}),
-      packageMap("bar", "1.0.0", {"baz": "any"}),
-      packageMap("baz", "1.0.0")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.0.0", deps: {"bar": "any"});
+      builder.serve("bar", "1.0.0", deps: {"baz": "any"});
+      builder.serve("baz", "1.0.0");
+    });
 
     schedulePub(args: ["global", "activate", "foo"], output: allOf([
       contains("Downloading bar 1.0.0..."),
diff --git a/test/global/activate/supports_version_solver_backtracking_test.dart b/test/global/activate/supports_version_solver_backtracking_test.dart
index 1aa6f5c2..c4647c2b 100644
--- a/test/global/activate/supports_version_solver_backtracking_test.dart
+++ b/test/global/activate/supports_version_solver_backtracking_test.dart
@@ -10,14 +10,14 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('performs verison solver backtracking if necessary', () {
-    servePackages([
-      packageMap("foo", "1.1.0")..addAll({
+    servePackages((builder) {
+      builder.serve("foo", "1.1.0", pubspec: {
         "environment": {"sdk": ">=0.1.2 <0.2.0"}
-      }),
-      packageMap("foo", "1.2.0")..addAll({
+      });
+      builder.serve("foo", "1.2.0", pubspec: {
         "environment": {"sdk": ">=0.1.3 <0.2.0"}
-      }),
-    ]);
+      });
+    });
 
     schedulePub(args: ["global", "activate", "foo"]);
 
diff --git a/test/global/activate/uncached_package_test.dart b/test/global/activate/uncached_package_test.dart
index 9f9041db..7194b99a 100644
--- a/test/global/activate/uncached_package_test.dart
+++ b/test/global/activate/uncached_package_test.dart
@@ -10,11 +10,11 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('installs and activates the best version of a package', () {
-    servePackages([
-      packageMap("foo", "1.0.0"),
-      packageMap("foo", "1.2.3"),
-      packageMap("foo", "2.0.0-wildly.unstable")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.0.0");
+      builder.serve("foo", "1.2.3");
+      builder.serve("foo", "2.0.0-wildly.unstable");
+    });
 
     schedulePub(args: ["global", "activate", "foo"], output: """
         Resolving dependencies...
diff --git a/test/global/activate/unknown_package_test.dart b/test/global/activate/unknown_package_test.dart
index 9bf1066a..70e0b971 100644
--- a/test/global/activate/unknown_package_test.dart
+++ b/test/global/activate/unknown_package_test.dart
@@ -10,7 +10,7 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('errors if the package could not be found', () {
-    servePackages([]);
+    serveNoPackages();
 
     schedulePub(args: ["global", "activate", "foo"],
         error: startsWith("Could not find package foo at"),
diff --git a/test/global/deactivate/deactivate_and_reactivate_package_test.dart b/test/global/deactivate/deactivate_and_reactivate_package_test.dart
index 17f02407..20b1b7eb 100644
--- a/test/global/deactivate/deactivate_and_reactivate_package_test.dart
+++ b/test/global/deactivate/deactivate_and_reactivate_package_test.dart
@@ -7,10 +7,10 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('activates a different version after deactivating', () {
-    servePackages([
-      packageMap("foo", "1.0.0"),
-      packageMap("foo", "2.0.0")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.0.0");
+      builder.serve("foo", "2.0.0");
+    });
 
     // Activate an old version.
     schedulePub(args: ["global", "activate", "foo", "1.0.0"]);
diff --git a/test/global/deactivate/hosted_package_test.dart b/test/global/deactivate/hosted_package_test.dart
index 5625ab82..240a11b4 100644
--- a/test/global/deactivate/hosted_package_test.dart
+++ b/test/global/deactivate/hosted_package_test.dart
@@ -7,9 +7,7 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('deactivates an active hosted package', () {
-    servePackages([
-      packageMap("foo", "1.0.0")
-    ]);
+    servePackages((builder) => builder.serve("foo", "1.0.0"));
 
     schedulePub(args: ["global", "activate", "foo"]);
 
diff --git a/test/global/deactivate/unknown_package_test.dart b/test/global/deactivate/unknown_package_test.dart
index 014cecfa..28864300 100644
--- a/test/global/deactivate/unknown_package_test.dart
+++ b/test/global/deactivate/unknown_package_test.dart
@@ -8,7 +8,7 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('errors if the package is not activated', () {
-    servePackages([]);
+    serveNoPackages();
 
     schedulePub(args: ["global", "deactivate", "foo"],
         error: "No active package foo.",
diff --git a/test/global/list_test.dart b/test/global/list_test.dart
index 6286c722..782c9b0f 100644
--- a/test/global/list_test.dart
+++ b/test/global/list_test.dart
@@ -12,9 +12,9 @@ main() {
   initConfig();
 
   integration('lists an activated hosted package', () {
-    servePackages([
-      packageMap('foo', '1.0.0')
-    ]);
+    servePackages((builder) {
+      builder.serve('foo', '1.0.0');
+    });
 
     schedulePub(args: ['global', 'activate', 'foo']);
 
@@ -53,11 +53,11 @@ main() {
   });
 
   integration('lists activated packages in alphabetical order', () {
-    servePackages([
-      packageMap('aaa', '1.0.0'),
-      packageMap('bbb', '1.0.0'),
-      packageMap('ccc', '1.0.0')
-    ]);
+    servePackages((builder) {
+      builder.serve('aaa', '1.0.0');
+      builder.serve('bbb', '1.0.0');
+      builder.serve('ccc', '1.0.0');
+    });
 
     schedulePub(args: ['global', 'activate', 'ccc']);
     schedulePub(args: ['global', 'activate', 'aaa']);
diff --git a/test/global/run/errors_if_outside_bin_test.dart b/test/global/run/errors_if_outside_bin_test.dart
index 8193876a..0d16cdc7 100644
--- a/test/global/run/errors_if_outside_bin_test.dart
+++ b/test/global/run/errors_if_outside_bin_test.dart
@@ -11,13 +11,13 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('errors if the script is in a subdirectory.', () {
-    servePackages([
-      packageMap("foo", "1.0.0")
-    ], contents: [
-      d.dir("example", [
-        d.file("script.dart", "main(args) => print('ok');")
-      ])
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.0.0", contents: [
+        d.dir("example", [
+          d.file("script.dart", "main(args) => print('ok');")
+        ])
+      ]);
+    });
 
     schedulePub(args: ["global", "activate", "foo"]);
     schedulePub(args: ["global", "run", "foo:example/script"],
diff --git a/test/global/run/implicit_executable_name_test.dart b/test/global/run/implicit_executable_name_test.dart
index ad93bac7..da68c8e1 100644
--- a/test/global/run/implicit_executable_name_test.dart
+++ b/test/global/run/implicit_executable_name_test.dart
@@ -9,13 +9,13 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('defaults to the package name if the script is omitted', () {
-    servePackages([
-      packageMap("foo", "1.0.0")
-    ], contents: [
-      d.dir("bin", [
-        d.file("foo.dart", "main(args) => print('foo');")
-      ])
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.0.0", contents: [
+        d.dir("bin", [
+          d.file("foo.dart", "main(args) => print('foo');")
+        ])
+      ]);
+    });
 
     schedulePub(args: ["global", "activate", "foo"]);
 
diff --git a/test/global/run/nonexistent_script_test.dart b/test/global/run/nonexistent_script_test.dart
index 76c3b31b..d69c65ab 100644
--- a/test/global/run/nonexistent_script_test.dart
+++ b/test/global/run/nonexistent_script_test.dart
@@ -10,7 +10,7 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('errors if the script does not exist.', () {
-    servePackages([packageMap("foo", "1.0.0")]);
+    servePackages((builder) => builder.serve("foo", "1.0.0"));
 
     schedulePub(args: ["global", "activate", "foo"]);
 
diff --git a/test/global/run/runs_script_test.dart b/test/global/run/runs_script_test.dart
index caf8f42d..bfd8bcbf 100644
--- a/test/global/run/runs_script_test.dart
+++ b/test/global/run/runs_script_test.dart
@@ -8,13 +8,13 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('runs a script in an activated package', () {
-    servePackages([
-      packageMap("foo", "1.0.0")
-    ], contents: [
-      d.dir("bin", [
-        d.file("script.dart", "main(args) => print('ok');")
-      ])
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.0.0", contents: [
+        d.dir("bin", [
+          d.file("script.dart", "main(args) => print('ok');")
+        ])
+      ]);
+    });
 
     schedulePub(args: ["global", "activate", "foo"]);
 
diff --git a/test/global/run/unknown_package_test.dart b/test/global/run/unknown_package_test.dart
index e5a4bab0..291577a3 100644
--- a/test/global/run/unknown_package_test.dart
+++ b/test/global/run/unknown_package_test.dart
@@ -10,7 +10,7 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration('errors if the package is not activated', () {
-    servePackages([]);
+    serveNoPackages();
 
     schedulePub(args: ["global", "run", "foo:bar"],
         error: startsWith("No active package foo."),
diff --git a/test/hosted/fail_gracefully_on_missing_package_test.dart b/test/hosted/fail_gracefully_on_missing_package_test.dart
index 60be82ff..df53819d 100644
--- a/test/hosted/fail_gracefully_on_missing_package_test.dart
+++ b/test/hosted/fail_gracefully_on_missing_package_test.dart
@@ -14,7 +14,7 @@ main() {
 
   forBothPubGetAndUpgrade((command) {
     integration('fails gracefully if the package does not exist', () {
-      servePackages([]);
+      serveNoPackages();
 
       d.appDir({"foo": "1.2.3"}).create();
 
diff --git a/test/hosted/offline_test.dart b/test/hosted/offline_test.dart
index 981d24d4..0d7b2d80 100644
--- a/test/hosted/offline_test.dart
+++ b/test/hosted/offline_test.dart
@@ -13,7 +13,7 @@ main() {
   forBothPubGetAndUpgrade((command) {
     integration('upgrades a package using the cache', () {
       // Run the server so that we know what URL to use in the system cache.
-      servePackages([]);
+      serveNoPackages();
 
       d.cacheDir({
         "foo": ["1.2.2", "1.2.3"],
@@ -41,7 +41,7 @@ main() {
 
     integration('fails gracefully if a dependency is not cached', () {
       // Run the server so that we know what URL to use in the system cache.
-      servePackages([]);
+      serveNoPackages();
 
       d.appDir({"foo": "any"}).create();
 
@@ -51,7 +51,7 @@ main() {
 
     integration('fails gracefully no cached versions match', () {
       // Run the server so that we know what URL to use in the system cache.
-      servePackages([]);
+      serveNoPackages();
 
       d.cacheDir({
         "foo": ["1.2.2", "1.2.3"]
diff --git a/test/hosted/remove_removed_dependency_test.dart b/test/hosted/remove_removed_dependency_test.dart
index 442d968b..36280c93 100644
--- a/test/hosted/remove_removed_dependency_test.dart
+++ b/test/hosted/remove_removed_dependency_test.dart
@@ -12,10 +12,10 @@ main() {
 
   forBothPubGetAndUpgrade((command) {
     integration("removes a dependency that's removed from the pubspec", () {
-      servePackages([
-        packageMap("foo", "1.0.0"),
-        packageMap("bar", "1.0.0")
-      ]);
+      servePackages((builder) {
+        builder.serve("foo", "1.0.0");
+        builder.serve("bar", "1.0.0");
+      });
 
       d.appDir({"foo": "any", "bar": "any"}).create();
 
diff --git a/test/hosted/remove_removed_transitive_dependency_test.dart b/test/hosted/remove_removed_transitive_dependency_test.dart
index e975b055..f6792257 100644
--- a/test/hosted/remove_removed_transitive_dependency_test.dart
+++ b/test/hosted/remove_removed_transitive_dependency_test.dart
@@ -13,17 +13,17 @@ main() {
   forBothPubGetAndUpgrade((command) {
     integration("removes a transitive dependency that's no longer depended "
         "on", () {
-      servePackages([
-        packageMap("foo", "1.0.0", {
+      servePackages((builder) {
+        builder.serve("foo", "1.0.0", deps: {
           "shared-dep": "any"
-        }),
-        packageMap("bar", "1.0.0", {
+        });
+        builder.serve("bar", "1.0.0", deps: {
           "shared-dep": "any",
           "bar-dep": "any"
-        }),
-        packageMap("shared-dep", "1.0.0"),
-        packageMap("bar-dep", "1.0.0")
-      ]);
+        });
+        builder.serve("shared-dep", "1.0.0");
+        builder.serve("bar-dep", "1.0.0");
+      });
 
       d.appDir({
         "foo": "any",
diff --git a/test/implicit_barback_dependency_test.dart b/test/implicit_barback_dependency_test.dart
index 03f18d87..6965fcde 100644
--- a/test/implicit_barback_dependency_test.dart
+++ b/test/implicit_barback_dependency_test.dart
@@ -22,14 +22,14 @@ main() {
 
   forBothPubGetAndUpgrade((command) {
     integration("implicitly constrains barback to versions pub supports", () {
-      servePackages([
-        packageMap("barback", previous),
-        packageMap("barback", current),
-        packageMap("barback", nextPatch),
-        packageMap("barback", max),
-        packageMap("source_span", sourceSpanVersion),
-        packageMap("stack_trace", stackTraceVersion)
-      ]);
+      servePackages((builder) {
+        builder.serve("barback", previous);
+        builder.serve("barback", current);
+        builder.serve("barback", nextPatch);
+        builder.serve("barback", max);
+        builder.serve("source_span", sourceSpanVersion);
+        builder.serve("stack_trace", stackTraceVersion);
+      });
 
       d.appDir({
         "barback": "any"
@@ -43,14 +43,14 @@ main() {
     });
 
     integration("discovers transitive dependency on barback", () {
-      servePackages([
-        packageMap("barback", previous),
-        packageMap("barback", current),
-        packageMap("barback", nextPatch),
-        packageMap("barback", max),
-        packageMap("source_span", sourceSpanVersion),
-        packageMap("stack_trace", stackTraceVersion)
-      ]);
+      servePackages((builder) {
+        builder.serve("barback", previous);
+        builder.serve("barback", current);
+        builder.serve("barback", nextPatch);
+        builder.serve("barback", max);
+        builder.serve("source_span", sourceSpanVersion);
+        builder.serve("stack_trace", stackTraceVersion);
+      });
 
       d.dir("foo", [
         d.libDir("foo", "foo 0.0.1"),
@@ -73,10 +73,10 @@ main() {
 
     integration("pub's implicit constraint uses the same source and "
         "description as a dependency override", () {
-      servePackages([
-        packageMap("source_span", sourceSpanVersion),
-        packageMap("stack_trace", stackTraceVersion)
-      ]);
+      servePackages((builder) {
+        builder.serve("source_span", sourceSpanVersion);
+        builder.serve("stack_trace", stackTraceVersion);
+      });
 
       d.dir('barback', [
         d.libDir('barback', 'barback $current'),
@@ -101,12 +101,12 @@ main() {
   });
 
   integration("unlock if the locked version doesn't meet pub's constraint", () {
-    servePackages([
-      packageMap("barback", previous),
-      packageMap("barback", current),
-      packageMap("source_span", sourceSpanVersion),
-      packageMap("stack_trace", stackTraceVersion)
-    ]);
+    servePackages((builder) {
+      builder.serve("barback", previous);
+      builder.serve("barback", current);
+      builder.serve("source_span", sourceSpanVersion);
+      builder.serve("stack_trace", stackTraceVersion);
+    });
 
     d.appDir({"barback": "any"}).create();
 
@@ -125,11 +125,11 @@ main() {
 
   integration("includes pub in the error if a solve failed because there "
       "is no version available", () {
-    servePackages([
-      packageMap("barback", previous),
-      packageMap("source_span", sourceSpanVersion),
-      packageMap("stack_trace", stackTraceVersion)
-    ]);
+    servePackages((builder) {
+      builder.serve("barback", previous);
+      builder.serve("source_span", sourceSpanVersion);
+      builder.serve("stack_trace", stackTraceVersion);
+    });
 
     d.appDir({"barback": "any"}).create();
 
@@ -141,12 +141,12 @@ Package barback 0.12.0 does not match >=$current <$max derived from:
 
   integration("includes pub in the error if a solve failed because there "
       "is a disjoint constraint", () {
-    servePackages([
-      packageMap("barback", previous),
-      packageMap("barback", current),
-      packageMap("source_span", sourceSpanVersion),
-      packageMap("stack_trace", stackTraceVersion)
-    ]);
+    servePackages((builder) {
+      builder.serve("barback", previous);
+      builder.serve("barback", current);
+      builder.serve("source_span", sourceSpanVersion);
+      builder.serve("stack_trace", stackTraceVersion);
+    });
 
     d.appDir({"barback": previous}).create();
 
diff --git a/test/implicit_dependency_test.dart b/test/implicit_dependency_test.dart
index 3f46637c..34e133f8 100644
--- a/test/implicit_dependency_test.dart
+++ b/test/implicit_dependency_test.dart
@@ -12,14 +12,14 @@ main() {
 
   forBothPubGetAndUpgrade((command) {
     integration("implicitly constrains it to versions pub supports", () {
-      servePackages([
-        packageMap("barback", current("barback")),
-        packageMap("stack_trace", previous("stack_trace")),
-        packageMap("stack_trace", current("stack_trace")),
-        packageMap("stack_trace", nextPatch("stack_trace")),
-        packageMap("stack_trace", max("stack_trace")),
-        packageMap("source_span", current("source_span"))
-      ]);
+      servePackages((builder) {
+        builder.serve("barback", current("barback"));
+        builder.serve("stack_trace", previous("stack_trace"));
+        builder.serve("stack_trace", current("stack_trace"));
+        builder.serve("stack_trace", nextPatch("stack_trace"));
+        builder.serve("stack_trace", max("stack_trace"));
+        builder.serve("source_span", current("source_span"));
+      });
 
       d.appDir({
         "barback": "any"
@@ -32,11 +32,11 @@ main() {
 
     integration("pub's implicit constraint uses the same source and "
         "description as a dependency override", () {
-      servePackages([
-        packageMap("barback", current("barback")),
-        packageMap("stack_trace", nextPatch("stack_trace")),
-        packageMap("source_span", current("source_span"))
-      ]);
+      servePackages((builder) {
+        builder.serve("barback", current("barback"));
+        builder.serve("stack_trace", nextPatch("stack_trace"));
+        builder.serve("source_span", current("source_span"));
+      });
 
       d.dir("stack_trace", [
         d.libDir("stack_trace", 'stack_trace ${current("stack_trace")}'),
@@ -64,13 +64,13 @@ main() {
 
     integration("doesn't add a constraint if barback isn't in the package "
         "graph", () {
-      servePackages([
-        packageMap("stack_trace", previous("stack_trace")),
-        packageMap("stack_trace", current("stack_trace")),
-        packageMap("stack_trace", nextPatch("stack_trace")),
-        packageMap("stack_trace", max("stack_trace")),
-        packageMap("source_span", current("source_span"))
-      ]);
+      servePackages((builder) {
+        builder.serve("stack_trace", previous("stack_trace"));
+        builder.serve("stack_trace", current("stack_trace"));
+        builder.serve("stack_trace", nextPatch("stack_trace"));
+        builder.serve("stack_trace", max("stack_trace"));
+        builder.serve("source_span", current("source_span"));
+      });
 
       d.appDir({
         "stack_trace": "any"
@@ -84,12 +84,12 @@ main() {
 
   integration("unlocks if the locked version doesn't meet pub's "
       "constraint", () {
-    servePackages([
-      packageMap("barback", current("barback")),
-      packageMap("stack_trace", previous("stack_trace")),
-      packageMap("stack_trace", current("stack_trace")),
-      packageMap("source_span", current("source_span"))
-    ]);
+    servePackages((builder) {
+      builder.serve("barback", current("barback"));
+      builder.serve("stack_trace", previous("stack_trace"));
+      builder.serve("stack_trace", current("stack_trace"));
+      builder.serve("source_span", current("source_span"));
+    });
 
     d.appDir({"barback": "any"}).create();
 
diff --git a/test/list_package_dirs/lists_dependency_directories_test.dart b/test/list_package_dirs/lists_dependency_directories_test.dart
index 95a8c5df..fe29d819 100644
--- a/test/list_package_dirs/lists_dependency_directories_test.dart
+++ b/test/list_package_dirs/lists_dependency_directories_test.dart
@@ -11,7 +11,7 @@ import '../test_pub.dart';
 main() {
   initConfig();
   integration('prints the local paths to all packages in the lockfile', () {
-    servePackages([packageMap("bar", "1.0.0")]);
+    servePackages((builder) => builder.serve("bar", "1.0.0"));
 
     d.dir("foo", [
       d.libDir("foo"),
diff --git a/test/no_package_symlinks_test.dart b/test/no_package_symlinks_test.dart
index 12d51514..2911debc 100644
--- a/test/no_package_symlinks_test.dart
+++ b/test/no_package_symlinks_test.dart
@@ -13,10 +13,10 @@ main() {
   forBothPubGetAndUpgrade((command) {
     group("with --no-package-symlinks", () {
       integration("installs hosted dependencies to the cache", () {
-        servePackages([
-          packageMap("foo", "1.0.0"),
-          packageMap("bar", "1.0.0")
-        ]);
+        servePackages((builder) {
+          builder.serve("foo", "1.0.0");
+          builder.serve("bar", "1.0.0");
+        });
 
         d.appDir({"foo": "any", "bar": "any"}).create();
 
diff --git a/test/serve/gets_first_if_dependency_is_not_installed_test.dart b/test/serve/gets_first_if_dependency_is_not_installed_test.dart
index eac41fea..d76d8367 100644
--- a/test/serve/gets_first_if_dependency_is_not_installed_test.dart
+++ b/test/serve/gets_first_if_dependency_is_not_installed_test.dart
@@ -15,7 +15,7 @@ import 'utils.dart';
 main() {
   initConfig();
   integration("gets first if a dependency is not installed", () {
-    servePackages([packageMap("foo", "1.2.3")]);
+    servePackages((builder) => builder.serve("foo", "1.2.3"));
 
     d.appDir({"foo": "1.2.3"}).create();
 
diff --git a/test/serve/gets_first_if_transitive_dependency_is_not_installed_test.dart b/test/serve/gets_first_if_transitive_dependency_is_not_installed_test.dart
index 76f90399..3d367450 100644
--- a/test/serve/gets_first_if_transitive_dependency_is_not_installed_test.dart
+++ b/test/serve/gets_first_if_transitive_dependency_is_not_installed_test.dart
@@ -15,7 +15,7 @@ import 'utils.dart';
 main() {
   initConfig();
   integration("gets first if a transitive dependency is not installed", () {
-    servePackages([packageMap("bar", "1.2.3")]);
+    servePackages((builder) => builder.serve("bar", "1.2.3"));
 
     d.dir("foo", [
       d.libPubspec("foo", "1.0.0", deps: {
diff --git a/test/serve_packages.dart b/test/serve_packages.dart
new file mode 100644
index 00000000..92a319ee
--- /dev/null
+++ b/test/serve_packages.dart
@@ -0,0 +1,195 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library serve_packages;
+
+import 'dart:async';
+import 'dart:convert';
+
+import 'package:path/path.dart' as p;
+import 'package:scheduled_test/scheduled_test.dart';
+import 'package:yaml/yaml.dart';
+
+import '../lib/src/io.dart';
+import '../lib/src/utils.dart';
+import '../lib/src/version.dart';
+import 'descriptor.dart' as d;
+import 'test_pub.dart';
+
+/// The [d.DirectoryDescriptor] describing the server layout of `/api/packages`
+/// on the test server.
+///
+/// This contains metadata for packages that are being served via
+/// [servePackages]. It's `null` if [servePackages] has not yet been called for
+/// this test.
+d.DirectoryDescriptor _servedApiPackageDir;
+
+/// The [d.DirectoryDescriptor] describing the server layout of `/packages` on
+/// the test server.
+///
+/// This contains the tarballs for packages that are being served via
+/// [servePackages]. It's `null` if [servePackages] has not yet been called for
+/// this test.
+d.DirectoryDescriptor _servedPackageDir;
+
+/// The current [PackageServerBuilder] that a user uses to specify which package
+/// to serve.
+///
+/// This is preserved over multiple calls to [servePackages] within the same
+/// test so that additional packages can be added.
+PackageServerBuilder _builder;
+
+/// Creates an HTTP server that replicates the structure of pub.dartlang.org.
+///
+/// Calls [callback] with a [PackageServerBuilder] that's used to specify
+/// which packages to serve.
+///
+/// If [replace] is false, subsequent calls to [servePackages] will add to the
+/// set of packages that are being served. Previous packages will continue to be
+/// served. Otherwise, the previous packages will no longer be served.
+void servePackages(void callback(PackageServerBuilder builder),
+    {bool replace: false}) {
+  if (_servedPackageDir == null) {
+    _builder = new PackageServerBuilder();
+    _servedApiPackageDir = d.dir('packages', []);
+    _servedPackageDir = d.dir('packages', []);
+    serve([
+      d.dir('api', [_servedApiPackageDir]),
+      _servedPackageDir
+    ]);
+
+    currentSchedule.onComplete.schedule(() {
+      _builder = null;
+      _servedApiPackageDir = null;
+      _servedPackageDir = null;
+    }, 'cleaning up served packages');
+  }
+
+  schedule(() {
+    if (replace) _builder = new PackageServerBuilder();
+    callback(_builder);
+    return _builder._await().then((resolvedPubspecs) {
+      _servedApiPackageDir.contents.clear();
+      _servedPackageDir.contents.clear();
+      _builder._packages.forEach((name, versions) {
+        _servedApiPackageDir.contents.addAll([
+          d.file('$name', JSON.encode({
+            'name': name,
+            'uploaders': ['nweiz@google.com'],
+            'versions': versions.map((version) =>
+                packageVersionApiMap(version.pubspec)).toList()
+          })),
+          d.dir(name, [
+            d.dir('versions', versions.map((version) {
+              return d.file(version.version.toString(), JSON.encode(
+                  packageVersionApiMap(version.pubspec, full: true)));
+            }))
+          ])
+        ]);
+
+        _servedPackageDir.contents.add(d.dir(name, [
+          d.dir('versions', versions.map((version) =>
+              d.tar('${version.version}.tar.gz', version.contents)))
+        ]));
+      });
+    });
+  }, 'initializing the package server');
+}
+
+/// Like [servePackages], but instead creates an empty server with no packages
+/// registered.
+///
+/// This will always replace a previous server.
+void serveNoPackages() => servePackages((_) {}, replace: true);
+
+/// A builder for specifying which packages should be served by [servePackages].
+class PackageServerBuilder {
+  /// A map from package names to a list of concrete packages to serve.
+  final _packages = new Map<String, List<_ServedPackage>>();
+
+  /// A group of futures from [serve] calls.
+  ///
+  /// This should be accessed by calling [_awair].
+  var _futures = new FutureGroup();
+
+  /// Specifies that a package named [name] with [version] should be served.
+  ///
+  /// If [deps] is passed, it's used as the "dependencies" field of the pubspec.
+  /// If [pubspec] is passed, it's used as the rest of the pubspec. Either of
+  /// these may recursively contain Futures.
+  ///
+  /// If [contents] is passed, it's used as the contents of the package. By
+  /// default, a package just contains a dummy lib directory.
+  void serve(String name, String version, {Map deps, Map pubspec,
+      Iterable<d.Descriptor> contents}) {
+    _futures.add(Future.wait([
+      awaitObject(deps),
+      awaitObject(pubspec)
+    ]).then((pair) {
+      var resolvedDeps = pair.first;
+      var resolvedPubspec = pair.last;
+
+      var pubspecFields = {
+        "name": name,
+        "version": version
+      };
+      if (resolvedPubspec != null) pubspecFields.addAll(resolvedPubspec);
+      if (resolvedDeps != null) pubspecFields["dependencies"] = resolvedDeps;
+
+      if (contents == null) contents = [d.libDir(name, "$name $version")];
+      contents = [d.file("pubspec.yaml", yaml(pubspecFields))]
+          ..addAll(contents);
+
+      var packages = _packages.putIfAbsent(name, () => []);
+      packages.add(new _ServedPackage(pubspecFields, contents));
+    }));
+  }
+
+  /// Serves the versions of [package] and all its dependencies that are
+  /// currently checked into the Dart repository.
+  void serveRepoPackage(String package) {
+    _addPackage(name) {
+      if (_packages.containsKey(name)) return;
+      _packages[name] = [];
+
+      var pubspec = new Map.from(loadYaml(
+          readTextFile(p.join(repoRoot, 'pkg', name, 'pubspec.yaml'))));
+
+      // Remove any SDK constraints since we don't have a valid SDK version
+      // while testing.
+      pubspec.remove('environment');
+
+      _packages[name].add(new _ServedPackage(pubspec, [
+        d.file('pubspec.yaml', yaml(pubspec)),
+        new d.DirectoryDescriptor.fromFilesystem('lib',
+            p.join(repoRoot, 'pkg', name, 'lib'))
+      ]));
+
+      if (pubspec.containsKey('dependencies')) {
+        pubspec['dependencies'].keys.forEach(_addPackage);
+      }
+    }
+
+    _addPackage(package);
+  }
+
+  /// Returns a Future that completes once all the [serve] calls have been fully
+  /// processed.
+  Future _await() {
+    if (_futures.futures.isEmpty) return new Future.value();
+    return _futures.future.then((_) {
+      _futures = new FutureGroup();
+    });
+  }
+}
+
+/// A package that's intended to be served.
+class _ServedPackage {
+  final Map pubspec;
+  final List<d.Descriptor> contents;
+
+  Version get version => new Version.parse(pubspec['version']);
+
+  _ServedPackage(this.pubspec, this.contents);
+}
diff --git a/test/snapshot/creates_a_snapshot_for_immediate_and_transitive_dep_test.dart b/test/snapshot/creates_a_snapshot_for_immediate_and_transitive_dep_test.dart
index a084aa79..f4110433 100644
--- a/test/snapshot/creates_a_snapshot_for_immediate_and_transitive_dep_test.dart
+++ b/test/snapshot/creates_a_snapshot_for_immediate_and_transitive_dep_test.dart
@@ -14,19 +14,19 @@ main() {
   initConfig();
   integration("creates a snapshot for an immediate dependency that's also a "
       "transitive dependency", () {
-    servePackages([
-      packageMap("foo", "1.2.3"),
-      packageMap("bar", "1.2.3", {"foo": "1.2.3"})
-    ], contents: [
-      d.dir("bin", [
-        d.file("hello.dart", "void main() => print('hello!');"),
-        d.file("goodbye.dart", "void main() => print('goodbye!');"),
-        d.file("shell.sh", "echo shell"),
-        d.dir("subdir", [
-          d.file("sub.dart", "void main() => print('sub!');")
+    servePackages((builder) {
+      builder.serve("foo", "1.2.3", contents: [
+        d.dir("bin", [
+          d.file("hello.dart", "void main() => print('hello!');"),
+          d.file("goodbye.dart", "void main() => print('goodbye!');"),
+          d.file("shell.sh", "echo shell"),
+          d.dir("subdir", [
+            d.file("sub.dart", "void main() => print('sub!');")
+          ])
         ])
-      ])
-    ]);
+      ]);
+      builder.serve("bar", "1.2.3", deps: {"foo": "1.2.3"});
+    });
 
     d.appDir({"foo": "1.2.3"}).create();
 
diff --git a/test/snapshot/creates_a_snapshot_test.dart b/test/snapshot/creates_a_snapshot_test.dart
index 27411dc1..6683d06c 100644
--- a/test/snapshot/creates_a_snapshot_test.dart
+++ b/test/snapshot/creates_a_snapshot_test.dart
@@ -14,16 +14,18 @@ main() {
   initConfig();
   integration("creates a snapshot for an immediate dependency's executables",
       () {
-    servePackages([packageMap("foo", "1.2.3")], contents: [
-      d.dir("bin", [
-        d.file("hello.dart", "void main() => print('hello!');"),
-        d.file("goodbye.dart", "void main() => print('goodbye!');"),
-        d.file("shell.sh", "echo shell"),
-        d.dir("subdir", [
-          d.file("sub.dart", "void main() => print('sub!');")
+    servePackages((builder) {
+      builder.serve("foo", "1.2.3", contents: [
+        d.dir("bin", [
+          d.file("hello.dart", "void main() => print('hello!');"),
+          d.file("goodbye.dart", "void main() => print('goodbye!');"),
+          d.file("shell.sh", "echo shell"),
+          d.dir("subdir", [
+            d.file("sub.dart", "void main() => print('sub!');")
+          ])
         ])
-      ])
-    ]);
+      ]);
+    });
 
     d.appDir({"foo": "1.2.3"}).create();
 
diff --git a/test/snapshot/doesnt_resnapshot_when_a_dependency_is_unchanged_test.dart b/test/snapshot/doesnt_resnapshot_when_a_dependency_is_unchanged_test.dart
index c4ab2f08..8750e799 100644
--- a/test/snapshot/doesnt_resnapshot_when_a_dependency_is_unchanged_test.dart
+++ b/test/snapshot/doesnt_resnapshot_when_a_dependency_is_unchanged_test.dart
@@ -14,12 +14,12 @@ main() {
   initConfig();
   integration("doesn't recreate a snapshot when no dependencies of a package "
       "have changed", () {
-    servePackages([
-      packageMap("foo", "1.2.3", {"bar": "any"}),
-      packageMap("bar", "1.2.3")
-    ], contents: [
-      d.dir("bin", [d.file("hello.dart", "void main() => print('hello!');")])
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.2.3", deps: {"bar": "any"}, contents: [
+        d.dir("bin", [d.file("hello.dart", "void main() => print('hello!');")])
+      ]);
+      builder.serve("bar", "1.2.3");
+    });
 
     d.appDir({"foo": "1.2.3"}).create();
 
diff --git a/test/snapshot/doesnt_snapshot_an_entrypoint_dependency_test.dart b/test/snapshot/doesnt_snapshot_an_entrypoint_dependency_test.dart
index 164344ce..5fd71a61 100644
--- a/test/snapshot/doesnt_snapshot_an_entrypoint_dependency_test.dart
+++ b/test/snapshot/doesnt_snapshot_an_entrypoint_dependency_test.dart
@@ -14,12 +14,12 @@ main() {
   initConfig();
   integration("doesn't create a snapshot for a package that depends on the "
       "entrypoint", () {
-    servePackages([
-      packageMap("foo", "1.2.3", {'bar': '1.2.3'}),
-      packageMap("bar", "1.2.3", {'myapp': 'any'})
-    ], contents: [
-      d.dir("bin", [d.file("hello.dart", "void main() => print('hello!');")])
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.2.3", deps: {'bar': '1.2.3'}, contents: [
+        d.dir("bin", [d.file("hello.dart", "void main() => print('hello!');")])
+      ]);
+      builder.serve("bar", "1.2.3", deps: {'myapp': 'any'});
+    });
 
     d.appDir({"foo": "1.2.3"}).create();
 
diff --git a/test/snapshot/doesnt_snapshot_transitive_dependencies_test.dart b/test/snapshot/doesnt_snapshot_transitive_dependencies_test.dart
index 9b4512e7..039c7fb6 100644
--- a/test/snapshot/doesnt_snapshot_transitive_dependencies_test.dart
+++ b/test/snapshot/doesnt_snapshot_transitive_dependencies_test.dart
@@ -14,12 +14,12 @@ main() {
   initConfig();
   integration("doesn't create a snapshot for transitive dependencies' "
       "executables", () {
-    servePackages([
-      packageMap("foo", "1.2.3", {'bar': '1.2.3'}),
-      packageMap("bar", "1.2.3")
-    ], contents: [
-      d.dir("bin", [d.file("hello.dart", "void main() => print('hello!');")])
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.2.3", deps: {'bar': '1.2.3'});
+      builder.serve("bar", "1.2.3", contents: [
+        d.dir("bin", [d.file("hello.dart", "void main() => print('hello!');")])
+      ]);
+    });
 
     d.appDir({"foo": "1.2.3"}).create();
 
diff --git a/test/snapshot/prints_errors_for_broken_snapshots_test.dart b/test/snapshot/prints_errors_for_broken_snapshots_test.dart
index 1c8af8f1..b398df7b 100644
--- a/test/snapshot/prints_errors_for_broken_snapshots_test.dart
+++ b/test/snapshot/prints_errors_for_broken_snapshots_test.dart
@@ -13,15 +13,20 @@ import '../test_pub.dart';
 main() {
   initConfig();
   integration("prints errors for broken snapshot compilation", () {
-    servePackages([
-      packageMap("foo", "1.2.3"),
-      packageMap("bar", "1.2.3")
-    ], contents: [
-      d.dir("bin", [
-        d.file("hello.dart", "void main() { no closing brace"),
-        d.file("goodbye.dart", "void main() { no closing brace"),
-      ])
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.2.3", contents: [
+        d.dir("bin", [
+          d.file("hello.dart", "void main() { no closing brace"),
+          d.file("goodbye.dart", "void main() { no closing brace"),
+        ])
+      ]);
+      builder.serve("bar", "1.2.3", contents: [
+        d.dir("bin", [
+          d.file("hello.dart", "void main() { no closing brace"),
+          d.file("goodbye.dart", "void main() { no closing brace"),
+        ])
+      ]);
+    });
 
     d.appDir({"foo": "1.2.3", "bar": "1.2.3"}).create();
 
diff --git a/test/snapshot/recompiles_if_the_sdk_is_out_of_date_test.dart b/test/snapshot/recompiles_if_the_sdk_is_out_of_date_test.dart
index 7712798d..41870c7f 100644
--- a/test/snapshot/recompiles_if_the_sdk_is_out_of_date_test.dart
+++ b/test/snapshot/recompiles_if_the_sdk_is_out_of_date_test.dart
@@ -15,9 +15,11 @@ main() {
   initConfig();
   integration("creates a snapshot for an immediate dependency's executables",
       () {
-    servePackages([packageMap("foo", "5.6.7")], contents: [
-      d.dir("bin", [d.file("hello.dart", "void main() => print('hello!');")])
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "5.6.7", contents: [
+        d.dir("bin", [d.file("hello.dart", "void main() => print('hello!');")])
+      ]);
+    });
 
     d.appDir({"foo": "5.6.7"}).create();
 
diff --git a/test/snapshot/snapshots_transformed_code_test.dart b/test/snapshot/snapshots_transformed_code_test.dart
index 38018ced..7c35cdc3 100644
--- a/test/snapshot/snapshots_transformed_code_test.dart
+++ b/test/snapshot/snapshots_transformed_code_test.dart
@@ -32,19 +32,23 @@ class ReplaceTransformer extends Transformer {
 main() {
   initConfig();
   integration("snapshots the transformed version of an executable", () {
-    servePackages([
-      packageMap("foo", "1.2.3", {"barback": "any"})
-          ..addAll({'transformers': ['foo']})
-    ], contents: [
-      d.dir("lib", [d.file("foo.dart", REPLACE_TRANSFORMER)]),
-      d.dir("bin", [
-        d.file("hello.dart", """
+    servePackages((builder) {
+      builder.serveRepoPackage('barback');
+
+      builder.serve("foo", "1.2.3",
+          deps: {"barback": "any"},
+          pubspec: {'transformers': ['foo']},
+          contents: [
+        d.dir("lib", [d.file("foo.dart", REPLACE_TRANSFORMER)]),
+        d.dir("bin", [
+          d.file("hello.dart", """
 final message = 'REPLACE ME';
 
 void main() => print(message);
 """),
-      ])
-    ], serveBarback: true);
+        ])
+      ]);
+    });
 
     d.appDir({"foo": "1.2.3"}).create();
 
diff --git a/test/snapshot/upgrades_snapshot_for_dependency_test.dart b/test/snapshot/upgrades_snapshot_for_dependency_test.dart
index f25d4768..36e4471a 100644
--- a/test/snapshot/upgrades_snapshot_for_dependency_test.dart
+++ b/test/snapshot/upgrades_snapshot_for_dependency_test.dart
@@ -13,19 +13,22 @@ import '../test_pub.dart';
 main() {
   initConfig();
   integration("upgrades a snapshot when a dependency is upgraded", () {
-    servePackages([
-      packageMap("foo", "1.2.3", {"bar": "any"}),
-      packageMap("bar", "1.2.3")
-    ], contents: [
-      d.dir("lib", [d.file("bar.dart", "final message = 'hello!';")]),
-      d.dir("bin", [
-        d.file("hello.dart", """
+    servePackages((builder) {
+      builder.serve("foo", "1.2.3", pubspec: {
+        "dependencies": {"bar": "any"}
+      }, contents: [
+        d.dir("bin", [
+          d.file("hello.dart", """
 import 'package:bar/bar.dart';
 
 void main() => print(message);
 """)
-      ])
-    ]);
+        ])
+      ]);
+      builder.serve("bar", "1.2.3", contents: [
+        d.dir("lib", [d.file("bar.dart", "final message = 'hello!';")])
+      ]);
+    });
 
     d.appDir({"foo": "any"}).create();
 
@@ -35,12 +38,11 @@ void main() => print(message);
       d.matcherFile('hello.dart.snapshot', contains('hello!'))
     ]).validate();
 
-    servePackages([
-      packageMap("foo", "1.2.3", {"bar": "any"}),
-      packageMap("bar", "1.2.4")
-    ], contents: [
-      d.dir("lib", [d.file("bar.dart", "final message = 'hello 2!';")]),
-    ], replace: true);
+    servePackages((builder) {
+      builder.serve("bar", "1.2.4", contents: [
+        d.dir("lib", [d.file("bar.dart", "final message = 'hello 2!';")]),
+      ]);
+    });
 
     pubUpgrade(output: contains("Precompiled foo:hello."));
 
diff --git a/test/snapshot/upgrades_snapshot_test.dart b/test/snapshot/upgrades_snapshot_test.dart
index 35316821..10aefb6b 100644
--- a/test/snapshot/upgrades_snapshot_test.dart
+++ b/test/snapshot/upgrades_snapshot_test.dart
@@ -13,11 +13,13 @@ import '../test_pub.dart';
 main() {
   initConfig();
   integration("upgrades a snapshot when its package is upgraded", () {
-    servePackages([packageMap("foo", "1.2.3")], contents: [
-      d.dir("bin", [
-        d.file("hello.dart", "void main() => print('hello!');")
-      ])
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.2.3", contents: [
+        d.dir("bin", [
+          d.file("hello.dart", "void main() => print('hello!');")
+        ])
+      ]);
+    });
 
     d.appDir({"foo": "any"}).create();
 
@@ -27,11 +29,13 @@ main() {
       d.matcherFile('hello.dart.snapshot', contains('hello!'))
     ]).validate();
 
-    servePackages([packageMap("foo", "1.2.4")], contents: [
-      d.dir("bin", [
-        d.file("hello.dart", "void main() => print('hello 2!');")
-      ])
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.2.4", contents: [
+        d.dir("bin", [
+          d.file("hello.dart", "void main() => print('hello 2!');")
+        ])
+      ]);
+    });
 
     pubUpgrade(output: contains("Precompiled foo:hello."));
 
diff --git a/test/test_pub.dart b/test/test_pub.dart
index ff5d9f9d..0c3121f4 100644
--- a/test/test_pub.dart
+++ b/test/test_pub.dart
@@ -45,6 +45,9 @@ import '../lib/src/utils.dart';
 import '../lib/src/validator.dart';
 import '../lib/src/version.dart';
 import 'descriptor.dart' as d;
+import 'serve_packages.dart';
+
+export 'serve_packages.dart';
 
 /// This should be called at the top of a test file to set up an appropriate
 /// test configuration for the machine running the tests.
@@ -222,139 +225,6 @@ Future _closeServer() {
 /// `true` if the current test spins up an HTTP server.
 bool _hasServer = false;
 
-/// The [d.DirectoryDescriptor] describing the server layout of `/api/packages`
-/// on the test server.
-///
-/// This contains metadata for packages that are being served via
-/// [servePackages]. It's `null` if [servePackages] has not yet been called for
-/// this test.
-d.DirectoryDescriptor _servedApiPackageDir;
-
-/// The [d.DirectoryDescriptor] describing the server layout of `/packages` on
-/// the test server.
-///
-/// This contains the tarballs for packages that are being served via
-/// [servePackages]. It's `null` if [servePackages] has not yet been called for
-/// this test.
-d.DirectoryDescriptor _servedPackageDir;
-
-/// A map from package names to parsed pubspec maps for those packages.
-///
-/// This represents the packages currently being served by [servePackages], and
-/// is `null` if [servePackages] has not yet been called for this test.
-Map<String, List<Map>> _servedPackages;
-
-/// Creates an HTTP server that replicates the structure of pub.dartlang.org.
-///
-/// [pubspecs] is a list of unserialized pubspecs representing the packages to
-/// serve.
-///
-/// If [replace] is false, subsequent calls to [servePackages] will add to the
-/// set of packages that are being served. Previous packages will continue to be
-/// served. Otherwise, the previous packages will no longer be served.
-///
-/// If [contents] is given, its contents are added to every served
-/// package.
-///
-/// If [serveBarback] is true, the repo versions of barback and its dependencies
-/// will be served as well.
-void servePackages(List<Map> pubspecs, {bool replace: false,
-    Iterable<d.Descriptor> contents, bool serveBarback: false}) {
-  if (_servedPackages == null || _servedPackageDir == null) {
-    _servedPackages = <String, List<Map>>{};
-    _servedApiPackageDir = d.dir('packages', []);
-    _servedPackageDir = d.dir('packages', []);
-    serve([
-      d.dir('api', [_servedApiPackageDir]),
-      _servedPackageDir
-    ]);
-
-    currentSchedule.onComplete.schedule(() {
-      _servedPackages = null;
-      _servedApiPackageDir = null;
-      _servedPackageDir = null;
-    }, 'cleaning up served packages');
-  }
-
-  schedule(() {
-    return awaitObject(pubspecs).then((resolvedPubspecs) {
-      if (replace) _servedPackages.clear();
-
-      for (var pubspec in resolvedPubspecs) {
-        var name = pubspec['name'];
-        var version = pubspec['version'];
-        var versions = _servedPackages.putIfAbsent(name, () => []);
-        versions.add(pubspec);
-      }
-
-      var repoPackages = new Set();
-      if (serveBarback) {
-        _addPackage(name) {
-          if (_servedPackages.containsKey(name)) return;
-          repoPackages.add(name);
-
-          var pubspec = new Map.from(loadYaml(
-              readTextFile(path.join(repoRoot, 'pkg', name, 'pubspec.yaml'))));
-
-          // Remove any SDK constraints since we don't have a valid SDK version
-          // while testing.
-          pubspec.remove('environment');
-
-          _servedPackages[name] = [pubspec];
-          if (pubspec.containsKey('dependencies')) {
-            pubspec['dependencies'].keys.forEach(_addPackage);
-          }
-        }
-
-        _addPackage('barback');
-      }
-
-      _servedApiPackageDir.contents.clear();
-      _servedPackageDir.contents.clear();
-      for (var name in _servedPackages.keys) {
-        _servedApiPackageDir.contents.addAll([
-          d.file('$name', JSON.encode({
-            'name': name,
-            'uploaders': ['nweiz@google.com'],
-            'versions': _servedPackages[name].map(packageVersionApiMap).toList()
-          })),
-          d.dir(name, [
-            d.dir('versions', _servedPackages[name].map((pubspec) {
-              return d.file(pubspec['version'], JSON.encode(
-                  packageVersionApiMap(pubspec, full: true)));
-            }))
-          ])
-        ]);
-
-        _servedPackageDir.contents.add(d.dir(name, [
-          d.dir('versions', _servedPackages[name].map((pubspec) {
-            var version = pubspec['version'];
-
-            if (repoPackages.contains(name)) {
-              return d.tar('$version.tar.gz', [
-                d.file('pubspec.yaml', JSON.encode(pubspec)),
-                new d.DirectoryDescriptor.fromFilesystem('lib',
-                    path.join(repoRoot, 'pkg', name, 'lib'))
-              ]);
-            }
-
-            var archiveContents = [
-                d.file('pubspec.yaml', JSON.encode(pubspec)),
-                d.libDir(name, '$name $version')
-            ];
-
-            if (contents != null) {
-              archiveContents.addAll(contents);
-            }
-
-            return d.tar('$version.tar.gz', archiveContents);
-          }))
-        ]));
-      }
-    });
-  }, 'initializing the package server');
-}
-
 /// Converts [value] into a YAML string.
 String yaml(value) => JSON.encode(value);
 
@@ -778,7 +648,7 @@ void makeGlobalPackage(String package, String version,
     Iterable<d.Descriptor> contents, {Iterable<String> pkg,
     Map<String, String> hosted}) {
   // Start the server so we know what port to use in the cache directory name.
-  servePackages([]);
+  serveNoPackages();
 
   // Create the package in the hosted cache.
   d.hostedCache([
diff --git a/test/upgrade/dry_run_does_not_apply_changes_test.dart b/test/upgrade/dry_run_does_not_apply_changes_test.dart
index da950b58..6747a447 100644
--- a/test/upgrade/dry_run_does_not_apply_changes_test.dart
+++ b/test/upgrade/dry_run_does_not_apply_changes_test.dart
@@ -12,10 +12,10 @@ import '../test_pub.dart';
 main() {
   initConfig();
   integration("--dry-run shows report but does not apply changes", () {
-    servePackages([
-      packageMap("foo", "1.0.0"),
-      packageMap("foo", "2.0.0"),
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.0.0");
+      builder.serve("foo", "2.0.0");
+    });
 
     // Create the first lockfile.
     d.appDir({
diff --git a/test/upgrade/hosted/unlock_dependers_test.dart b/test/upgrade/hosted/unlock_dependers_test.dart
index b217321b..e82146ae 100644
--- a/test/upgrade/hosted/unlock_dependers_test.dart
+++ b/test/upgrade/hosted/unlock_dependers_test.dart
@@ -11,10 +11,10 @@ main() {
   initConfig();
   integration("upgrades a locked package's dependers in order to get it to max "
       "version", () {
-    servePackages([
-      packageMap("foo", "1.0.0", {"bar": "<2.0.0"}),
-      packageMap("bar", "1.0.0")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.0.0", deps: {"bar": "<2.0.0"});
+      builder.serve("bar", "1.0.0");
+    });
 
     d.appDir({"foo": "any", "bar": "any"}).create();
 
@@ -25,10 +25,10 @@ main() {
       "bar": "1.0.0"
     }).validate();
 
-    servePackages([
-      packageMap("foo", "2.0.0", {"bar": "<3.0.0"}),
-      packageMap("bar", "2.0.0")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "2.0.0", deps: {"bar": "<3.0.0"});
+      builder.serve("bar", "2.0.0");
+    });
 
     pubUpgrade(args: ['bar']);
 
diff --git a/test/upgrade/hosted/unlock_if_necessary_test.dart b/test/upgrade/hosted/unlock_if_necessary_test.dart
index 7de20619..76edd983 100644
--- a/test/upgrade/hosted/unlock_if_necessary_test.dart
+++ b/test/upgrade/hosted/unlock_if_necessary_test.dart
@@ -11,10 +11,10 @@ main() {
   initConfig();
   integration("upgrades one locked pub server package's dependencies if it's "
       "necessary", () {
-    servePackages([
-      packageMap("foo", "1.0.0", {"foo_dep": "any"}),
-      packageMap("foo_dep", "1.0.0")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.0.0", deps: {"foo_dep": "any"});
+      builder.serve("foo_dep", "1.0.0");
+    });
 
     d.appDir({"foo": "any"}).create();
 
@@ -25,10 +25,10 @@ main() {
       "foo_dep": "1.0.0"
     }).validate();
 
-    servePackages([
-      packageMap("foo", "2.0.0", {"foo_dep": ">1.0.0"}),
-      packageMap("foo_dep", "2.0.0")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "2.0.0", deps: {"foo_dep": ">1.0.0"});
+      builder.serve("foo_dep", "2.0.0");
+    });
 
     pubUpgrade(args: ['foo']);
 
diff --git a/test/upgrade/hosted/upgrade_removed_constraints_test.dart b/test/upgrade/hosted/upgrade_removed_constraints_test.dart
index 3dea9766..d641cd25 100644
--- a/test/upgrade/hosted/upgrade_removed_constraints_test.dart
+++ b/test/upgrade/hosted/upgrade_removed_constraints_test.dart
@@ -10,12 +10,12 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration("upgrades dependencies whose constraints have been removed", () {
-    servePackages([
-      packageMap("foo", "1.0.0", {"shared-dep": "any"}),
-      packageMap("bar", "1.0.0", {"shared-dep": "<2.0.0"}),
-      packageMap("shared-dep", "1.0.0"),
-      packageMap("shared-dep", "2.0.0")
-    ]);
+    servePackages((builder) {
+      builder.serve("foo", "1.0.0", deps: {"shared-dep": "any"});
+      builder.serve("bar", "1.0.0", deps: {"shared-dep": "<2.0.0"});
+      builder.serve("shared-dep", "1.0.0");
+      builder.serve("shared-dep", "2.0.0");
+    });
 
     d.appDir({"foo": "any", "bar": "any"}).create();
 
diff --git a/test/upgrade/report/describes_change_test.dart b/test/upgrade/report/describes_change_test.dart
index cc84127f..18110fc4 100644
--- a/test/upgrade/report/describes_change_test.dart
+++ b/test/upgrade/report/describes_change_test.dart
@@ -10,12 +10,12 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration("shows how package changed from previous lockfile", () {
-    servePackages([
-      packageMap("unchanged", "1.0.0"),
-      packageMap("version_changed", "1.0.0"),
-      packageMap("version_changed", "2.0.0"),
-      packageMap("source_changed", "1.0.0")
-    ]);
+    servePackages((builder) {
+      builder.serve("unchanged", "1.0.0");
+      builder.serve("version_changed", "1.0.0");
+      builder.serve("version_changed", "2.0.0");
+      builder.serve("source_changed", "1.0.0");
+    });
 
     d.dir("source_changed", [
       d.libDir("source_changed"),
diff --git a/test/upgrade/report/does_not_show_newer_versions_for_locked_packages_test.dart b/test/upgrade/report/does_not_show_newer_versions_for_locked_packages_test.dart
index 1473fe18..25206786 100644
--- a/test/upgrade/report/does_not_show_newer_versions_for_locked_packages_test.dart
+++ b/test/upgrade/report/does_not_show_newer_versions_for_locked_packages_test.dart
@@ -11,14 +11,14 @@ main() {
   initConfig();
   integration("does not show how many newer versions are available for "
       "packages that are locked and not being upgraded", () {
-    servePackages([
-      packageMap("not_upgraded", "1.0.0"),
-      packageMap("not_upgraded", "2.0.0"),
-      packageMap("not_upgraded", "3.0.0-dev"),
-      packageMap("upgraded", "1.0.0"),
-      packageMap("upgraded", "2.0.0"),
-      packageMap("upgraded", "3.0.0-dev")
-    ]);
+    servePackages((builder) {
+      builder.serve("not_upgraded", "1.0.0");
+      builder.serve("not_upgraded", "2.0.0");
+      builder.serve("not_upgraded", "3.0.0-dev");
+      builder.serve("upgraded", "1.0.0");
+      builder.serve("upgraded", "2.0.0");
+      builder.serve("upgraded", "3.0.0-dev");
+    });
 
     // Constraint everything to the first version.
     d.appDir({
diff --git a/test/upgrade/report/highlights_overrides_test.dart b/test/upgrade/report/highlights_overrides_test.dart
index b91cd083..b33e1ed9 100644
--- a/test/upgrade/report/highlights_overrides_test.dart
+++ b/test/upgrade/report/highlights_overrides_test.dart
@@ -10,9 +10,7 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration("highlights overridden packages", () {
-    servePackages([
-      packageMap("overridden", "1.0.0")
-    ]);
+    servePackages((builder) => builder.serve("overridden", "1.0.0"));
 
     d.dir(appPath, [
       d.pubspec({
diff --git a/test/upgrade/report/leading_character_shows_change_test.dart b/test/upgrade/report/leading_character_shows_change_test.dart
index 3d94d7a5..eef1946d 100644
--- a/test/upgrade/report/leading_character_shows_change_test.dart
+++ b/test/upgrade/report/leading_character_shows_change_test.dart
@@ -10,17 +10,17 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration("the character before each package describes the change", () {
-    servePackages([
-      packageMap("added", "1.0.0"),
-      packageMap("downgraded", "1.0.0"),
-      packageMap("downgraded", "2.0.0"),
-      packageMap("overridden", "1.0.0"),
-      packageMap("removed", "1.0.0"),
-      packageMap("source_changed", "1.0.0"),
-      packageMap("upgraded", "1.0.0"),
-      packageMap("upgraded", "2.0.0"),
-      packageMap("unchanged", "1.0.0")
-    ]);
+    servePackages((builder) {
+      builder.serve("added", "1.0.0");
+      builder.serve("downgraded", "1.0.0");
+      builder.serve("downgraded", "2.0.0");
+      builder.serve("overridden", "1.0.0");
+      builder.serve("removed", "1.0.0");
+      builder.serve("source_changed", "1.0.0");
+      builder.serve("upgraded", "1.0.0");
+      builder.serve("upgraded", "2.0.0");
+      builder.serve("unchanged", "1.0.0");
+    });
 
     d.dir("description_changed_1", [
       d.libDir("description_changed"),
diff --git a/test/upgrade/report/shows_newer_available_versions_test.dart b/test/upgrade/report/shows_newer_available_versions_test.dart
index 18d4f761..99364476 100644
--- a/test/upgrade/report/shows_newer_available_versions_test.dart
+++ b/test/upgrade/report/shows_newer_available_versions_test.dart
@@ -10,23 +10,23 @@ import '../../test_pub.dart';
 main() {
   initConfig();
   integration("shows how many newer versions are available", () {
-    servePackages([
-      packageMap("multiple_newer", "1.0.0"),
-      packageMap("multiple_newer", "1.0.1-unstable.1"),
-      packageMap("multiple_newer", "1.0.1"),
-      packageMap("multiple_newer", "1.0.2-unstable.1"),
-      packageMap("multiple_newer_stable", "1.0.0"),
-      packageMap("multiple_newer_stable", "1.0.1"),
-      packageMap("multiple_newer_stable", "1.0.2"),
-      packageMap("multiple_newer_unstable", "1.0.0"),
-      packageMap("multiple_newer_unstable", "1.0.1-unstable.1"),
-      packageMap("multiple_newer_unstable", "1.0.1-unstable.2"),
-      packageMap("no_newer", "1.0.0"),
-      packageMap("one_newer_unstable", "1.0.0"),
-      packageMap("one_newer_unstable", "1.0.1-unstable.1"),
-      packageMap("one_newer_stable", "1.0.0"),
-      packageMap("one_newer_stable", "1.0.1")
-    ]);
+    servePackages((builder) {
+      builder.serve("multiple_newer", "1.0.0");
+      builder.serve("multiple_newer", "1.0.1-unstable.1");
+      builder.serve("multiple_newer", "1.0.1");
+      builder.serve("multiple_newer", "1.0.2-unstable.1");
+      builder.serve("multiple_newer_stable", "1.0.0");
+      builder.serve("multiple_newer_stable", "1.0.1");
+      builder.serve("multiple_newer_stable", "1.0.2");
+      builder.serve("multiple_newer_unstable", "1.0.0");
+      builder.serve("multiple_newer_unstable", "1.0.1-unstable.1");
+      builder.serve("multiple_newer_unstable", "1.0.1-unstable.2");
+      builder.serve("no_newer", "1.0.0");
+      builder.serve("one_newer_unstable", "1.0.0");
+      builder.serve("one_newer_unstable", "1.0.1-unstable.1");
+      builder.serve("one_newer_stable", "1.0.0");
+      builder.serve("one_newer_stable", "1.0.1");
+    });
 
     // Constraint everything to the first version.
     d.appDir({
diff --git a/test/upgrade/report/shows_number_of_changed_dependencies_test.dart b/test/upgrade/report/shows_number_of_changed_dependencies_test.dart
index 77010e2c..ebbe2ee7 100644
--- a/test/upgrade/report/shows_number_of_changed_dependencies_test.dart
+++ b/test/upgrade/report/shows_number_of_changed_dependencies_test.dart
@@ -11,11 +11,11 @@ main() {
   initConfig();
   integration("does not show how many newer versions are available for "
       "packages that are locked and not being upgraded", () {
-    servePackages([
-      packageMap("a", "1.0.0"),
-      packageMap("b", "1.0.0"),
-      packageMap("c", "2.0.0")
-    ]);
+    servePackages((builder) {
+      builder.serve("a", "1.0.0");
+      builder.serve("b", "1.0.0");
+      builder.serve("c", "2.0.0");
+    });
 
     d.appDir({
       "a": "any"
-- 
GitLab