Print a warning when running "pub build" and "pub serve" (#1832)

Closes #1823
diff --git a/lib/src/command/barback.dart b/lib/src/command/barback.dart
index 4a9e296..505f111 100644
--- a/lib/src/command/barback.dart
+++ b/lib/src/command/barback.dart
@@ -83,6 +83,11 @@
     log.json.enabled =
         argResults.options.contains("format") && argResults["format"] == "json";
 
+    log.warning(
+        log.yellow("Dart 2 will have a new build system. Learn how to migrate "
+            "from ${log.bold('pub build')} and\n"
+            "${log.bold('pub serve')}: https://webdev.dartlang.org/dart-2\n"));
+
     _parseSourceDirectories();
     return onRunTransformerCommand();
   }
diff --git a/lib/src/log.dart b/lib/src/log.dart
index e744a49..4fc4b81 100644
--- a/lib/src/log.dart
+++ b/lib/src/log.dart
@@ -491,33 +491,46 @@
 /// that supports that.
 ///
 /// Use this to highlight something interesting but neither good nor bad.
-String cyan(text) => sparkle ? "$text" : "$_cyan$text$_noColor";
+String cyan(text) => _addColor(text, _cyan);
 
 /// Wraps [text] in the ANSI escape codes to color it green when on a platform
 /// that supports that.
 ///
 /// Use this to highlight something successful or otherwise positive.
-String green(text) => sparkle ? "$text" : "$_green$text$_noColor";
+String green(text) => _addColor(text, _green);
 
 /// Wraps [text] in the ANSI escape codes to color it magenta when on a
 /// platform that supports that.
 ///
 /// Use this to highlight something risky that the user should be aware of but
 /// may intend to do.
-String magenta(text) => sparkle ? "$text" : "$_magenta$text$_noColor";
+String magenta(text) => _addColor(text, _magenta);
 
 /// Wraps [text] in the ANSI escape codes to color it red when on a platform
 /// that supports that.
 ///
 /// Use this to highlight unequivocal errors, problems, or failures.
-String red(text) => sparkle ? "$text" : "$_red$text$_noColor";
+String red(text) => _addColor(text, _red);
 
 /// Wraps [text] in the ANSI escape codes to color it yellow when on a platform
 /// that supports that.
 ///
 /// Use this to highlight warnings, cautions or other things that are bad but
 /// do not prevent the user's goal from being reached.
-String yellow(text) => sparkle ? "$text" : "$_yellow$text$_noColor";
+String yellow(text) => _addColor(text, _yellow);
+
+/// Returns [text] colored using the given [colorCode].
+///
+/// This is resilient to the text containing other colors or bold text.
+String _addColor(Object text, String colorCode) {
+  if (sparkle) return text.toString();
+  return colorCode +
+      text
+          .toString()
+          .replaceAll(_none, _none + colorCode)
+          .replaceAll(_noColor, _none + colorCode) +
+      _noColor;
+}
 
 /// Log function that prints the message to stdout.
 void _logToStdout(Entry entry) {
diff --git a/test/barback/utils.dart b/test/barback/utils.dart
index 956406d..69ccfe3 100644
--- a/test/barback/utils.dart
+++ b/test/barback/utils.dart
@@ -37,9 +37,12 @@
   Object serveExpectation = serveError;
   if (exitCode == exit_codes.USAGE) {
     buildExpectation =
-        allOf(startsWith(buildExpectation), contains("Usage: pub build"));
+        allOf(contains(buildExpectation), contains("Usage: pub build"));
     serveExpectation =
-        allOf(startsWith(serveExpectation), contains("Usage: pub serve"));
+        allOf(contains(serveExpectation), contains("Usage: pub serve"));
+  } else {
+    buildExpectation = contains(buildExpectation);
+    serveExpectation = contains(serveExpectation);
   }
 
   test("build fails $description", () {
diff --git a/test/compiler/does_not_support_invalid_command_line_options_type_test.dart b/test/compiler/does_not_support_invalid_command_line_options_type_test.dart
index a7827f6..f6d3554 100644
--- a/test/compiler/does_not_support_invalid_command_line_options_type_test.dart
+++ b/test/compiler/does_not_support_invalid_command_line_options_type_test.dart
@@ -30,10 +30,10 @@
     await requestShould404("main.dart.js");
     expect(
         server.stderr,
-        emitsLines('Build error:\n'
+        emitsThrough(emitsLines('Build error:\n'
             'Transform Dart2JS on myapp|web/main.dart threw error: '
             'Invalid value for \$dart2js.commandLineOptions: '
-            '"foo" (expected list of strings).'));
+            '"foo" (expected list of strings).')));
     await endPubServe();
   });
 }
