Initial import
diff --git a/pkgs/coverage/.gitignore b/pkgs/coverage/.gitignore
new file mode 100644
index 0000000..5cd143d
--- /dev/null
+++ b/pkgs/coverage/.gitignore
@@ -0,0 +1,2 @@
+packages
+pubspec.lock
diff --git a/pkgs/coverage/AUTHORS b/pkgs/coverage/AUTHORS
new file mode 100644
index 0000000..f21345f
--- /dev/null
+++ b/pkgs/coverage/AUTHORS
@@ -0,0 +1,6 @@
+# Below is a list of people and organizations that have contributed
+# to the coverage project. Names should be added to the list like so:
+#
+#   Name/Organization <email address>
+
+Google Inc.
diff --git a/pkgs/coverage/LICENSE b/pkgs/coverage/LICENSE
new file mode 100644
index 0000000..7a4a3ea
--- /dev/null
+++ b/pkgs/coverage/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
\ No newline at end of file
diff --git a/pkgs/coverage/PATENTS b/pkgs/coverage/PATENTS
new file mode 100644
index 0000000..6954196
--- /dev/null
+++ b/pkgs/coverage/PATENTS
@@ -0,0 +1,23 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Dart Project.
+
+Google hereby grants to you a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this
+section) patent license to make, have made, use, offer to sell, sell,
+import, transfer, and otherwise run, modify and propagate the contents
+of this implementation of Dart, where such license applies only to
+those patent claims, both currently owned by Google and acquired in
+the future, licensable by Google that are necessarily infringed by
+this implementation of Dart. This grant does not include claims that
+would be infringed only as a consequence of further modification of
+this implementation. If you or your agent or exclusive licensee
+institute or order or agree to the institution of patent litigation
+against any entity (including a cross-claim or counterclaim in a
+lawsuit) alleging that this implementation of Dart or any code
+incorporated within this implementation of Dart constitutes direct or
+contributory patent infringement, or inducement of patent
+infringement, then any patent rights granted to you under this License
+for this implementation of Dart shall terminate as of the date such
+litigation is filed.
diff --git a/pkgs/coverage/README.md b/pkgs/coverage/README.md
new file mode 100644
index 0000000..d944aa2
--- /dev/null
+++ b/pkgs/coverage/README.md
@@ -0,0 +1,5 @@
+Coverage
+========
+
+Coverage provides coverage data manipulation and formatting for Dart.
+
diff --git a/pkgs/coverage/bin/format_coverage.dart b/pkgs/coverage/bin/format_coverage.dart
new file mode 100644
index 0000000..c44df8a
--- /dev/null
+++ b/pkgs/coverage/bin/format_coverage.dart
@@ -0,0 +1,502 @@
+// Copyright (c) 2013, 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.
+
+import "dart:async";
+import "dart:convert";
+import "dart:io";
+import "dart:isolate";
+
+import "package:args/args.dart";
+import "package:path/path.dart";
+
+/// [Environment] stores gathered arguments information.
+class Environment {
+  String sdkRoot;
+  String pkgRoot;
+  var input;
+  var output;
+  int workers;
+  bool prettyPrint;
+  bool lcov;
+  bool expectMarkers;
+  bool verbose;
+}
+
+/// [Resolver] resolves imports with respect to a given environment.
+class Resolver {
+  static const DART_PREFIX = "dart:";
+  static const PACKAGE_PREFIX = "package:";
+  static const FILE_PREFIX = "file://";
+  static const HTTP_PREFIX = "http://";
+
+  Map _env;
+  List failed = [];
+
+  Resolver(this._env);
+
+  /// Returns the absolute path wrt. to the given environment or null, if the
+  /// import could not be resolved.
+  resolve(String import) {
+    if (import.startsWith(DART_PREFIX)) {
+      if (_env["sdkRoot"] == null) {
+        // No sdk-root given, do not resolve dart: URIs.
+        return null;
+      }
+      var slashPos = import.indexOf("/");
+      var filePath;
+      if (slashPos != -1) {
+        var path = import.substring(DART_PREFIX.length, slashPos);
+        // Drop patch files, since we don't have their source in the compiled
+        // SDK.
+        if (path.endsWith("-patch")) {
+          failed.add(import);
+          return null;
+        }
+        // Canonicalize path. For instance: _collection-dev => _collection_dev.
+        path = path.replaceAll("-", "_");
+        filePath = "${_env["sdkRoot"]}"
+                   "/${path}${import.substring(slashPos, import.length)}";
+      } else {
+        // Resolve 'dart:something' to be something/something.dart in the SDK.
+        var lib = import.substring(DART_PREFIX.length, import.length);
+        filePath = "${_env["sdkRoot"]}/${lib}/${lib}.dart";
+      }
+      return filePath;
+    }
+    if (import.startsWith(PACKAGE_PREFIX)) {
+      if (_env["pkgRoot"] == null) {
+        // No package-root given, do not resolve package: URIs.
+        return null;
+      }
+      var filePath =
+          "${_env["pkgRoot"]}"
+          "/${import.substring(PACKAGE_PREFIX.length, import.length)}";
+      return filePath;
+    }
+    if (import.startsWith(FILE_PREFIX)) {
+      var filePath = fromUri(Uri.parse(import));
+      return filePath;
+    }
+    if (import.startsWith(HTTP_PREFIX)) {
+      return import;
+    }
+    // We cannot deal with anything else.
+    failed.add(import);
+    return null;
+  }
+}
+
+/// Converts the given hitmap to lcov format and appends the result to
+/// env.output.
+///
+/// Returns a [Future] that completes as soon as all map entries have been
+/// emitted.
+Future lcov(Map hitmap) {
+  var emitOne = (key) {
+    var v = hitmap[key];
+    StringBuffer entry = new StringBuffer();
+    entry.write("SF:${key}\n");
+    v.keys.toList()
+          ..sort()
+          ..forEach((k) {
+      entry.write("DA:${k},${v[k]}\n");
+    });
+    entry.write("end_of_record\n");
+    env.output.write(entry.toString());
+    return new Future.value(null);
+  };
+
+  return Future.forEach(hitmap.keys, emitOne);
+}
+
+/// Converts the given hitmap to a pretty-print format and appends the result
+/// to env.output.
+///
+/// Returns a [Future] that completes as soon as all map entries have been
+/// emitted.
+Future prettyPrint(Map hitMap, List failedLoads) {
+  var emitOne = (key) {
+    var v = hitMap[key];
+    var c = new Completer();
+    loadResource(key).then((lines) {
+      if (lines == null) {
+        failedLoads.add(key);
+        c.complete();
+        return;
+      }
+      env.output.write("${key}\n");
+      for (var line = 1; line <= lines.length; line++) {
+        String prefix = "       ";
+        if (v.containsKey(line)) {
+          prefix = v[line].toString();
+          StringBuffer b = new StringBuffer();
+          for (int i = prefix.length; i < 7; i++) {
+            b.write(" ");
+          }
+          b.write(prefix);
+          prefix = b.toString();
+        }
+        env.output.write("${prefix}|${lines[line-1]}\n");
+      }
+      c.complete();
+    });
+    return c.future;
+  };
+
+  return Future.forEach(hitMap.keys, emitOne);
+}
+
+/// Load an import resource and return a [Future] with a [List] of its lines.
+/// Returns [null] instead of a list if the resource could not be loaded.
+Future<List> loadResource(String import) {
+  if (import.startsWith("http")) {
+    Completer c = new Completer();
+    HttpClient client = new HttpClient();
+    client.getUrl(Uri.parse(import))
+        .then((HttpClientRequest request) {
+          return request.close();
+        })
+        .then((HttpClientResponse response) {
+          response.transform(UTF8.decoder).toList().then((data) {
+            c.complete(data);
+            client.close();
+          });
+        })
+        .catchError((e) {
+          c.complete(null);
+        });
+    return c.future;
+  } else {
+    File f = new File(import);
+    return f.readAsLines()
+        .catchError((e) {
+          return new Future.value(null);
+        });
+  }
+}
+
+/// Creates a single hitmap from a raw json object. Throws away all entries that
+/// are not resolvable.
+Map createHitmap(String rawJson, Resolver resolver) {
+  Map<String, Map<int,int>> hitMap = {};
+
+  addToMap(source, line, count) {
+    if (!hitMap[source].containsKey(line)) {
+      hitMap[source][line] = 0;
+    }
+    hitMap[source][line] += count;
+  }
+
+  JSON.decode(rawJson)['coverage'].forEach((Map e) {
+    String source = resolver.resolve(e["source"]);
+    if (source == null) {
+      // Couldnt resolve import, so skip this entry.
+      return;
+    }
+    if (!hitMap.containsKey(source)) {
+      hitMap[source] = {};
+    }
+    var hits = e["hits"];
+    // hits is a flat array of the following format:
+    // [ <line|linerange>, <hitcount>,...]
+    // line: number.
+    // linerange: "<line>-<line>".
+    for (var i = 0; i < hits.length; i += 2) {
+      var k = hits[i];
+      if (k is num) {
+        // Single line.
+        addToMap(source, k, hits[i+1]);
+      }
+      if (k is String) {
+        // Linerange. We expand line ranges to actual lines at this point.
+        var splitPos = k.indexOf("-");
+        int start = int.parse(k.substring(0, splitPos));
+        int end = int.parse(k.substring(splitPos + 1, k.length));
+        for (var j = start; j <= end; j++) {
+          addToMap(source, j, hits[i+1]);
+        }
+      }
+    }
+  });
+  return hitMap;
+}
+
+/// Merges [newMap] into [result].
+mergeHitmaps(Map newMap, Map result) {
+  newMap.forEach((String file, Map v) {
+    if (result.containsKey(file)) {
+      v.forEach((int line, int cnt) {
+        if (result[file][line] == null) {
+          result[file][line] = cnt;
+        } else {
+          result[file][line] += cnt;
+        }
+      });
+    } else {
+      result[file] = v;
+    }
+  });
+}
+
+/// Given an absolute path absPath, this function returns a [List] of files
+/// are contained by it if it is a directory, or a [List] containing the file if
+/// it is a file.
+List filesToProcess(String absPath) {
+  var filePattern = new RegExp(r"^dart-cov-\d+-\d+.json$");
+  if (FileSystemEntity.isDirectorySync(absPath)) {
+    return new Directory(absPath).listSync(recursive: true)
+        .where((entity) => entity is File &&
+            filePattern.hasMatch(basename(entity.path)))
+        .toList();
+  }
+
+  return [new File(absPath)];
+}
+
+worker(WorkMessage msg) {
+  final start = new DateTime.now().millisecondsSinceEpoch;
+
+  var env = msg.environment;
+  List files = msg.files;
+  Resolver resolver = new Resolver(env);
+  var workerHitmap = {};
+  files.forEach((File fileEntry) {
+    // Read file sync, as it only contains 1 object.
+    String contents = fileEntry.readAsStringSync();
+    if (contents.length > 0) {
+      mergeHitmaps(createHitmap(contents, resolver), workerHitmap);
+    }
+  });
+
+  if (env["verbose"]) {
+    final end = new DateTime.now().millisecondsSinceEpoch;
+    print("${msg.workerName}: Finished processing ${files.length} files. "
+          "Took ${end - start} ms.");
+  }
+
+  msg.replyPort.send(new ResultMessage(workerHitmap, resolver.failed));
+}
+
+class WorkMessage {
+  final String workerName;
+  final Map environment;
+  final List files;
+  final SendPort replyPort;
+  WorkMessage(this.workerName, this.environment, this.files, this.replyPort);
+}
+
+class ResultMessage {
+  final hitmap;
+  final failedResolves;
+  ResultMessage(this.hitmap, this.failedResolves);
+}
+
+final env = new Environment();
+
+List<List> split(List list, int nBuckets) {
+  var buckets = new List(nBuckets);
+  var bucketSize = list.length ~/ nBuckets;
+  var leftover = list.length % nBuckets;
+  var taken = 0;
+  var start = 0;
+  for (int i = 0; i < nBuckets; i++) {
+    var end = (i < leftover) ? (start + bucketSize + 1) : (start + bucketSize);
+    buckets[i] = list.sublist(start, end);
+    taken += buckets[i].length;
+    start = end;
+  }
+  if (taken != list.length) throw "Error splitting";
+  return buckets;
+}
+
+Future<ResultMessage> spawnWorker(name, environment, files) {
+  RawReceivePort port = new RawReceivePort();
+  var completer = new Completer();
+  port.handler = ((ResultMessage msg) {
+    completer.complete(msg);
+    port.close();
+  });
+  var msg = new WorkMessage(name, environment, files, port.sendPort);
+  Isolate.spawn(worker, msg);
+  return completer.future;
+}
+
+main(List<String> arguments) {
+  parseArgs(arguments);
+
+  List files = filesToProcess(env.input);
+
+  List failedResolves = [];
+  List failedLoads = [];
+  Map globalHitmap = {};
+  int start = new DateTime.now().millisecondsSinceEpoch;
+
+  if (env.verbose) {
+    print("Environment:");
+    print("  # files: ${files.length}");
+    print("  # workers: ${env.workers}");
+    print("  sdk-root: ${env.sdkRoot}");
+    print("  package-root: ${env.pkgRoot}");
+  }
+
+  Map sharedEnv = {
+    "sdkRoot": env.sdkRoot,
+    "pkgRoot": env.pkgRoot,
+    "verbose": env.verbose,
+  };
+
+  // Create workers.
+  int workerId = 0;
+  var results = split(files, env.workers).map((workerFiles) {
+    var result = spawnWorker("Worker ${workerId++}", sharedEnv, workerFiles);
+    return result.then((ResultMessage message) {
+      mergeHitmaps(message.hitmap, globalHitmap);
+      failedResolves.addAll(message.failedResolves);
+    });
+  });
+
+  Future.wait(results).then((ignore) {
+    // All workers are done. Process the data.
+    if (env.verbose) {
+      final end = new DateTime.now().millisecondsSinceEpoch;
+      print("Done creating a global hitmap. Took ${end - start} ms.");
+    }
+
+    Future out;
+    if (env.prettyPrint) {
+      out = prettyPrint(globalHitmap, failedLoads);
+    }
+    if (env.lcov) {
+      out = lcov(globalHitmap);
+    }
+
+    out.then((_) {
+      env.output.close().then((_) {
+        if (env.verbose) {
+          final end = new DateTime.now().millisecondsSinceEpoch;
+          print("Done flushing output. Took ${end - start} ms.");
+        }
+      });
+
+      if (env.verbose) {
+        if (failedResolves.length > 0) {
+          print("Failed to resolve:");
+          failedResolves.toSet().forEach((e) {
+            print("  ${e}");
+          });
+        }
+        if (failedLoads.length > 0) {
+          print("Failed to load:");
+          failedLoads.toSet().forEach((e) {
+            print("  ${e}");
+          });
+        }
+      }
+    });
+  });
+}
+
+/// Checks the validity of the provided arguments. Does not initialize actual
+/// processing.
+parseArgs(List<String> arguments) {
+  var parser = new ArgParser();
+
+  parser.addOption("sdk-root", abbr: "s",
+                   help: "path to the SDK root");
+  parser.addOption("package-root", abbr: "p",
+                   help: "path to the package root");
+  parser.addOption("in", abbr: "i",
+                   help: "input(s): may be file or directory");
+  parser.addOption("out", abbr: "o",
+                   help: "output: may be file or stdout",
+                   defaultsTo: "stdout");
+  parser.addOption("workers", abbr: "j",
+                   help: "number of workers",
+                   defaultsTo: "1");
+  parser.addFlag("pretty-print", abbr: "r",
+                 help: "convert coverage data to pretty print format",
+                 negatable: false);
+  parser.addFlag("lcov", abbr :"l",
+                 help: "convert coverage data to lcov format",
+                 negatable: false);
+  parser.addFlag("verbose", abbr :"v",
+                 help: "verbose output",
+                 negatable: false);
+  parser.addFlag("help", abbr: "h",
+                 help: "show this help",
+                 negatable: false);
+
+  var args = parser.parse(arguments);
+
+  printUsage() {
+    print("Usage: dart full-coverage.dart [OPTION...]\n");
+    print(parser.getUsage());
+  }
+
+  fail(String msg) {
+    print("\n$msg\n");
+    printUsage();
+    exit(1);
+  }
+
+  if (args["help"]) {
+    printUsage();
+    exit(0);
+  }
+
+  env.sdkRoot = args["sdk-root"];
+  if (env.sdkRoot == null) {
+    if (Platform.environment.containsKey("DART_SDK")) {
+      env.sdkRoot =
+        join(absolute(normalize(Platform.environment["DART_SDK"])), "lib");
+    }
+  } else {
+    env.sdkRoot = join(absolute(normalize(env.sdkRoot)), "lib");
+  }
+  if ((env.sdkRoot != null) && !FileSystemEntity.isDirectorySync(env.sdkRoot)) {
+    fail("Provided SDK root '${args["sdk-root"]}' is not a valid SDK "
+         "top-level directory");
+  }
+
+  env.pkgRoot = args["package-root"];
+  if (env.pkgRoot != null) {
+    env.pkgRoot = absolute(normalize(args["package-root"]));
+    if (!FileSystemEntity.isDirectorySync(env.pkgRoot)) {
+      fail("Provided package root '${args["package-root"]}' is not directory.");
+    }
+  }
+
+  if (args["in"] == null) {
+    fail("No input files given.");
+  } else {
+    env.input = absolute(normalize(args["in"]));
+    if (!FileSystemEntity.isDirectorySync(env.input) &&
+        !FileSystemEntity.isFileSync(env.input)) {
+      fail("Provided input '${args["in"]}' is neither a directory, nor a file.");
+    }
+  }
+
+  if (args["out"] == "stdout") {
+    env.output = stdout;
+  } else {
+    env.output = absolute(normalize(args["out"]));
+    env.output = new File(env.output).openWrite();
+  }
+
+  env.lcov = args["lcov"];
+  if (args["pretty-print"] && env.lcov) {
+    fail("Choose one of pretty-print or lcov output");
+  } else if (!env.lcov) {
+    // Use pretty-print either explicitly or by default.
+    env.prettyPrint = true;
+  }
+
+  try {
+    env.workers = int.parse("${args["workers"]}");
+  } catch (e) {
+    fail("Invalid worker count: $e");
+  }
+
+  env.verbose = args["verbose"];
+}
\ No newline at end of file
diff --git a/pkgs/coverage/pubspec.yaml b/pkgs/coverage/pubspec.yaml
new file mode 100644
index 0000000..d2bda76
--- /dev/null
+++ b/pkgs/coverage/pubspec.yaml
@@ -0,0 +1,5 @@
+name: coverage
+description: Coverage data manipulation and formatting
+dependencies:
+  args: any
+  path: any