diff --git a/test/compiler/does_not_support_invalid_environment_type_test.dart b/test/compiler/does_not_support_invalid_environment_type_test.dart
index efbb074..0093464 100644
--- a/test/compiler/does_not_support_invalid_environment_type_test.dart
+++ b/test/compiler/does_not_support_invalid_environment_type_test.dart
@@ -30,10 +30,10 @@
     await requestShould404("main.dart.js");
     expect(
         server.stderr,
-        emitsLines('Build error:\n'
+        emitsThrough(emitsLines('Build error:\n'
             'Transform Dart2JS on myapp|web/main.dart threw error: '
             'Invalid value for \$dart2js.environment: "foo" '
-            '(expected map from strings to strings).'));
+            '(expected map from strings to strings).')));
     await endPubServe();
   });
 }
diff --git a/test/compiler/does_not_support_invalid_option_test.dart b/test/compiler/does_not_support_invalid_option_test.dart
index 7bf1642..3a3e7d7 100644
--- a/test/compiler/does_not_support_invalid_option_test.dart
+++ b/test/compiler/does_not_support_invalid_option_test.dart
@@ -28,8 +28,8 @@
     // TODO(nweiz): This should provide more context about how the option got
     // passed to dart2js. See issue 16008.
     var pub = await startPubServe();
-    await expect(
-        pub.stderr, emits('Unrecognized dart2js option "invalidOption".'));
+    await expect(pub.stderr,
+        emitsThrough('Unrecognized dart2js option "invalidOption".'));
     await pub.shouldExit(exit_codes.DATA);
   });
 }
diff --git a/test/compiler/doesnt_support_invalid_type_for_boolean_option_test.dart b/test/compiler/doesnt_support_invalid_type_for_boolean_option_test.dart
index a4654b7..ee727ea 100644
--- a/test/compiler/doesnt_support_invalid_type_for_boolean_option_test.dart
+++ b/test/compiler/doesnt_support_invalid_type_for_boolean_option_test.dart
@@ -29,10 +29,10 @@
     await requestShould404("main.dart.js");
     expect(
         server.stderr,
-        emitsLines('Build error:\n'
+        emitsThrough(emitsLines('Build error:\n'
             'Transform Dart2JS on myapp|web/main.dart threw error: '
             'Invalid value for \$dart2js.checked: "foo" '
-            '(expected true or false).'));
+            '(expected true or false).')));
     await endPubServe();
   });
 }
diff --git a/test/compiler/reports_dart_parse_errors_test.dart b/test/compiler/reports_dart_parse_errors_test.dart
index 1c7bced..cf66716 100644
--- a/test/compiler/reports_dart_parse_errors_test.dart
+++ b/test/compiler/reports_dart_parse_errors_test.dart
@@ -107,5 +107,6 @@
 
   // It's nondeterministic what order the dart2js transformers start running,
   // so we allow the error messages to be emitted in either order.
-  await expectLater(pub.stderr, emitsInAnyOrder([consumeFile, consumeSubfile]));
+  await expectLater(
+      pub.stderr, emitsThrough(emitsInAnyOrder([consumeFile, consumeSubfile])));
 }
diff --git a/test/transformer/a_transformer_rejects_its_config_test.dart b/test/transformer/a_transformer_rejects_its_config_test.dart
index 7491eef..de1e06a 100644
--- a/test/transformer/a_transformer_rejects_its_config_test.dart
+++ b/test/transformer/a_transformer_rejects_its_config_test.dart
@@ -46,7 +46,7 @@
     var pub = await startPubServe();
     expect(
         pub.stderr,
-        emits(endsWith('Error loading transformer: I hate these '
+        emitsThrough(endsWith('Error loading transformer: I hate these '
             'settings!')));
     await pub.shouldExit(1);
   });
diff --git a/test/transformer/asset_not_found_exceptions_are_detectable_test.dart b/test/transformer/asset_not_found_exceptions_are_detectable_test.dart
index 6413744..7f19996 100644
--- a/test/transformer/asset_not_found_exceptions_are_detectable_test.dart
+++ b/test/transformer/asset_not_found_exceptions_are_detectable_test.dart
@@ -59,6 +59,6 @@
 
     // Since the AssetNotFoundException was caught and handled, the server
     // shouldn't print any error information for it.
-    expect(server.stderr, emitsDone);
+    expect(server.stderr, neverEmits(contains("nonexistent")));
   });
 }
diff --git a/test/transformer/can_log_messages_test.dart b/test/transformer/can_log_messages_test.dart
index c4ceb82..81c176e 100644
--- a/test/transformer/can_log_messages_test.dart
+++ b/test/transformer/can_log_messages_test.dart
@@ -61,10 +61,10 @@
 [Rewrite on myapp|web/foo.txt]:
 info!"""));
 
-    expect(pub.stderr, emitsLines("""
+    expect(pub.stderr, emitsThrough(emitsLines("""
 [Rewrite on myapp|web/foo.txt with input myapp|web/foo.foo]:
 Warning!
-[Rewrite on myapp|web/foo.txt]:"""));
+[Rewrite on myapp|web/foo.txt]:""")));
 
     // The details of the analyzer's error message change pretty frequently,
     // so instead of validating the entire line, just look for a couple of
diff --git a/test/transformer/fails_to_load_a_file_that_defines_no_transforms_test.dart b/test/transformer/fails_to_load_a_file_that_defines_no_transforms_test.dart
index b42ec10..12e8255 100644
--- a/test/transformer/fails_to_load_a_file_that_defines_no_transforms_test.dart
+++ b/test/transformer/fails_to_load_a_file_that_defines_no_transforms_test.dart
@@ -23,7 +23,8 @@
 
     await pubGet();
     var pub = await startPubServe();
-    expect(pub.stderr, emits(startsWith('No transformers were defined in ')));
+    expect(pub.stderr,
+        emitsThrough(startsWith('No transformers were defined in ')));
     expect(pub.stderr, emits(startsWith('required by myapp.')));
     expect(pub.stderrStream(),
         neverEmits(contains('This is an unexpected error')));
diff --git a/test/transformer/fails_to_load_a_non_existent_transform_test.dart b/test/transformer/fails_to_load_a_non_existent_transform_test.dart
index 9d61745..281d1f8 100644
--- a/test/transformer/fails_to_load_a_non_existent_transform_test.dart
+++ b/test/transformer/fails_to_load_a_non_existent_transform_test.dart
@@ -19,8 +19,10 @@
 
     await pubGet();
     var pub = await startPubServe();
-    expect(pub.stderr,
-        emits('Transformer library "package:myapp/transform.dart" not found.'));
+    expect(
+        pub.stderr,
+        emitsThrough(
+            'Transformer library "package:myapp/transform.dart" not found.'));
     await pub.shouldExit(1);
   });
 }
diff --git a/test/transformer/fails_to_load_a_pubspec_with_reserved_transformer_test.dart b/test/transformer/fails_to_load_a_pubspec_with_reserved_transformer_test.dart
index 4393e4a..ae0442b 100644
--- a/test/transformer/fails_to_load_a_pubspec_with_reserved_transformer_test.dart
+++ b/test/transformer/fails_to_load_a_pubspec_with_reserved_transformer_test.dart
@@ -29,7 +29,7 @@
     var pub = await startPubServe();
     expect(
         pub.stderr,
-        emits(contains('Invalid transformer config: Unsupported '
+        emitsThrough(contains('Invalid transformer config: Unsupported '
             'built-in transformer \$nonexistent.')));
     await pub.shouldExit(exit_codes.DATA);
   });
diff --git a/test/transformer/fails_to_load_a_transform_from_a_deps_dev_dependency_test.dart b/test/transformer/fails_to_load_a_transform_from_a_deps_dev_dependency_test.dart
index ed69ec7..ac5c3c9 100644
--- a/test/transformer/fails_to_load_a_transform_from_a_deps_dev_dependency_test.dart
+++ b/test/transformer/fails_to_load_a_transform_from_a_deps_dev_dependency_test.dart
@@ -46,7 +46,7 @@
     var pub = await startPubServe();
     expect(
         pub.stderr,
-        emits(contains('Error loading transformer "bar": package '
+        emitsThrough(contains('Error loading transformer "bar": package '
             '"bar" is not a dependency.')));
     await pub.shouldExit(exit_codes.DATA);
   });
diff --git a/test/transformer/fails_to_load_a_transform_from_a_non_dependency_test.dart b/test/transformer/fails_to_load_a_transform_from_a_non_dependency_test.dart
index 5146565..8926104 100644
--- a/test/transformer/fails_to_load_a_transform_from_a_non_dependency_test.dart
+++ b/test/transformer/fails_to_load_a_transform_from_a_non_dependency_test.dart
@@ -21,7 +21,7 @@
 
     await pubGet();
     var pub = await startPubServe();
-    expect(pub.stderr, emits(contains('"foo" is not a dependency.')));
+    expect(pub.stderr, emitsThrough(contains('"foo" is not a dependency.')));
     await pub.shouldExit(exit_codes.DATA);
   });
 }
diff --git a/test/transformer/fails_to_load_a_transform_with_a_syntax_error_test.dart b/test/transformer/fails_to_load_a_transform_with_a_syntax_error_test.dart
index b30bb7b..dbc2f55 100644
--- a/test/transformer/fails_to_load_a_transform_with_a_syntax_error_test.dart
+++ b/test/transformer/fails_to_load_a_transform_with_a_syntax_error_test.dart
@@ -27,7 +27,7 @@
 
     await pubGet();
     var pub = await startPubServe();
-    expect(pub.stderr, emits(contains("unexpected token 'syntax'")));
+    expect(pub.stderr, emitsThrough(contains("unexpected token 'syntax'")));
     expect(pub.stderrStream(),
         neverEmits(contains('This is an unexpected error')));
     await pub.shouldExit(1);
diff --git a/test/transformer/fails_to_load_a_transform_with_an_import_error_test.dart b/test/transformer/fails_to_load_a_transform_with_an_import_error_test.dart
index 3815091..981d07e 100644
--- a/test/transformer/fails_to_load_a_transform_with_an_import_error_test.dart
+++ b/test/transformer/fails_to_load_a_transform_with_an_import_error_test.dart
@@ -28,7 +28,8 @@
 
     await pubGet();
     var pub = await startPubServe();
-    expect(pub.stderr, emits("Unable to spawn isolate: Unhandled exception:"));
+    expect(pub.stderr,
+        emitsThrough("Unable to spawn isolate: Unhandled exception:"));
     expect(pub.stderr, emits(startsWith('Could not import "')));
     await pub.shouldExit(1);
   });
diff --git a/test/transformer/fails_to_load_an_unconfigurable_transformer_when_config_is_passed_test.dart b/test/transformer/fails_to_load_an_unconfigurable_transformer_when_config_is_passed_test.dart
index fc31628..0977803 100644
--- a/test/transformer/fails_to_load_an_unconfigurable_transformer_when_config_is_passed_test.dart
+++ b/test/transformer/fails_to_load_an_unconfigurable_transformer_when_config_is_passed_test.dart
@@ -33,7 +33,7 @@
     var pub = await startPubServe();
     expect(
         pub.stderr,
-        emits(startsWith('No transformers that accept configuration '
+        emitsThrough(startsWith('No transformers that accept configuration '
             'were defined in ')));
     await pub.shouldExit(1);
   });
diff --git a/test/transformer/prints_a_transform_error_in_apply_test.dart b/test/transformer/prints_a_transform_error_in_apply_test.dart
index 02c851c..7ca6bde 100644
--- a/test/transformer/prints_a_transform_error_in_apply_test.dart
+++ b/test/transformer/prints_a_transform_error_in_apply_test.dart
@@ -42,8 +42,8 @@
     var server = await pubServe();
     await expectLater(
         server.stderr,
-        emitsLines('Build error:\n'
-            'Transform Rewrite on myapp|web/foo.txt threw error: oh no!'));
+        emitsThrough(emitsLines('Build error:\n'
+            'Transform Rewrite on myapp|web/foo.txt threw error: oh no!')));
     await endPubServe();
   });
 }
diff --git a/test/transformer/prints_a_transform_interface_error_test.dart b/test/transformer/prints_a_transform_interface_error_test.dart
index edfbbbb..dd2b9bc 100644
--- a/test/transformer/prints_a_transform_interface_error_test.dart
+++ b/test/transformer/prints_a_transform_interface_error_test.dart
@@ -40,9 +40,9 @@
     var server = await pubServe();
     await expectLater(
         server.stderr,
-        emitsLines("Build error:\n"
+        emitsThrough(emitsLines("Build error:\n"
             "Transform Rewrite on myapp|web/foo.txt threw error: Class "
-            "'RewriteTransformer' has no instance method 'apply'."));
+            "'RewriteTransformer' has no instance method 'apply'.")));
     await endPubServe();
   });
 }