[libdevel-cover-perl] 01/05: Imported Upstream version 1.15

gregor herrmann gregoa at debian.org
Fri Jun 6 12:39:51 UTC 2014


This is an automated email from the git hooks/post-receive script.

gregoa pushed a commit to branch master
in repository libdevel-cover-perl.

commit 89d9b0a067f926ba87964e5017314b516d41628b
Author: gregor herrmann <gregoa at debian.org>
Date:   Fri Jun 6 14:05:32 2014 +0200

    Imported Upstream version 1.15
---
 .gitignore                             |   1 +
 Changes                                |   7 +
 MANIFEST                               |  10 +-
 META.json                              | 124 ++++--
 META.yml                               | 109 ++++--
 Makefile.PL                            | 102 ++---
 bin/cover                              |  49 ++-
 bin/cpancover                          | 550 +++++----------------------
 bin/gcov2perl                          |   4 +-
 dist.ini                               |   4 +
 docs/RELEASE                           |  12 +-
 docs/cpancover                         |  32 ++
 lib/Devel/Cover.pm                     |  42 ++-
 lib/Devel/Cover/Annotation/Git.pm      |   4 +-
 lib/Devel/Cover/Annotation/Random.pm   |   4 +-
 lib/Devel/Cover/Annotation/Svk.pm      |   4 +-
 lib/Devel/Cover/Branch.pm              |   4 +-
 lib/Devel/Cover/Collection.pm          | 665 +++++++++++++++++++++++++++++++++
 lib/Devel/Cover/Condition.pm           |   4 +-
 lib/Devel/Cover/Condition_and_2.pm     |   4 +-
 lib/Devel/Cover/Condition_and_3.pm     |   4 +-
 lib/Devel/Cover/Condition_or_2.pm      |   4 +-
 lib/Devel/Cover/Condition_or_3.pm      |   4 +-
 lib/Devel/Cover/Condition_xor_4.pm     |   4 +-
 lib/Devel/Cover/Criterion.pm           |   4 +-
 lib/Devel/Cover/DB.pm                  |  10 +-
 lib/Devel/Cover/DB/Digests.pm          |   4 +-
 lib/Devel/Cover/DB/File.pm             |   4 +-
 lib/Devel/Cover/DB/IO.pm               |   4 +-
 lib/Devel/Cover/DB/IO/JSON.pm          |   6 +-
 lib/Devel/Cover/DB/IO/Sereal.pm        |   4 +-
 lib/Devel/Cover/DB/IO/Storable.pm      |   4 +-
 lib/Devel/Cover/DB/Structure.pm        |   4 +-
 lib/Devel/Cover/Dumper.pm              |   4 +-
 lib/Devel/Cover/Html_Common.pm         |   4 +-
 lib/Devel/Cover/Op.pm                  |   4 +-
 lib/Devel/Cover/Pod.pm                 |   4 +-
 lib/Devel/Cover/Report/Compilation.pm  |   4 +-
 lib/Devel/Cover/Report/Html.pm         |   4 +-
 lib/Devel/Cover/Report/Html_basic.pm   |  18 +-
 lib/Devel/Cover/Report/Html_minimal.pm |   4 +-
 lib/Devel/Cover/Report/Html_subtle.pm  |   6 +-
 lib/Devel/Cover/Report/Json.pm         |  87 +++++
 lib/Devel/Cover/Report/Sort.pm         |   4 +-
 lib/Devel/Cover/Report/Text.pm         |   4 +-
 lib/Devel/Cover/Report/Text2.pm        |   4 +-
 lib/Devel/Cover/Report/Vim.pm          |   6 +-
 lib/Devel/Cover/Statement.pm           |   4 +-
 lib/Devel/Cover/Subroutine.pm          |   4 +-
 lib/Devel/Cover/Test.pm                |   6 +-
 lib/Devel/Cover/Time.pm                |   4 +-
 lib/Devel/Cover/Truth_Table.pm         |   4 +-
 lib/Devel/Cover/Tutorial.pod           |   2 +-
 lib/Devel/Cover/Util.pm                |   4 +-
 lib/Devel/Cover/Web.pm                 |  11 +-
 test_output/cover/inc_sub.5.010000     |  82 ----
 tests/change.t                         |   2 +-
 tests/inc_sub                          |   2 +
 tests/md5.t                            |   2 +-
 utils/all_versions                     |   4 +-
 utils/build_cpancover_perl             |   5 +
 utils/cpancover_modules                | 394 +++++++++++++++++++
 utils/dc                               |  93 ++++-
 utils/install_modules                  | 422 ---------------------
 utils/run_cpancover                    |  17 +-
 utils/setup                            |  14 +
 66 files changed, 1807 insertions(+), 1221 deletions(-)

diff --git a/.gitignore b/.gitignore
index 6467267..cfca681 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,3 +27,4 @@ tags
 README
 .build/
 callgrind.out.*
+staging/
diff --git a/Changes b/Changes
index 9659a83..76a01fd 100644
--- a/Changes
+++ b/Changes
@@ -1,5 +1,12 @@
 Devel::Cover history
 
+Release 1.15 - 1 June 2014
+ - Allow -coverage default,-pod option to cover (David Cantrell) (github 89).
+ - Get cpancover coverage in docker containers.
+ - Add CGI.pm as a prerequisite.
+ - Test against 5.20.0 and 5.21.0.
+ - Add longer delay in tests to try to appease *BSD.
+
 Release 1.14 - 2 May 2014
  - Fix test failures on OpenBSD, NetBSD and Windows.
 
diff --git a/MANIFEST b/MANIFEST
index 5e06ce3..70013ef 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -1,4 +1,4 @@
-# This file was automatically generated by Dist::Zilla::Plugin::Manifest v5.013.
+# This file was automatically generated by Dist::Zilla::Plugin::Manifest v5.019.
 .gitignore
 .travis.yml
 Changes
@@ -17,11 +17,13 @@ dist.ini
 docs/BUGS
 docs/RELEASE
 docs/TODO
+docs/cpancover
 lib/Devel/Cover.pm
 lib/Devel/Cover/Annotation/Git.pm
 lib/Devel/Cover/Annotation/Random.pm
 lib/Devel/Cover/Annotation/Svk.pm
 lib/Devel/Cover/Branch.pm
+lib/Devel/Cover/Collection.pm
 lib/Devel/Cover/Condition.pm
 lib/Devel/Cover/Condition_and_2.pm
 lib/Devel/Cover/Condition_and_3.pm
@@ -46,6 +48,7 @@ lib/Devel/Cover/Report/Html.pm
 lib/Devel/Cover/Report/Html_basic.pm
 lib/Devel/Cover/Report/Html_minimal.pm
 lib/Devel/Cover/Report/Html_subtle.pm
+lib/Devel/Cover/Report/Json.pm
 lib/Devel/Cover/Report/Sort.pm
 lib/Devel/Cover/Report/Text.pm
 lib/Devel/Cover/Report/Text2.pm
@@ -141,7 +144,6 @@ test_output/cover/exec_die.5.006001
 test_output/cover/fork.5.006001
 test_output/cover/if.5.006001
 test_output/cover/if.5.008
-test_output/cover/inc_sub.5.010000
 test_output/cover/md5.5.006001
 test_output/cover/module1.5.006001
 test_output/cover/module1.5.008
@@ -292,6 +294,8 @@ tests/xor_constant_fold
 utils/Devel/Cover/BuildUtils.pm
 utils/all_versions
 utils/bisect.sh
+utils/build_cpancover_perl
+utils/cpancover_modules
 utils/cpanmcover
 utils/create_all_gold
 utils/create_gold
@@ -299,9 +303,9 @@ utils/dc
 utils/install/System.pm
 utils/install/buildperl
 utils/install_dev_modules
-utils/install_modules
 utils/mail_contributors
 utils/makeh
 utils/run_cpancover
 utils/scanuncov
+utils/setup
 utils/typemap
diff --git a/META.json b/META.json
index e6effd9..0b185d9 100644
--- a/META.json
+++ b/META.json
@@ -4,7 +4,7 @@
       "Paul Johnson <paul at pjcj.net>"
    ],
    "dynamic_config" : 0,
-   "generated_by" : "Dist::Zilla version 5.013, CPAN::Meta::Converter version 2.140640",
+   "generated_by" : "Dist::Zilla version 5.019, CPAN::Meta::Converter version 2.140640",
    "license" : [
       "perl_5"
    ],
@@ -29,7 +29,10 @@
       "runtime" : {
          "recommends" : {
             "Browser::Open" : "0",
+            "Capture::Tiny" : "0",
+            "Class::XSAccessor" : "0",
             "JSON::PP" : "0",
+            "Moo" : "0",
             "PPI::HTML" : "1.07",
             "Parallel::Iterator" : "0",
             "Perl::Tidy" : "20060719",
@@ -37,6 +40,7 @@
             "Pod::Coverage::CountParents" : "0",
             "Template" : "2.00",
             "Test::Differences" : "0",
+            "namespace::clean" : "0",
             "perl" : "5.008002"
          },
          "requires" : {
@@ -71,10 +75,10 @@
       },
       "x_mailing_list" : "http://lists.perl.org/list/perl-qa.html"
    },
-   "version" : "1.14",
+   "version" : "1.15",
    "x_Dist_Zilla" : {
       "perl" : {
-         "version" : "5.018002"
+         "version" : "5.020000"
       },
       "plugins" : [
          {
@@ -90,17 +94,17 @@
          {
             "class" : "Dist::Zilla::Plugin::GatherDir",
             "name" : "GatherDir",
-            "version" : "5.013"
+            "version" : "5.019"
          },
          {
             "class" : "Dist::Zilla::Plugin::ManifestSkip",
             "name" : "ManifestSkip",
-            "version" : "5.013"
+            "version" : "5.019"
          },
          {
             "class" : "Dist::Zilla::Plugin::ExecDir",
             "name" : "ExecDir",
-            "version" : "5.013"
+            "version" : "5.019"
          },
          {
             "class" : "Dist::Zilla::Plugin::OurPkgVersion",
@@ -110,37 +114,37 @@
          {
             "class" : "Dist::Zilla::Plugin::PodVersion",
             "name" : "PodVersion",
-            "version" : "5.013"
+            "version" : "5.019"
          },
          {
             "class" : "Dist::Zilla::Plugin::MetaYAML",
             "name" : "MetaYAML",
-            "version" : "5.013"
+            "version" : "5.019"
          },
          {
             "class" : "Dist::Zilla::Plugin::MetaJSON",
             "name" : "MetaJSON",
-            "version" : "5.013"
+            "version" : "5.019"
          },
          {
             "class" : "Dist::Zilla::Plugin::MetaConfig",
             "name" : "MetaConfig",
-            "version" : "5.013"
+            "version" : "5.019"
          },
          {
             "class" : "Dist::Zilla::Plugin::MetaResources",
             "name" : "MetaResources",
-            "version" : "5.013"
+            "version" : "5.019"
          },
          {
             "class" : "Dist::Zilla::Plugin::MetaNoIndex",
             "name" : "MetaNoIndex",
-            "version" : "5.013"
+            "version" : "5.019"
          },
          {
             "class" : "Dist::Zilla::Plugin::Manifest",
             "name" : "Manifest",
-            "version" : "5.013"
+            "version" : "5.019"
          },
          {
             "class" : "Dist::Zilla::Plugin::Prereqs",
@@ -151,7 +155,7 @@
                }
             },
             "name" : "Prereqs",
-            "version" : "5.013"
+            "version" : "5.019"
          },
          {
             "class" : "Dist::Zilla::Plugin::Prereqs",
@@ -162,7 +166,7 @@
                }
             },
             "name" : "Recommends",
-            "version" : "5.013"
+            "version" : "5.019"
          },
          {
             "class" : "Dist::Zilla::Plugin::Prereqs",
@@ -173,7 +177,7 @@
                }
             },
             "name" : "ConfigureRequires",
-            "version" : "5.013"
+            "version" : "5.019"
          },
          {
             "class" : "Dist::Zilla::Plugin::Prereqs",
@@ -184,7 +188,7 @@
                }
             },
             "name" : "TestRequires",
-            "version" : "5.013"
+            "version" : "5.019"
          },
          {
             "class" : "Dist::Zilla::Plugin::Prereqs",
@@ -195,87 +199,139 @@
                }
             },
             "name" : "TestRecommends",
-            "version" : "5.013"
+            "version" : "5.019"
          },
          {
             "class" : "Dist::Zilla::Plugin::Run::Test",
+            "config" : {
+               "Dist::Zilla::Role::TestRunner" : {
+                  "default_jobs" : 1
+               }
+            },
             "name" : "Run::Test",
             "version" : "0.021"
          },
          {
             "class" : "Dist::Zilla::Plugin::Git::Check",
+            "config" : {
+               "Dist::Zilla::Plugin::Git::Check" : {
+                  "untracked_files" : "die"
+               },
+               "Dist::Zilla::Role::Git::DirtyFiles" : {
+                  "allow_dirty" : [
+                     "dist.ini",
+                     "Changes"
+                  ],
+                  "allow_dirty_match" : [],
+                  "changelog" : "Changes"
+               },
+               "Dist::Zilla::Role::Git::Repo" : {
+                  "repo_root" : "."
+               }
+            },
             "name" : "Git::Check",
-            "version" : "2.020"
+            "version" : "2.022"
          },
          {
             "class" : "Dist::Zilla::Plugin::NextRelease",
             "name" : "NextRelease",
-            "version" : "5.013"
+            "version" : "5.019"
          },
          {
             "class" : "Dist::Zilla::Plugin::Git::Commit",
+            "config" : {
+               "Dist::Zilla::Plugin::Git::Commit" : {
+                  "add_files_in" : [],
+                  "commit_msg" : "v%v%n%n%c",
+                  "time_zone" : "local"
+               },
+               "Dist::Zilla::Role::Git::DirtyFiles" : {
+                  "allow_dirty" : [
+                     "dist.ini",
+                     "Changes"
+                  ],
+                  "allow_dirty_match" : [],
+                  "changelog" : "Changes"
+               },
+               "Dist::Zilla::Role::Git::Repo" : {
+                  "repo_root" : "."
+               }
+            },
             "name" : "Git::Commit",
-            "version" : "2.020"
+            "version" : "2.022"
          },
          {
             "class" : "Dist::Zilla::Plugin::Git::Tag",
+            "config" : {
+               "Dist::Zilla::Plugin::Git::Tag" : {
+                  "branch" : null,
+                  "signed" : 0,
+                  "tag" : "v1.15",
+                  "tag_format" : "v%v",
+                  "tag_message" : "v%v",
+                  "time_zone" : "local"
+               },
+               "Dist::Zilla::Role::Git::Repo" : {
+                  "repo_root" : "."
+               }
+            },
             "name" : "Git::Tag",
-            "version" : "2.020"
+            "version" : "2.022"
          },
          {
             "class" : "Dist::Zilla::Plugin::TestRelease",
             "name" : "TestRelease",
-            "version" : "5.013"
+            "version" : "5.019"
          },
          {
             "class" : "Dist::Zilla::Plugin::ConfirmRelease",
             "name" : "ConfirmRelease",
-            "version" : "5.013"
+            "version" : "5.019"
          },
          {
             "class" : "Dist::Zilla::Plugin::UploadToCPAN",
             "name" : "UploadToCPAN",
-            "version" : "5.013"
+            "version" : "5.019"
          },
          {
             "class" : "Dist::Zilla::Plugin::FinderCode",
             "name" : ":InstallModules",
-            "version" : "5.013"
+            "version" : "5.019"
          },
          {
             "class" : "Dist::Zilla::Plugin::FinderCode",
             "name" : ":IncModules",
-            "version" : "5.013"
+            "version" : "5.019"
          },
          {
             "class" : "Dist::Zilla::Plugin::FinderCode",
             "name" : ":TestFiles",
-            "version" : "5.013"
+            "version" : "5.019"
          },
          {
             "class" : "Dist::Zilla::Plugin::FinderCode",
             "name" : ":ExecFiles",
-            "version" : "5.013"
+            "version" : "5.019"
          },
          {
             "class" : "Dist::Zilla::Plugin::FinderCode",
             "name" : ":ShareFiles",
-            "version" : "5.013"
+            "version" : "5.019"
          },
          {
             "class" : "Dist::Zilla::Plugin::FinderCode",
             "name" : ":MainModule",
-            "version" : "5.013"
+            "version" : "5.019"
          },
          {
             "class" : "Dist::Zilla::Plugin::FinderCode",
             "name" : ":AllFiles",
-            "version" : "5.013"
+            "version" : "5.019"
          },
          {
             "class" : "Dist::Zilla::Plugin::FinderCode",
             "name" : ":NoFiles",
-            "version" : "5.013"
+            "version" : "5.019"
          }
       ],
       "zilla" : {
@@ -283,7 +339,7 @@
          "config" : {
             "is_trial" : "0"
          },
-         "version" : "5.013"
+         "version" : "5.019"
       }
    }
 }
diff --git a/META.yml b/META.yml
index b8e4e5d..6b4d898 100644
--- a/META.yml
+++ b/META.yml
@@ -8,7 +8,7 @@ build_requires:
 configure_requires:
   ExtUtils::MakeMaker: '0'
 dynamic_config: 0
-generated_by: 'Dist::Zilla version 5.013, CPAN::Meta::Converter version 2.140640'
+generated_by: 'Dist::Zilla version 5.019, CPAN::Meta::Converter version 2.140640'
 license: perl
 meta-spec:
   url: http://module-build.sourceforge.net/META-spec-v1.4.html
@@ -21,7 +21,10 @@ no_index:
     - utils
 recommends:
   Browser::Open: '0'
+  Capture::Tiny: '0'
+  Class::XSAccessor: '0'
   JSON::PP: '0'
+  Moo: '0'
   PPI::HTML: '1.07'
   Parallel::Iterator: '0'
   Perl::Tidy: '20060719'
@@ -29,6 +32,7 @@ recommends:
   Pod::Coverage::CountParents: '0'
   Template: '2.00'
   Test::Differences: '0'
+  namespace::clean: '0'
   perl: '5.008002'
 requires:
   Digest::MD5: '0'
@@ -40,10 +44,10 @@ resources:
   homepage: http://www.pjcj.net/perl.html
   license: http://dev.perl.org/licenses
   repository: http://github.com/pjcj/Devel--Cover
-version: '1.14'
+version: '1.15'
 x_Dist_Zilla:
   perl:
-    version: '5.018002'
+    version: '5.020000'
   plugins:
     -
       class: Dist::Zilla::Plugin::VersionFromScript
@@ -56,15 +60,15 @@ x_Dist_Zilla:
     -
       class: Dist::Zilla::Plugin::GatherDir
       name: GatherDir
-      version: '5.013'
+      version: '5.019'
     -
       class: Dist::Zilla::Plugin::ManifestSkip
       name: ManifestSkip
-      version: '5.013'
+      version: '5.019'
     -
       class: Dist::Zilla::Plugin::ExecDir
       name: ExecDir
-      version: '5.013'
+      version: '5.019'
     -
       class: Dist::Zilla::Plugin::OurPkgVersion
       name: OurPkgVersion
@@ -72,31 +76,31 @@ x_Dist_Zilla:
     -
       class: Dist::Zilla::Plugin::PodVersion
       name: PodVersion
-      version: '5.013'
+      version: '5.019'
     -
       class: Dist::Zilla::Plugin::MetaYAML
       name: MetaYAML
-      version: '5.013'
+      version: '5.019'
     -
       class: Dist::Zilla::Plugin::MetaJSON
       name: MetaJSON
-      version: '5.013'
+      version: '5.019'
     -
       class: Dist::Zilla::Plugin::MetaConfig
       name: MetaConfig
-      version: '5.013'
+      version: '5.019'
     -
       class: Dist::Zilla::Plugin::MetaResources
       name: MetaResources
-      version: '5.013'
+      version: '5.019'
     -
       class: Dist::Zilla::Plugin::MetaNoIndex
       name: MetaNoIndex
-      version: '5.013'
+      version: '5.019'
     -
       class: Dist::Zilla::Plugin::Manifest
       name: Manifest
-      version: '5.013'
+      version: '5.019'
     -
       class: Dist::Zilla::Plugin::Prereqs
       config:
@@ -104,7 +108,7 @@ x_Dist_Zilla:
           phase: runtime
           type: requires
       name: Prereqs
-      version: '5.013'
+      version: '5.019'
     -
       class: Dist::Zilla::Plugin::Prereqs
       config:
@@ -112,7 +116,7 @@ x_Dist_Zilla:
           phase: runtime
           type: recommends
       name: Recommends
-      version: '5.013'
+      version: '5.019'
     -
       class: Dist::Zilla::Plugin::Prereqs
       config:
@@ -120,7 +124,7 @@ x_Dist_Zilla:
           phase: configure
           type: requires
       name: ConfigureRequires
-      version: '5.013'
+      version: '5.019'
     -
       class: Dist::Zilla::Plugin::Prereqs
       config:
@@ -128,7 +132,7 @@ x_Dist_Zilla:
           phase: test
           type: requires
       name: TestRequires
-      version: '5.013'
+      version: '5.019'
     -
       class: Dist::Zilla::Plugin::Prereqs
       config:
@@ -136,73 +140,110 @@ x_Dist_Zilla:
           phase: test
           type: recommends
       name: TestRecommends
-      version: '5.013'
+      version: '5.019'
     -
       class: Dist::Zilla::Plugin::Run::Test
+      config:
+        Dist::Zilla::Role::TestRunner:
+          default_jobs: 1
       name: Run::Test
       version: '0.021'
     -
       class: Dist::Zilla::Plugin::Git::Check
+      config:
+        Dist::Zilla::Plugin::Git::Check:
+          untracked_files: die
+        Dist::Zilla::Role::Git::DirtyFiles:
+          allow_dirty:
+            - dist.ini
+            - Changes
+          allow_dirty_match: []
+          changelog: Changes
+        Dist::Zilla::Role::Git::Repo:
+          repo_root: .
       name: Git::Check
-      version: '2.020'
+      version: '2.022'
     -
       class: Dist::Zilla::Plugin::NextRelease
       name: NextRelease
-      version: '5.013'
+      version: '5.019'
     -
       class: Dist::Zilla::Plugin::Git::Commit
+      config:
+        Dist::Zilla::Plugin::Git::Commit:
+          add_files_in: []
+          commit_msg: v%v%n%n%c
+          time_zone: local
+        Dist::Zilla::Role::Git::DirtyFiles:
+          allow_dirty:
+            - dist.ini
+            - Changes
+          allow_dirty_match: []
+          changelog: Changes
+        Dist::Zilla::Role::Git::Repo:
+          repo_root: .
       name: Git::Commit
-      version: '2.020'
+      version: '2.022'
     -
       class: Dist::Zilla::Plugin::Git::Tag
+      config:
+        Dist::Zilla::Plugin::Git::Tag:
+          branch: ~
+          signed: 0
+          tag: v1.15
+          tag_format: v%v
+          tag_message: v%v
+          time_zone: local
+        Dist::Zilla::Role::Git::Repo:
+          repo_root: .
       name: Git::Tag
-      version: '2.020'
+      version: '2.022'
     -
       class: Dist::Zilla::Plugin::TestRelease
       name: TestRelease
-      version: '5.013'
+      version: '5.019'
     -
       class: Dist::Zilla::Plugin::ConfirmRelease
       name: ConfirmRelease
-      version: '5.013'
+      version: '5.019'
     -
       class: Dist::Zilla::Plugin::UploadToCPAN
       name: UploadToCPAN
-      version: '5.013'
+      version: '5.019'
     -
       class: Dist::Zilla::Plugin::FinderCode
       name: ':InstallModules'
-      version: '5.013'
+      version: '5.019'
     -
       class: Dist::Zilla::Plugin::FinderCode
       name: ':IncModules'
-      version: '5.013'
+      version: '5.019'
     -
       class: Dist::Zilla::Plugin::FinderCode
       name: ':TestFiles'
-      version: '5.013'
+      version: '5.019'
     -
       class: Dist::Zilla::Plugin::FinderCode
       name: ':ExecFiles'
-      version: '5.013'
+      version: '5.019'
     -
       class: Dist::Zilla::Plugin::FinderCode
       name: ':ShareFiles'
-      version: '5.013'
+      version: '5.019'
     -
       class: Dist::Zilla::Plugin::FinderCode
       name: ':MainModule'
-      version: '5.013'
+      version: '5.019'
     -
       class: Dist::Zilla::Plugin::FinderCode
       name: ':AllFiles'
-      version: '5.013'
+      version: '5.019'
     -
       class: Dist::Zilla::Plugin::FinderCode
       name: ':NoFiles'
-      version: '5.013'
+      version: '5.019'
   zilla:
     class: Dist::Zilla::Dist::Builder
     config:
       is_trial: '0'
-    version: '5.013'
+    version: '5.019'
diff --git a/Makefile.PL b/Makefile.PL
index 3717a48..254a1ae 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -18,7 +18,7 @@ use File::Copy;
 
 $| = 1;
 
-my $Version = "1.14";
+my $Version = "1.15";
 my $Author  = 'paul at pjcj.net';
 my @perlbug = ("perlbug", "-a", $Author,
                           "-s", "Installation of Devel::Cover $Version");
@@ -169,16 +169,16 @@ sub check {
 
 my $d = <<EOM;
 The coverage database can be stored in any of the Storable, JSON or Sereal
-formats.  To use the Storable format, the Storable module is required.  This
-has been a core module since perl-5.8.0.  To store the database in JSON format
+formats.  To use the Storable format, the Storable module is required.  This has
+been a core module since perl-5.8.0.  To store the database in JSON format
 JSON::PP can be used.  This has been a core module since perl-5.14.0.  If you
-wish, you may install the JSON module which will be used in preference.  To
-use the Sereal format, the Sereal module should be installed.  This is
-available on CPAN.
+wish, you may install the JSON module which will be used in preference.  To use
+the Sereal format, the Sereal module should be installed.  This is available on
+CPAN.
 
 Sereal is used if it is available.  Otherwise JSON is used, if available.
-Otherwise Storable will be used.  The Sereal and JSON formats should be
-portable between all systems, whereas Storable format may not be.
+Otherwise Storable will be used.  The Sereal and JSON formats should be portable
+between all systems, whereas Storable format may not be.
 EOM
 
 check "Storable", $d;
@@ -197,25 +197,25 @@ Test::More from CPAN.
 EOM
 
 check "Test::Warn", <<EOM;
-Test::Warn is required to run some of the Devel::Cover tests.  You can
-download Test::Warn from CPAN.
+Test::Warn is required to run some of the Devel::Cover tests.  You can download
+Test::Warn from CPAN.
 EOM
 
 check "Template", <<EOM, "2.00";
-Template 2.00 is required to run the some HTML backends to cover and
-for cpancover.  Unless you have specific requirements this should not be
-a problem, but you will not be able to use these reports until you
-install the Template Toolkit, available from CPAN.  In the meantime you
-may continue to use the rest of Devel::Cover.
+Template 2.00 is required to run the some HTML backends to cover and for
+cpancover.  Unless you have specific requirements this should not be a problem,
+but you will not be able to use these reports until you install the Template
+Toolkit, available from CPAN.  In the meantime you may continue to use the rest
+of Devel::Cover.
 EOM
 
 my $m = <<EOM;
 One of PPI::HTML 1.07 or Perl::Tidy 20060719 is required to add syntax
-highlighting to some HTML backends to cover and for cpancover.  Unless
-you have specific requirements this should not be a problem, but you will
-not be able to use syntax highlighting in these reports until you install
-PPI::HTML or Perl::Tidy, available from the CPAN.  In the meantime you
-may continue to use the rest of Devel::Cover.
+highlighting to some HTML backends to cover and for cpancover.  Unless you have
+specific requirements this should not be a problem, but you will not be able to
+use syntax highlighting in these reports until you install PPI::HTML or
+Perl::Tidy, available from the CPAN.  However, the rest of Devel::Cover will be
+available as usual.
 EOM
 
 check "PPI::HTML",  $m, "1.07";
@@ -223,10 +223,10 @@ check "Perl::Tidy", $m, "20060719";
 
 print "checking for Pod::Coverage      version 0.06     .... ";
 my $e = <<EOM;
-Pod::Coverage 0.06 is required to do pod coverage.  This will tell
-you how well you have documented your modules.  Pod coverage will be
-unavailable until you install this module, available from CPAN.  In the
-meantime, you may continue to use the rest of Devel::Cover.
+Pod::Coverage 0.06 is required to do pod coverage.  This will tell you how well
+you have documented your modules.  Pod coverage will be unavailable until you
+install this module, available from CPAN.  In the meantime, you may continue to
+use the rest of Devel::Cover.
 EOM
 
 eval "use Pod::Coverage";
@@ -235,9 +235,9 @@ if (my $m = $INC{"Pod/Coverage.pm"}) {
     print $v < 0.06 ? "$v\n\n\n$e\n\n" : "$v     $m\n";
     print "checking for Pod::Coverage::CountParents         .... ";
     $e = <<EOM;
-    Pod::Coverage::CountParents.pm is used for Pod coverage if it is available.
-    We will fall back to using Pod::Coverage.pm.  If you want to use
-    Pod::Coverage::CountParents.pm, just install it from CPAN.
+Pod::Coverage::CountParents.pm is used for Pod coverage if it is available.  We
+will fall back to using Pod::Coverage.pm.  If you want to use
+Pod::Coverage::CountParents.pm, just install it from CPAN.
 EOM
     eval "use Pod::Coverage::CountParents";
     if (my $m = $INC{"Pod/Coverage/CountParents.pm"}) {
@@ -252,27 +252,27 @@ EOM
 }
 
 check "Test::Differences", <<EOM;
-Test::Differences is used to display output from failed tests.
-Hopefully there won't be any failed tests, but if there are you will get
-output that may not be a model of clarity.  If you do get test failures
-and you fancy helping me by debugging them, then you might like to
-consider installing Test::Differences.  You can download
-Test::Differences from CPAN.
+Test::Differences is used to display output from failed tests.  Hopefully there
+won't be any failed tests, but if there are you will get output that may not be
+a model of clarity.  If you do get test failures and you fancy helping me by
+debugging them, then you might like to consider installing Test::Differences.
+You can download Test::Differences from CPAN.
 EOM
 
 check "Browser::Open", <<EOM;
-Browser::Open is used to launch a web browser when the -launch flag is
-specified with HTML report formats. You can download Browser::Open from CPAN.
+Browser::Open is used to launch a web browser when the -launch flag is specified
+with HTML report formats. You can download Browser::Open from CPAN.
 EOM
 
 check "CGI", <<EOM;
-CGI is used to run the Html_minimal report.  It used to be a part of the perl
-core, but as of perl 5.20 it will need to be downloaded from CPAN.  If you
-would like to use the Html_minimal report, please install CGI.  Otherwise,
-other reports will be available as usual.
+CGI is used to run the HTML reports.  It used to be a part of the perl core, but
+as of perl 5.20 it will need to be downloaded from CPAN.  If you would like to
+use the HTML report, please install CGI.  Otherwise, other reports will be
+available as usual.  Because HTML reports are expected, GCI has been added to
+the prerequisites.
 EOM
 
-my $latest_tested = "5.018002";
+my $latest_tested = "5.020000";
 print <<EOM if $] > $latest_tested;
 
 Devel::Cover $Version has not been tested with perl $].
@@ -284,26 +284,25 @@ EOM
 if ($] < 5.008) {
     print <<EOM;
 
-Devel::Cover $Version is not fully functional on perl $].  It should
-mostly work, but there are some constructs for which coverage will not
-be collected, and you may well encounter bugs which have been fixed in
-subsequent versions of perl.  Perl versions 5.8.8 and above should work
-better.
+Devel::Cover $Version is not fully functional on perl $].  It should mostly
+work, but there are some constructs for which coverage will not be collected,
+and you may well encounter bugs which have been fixed in subsequent versions of
+perl.  Perl versions 5.8.8 and above should work better.
 
 EOM
 
     print <<EOM if $^O eq "MSWin32";
-And things are even worse under Windows.  You may well find random bugs
-of various severities.
+And things are even worse under Windows.  You may well find random bugs of
+various severities.
 
 EOM
 } elsif ($] < 5.008002) {
     print <<EOM;
 
-Devel::Cover $Version mostly works on perl $], but you may encounter
-strange behaviours (bugs) which have been fixed in subsequent versions
-of perl.  This is particularly true if you are running a threaded perl.
-Perl versions 5.8.2 and above should work better.
+Devel::Cover $Version mostly works on perl $], but you may encounter strange
+behaviours (bugs) which have been fixed in subsequent versions of perl.  This is
+particularly true if you are running a threaded perl.  Perl versions 5.8.2 and
+above should work better.
 
 EOM
 }
@@ -323,6 +322,7 @@ my $opts = {
     PREREQ_PM        => {
                             Storable      => 0,
                             "Digest::MD5" => 0,
+                            CGI           => 0,
                             $ENV{DEVEL_COVER_NO_TESTS}
                                 ? ()
                                 : ( "Test::More"  => 0, "Test::Warn"  => 0 )
diff --git a/bin/cover b/bin/cover
index a52345e..952d75c 100755
--- a/bin/cover
+++ b/bin/cover
@@ -12,7 +12,7 @@ require 5.6.1;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use Devel::Cover::DB;
 
@@ -85,16 +85,28 @@ sub get_options {
     $Options->{report} ||= "html" unless exists $Options->{write};
 
     # handle comma seperated ops, like -coverage branch,statement
-    @{$Options->{coverage}} = split(/,/, join(",", @{$Options->{coverage}}));
 
     # also accept them in the same format they're output
     my %coverage_abbrev = (
-        stmt => 'statement',
-        bran => 'branch',
-        cond => 'condition',
-        sub  => 'subroutine',
+        stmt => "statement",
+        bran => "branch",
+        cond => "condition",
+        sub  => "subroutine",
     );
 
+    my %coverage_allowed = map {$_ => 1} values %coverage_abbrev, "time", "pod";
+
+    # expanding 'default' to all available
+    @{$Options->{coverage}} = map {
+        $_ eq "default" ? (keys %coverage_allowed) : $_
+    } split(/,/, join(",", @{$Options->{coverage}}));
+
+    # delete exclusions from that list
+    for my $exclusion (grep /^-/, @{$Options->{coverage}}) {
+        $exclusion = substr($exclusion, 1);  # chop off leading -
+        $Options->{coverage} = [grep $_ ne $exclusion, @{$Options->{coverage}}];
+    }
+
     my %options_coverage = map {$_ => 1} @{$Options->{coverage}};
     while (my ($abbr, $full) = each %coverage_abbrev) {
         $options_coverage{$full} = delete $options_coverage{$abbr}
@@ -104,7 +116,6 @@ sub get_options {
     @{$Options->{coverage}} = keys %options_coverage;
 
     # generating data may take time, so bail now if options are wrong
-    my %coverage_allowed = map {$_ => 1} values %coverage_abbrev, "time", "pod";
     for my $cov (@{$Options->{coverage}}) {
         die "Unrecognised -coverage: $cov" unless $coverage_allowed{$cov};
     }
@@ -142,7 +153,7 @@ sub mm_test_command {
 
 # Test command for Module::Build
 sub mb_test_command {
-    my $test = './Build test';
+    my $test = "./Build test";
     if ($Options->{gcov}) {
         my $o = gcov_args();
         $test .= qq{ "--extra_compiler_flags=-O0 $o" "--extra_linker_flags=$o"};
@@ -406,7 +417,7 @@ cover - report coverage statistics
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
@@ -488,7 +499,7 @@ via -report_c0 <integer>, -report_c1 <integer> and -report_c2 <integer>.:
 
 HTML reporting with syntax highlighting if L<PPI::HTML> or L<Perl::Tidy>
 module is detected. Like html|html_minimal reporting, percentage thresholds
-are color-coded and configurable.
+are colour-coded and configurable.
 
 =item text
 
@@ -516,16 +527,20 @@ default.
 
 Specify the -select, -select_re, -ignore, and -ignore_re options to report
 on specific files.  -select and -ignore are interpreted as shell globs;
--select_re and -ignore_re are interpeted as regular expressions.
+-select_re and -ignore_re are interpreted as regular expressions.
 
 Specify -coverage options to report on specific criteria.  By default all
 available information on all criteria in all files will be reported.
-Available coverage options are statement, branch, condition, subroutine, and
-pod.  However, if you know you only want coverage information for certain
-criteria it is better to only collect data for those criteria in the first
-place by specifying them at that point.  This will make the data collection
-and reporting processes faster and less memory intensive.  See the
-documentation for L<Devel::Cover> for more information.
+Available coverage options are statement, branch, condition, subroutine, pod,
+and default (which equates to all available options).  However, if you know
+you only want coverage information for certain criteria it is better to only
+collect data for those criteria in the first place by specifying them at that
+point.  This will make the data collection and reporting processes faster and
+less memory intensive.  See the documentation for L<Devel::Cover> for more
+information.
+
+If you want all *except* some criteria, then you can say something like
+'-coverage default,-pod'.
 
 The -test option will delete the databases and run your tests to generate
 new coverage data before reporting on it.  L<Devel::Cover> knows how to work
diff --git a/bin/cpancover b/bin/cpancover
index 19d3905..372669a 100755
--- a/bin/cpancover
+++ b/bin/cpancover
@@ -7,491 +7,133 @@
 # The latest version of this software should be available from my homepage:
 # http://www.pjcj.net
 
-require 5.6.1;
-
-use strict;
+use 5.16.0;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
-use Devel::Cover::DB;
-use Devel::Cover::Dumper;
+use Devel::Cover::Collection;
 
-use Cwd ();
+use Cwd qw( abs_path cwd );
 use Fcntl ":flock";
 use Getopt::Long;
 use Pod::Usage;
-use Template 2.00;
-use Parallel::Iterator "iterate_as_array";
 
 # use Carp; $SIG{__DIE__} = \&Carp::confess;
 
 $|++;
 
-my $Template;
-
 my $Options = {
-    collect      => 1,
-    directory    => Cwd::cwd(),
-    force        => 0,
-    module       => [],
-    report       => "html_basic",
+    bin_dir         => abs_path($0) =~ s|/cpancover$||r,
+    build           => 1,
+    docker          => "docker",
+    force           => 0,
+    generate_html   => 0,
+    latest          => 0,
+    local_build     => 0,
+    module          => [],
+    output_file     => "index.html",
+    report          => "html_basic",
+    results_dir     => cwd(),
+    timeout         => 1800,  # half an hour
+    verbose         => 0,
+    workers         => 0,
 };
 
 sub get_options {
-    die "Bad option" unless
-    GetOptions($Options,                # Store the options in the Options hash.
-               qw(
-                   collect!
-                   directory=s
-                   force!
-                   help|h!
-                   info|i!
-                   module=s
-                   outputdir=s
-                   outputfile=s
-                   redo_cpancover_html!
-                   redo_html!
-                   report=s
-                   version|v!
-                 ));
-
-    print "$0 version " . __PACKAGE__->VERSION . "\n" and exit 0
-        if $Options->{version};
-    pod2usage(-exitval => 0, -verbose => 0)  if $Options->{help};
-    pod2usage(-exitval => 0, -verbose => 2)  if $Options->{info};
-
-    $Options->{outputdir}  ||= $Options->{directory};
-    $Options->{outputfile} ||= "coverage.html";
-    push @{$Options->{module}}, @ARGV;
-    if (!$Options->{redo_cpancover_html} && !@{$Options->{module}}) {
-        my $d = $Options->{directory};
-        opendir D, $d or die "Can't opendir $d: $!\n";
-        @{$Options->{module}} = grep !/^\./ && -e "$d/$_/Makefile.PL",
-                                     sort readdir D
-            or die "No module directories found\n";
-        closedir D or die "Can't closedir $d: $!\n";
-    }
-}
-
-sub sys {
-    my ($command) = @_;
-    print "$command\n";
-    system $command;
+    die "Bad option" unless GetOptions($Options, qw(
+        bin_dir=s
+        build!
+        docker=s
+        force!
+        generate_html!
+        help|h!
+        info|i!
+        latest!
+        local_build!
+        module_file=s
+        module=s
+        output_file=s
+        report=s
+        results_dir=s
+        timeout=i
+        verbose!
+        version|v!
+        workers=i
+    ));
+
+    say "$0 version " . __PACKAGE__->VERSION and exit 0 if $Options->{version};
+    pod2usage(-exitval => 0, -verbose => 0)             if $Options->{help};
+    pod2usage(-exitval => 0, -verbose => 2)             if $Options->{info};
+}
+
+sub newcp {
+    my $self = shift;
+    Devel::Cover::Collection->new(
+        bin_dir         => $Options->{bin_dir},
+        docker          => $Options->{docker},
+        force           => $Options->{force},
+        modules         => $Options->{module},
+        output_file     => $Options->{output_file},
+        report          => $Options->{report},
+        results_dir     => $Options->{results_dir},
+        timeout         => $Options->{timeout},
+        verbose         => $Options->{verbose},
+        workers         => $Options->{workers},
+    )
 }
 
-sub read_results {
-    my $f = "$Options->{outputdir}/cover.results";
-    my %results;
+sub main {
+    # TODO - only one instance should run at a time
+    get_options;
 
-    open my $fh, "<", $f or return;
-    my $try;
-    until (flock $fh, LOCK_SH) {
-        die "Can't lock $f: $!\n" if $try++ > 60;
-        sleep 1;
+    if ($Options->{latest}) {
+        my $cp = newcp;
+        $cp->get_latest;
+        return;
     }
-    while (<$fh>) {
-        my ($mod, $status) = split;
-        $results{$mod} = $status;
-    }
-    close $fh or die "Can't close $f: $!\n";
 
-    \%results
-}
-
-sub get_cover {
-    my ($module) = @_;
-
-    print "\n\n\n**** Checking coverage of $module ****\n\n\n";
-
-    my $d = "$Options->{directory}/$module";
-    chdir $d or die "Can't chdir $d: $!\n";
-
-    my $db = "$d/cover_db";
-    print "Already analysed\n" if -d $db;
-
-    my $out = "cover.out";
-    unlink $out;
-
-    my $test = !-e "$db/runs" || $Options->{force} ? " -test" : "";
-    if ($test) {
-        print "Testing $module\n";
-        sys "$^X Makefile.PL >> $out 2>&1" unless -e "Makefile";
+    if ($Options->{local_build}) {
+        my $cp = newcp;
+        $cp->set_modules(@ARGV);
+        $cp->local_build;
+        return;
     }
 
-    my $od = "$Options->{outputdir}/$module";
-    my $of = $Options->{outputfile};
-    my $timeout = 900;  # fifteen minutes should be enough
-
-    if ($test || !-e "$od/$of" || $Options->{redo_html}) {
-        eval {
-            local $SIG{ALRM} = sub { die "alarm\n" };
-            alarm $timeout;
-            sys "cover$test -report $Options->{report} " .
-                "-outputdir $od -outputfile $of " .
-                ">> $out 2>&1";
-            alarm 0;
-        };
-        if ($@) {
-            die unless $@ eq "alarm\n";   # propagate unexpected errors
-            warn "Timed out after $timeout seconds!\n";
-        }
+    if ($Options->{module_file}) {
+        my $cp = newcp;
+        $cp->set_module_file($Options->{module_file});
+        $cp->cover_modules;
     }
 
-    my $results = read_results;
-    my $f = "$Options->{outputdir}/cover.results";
-
-    $results->{$module} = 1;
-
-    open my $fh, ">", $f or die "Can't open $f: $!\n";
-    my $try;
-    until (flock $fh, LOCK_EX) {
-        die "Can't lock $f: $!\n" if $try++ > 60;
-        sleep 1;
-    }
-    for my $mod (sort keys %$results) {
-        print $fh "$mod $results->{$mod}\n";
-    }
-    close $fh or die "Can't close $f: $!\n";
-
-    sys "cat $out" if -e $out;
-}
-
-sub write_stylesheet
-{
-    my $css = "$Options->{outputdir}/cpancover.css";
-    open CSS, ">", $css or return;
-    print CSS <<EOF;
-/* Stylesheet for Devel::Cover cpancover reports */
-
-/* You may modify this file to alter the appearance of your coverage
- * reports. If you do, you should probably flag it read-only to prevent
- * future runs from overwriting it.
- */
-
-/* Note: default values use the color-safe web palette. */
-
-body {
-    font-family: sans-serif;
-}
-
-h1 {
-    text-align : center;
-    background-color: #cc99ff;
-    border: solid 1px #999999;
-    padding: 0.2em;
-    -moz-border-radius: 10px;
-}
-
-a {
-    color: #000000;
-}
-a:visited {
-    color: #333333;
-}
-
-table {
-    border-spacing: 0px;
-}
-tr {
-    text-align : center;
-    vertical-align: top;
-}
-th,.h,.hh {
-    background-color: #cccccc;
-    border: solid 1px #333333;
-    padding: 0em 0.2em;
-    width: 2.5em;
-    -moz-border-radius: 4px;
-}
-.hh {
-    width: 25%;
-}
-td {
-    border: solid 1px #cccccc;
-    border-top: none;
-    border-left: none;
-    -moz-border-radius: 4px;
-}
-.hblank {
-    height: 0.5em;
-}
-.dblank {
-    border: none;
-}
-
-/* source code */
-pre,.s {
-    text-align: left;
-    font-family: monospace;
-    white-space: pre;
-    padding: 0.2em 0.5em 0em 0.5em;
-}
-
-/* Classes for color-coding coverage information:
- *   c0  : path not covered or coverage < 75%
- *   c1  : coverage >= 75%
- *   c2  : coverage >= 90%
- *   c3  : path covered or coverage = 100%
- */
-.c0 {
-    background-color: #ff9999;
-    border: solid 1px #cc0000;
-}
-.c1 {
-    background-color: #ffcc99;
-    border: solid 1px #ff9933;
-}
-.c2 {
-    background-color: #ffff99;
-    border: solid 1px #cccc66;
-}
-.c3 {
-    background-color: #99ff99;
-    border: solid 1px #009900;
-}
-EOF
-
-    close CSS or die "Can't close $css: $!\n";
-}
-
-sub class {
-    my ($pc) = @_;
-    $pc eq "n/a" ? "na" :
-    $pc <    75  ? "c0" :
-    $pc <    90  ? "c1" :
-    $pc <   100  ? "c2" :
-                   "c3"
-}
-
-sub write_csv {
-    my ($data) = @_;
-
-    open(my $fh, ">", "$Options->{outputdir}/cpan_cover.csv")
-            or die "cannot open > cpan_cover.txt: $!";
-
-    # TODO GET DISTRIBUTION
-    my @header = qw/release distribution link
-                    branch_class branch_details branch_pc
-                    condition_class condition_details condition_pc
-                    pod_class pod_details pod_pc
-                    statement_class statement_details statement_pc
-                    subroutine_class subroutine_details subroutine_pc
-                    total_class total_details total_pc/;
-    print $fh join(",", @header ) . "\n";
-    for my $release (keys %{$data->{vals}} ) {
-        my $line = [];
-        push @$line, $release,
-        push @$line, $data->{vals}{$release}{link};
-
-        for my $level1 (
-            qw/branch condition pod statement subroutine total/ ) {
-                foreach my $level2 ( qw/class details pc/ ) {
-                    push @$line, $data->{vals}{$release}{$level1}{$level2};
-                }
-        }
-        print $fh join ( ",",@$line)."\n";
-    }
-    close $fh;
-    print "\n\nWrote cpan_cover.csv output to " .
-          "$Options->{outputdir}/cpan_cover.csv\n";
-}
-
-sub write_html {
-    my $d = $Options->{directory};
-    chdir $d or die "Can't chdir $d: $!\n";
-
-    my $results = read_results;
-    my $f = "$Options->{outputdir}/$Options->{outputfile}";
-    print "\n\nWriting cpancover output to $f ...\n";
-
-    my %vals;
-    my $vars = {
-        title   => "CPAN Coverage report",
-        modules => [],
-        vals    => \%vals,
-    };
-
-    for my $module (sort keys %$results) {
-        my $dbdir = "$Options->{directory}/$module/cover_db";
-        next unless -d $dbdir;
-        chdir "$Options->{directory}/$module";
-        print "Adding $module from $dbdir\n";
-
-        eval {
-            my $db = Devel::Cover::DB->new(db => $dbdir);
-            # next unless $db->is_valid;
-
-            my $criteria = $vars->{criteria} ||=
-                           [ grep(!/path|time/, $db->all_criteria) ];
-            $vars->{headers} ||=
-                           [ grep(!/path|time/, $db->all_criteria_short) ];
-
-            my %options = map { $_ => 1 } @$criteria;
-            $db->calculate_summary(%options);
-
-            push @{$vars->{modules}}, $module;
-            $vals{$module}{link} = "$module/$Options->{outputfile}";
-
-            for my $criterion (@$criteria) {
-                my $summary = $db->summary("Total", $criterion);
-                my $pc = $summary->{percentage};
-                $pc = defined $pc ? sprintf "%6.2f", $pc : "n/a";
-                $vals{$module}{$criterion}{pc}      = $pc;
-                $vals{$module}{$criterion}{class}   = class($pc);
-                $vals{$module}{$criterion}{details} =
-                  ($summary->{covered} || 0) . " / " . ($summary->{total} || 0);
+    if ($Options->{build}) {
+        if (@ARGV) {
+            my $cp = newcp;
+            $cp->set_modules(@ARGV);
+            $cp->cover_modules;
+        } elsif (! -t STDIN) {
+            my @modules;
+            while (<>) {
+                chomp;
+                push @modules, split;
             }
+            my $cp = newcp;
+            $cp->set_modules(@modules);
+            $cp->cover_modules;
+        } else {
+            my $cp = newcp;
+            $cp->cover_modules;
         }
     }
-    write_stylesheet;
-    $Template->process("summary", $vars, $f) or die $Template->error();
-    write_csv($vars);
 
-    print "done.\n";
-    print "\n\nWrote cpancover output to $f\n";
-}
-
-sub main {
-    get_options;
-
-    $Template = Template->new ({
-        LOAD_TEMPLATES => [
-            Devel::Cover::Cpancover::Template::Provider->new({}),
-        ],
-    });
-
-    if ($Options->{collect}) {
-        my $workers = $ENV{CPANCOVER_WORKERS} || 0;
-        my @res = iterate_as_array (
-            { workers => $workers },
-            sub { eval { get_cover $_[1] };
-                  warn "\n\n\n[$_[1]]: $@\n\n\n" if $@ },
-            $Options->{module}
-        );
-        # print Dumper \@res;
-        # get_cover($_) for @{$Options->{module}};
+    if ($Options->{generate_html}) {
+        my $cp = newcp;
+        $cp->generate_html;
     }
 
-    write_html;
-}
-
-package Devel::Cover::Cpancover::Template::Provider;
-
-use strict;
-use warnings;
-
-our $VERSION = '1.14'; # VERSION
-
-use base "Template::Provider";
-
-my %Templates;
-
-sub fetch {
-    my $self = shift;
-    my ($name) = @_;
-    # print "Looking for <$name>\n";
-    $self->SUPER::fetch(exists $Templates{$name} ? \$Templates{$name} : $name)
 }
 
-$Templates{colours} = <<'EOT';
-[%
-    colours = {
-        default => "#ffffad",
-        text    => "#000000",
-        number  => "#ffffc0",
-        error   => "#ff0000",
-        ok      => "#00ff00",
-    }
-%]
-
-[% MACRO bg BLOCK -%]
-bgcolor="[% colours.$colour %]"
-[%- END %]
-EOT
-
-$Templates{html} = <<'EOT';
-<!DOCTYPE html
-     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<!--
-This file was generated by Devel::Cover Version $VERSION
-Devel::Cover is copyright 2001-2012, Paul Johnson (paul\@pjcj.net)
-Devel::Cover is free. It is licensed under the same terms as Perl itself.
-The latest version of Devel::Cover should be available from my homepage:
-http://www.pjcj.net
--->
-[% PROCESS colours %]
-<head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
-    <meta http-equiv="Content-Language" content="en-us"></meta>
-    <link rel="stylesheet" type="text/css" href="cpancover.css"></link>
-    <title> [% title %] </title>
-</head>
-<body>
-    [% content %]
-</body>
-</html>
-EOT
-
-$Templates{summary} = <<'EOT';
-[% WRAPPER html %]
-
-<h1> [% title %] </h1>
-
-<table>
-
-    [% IF modules %]
-        <tr align="right" valign="middle">
-            <th class="header" align="left"> File </th>
-            [% FOREACH header = headers %]
-                <th class="header"> [% header %] </th>
-            [% END %]
-        </tr>
-    [% END %]
-
-    [% FOREACH module = modules %]
-        <tr align="right" valign="middle">
-            <td align="left">
-                <a href="[%- vals.$module.link -%]"> [% module %] </a>
-            </td>
-
-            [% FOREACH criterion = criteria %]
-                <td class="[%- vals.$module.$criterion.class -%]"
-                    title="[%- vals.$module.$criterion.details -%]">
-                    [% vals.$module.$criterion.pc %]
-                </td>
-            [% END %]
-        </tr>
-    [% END %]
-
-</table>
-
-<br/>
-
-<hr/>
-Coverage information from <a href="https://metacpan.org/module/Devel::Cover">
-  Devel::Cover
-</a> by <a href="http://pjcj.net">Paul Johnson</a>.
-
-<br/>
-
-<a href="http://cpancover.com/blead/latest/coverage.html">Core coverage</a>
-(under development)
-
-<br/>
-<br/>
-
-This server generously donated by
-<a href="http://www.bytemark.co.uk/r/cpancover">
-  <img src="http://www.bytemark.co.uk/images/subpages/spreadtheword/bytemark_logo_179_x_14.png" alt="bytemark"/>
-</a>
-
-[% END %]
-EOT
-
-::main
+main
 
 __END__
 
@@ -501,14 +143,14 @@ cpancover - report coverage statistics on CPAN modules
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
  cpancover -help -info -version
            -collect -redo_cpancover_html -redo_html -force
            -module module_name
-           -directory /path/to/dir
+           -results_dir /path/to/dir
            -outputdir /path/to/dir
            -outputfile filename.html
            -report report_name
diff --git a/bin/gcov2perl b/bin/gcov2perl
index 386af54..e5d1ea7 100755
--- a/bin/gcov2perl
+++ b/bin/gcov2perl
@@ -12,7 +12,7 @@ require 5.6.1;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use Devel::Cover::DB;
 
@@ -145,7 +145,7 @@ gcov2perl - convert gcov files to Devel::Cover databases
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/dist.ini b/dist.ini
index 42c8ed9..d794edb 100644
--- a/dist.ini
+++ b/dist.ini
@@ -48,6 +48,10 @@ Parallel::Iterator            = 0
 JSON::PP                      = 0
 Test::Differences             = 0           ; make sure it gets added
 Browser::Open                 = 0
+Capture::Tiny                 = 0
+Class::XSAccessor             = 0
+Moo                           = 0
+namespace::clean              = 0
 [Prereqs / ConfigureRequires]
 ExtUtils::MakeMaker           = 0
 [Prereqs / TestRequires]
diff --git a/docs/RELEASE b/docs/RELEASE
index be50c8f..f58820c 100644
--- a/docs/RELEASE
+++ b/docs/RELEASE
@@ -1,7 +1,7 @@
 1. Update Changes.
   - Add important changes.
   - Credit the author as appropriate.
-  - Include RT numbers.
+  - Include github and RT numbers.
 
 2. Check it in.
   $ git commit -m "Add Changes." Changes
@@ -23,12 +23,16 @@
 8. Test against all versions.
   $ make all_test
 
-7. Return to base perl version.
+9. Return to base perl version.
   $ perl Makefile.PL && make
 
-10. Make the release.
+10. If there's a new stable release of perl:
+  $ cpan Dist::Zilla
+  $ cpan `dzil authordeps --missing`
+
+11. Make the release.
   $ dzil release
 
-11. Push the changes.
+12. Push the changes.
   - The dzil Git::Push plugin hangs for me
   $ git push && git push --tags
diff --git a/docs/cpancover b/docs/cpancover
new file mode 100644
index 0000000..ea18f1b
--- /dev/null
+++ b/docs/cpancover
@@ -0,0 +1,32 @@
+How to set up cpancover
+
+Cpancover requires a bourne shell and docker, as well as a recent perl.  The
+code requires 5.16.0 but earlier versions may work.
+
+Each module is built in an individual docker container.  This should allow its
+resources to be constrained.  In addition the docker container is killed after a
+certain time.
+
+I have only run this in Ubuntu 14.04.  The docker version there, 0.9.1 (as of
+31.05.2104) is insufficient.  Version 0.11.1 is fine.  I don't know about the
+versions inbetween.
+
+The latest version of docker can be installed on Ubuntu as follows:
+(see http://askubuntu.com/questions/472412/how-do-i-upgrade-docker)
+
+# wget -qO- https://get.docker.io/gpg | apt-key add -
+# echo deb http://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list
+# aptitude update
+# aptitude remove docker.io
+# aptitude install lxc-docker
+
+You may need to add yourself to the docker group.
+
+Jobs are run as follows:
+
+$ . ./utils/setup
+$ dc cpancover-latest | head -2000 | dc cpancover
+
+The top level html and json is generated with:
+
+$ dc cpancover-generate-html
diff --git a/lib/Devel/Cover.pm b/lib/Devel/Cover.pm
index 32a9d64..da44bbf 100644
--- a/lib/Devel/Cover.pm
+++ b/lib/Devel/Cover.pm
@@ -10,7 +10,7 @@ package Devel::Cover;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 our $LVERSION = do { eval '$VERSION' || "0.001" };  # for development purposes
 
 use DynaLoader ();
@@ -236,11 +236,7 @@ EOM
               "Ignoring packages in:",        join("\n    ", "", @Inc),    "\n"
             unless $Silent;
 
-        $Run{OS}    = $^O;
-        $Run{perl}  = $] < 5.010 ? join ".", map ord, split //, $^V
-                                 : sprintf "%vd", $^V;
-        $Run{run}   = $0;
-        $Run{start} = get_elapsed() / 1e6;
+        populate_run();
     }
 
     no warnings "void";  # avoid "Too late to run CHECK block" warning
@@ -386,7 +382,34 @@ sub import {
     }
 }
 
-sub cover_names_to_val {
+sub populate_run {
+    my $self = shift;
+
+    $Run{OS}   = $^O;
+    $Run{perl} = $] < 5.010 ? join ".", map ord, split //, $^V
+                            : sprintf "%vd", $^V;
+    $Run{dir}  = $Dir;
+    $Run{run}  = $0;
+
+    my $version;
+    my $mymeta = "$Dir/MYMETA.json";
+    if (-e $mymeta) {
+        eval {
+            require Devel::Cover::DB::IO::JSON;
+            my $io   = Devel::Cover::DB::IO::JSON->new;
+            my $json = $io->read($mymeta);
+            $Run{$_} = $json->{$_} for qw( name version abstract );
+        }
+    } elsif ($Dir =~ m|.*/([^/]+?)(\d+\.\d+)(?:-\w{6})$|) {
+        $Run{name}    = $1;
+        $Run{version} = $2;
+    }
+
+    $Run{start} = get_elapsed() / 1e6;
+}
+
+sub cover_names_to_val
+{
     my $val = 0;
     for my $c (@_) {
         if (exists $Criteria{$c}) {
@@ -1195,7 +1218,7 @@ Devel::Cover - Code coverage metrics for Perl
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
@@ -1649,6 +1672,9 @@ If you redefine a subroutine you may find that the original subroutine is not
 reported on.  This is because I haven't yet found a way to locate the original
 CV.  Hints, tips or patches to resolve this will be gladly accepted.
 
+The module Test::TestCoverage uses this technique and so should not be used in
+conjunction with Devel::Cover.
+
 =head1 BUGS
 
 Almost certainly.
diff --git a/lib/Devel/Cover/Annotation/Git.pm b/lib/Devel/Cover/Annotation/Git.pm
index c8f205c..c4837ee 100644
--- a/lib/Devel/Cover/Annotation/Git.pm
+++ b/lib/Devel/Cover/Annotation/Git.pm
@@ -10,7 +10,7 @@ package Devel::Cover::Annotation::Git;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use Getopt::Long;
 
@@ -121,7 +121,7 @@ Devel::Cover::Annotation::Git - Annotate with git information
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/Annotation/Random.pm b/lib/Devel/Cover/Annotation/Random.pm
index 5bc92c3..856c2b1 100644
--- a/lib/Devel/Cover/Annotation/Random.pm
+++ b/lib/Devel/Cover/Annotation/Random.pm
@@ -10,7 +10,7 @@ package Devel::Cover::Annotation::Random;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use Getopt::Long;
 
@@ -78,7 +78,7 @@ Devel::Cover::Annotation::Random - Example annotation for formatters
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/Annotation/Svk.pm b/lib/Devel/Cover/Annotation/Svk.pm
index 2df3a0e..54fbde1 100644
--- a/lib/Devel/Cover/Annotation/Svk.pm
+++ b/lib/Devel/Cover/Annotation/Svk.pm
@@ -10,7 +10,7 @@ package Devel::Cover::Annotation::Svk;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use Getopt::Long;
 use Digest::MD5;
@@ -144,7 +144,7 @@ Devel::Cover::Annotation::Svk - Annotate with svk information
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/Branch.pm b/lib/Devel/Cover/Branch.pm
index e8d967d..552085c 100644
--- a/lib/Devel/Cover/Branch.pm
+++ b/lib/Devel/Cover/Branch.pm
@@ -10,7 +10,7 @@ package Devel::Cover::Branch;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use base "Devel::Cover::Criterion";
 
@@ -66,7 +66,7 @@ Devel::Cover::Branch - Code coverage metrics for Perl
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/Collection.pm b/lib/Devel/Cover/Collection.pm
new file mode 100644
index 0000000..0820e60
--- /dev/null
+++ b/lib/Devel/Cover/Collection.pm
@@ -0,0 +1,665 @@
+# Copyright 2014, Paul Johnson (paul at pjcj.net)
+
+# This software is free.  It is licensed under the same terms as Perl itself.
+
+# The latest version of this software should be available from my homepage:
+# http://www.pjcj.net
+
+package Devel::Cover::Collection;
+
+use 5.16.0;
+use warnings;
+
+our $VERSION = '1.15'; # VERSION
+
+use Devel::Cover::DB;
+use Devel::Cover::DB::IO::JSON;
+use Devel::Cover::Dumper;
+
+use Parallel::Iterator "iterate_as_array";
+use POSIX              "setsid";
+use Template;
+use Time::HiRes        "time";
+
+use Class::XSAccessor ();
+use Moo;
+use namespace::clean;
+use warnings FATAL => "all";  # be explicit since Moo sets this
+
+my %A = (
+    ro  => [ qw( bin_dir cpancover_dir cpan_dir results_dir force output_file
+                 report timeout verbose workers docker                      ) ],
+    rwp => [ qw( build_dirs local_timeout modules module_file               ) ],
+    rw  => [ qw(                                                            ) ],
+);
+while (my ($type, $names) = each %A) { has $_ => (is => $type) for @$names }
+
+sub BUILDARGS {
+    my $class = shift;
+    my (%args) = @_;
+    {
+        build_dirs      => [],
+        cpan_dir        => [grep -d, glob("~/.cpan ~/.local/share/.cpan")],
+        docker          => "docker",
+        force           => 0,
+        local_timeout   => 0,
+        modules         => [],
+        output_file     => "index.html",
+        report          => "html_basic",
+        timeout         => 1800,  # half an hour
+        verbose         => 0,
+        workers         => 0,
+        %args,
+    }
+};
+
+# display $non_buffered characters, then buffer
+sub _sys {
+    my $self = shift;
+    my ($non_buffered, @command) = @_;
+    my ($output1, $output2) = ("", "");
+    $output1 = "dc -> @command\n" if $self->verbose;
+    my $timeout = $self->local_timeout || $self->timeout || 30 * 60;
+    my $max = 4e4;
+    # say "Setting alarm for $timeout seconds";
+    my $pid;
+    eval {
+        open STDIN, "<", "/dev/null" or die "Can't read /dev/null: $!";
+        $pid = open my $fh, "-|"     // die "Can't fork: $!";
+        if ($pid) {
+            my $printed = 0;
+            local $SIG{ALRM} = sub { die "alarm\n" };
+            alarm $timeout;
+            while (<$fh>) {
+                # print "got: $_";
+                # say "printed $printed of $non_buffered";
+                if ($printed < $non_buffered) {
+                    print;
+                    if (($printed += length) >= $non_buffered) {
+                        say "Devel::Cover: buffering ...";
+                    }
+                } elsif (length $output2) {
+                    $output2 = substr $output2 . $_, $max * -.1, $max * .1;
+                } else {
+                    $output1 .= $_;
+                    if (length $output1 > $max * .9) {
+                        $output1 = substr $output1, 0, $max * .9;
+                        $output2 = "\n";
+                    }
+                }
+            }
+            alarm 0;
+        } else {
+            setsid() != -1          or die "Can't start a new session: $!";
+            open STDERR, ">&STDOUT" or die "Can't dup stdout: $!";
+            exec @command           or die "Can't exec @command: $!";
+        }
+    };
+    if ($@) {
+        die "propogate: $@" unless $@ eq "alarm\n";   # propagate unexpected errors
+        warn "Timed out after $timeout seconds!\n";
+        my $pgrp = getpgrp($pid);
+        my $n = kill "-KILL", $pgrp;
+        warn "killed $n processes";
+    }
+    length $output2 ? "$output1\n...\n$output2" : $output1
+}
+
+sub sys  { my $self = shift; $self->_sys(4e4, @_) }
+sub bsys { my $self = shift; $self->_sys(0,   @_) }
+
+sub add_modules {
+    my $self = shift;
+    push @{$self->modules}, @_;
+}
+
+sub set_modules {
+    my $self = shift;
+    @{$self->modules} = @_;
+}
+
+sub set_module_file {
+    my $self = shift;
+    my ($file) = @_;
+    $self->set_module_file($file);
+}
+
+sub process_module_file {
+    my $self = shift;
+    my $file = $self->module_file;
+    return unless defined $file && length $file;
+    open my $fh, "<", $file or die "Can't open $file: $!";
+    my $modules = do { local $/; <$fh> };
+    close $fh or die "Can't close $file: $!";
+    my @modules = grep /\S/, grep !/^ *#/, split /\n/, $modules;
+    $self->add_modules(@modules);
+}
+
+sub build_modules {
+    my $self = shift;
+    my @command = qw( cpan -i -T );
+    push @command, "-f" if $self->force;
+    # my @command = qw( cpan );
+    # $ENV{CPAN_OPTS} = "-i -T";
+    # $ENV{CPAN_OPTS} .= " -f" if $self->force;
+    # $self->_set_local_timeout(300);
+    my %m;
+    for my $module (sort grep !$m{$_}++, @{$self->modules}) {
+        say "Building $module";
+        my $output = $self->sys(@command, $module);
+        say $output;
+    }
+    $self->_set_local_timeout(0);
+}
+
+sub add_build_dirs {
+    my $self = shift;
+    push @{$self->build_dirs},
+         grep -d,
+         map glob("$_/build/*"), @{$self->cpan_dir};
+}
+
+sub run {
+    my $self = shift;
+    my ($build_dir) = @_;
+
+    my ($module)    = $build_dir =~ m|.*/([^/]+?)(?:-\w{6})$| or return;
+    my $db          = "$build_dir/cover_db";
+    my $line        = "=" x 80;
+    my $output      = "**** Checking coverage of $module ****\n";
+    my $results_dir = $self->results_dir // die "No results dir";
+    $output        .= $self->sys("mkdir", "-p", $results_dir);
+    $results_dir   .= "/$module";
+
+    chdir $build_dir or die "Can't chdir $build_dir: $!\n";
+    say "Checking coverage of $module";
+
+    if (-d $db || -d "$build_dir/structure" || -d $results_dir) {
+        $output .= "Already analysed\n";
+        unless ($self->force) {
+            say "\n$line\n$output$line\n";
+            return;
+        }
+    }
+
+    $output .= "Testing $module in $build_dir\n";
+    # say "\n$line\n$output$line\n"; return;
+
+    $ENV{DEVEL_COVER_TEST_OPTS} = "-Mblib=" . $self->bin_dir;
+    my @cmd = ($^X, $ENV{DEVEL_COVER_TEST_OPTS}, $self->bin_dir . "/cover");
+    $output .= $self->bsys(
+        @cmd,          "-test",
+        "-report",     $self->report,
+        "-outputfile", $self->output_file,
+    );
+    $output .= $self->sys(@cmd, "-report", "json", "-nosummary");
+
+    # TODO - option to merge DB with existing one
+    # TODO - portability
+    $output .= $self->sys("rm", "-rf", $results_dir);
+    $output .= $self->sys("mv", $db, $results_dir);
+    $output .= $self->sys("rm", "-rf", $db);
+
+    say "\n$line\n$output$line\n";
+}
+
+sub run_all {
+    my $self = shift;
+
+    my $results_dir = $self->results_dir // die "No results dir";
+    $self->sys("mkdir", "-p", $results_dir);
+
+    my @res = iterate_as_array(
+        { workers => $self->workers },
+        sub {
+            my (undef, $dir) = @_;
+            eval { $self->run($dir) };
+            warn "\n\n\n[$dir]: $@\n\n\n" if $@;
+        },
+        $self->build_dirs
+    );
+    # print Dumper \@res;
+}
+
+sub write_json {
+    my $self = shift;
+    my ($vars) = @_;
+
+    # print Dumper $vars;
+    my $results = {};
+    for my $module (keys %{$vars->{vals}}) {
+        my $m   = $vars->{vals}{$module};
+        my $mod = $m->{module};
+        my ($name, $version) =
+            ($mod->{module} // $module) =~ /(.+)-(\d+\.\d+)$/;
+        $name    = $mod->{name}     if defined $mod->{name};
+        $version = $mod->{version}  if defined $mod->{version};
+        if (defined $name && defined $version) {
+            $results->{$name}{$version}{coverage}{total} = {
+                map { $_ => $m->{$_}{pc} }
+                grep $m->{$_}{pc} ne 'n/a',
+                grep !/link|module/,
+                keys %$m
+            };
+        } else {
+            print "Cannot process $module: ", Dumper $m;
+        }
+    };
+    # print Dumper $vars, $results;
+
+    my $io = Devel::Cover::DB::IO::JSON->new(options => "pretty");
+    my $file = $self->results_dir . "/cpancover.json";
+    $io->write($results, $file);
+    say "Wrote json output to $file";
+}
+
+sub class
+{
+    my ($pc) = @_;
+    $pc eq "n/a" ? "na" :
+    $pc <    75  ? "c0" :
+    $pc <    90  ? "c1" :
+    $pc <   100  ? "c2" :
+                   "c3"
+}
+
+sub generate_html {
+    my $self = shift;
+
+    my $d = $self->results_dir;
+    chdir $d or die "Can't chdir $d: $!\n";
+
+    my $f = "$d/index.html";
+    say "\n\nWriting collection output to $f ...";
+
+    my $vars = {
+        title    => "Coverage report",
+        modules  => [],
+        vals     => {},
+        headers  => [ grep !/path|time/,
+                           @Devel::Cover::DB::Criteria_short, "total" ],
+        criteria => [ grep !/path|time/,
+                           @Devel::Cover::DB::Criteria,       "total" ],
+    };
+
+    opendir my $dh, $d or die "Can't opendir $d: $!";
+    my @modules = sort grep !/^\./, readdir $dh;
+    closedir $dh or die "Can't closedir $d: $!";
+
+    for my $module (@modules) {
+        my $cover = "$d/$module/cover.json";
+        next unless -e $cover;
+        say "Adding $module";
+
+        my $io   = Devel::Cover::DB::IO::JSON->new;
+        my $json = $io->read($cover);
+
+        my $mod = {
+            module => $module,
+            map { $_ => $json->{runs}[0]{$_} } qw( name version dir )
+        };
+        unless (defined $mod->{name} && defined $mod->{version}) {
+            my ($name, $version) =
+                ($mod->{module} // $module) =~ /(.+)-(\d+\.\d+)$/;
+            $mod->{name}    //= $name;
+            $mod->{version} //= $version;
+        }
+        push @{$vars->{modules}}, $mod;
+
+        my $m = $vars->{vals}{$module} = {};
+        $m->{module} = $mod;
+        $m->{link}   = "$module/index.html"
+            if $json->{summary}{Total}{total}{total};
+
+        for my $criterion (@{$vars->{criteria}}) {
+            my $summary = $json->{summary}{Total}{$criterion};
+            # print "summary:", Dumper $summary;
+            my $pc = $summary->{percentage};
+            $pc = defined $pc ? sprintf "%.2f", $pc : "n/a";
+            $m->{$criterion}{pc}      = $pc;
+            $m->{$criterion}{class}   = class($pc);
+            $m->{$criterion}{details} =
+                ($summary->{covered} || 0) . " / " . ($summary->{total} || 0);
+        }
+    }
+    # print "vars ", Dumper $vars;
+
+    $self->write_stylesheet;
+    my $template = Template->new({
+        LOAD_TEMPLATES => [
+            Devel::Cover::Collection::Template::Provider->new({}),
+        ],
+    });
+    $template->process("summary", $vars, $f) or die $template->error;
+
+    $self->write_json($vars);
+
+    say "Wrote collection output to $f";
+}
+
+sub local_build {
+    my $self = shift;
+
+    $self->process_module_file;
+    $self->build_modules;
+    $self->add_build_dirs;
+    $self->run_all;
+    $self->generate_html;
+}
+
+sub cover_modules {
+    my $self = shift;
+
+    $self->process_module_file;
+
+    my @command = qw( utils/dc cpancover-docker-module );
+    $self->_set_local_timeout(0);
+    my @res = iterate_as_array(
+        { workers => $self->workers },
+        sub {
+            my (undef, $module) = @_;
+            my $dir = $module =~ s|.*/||r
+                              =~ s/\.(?:zip|tgz|(?:tar\.(?:gz|bz2)))$//r;
+            if (-d $self->results_dir . "/$dir") {
+                say "$module already covered";
+                return;
+            }
+            my $timeout = $self->local_timeout || $self->timeout || 30 * 60;
+            # say "Setting alarm for $timeout seconds";
+            my $name = sprintf("%s-%18.6f", $module, time)
+                         =~ tr/a-zA-Z0-9_./-/cr;
+            say "$dir -> $name";
+            eval {
+                local $SIG{ALRM} = sub { die "alarm\n" };
+                alarm $timeout;
+                system @command, $module, $name;
+                alarm 0;
+                say "$dir done";
+            };
+            if ($@) {
+                die "propogate: $@" unless $@ eq "alarm\n";  # unexpected errors
+                say "Timed out after $timeout seconds!";
+                $self->sys($self->docker, "kill", $name);
+                say "Killed docker container $name";
+            }
+        },
+        do { my %m; [sort grep !$m{$_}++, @{$self->modules}] }
+    );
+    $self->_set_local_timeout(0);
+}
+
+sub get_latest {
+    my $self = shift;
+
+    require CPAN::Releases::Latest;
+
+    my $latest   = CPAN::Releases::Latest->new;
+    my $iterator = $latest->release_iterator;
+
+    while (my $release = $iterator->next_release) {
+        say $release->path;
+        next;
+        printf "%s path=%s  time=%d  size=%d\n",
+               $release->distname,
+               $release->path,
+               $release->timestamp,
+               $release->size;
+    }
+}
+
+sub write_stylesheet {
+    my $self = shift;
+
+    my $css = $self->results_dir . "/collection.css";
+    open my $fh, ">", $css or die "Can't open $css: $!\n";
+    print $fh <<EOF;
+/* Stylesheet for Devel::Cover collection reports */
+
+/* You may modify this file to alter the appearance of your coverage
+ * reports. If you do, you should probably flag it read-only to prevent
+ * future runs from overwriting it.
+ */
+
+/* Note: default values use the color-safe web palette. */
+
+body {
+    font-family: sans-serif;
+}
+
+h1 {
+    text-align : center;
+    background-color: #cc99ff;
+    border: solid 1px #999999;
+    padding: 0.2em;
+    -moz-border-radius: 10px;
+}
+
+a {
+    color: #000000;
+}
+a:visited {
+    color: #333333;
+}
+
+table {
+    border-spacing: 0px;
+}
+tr {
+    text-align : center;
+    vertical-align: top;
+}
+th,.h,.hh {
+    background-color: #cccccc;
+    border: solid 1px #333333;
+    padding: 0em 0.2em;
+    -moz-border-radius: 4px;
+}
+td {
+    border: solid 1px #cccccc;
+    border-top: none;
+    border-left: none;
+    -moz-border-radius: 4px;
+}
+.hblank {
+    height: 0.5em;
+}
+.dblank {
+    border: none;
+}
+
+/* source code */
+pre,.s {
+    text-align: left;
+    font-family: monospace;
+    white-space: pre;
+    padding: 0.2em 0.5em 0em 0.5em;
+}
+
+/* Classes for color-coding coverage information:
+ *   c0  : path not covered or coverage < 75%
+ *   c1  : coverage >= 75%
+ *   c2  : coverage >= 90%
+ *   c3  : path covered or coverage = 100%
+ */
+.c0 {
+    background-color: #ff9999;
+    border: solid 1px #cc0000;
+}
+.c1 {
+    background-color: #ffcc99;
+    border: solid 1px #ff9933;
+}
+.c2 {
+    background-color: #ffff99;
+    border: solid 1px #cccc66;
+}
+.c3 {
+    background-color: #99ff99;
+    border: solid 1px #009900;
+}
+EOF
+
+    close $fh or die "Can't close $css: $!\n";
+}
+
+package Devel::Cover::Collection::Template::Provider;
+
+use strict;
+use warnings;
+
+our $VERSION = '1.15'; # VERSION
+
+use base "Template::Provider";
+
+my %Templates;
+
+sub fetch
+{
+    my $self = shift;
+    my ($name) = @_;
+    # print "Looking for <$name>\n";
+    $self->SUPER::fetch(exists $Templates{$name} ? \$Templates{$name} : $name)
+}
+
+$Templates{colours} = <<'EOT';
+[%
+    colours = {
+        default => "#ffffad",
+        text    => "#000000",
+        number  => "#ffffc0",
+        error   => "#ff0000",
+        ok      => "#00ff00",
+    }
+%]
+
+[% MACRO bg BLOCK -%]
+bgcolor="[% colours.$colour %]"
+[%- END %]
+EOT
+
+$Templates{html} = <<'EOT';
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+This file was generated by Devel::Cover Version $VERSION
+Devel::Cover is copyright 2001-2014, Paul Johnson (paul\@pjcj.net)
+Devel::Cover is free. It is licensed under the same terms as Perl itself.
+The latest version of Devel::Cover should be available from my homepage:
+http://www.pjcj.net
+-->
+[% PROCESS colours %]
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+    <meta http-equiv="Content-Language" content="en-us"></meta>
+    <link rel="stylesheet" type="text/css" href="collection.css"></link>
+    <title> [% title %] </title>
+</head>
+<body>
+    [% content %]
+</body>
+</html>
+EOT
+
+$Templates{summary} = <<'EOT';
+[% WRAPPER html %]
+
+<h1> [% title %] </h1>
+
+<table>
+
+    [% IF modules %]
+        <tr align="right" valign="middle">
+            <th class="header" align="left" style='white-space: nowrap;'> Module </th>
+            <th class="header">              Version </th>
+            [% FOREACH header = headers %]
+                <th class="header"> [% header %] </th>
+            [% END %]
+        </tr>
+    [% END %]
+
+    [% FOREACH module = modules %]
+        [% m = module.module %]
+        <tr align="right" valign="middle">
+            <td align="left">
+                [% IF vals.$m.link %]
+                    <a href="[%- vals.$m.link -%]">
+                        [% module.name || module.module %]
+                    </a>
+                [% ELSE %]
+                    [% module.name || module.module %]
+                [% END %]
+            </td>
+            <td> [% module.version %] </td>
+            [% FOREACH criterion = criteria %]
+                <td class="[%- vals.$m.$criterion.class -%]"
+                    title="[%- vals.$m.$criterion.details -%]">
+                    [% vals.$m.$criterion.pc %]
+                </td>
+            [% END %]
+        </tr>
+    [% END %]
+
+</table>
+
+<br/>
+
+<hr/>
+Coverage information from <a href="https://metacpan.org/module/Devel::Cover">
+  Devel::Cover
+</a> by <a href="http://pjcj.net">Paul Johnson</a>.
+
+<br/>
+
+<a href="http://cpancover.com/blead/latest/coverage.html">Core coverage</a>
+(under development)
+
+<br/>
+<br/>
+
+This server generously donated by
+<a href="http://www.bytemark.co.uk/r/cpancover">
+  <img src="http://www.bytemark.co.uk/images/subpages/spreadtheword/bytemark_logo_179_x_14.png" alt="bytemark"/>
+</a>
+
+[% END %]
+EOT
+
+"
+We have normality, I repeat we have normality.
+Anything you still can’t cope with is therefore your own problem.
+"
+
+__END__
+
+=head1 NAME
+
+Devel::Cover::Collection - Code coverage for a collection of modules
+
+=head1 VERSION
+
+version 1.15
+
+=head1 SYNOPSIS
+
+=head1 DESCRIPTION
+
+=head1 OPTIONS
+
+=head1 ENVIRONMENT
+
+=head1 BUGS
+
+Almost certainly.
+
+=head1 LICENCE
+
+Copyright 2014, Paul Johnson (paul at pjcj.net)
+
+This software is free.  It is licensed under the same terms as Perl itself.
+
+The latest version of this software should be available on CPAN and from my
+homepage: http://www.pjcj.net/.
+
+=cut
diff --git a/lib/Devel/Cover/Condition.pm b/lib/Devel/Cover/Condition.pm
index 0cb9590..4faa9b4 100644
--- a/lib/Devel/Cover/Condition.pm
+++ b/lib/Devel/Cover/Condition.pm
@@ -10,7 +10,7 @@ package Devel::Cover::Condition;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use base "Devel::Cover::Branch";
 
@@ -31,7 +31,7 @@ Devel::Cover::Condition - Code coverage metrics for Perl
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/Condition_and_2.pm b/lib/Devel/Cover/Condition_and_2.pm
index 55ce503..0c6d809 100644
--- a/lib/Devel/Cover/Condition_and_2.pm
+++ b/lib/Devel/Cover/Condition_and_2.pm
@@ -10,7 +10,7 @@ package Devel::Cover::Condition_and_2;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use base "Devel::Cover::Condition";
 
@@ -27,7 +27,7 @@ Devel::Cover::Condition_and_2 - Code coverage metrics for Perl
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/Condition_and_3.pm b/lib/Devel/Cover/Condition_and_3.pm
index 266ed29..8bd0a16 100644
--- a/lib/Devel/Cover/Condition_and_3.pm
+++ b/lib/Devel/Cover/Condition_and_3.pm
@@ -10,7 +10,7 @@ package Devel::Cover::Condition_and_3;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use base "Devel::Cover::Condition";
 
@@ -27,7 +27,7 @@ Devel::Cover::Condition_and_3 - Code coverage metrics for Perl
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/Condition_or_2.pm b/lib/Devel/Cover/Condition_or_2.pm
index e8a5249..b959c62 100644
--- a/lib/Devel/Cover/Condition_or_2.pm
+++ b/lib/Devel/Cover/Condition_or_2.pm
@@ -10,7 +10,7 @@ package Devel::Cover::Condition_or_2;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use base "Devel::Cover::Condition";
 
@@ -27,7 +27,7 @@ Devel::Cover::Condition_or_2 - Code coverage metrics for Perl
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/Condition_or_3.pm b/lib/Devel/Cover/Condition_or_3.pm
index 5abf312..46a9a25 100644
--- a/lib/Devel/Cover/Condition_or_3.pm
+++ b/lib/Devel/Cover/Condition_or_3.pm
@@ -10,7 +10,7 @@ package Devel::Cover::Condition_or_3;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use base "Devel::Cover::Condition";
 
@@ -27,7 +27,7 @@ Devel::Cover::Condition_or_3 - Code coverage metrics for Perl
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/Condition_xor_4.pm b/lib/Devel/Cover/Condition_xor_4.pm
index 769939d..7782a00 100644
--- a/lib/Devel/Cover/Condition_xor_4.pm
+++ b/lib/Devel/Cover/Condition_xor_4.pm
@@ -10,7 +10,7 @@ package Devel::Cover::Condition_xor_4;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use base "Devel::Cover::Condition";
 
@@ -27,7 +27,7 @@ Devel::Cover::Condition_xor_4 - Code coverage metrics for Perl
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/Criterion.pm b/lib/Devel/Cover/Criterion.pm
index 2341375..1f81654 100644
--- a/lib/Devel/Cover/Criterion.pm
+++ b/lib/Devel/Cover/Criterion.pm
@@ -10,7 +10,7 @@ package Devel::Cover::Criterion;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use Devel::Cover::Statement;
 use Devel::Cover::Branch;
@@ -76,7 +76,7 @@ Devel::Cover::Criterion - Code coverage metrics for Perl
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/DB.pm b/lib/Devel/Cover/DB.pm
index 033c332..6b928b0 100644
--- a/lib/Devel/Cover/DB.pm
+++ b/lib/Devel/Cover/DB.pm
@@ -10,7 +10,7 @@ package Devel::Cover::DB;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use Devel::Cover::Criterion;
 use Devel::Cover::DB::File;
@@ -22,7 +22,7 @@ use File::Path;
 
 use Devel::Cover::Dumper;  # For debugging
 
-my $DB = "cover.13";  # Version 13 of the database.
+my $DB = "cover.14";  # Version of the database.
 
 @Devel::Cover::DB::Criteria =
     (qw( statement branch path condition subroutine pod time ));
@@ -357,6 +357,8 @@ sub calculate_summary {
         $c->calculate_percentage($self, $t->{$criterion});
     }
     Devel::Cover::Criterion->calculate_percentage($self, $t->{total});
+
+    # print STDERR Dumper $self->{summary};
 }
 
 sub trimmed_file {
@@ -890,7 +892,7 @@ Devel::Cover::DB - Code coverage metrics for Perl
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
@@ -948,7 +950,7 @@ Devel::Cover::DB::Criterion->locations, and Devel::Cover::DB::Location->data
 
 =item * Devel::Cover::DB::Base->get
 
-Aliased to Devel::Cover::DB::Cover->file, Devel::Cover::DB::File->criteriom,
+Aliased to Devel::Cover::DB::Cover->file, Devel::Cover::DB::File->criterion,
 Devel::Cover::DB::Criterion->location, and Devel::Cover::DB::Location->datum
 
 =back
diff --git a/lib/Devel/Cover/DB/Digests.pm b/lib/Devel/Cover/DB/Digests.pm
index 224651a..39ed6fd 100644
--- a/lib/Devel/Cover/DB/Digests.pm
+++ b/lib/Devel/Cover/DB/Digests.pm
@@ -10,7 +10,7 @@ package Devel::Cover::DB::Digests;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use Devel::Cover::DB::Structure;
 use Devel::Cover::DB::IO;
@@ -90,7 +90,7 @@ Devel::Cover::DB::Digests - store digests for Devel::Cover::DB
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/DB/File.pm b/lib/Devel/Cover/DB/File.pm
index 6479c2b..c99e630 100644
--- a/lib/Devel/Cover/DB/File.pm
+++ b/lib/Devel/Cover/DB/File.pm
@@ -10,7 +10,7 @@ package Devel::Cover::DB::File;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use Devel::Cover::Criterion;
 
@@ -59,7 +59,7 @@ Devel::Cover::DB::File - Code coverage metrics for Perl
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/DB/IO.pm b/lib/Devel/Cover/DB/IO.pm
index 537ef9d..2fe26f6 100644
--- a/lib/Devel/Cover/DB/IO.pm
+++ b/lib/Devel/Cover/DB/IO.pm
@@ -10,7 +10,7 @@ package Devel::Cover::DB::IO;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 my $Format;
 
@@ -46,7 +46,7 @@ Devel::Cover::DB::IO - IO routines for Devel::Cover::DB
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/DB/IO/JSON.pm b/lib/Devel/Cover/DB/IO/JSON.pm
index 2c76296..c863b48 100644
--- a/lib/Devel/Cover/DB/IO/JSON.pm
+++ b/lib/Devel/Cover/DB/IO/JSON.pm
@@ -12,7 +12,7 @@ use warnings;
 
 use Fcntl ":flock";
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 my $Format;
 
@@ -24,7 +24,7 @@ BEGIN {
 
 sub new {
     my $class = shift;
-    my $self  = { @_ };
+    my $self  = { options => "", @_ };
     bless $self, $class
 }
 
@@ -70,7 +70,7 @@ Devel::Cover::DB::IO::JSON - JSON based IO routines for Devel::Cover::DB
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/DB/IO/Sereal.pm b/lib/Devel/Cover/DB/IO/Sereal.pm
index 53d44d9..3cbaa15 100644
--- a/lib/Devel/Cover/DB/IO/Sereal.pm
+++ b/lib/Devel/Cover/DB/IO/Sereal.pm
@@ -14,7 +14,7 @@ use Fcntl ":flock";
 use Sereal::Decoder;
 use Sereal::Encoder;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 my $Decoder;
 my $Encoder;
@@ -64,7 +64,7 @@ Devel::Cover::DB::IO::Sereal - Sereal based IO routines for Devel::Cover::DB
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/DB/IO/Storable.pm b/lib/Devel/Cover/DB/IO/Storable.pm
index 0107144..6afdd33 100644
--- a/lib/Devel/Cover/DB/IO/Storable.pm
+++ b/lib/Devel/Cover/DB/IO/Storable.pm
@@ -12,7 +12,7 @@ use warnings;
 
 use Storable;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 sub new {
     my $class = shift;
@@ -43,7 +43,7 @@ Devel::Cover::DB::IO::Storable - Storable based IO routines for Devel::Cover::DB
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/DB/Structure.pm b/lib/Devel/Cover/DB/Structure.pm
index e5abb6b..7e92f26 100644
--- a/lib/Devel/Cover/DB/Structure.pm
+++ b/lib/Devel/Cover/DB/Structure.pm
@@ -20,7 +20,7 @@ use Devel::Cover::Dumper;
 # For comprehensive debug logging.
 use constant DEBUG => 0;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 our $AUTOLOAD;
 
 sub new {
@@ -349,7 +349,7 @@ Devel::Cover::DB::Structure - Internal: abstract structure of a source file
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/Dumper.pm b/lib/Devel/Cover/Dumper.pm
index b986d0b..f578769 100644
--- a/lib/Devel/Cover/Dumper.pm
+++ b/lib/Devel/Cover/Dumper.pm
@@ -13,7 +13,7 @@ package  # Private module
 use strict qw( vars subs );  # no refs
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 sub import {
     my $caller = caller;
@@ -44,7 +44,7 @@ Devel::Cover::Dumper - Internal module for debugging purposes
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/Html_Common.pm b/lib/Devel/Cover/Html_Common.pm
index dbbdcb1..3bd7162 100644
--- a/lib/Devel/Cover/Html_Common.pm
+++ b/lib/Devel/Cover/Html_Common.pm
@@ -3,7 +3,7 @@ BEGIN {require 5.006}
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use Exporter;
 
@@ -29,7 +29,7 @@ Devel::Cover::Report::Html_Common - Common code for HTML reporters
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 DESCRIPTION
 
diff --git a/lib/Devel/Cover/Op.pm b/lib/Devel/Cover/Op.pm
index 37998b4..fb149bb 100644
--- a/lib/Devel/Cover/Op.pm
+++ b/lib/Devel/Cover/Op.pm
@@ -12,7 +12,7 @@ require 5.8.0;  # My patches to B::Concise didn't get released till 5.8.0.
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use Devel::Cover::Dumper;
 
@@ -84,7 +84,7 @@ Devel::Cover::Op - B::Concise with coverage data
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/Pod.pm b/lib/Devel/Cover/Pod.pm
index 07fe9d4..f9d29e7 100644
--- a/lib/Devel/Cover/Pod.pm
+++ b/lib/Devel/Cover/Pod.pm
@@ -10,7 +10,7 @@ package Devel::Cover::Pod;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use base "Devel::Cover::Criterion";
 
@@ -47,7 +47,7 @@ Devel::Cover::Pod - Code coverage metrics for Perl
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/Report/Compilation.pm b/lib/Devel/Cover/Report/Compilation.pm
index 4a5f2ec..58a95b4 100644
--- a/lib/Devel/Cover/Report/Compilation.pm
+++ b/lib/Devel/Cover/Report/Compilation.pm
@@ -18,7 +18,7 @@ package Devel::Cover::Report::Compilation;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use Devel::Cover::DB;
 
@@ -131,7 +131,7 @@ Devel::Cover::Report::Compilation - backend for Devel::Cover
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/Report/Html.pm b/lib/Devel/Cover/Report/Html.pm
index 44babf7..f0a748e 100644
--- a/lib/Devel/Cover/Report/Html.pm
+++ b/lib/Devel/Cover/Report/Html.pm
@@ -10,7 +10,7 @@ package Devel::Cover::Report::Html;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use base "Devel::Cover::Report::Html_minimal";
 
@@ -24,7 +24,7 @@ Devel::Cover::Report::Html - HTML backend for Devel::Cover
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/Report/Html_basic.pm b/lib/Devel/Cover/Report/Html_basic.pm
index 90203ef..23c1d65 100644
--- a/lib/Devel/Cover/Report/Html_basic.pm
+++ b/lib/Devel/Cover/Report/Html_basic.pm
@@ -10,7 +10,7 @@ package Devel::Cover::Report::Html_basic;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 our $LVERSION = do { eval '$VERSION' || "0.001" };  # for development purposes
 
 use Devel::Cover::DB;
@@ -371,7 +371,11 @@ sub report {
     my $le = sub { ($_[0] >   0 ? "<" : "=") . " $_[0]" };
     my $ge = sub { ($_[0] < 100 ? ">" : "") . "= $_[0]" };
 
+    my $fname = (sort keys %{$db->{runs}})[0] or return;
+    my $run   = $db->{runs}{$fname};
+
     %R = (
+        module  => { name => $run->name, version => $run->version },
         db      => $db,
         date    => do {
             my ($sec, $min, $hour, $mday, $mon, $year) = localtime;
@@ -428,7 +432,7 @@ package Devel::Cover::Report::Html_basic::Template::Provider;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use base "Template::Provider";
 
@@ -505,6 +509,14 @@ $Templates{summary} = <<'EOT';
 <h1> Coverage Summary </h1>
 <table>
     <tr>
+        <td class="sh" align="right">Module</td>
+        <td class="sv" align="left" colspan="4">[% R.module.name %]</td>
+    </tr>
+    <tr>
+        <td class="sh" align="right">Version</td>
+        <td class="sv" align="left" colspan="4">[% R.module.version %]</td>
+    </tr>
+    <tr>
         <td class="sh" align="right">Database:</td>
         <td class="sv" align="left" colspan="4">[% R.db.db %]</td>
     </tr>
@@ -779,7 +791,7 @@ Devel::Cover::Report::Html_basic - HTML backend for Devel::Cover
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/Report/Html_minimal.pm b/lib/Devel/Cover/Report/Html_minimal.pm
index 7f66990..764d923 100644
--- a/lib/Devel/Cover/Report/Html_minimal.pm
+++ b/lib/Devel/Cover/Report/Html_minimal.pm
@@ -8,7 +8,7 @@ use Devel::Cover::DB;
 use Devel::Cover::Html_Common "launch";
 use Devel::Cover::Truth_Table;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 our $LVERSION = do { eval '$VERSION' || "0.001" };  # for development purposes
 
 #-------------------------------------------------------------------------------
@@ -751,7 +751,7 @@ Devel::Cover::Report::Html_minimal - HTML backend for Devel::Cover
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/Report/Html_subtle.pm b/lib/Devel/Cover/Report/Html_subtle.pm
index ce02966..f6b858a 100644
--- a/lib/Devel/Cover/Report/Html_subtle.pm
+++ b/lib/Devel/Cover/Report/Html_subtle.pm
@@ -2,7 +2,7 @@ package Devel::Cover::Report::Html_subtle;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use Devel::Cover::DB;
 use Devel::Cover::Html_Common "launch";
@@ -389,7 +389,7 @@ package Devel::Cover::Report::Html_subtle::Template::Provider;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use base "Template::Provider";
 
@@ -708,7 +708,7 @@ Devel::Cover::Report::Html_subtle - HTML backend for Devel::Cover
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/Report/Json.pm b/lib/Devel/Cover/Report/Json.pm
new file mode 100644
index 0000000..9cb8202
--- /dev/null
+++ b/lib/Devel/Cover/Report/Json.pm
@@ -0,0 +1,87 @@
+# Copyright 2014, Paul Johnson (paul at pjcj.net)
+
+# This software is free.  It is licensed under the same terms as Perl itself.
+
+# The latest version of this software should be available from my homepage:
+# http://www.pjcj.net
+
+package Devel::Cover::Report::Json;
+
+use strict;
+use warnings;
+
+our $VERSION = '1.15'; # VERSION
+
+use Devel::Cover::DB::IO::JSON;
+use Devel::Cover::Dumper;  # For debugging
+
+sub add_runs
+{
+    my ($db) = @_;
+    my @runs;
+    for my $r (sort {$a->{start} <=> $b->{start}} $db->runs) {
+        push @runs, {
+            map { $_ => $r->$_ }
+                qw( run perl OS dir name version abstract start finish )
+        };
+    }
+    \@runs
+}
+
+sub report
+{
+    my ($pkg, $db, $options) = @_;
+
+    my %options = map { $_ => 1 } grep !/path|time/, $db->all_criteria, "force";
+    $db->calculate_summary(%options);
+
+    my $json = {
+        runs    => add_runs($db),
+        summary => $db->{summary},
+    };
+    # print "JSON: ", Dumper $json;
+    print "JSON sent to $options->{outputdir}/cover.json\n";
+
+    my $io = Devel::Cover::DB::IO::JSON->new(options => "pretty");
+    $io->write($json, "$options->{outputdir}/cover.json");
+}
+
+1
+
+__END__
+
+=head1 NAME
+
+Devel::Cover::Report::Json - JSON backend for Devel::Cover
+
+=head1 VERSION
+
+version 1.15
+
+=head1 SYNOPSIS
+
+ cover -report json
+
+=head1 DESCRIPTION
+
+This module provides JSON output for coverage data.
+It is designed to be called from the C<cover> program.
+
+=head1 SEE ALSO
+
+ Devel::Cover
+
+=head1 BUGS
+
+Huh?
+
+=head1 LICENCE
+
+Copyright 2014, Paul Johnson (paul at pjcj.net)
+
+This software is free.  It is licensed under the same terms as Perl itself.
+
+The latest version of this software should be available from my homepage:
+http://www.pjcj.net
+
+=cut
diff --git a/lib/Devel/Cover/Report/Sort.pm b/lib/Devel/Cover/Report/Sort.pm
index 66d5bf2..8ee9d55 100644
--- a/lib/Devel/Cover/Report/Sort.pm
+++ b/lib/Devel/Cover/Report/Sort.pm
@@ -10,7 +10,7 @@ package Devel::Cover::Report::Sort;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use Devel::Cover::DB;
 
@@ -71,7 +71,7 @@ Devel::Cover::Report::Sort - backend for Devel::Cover
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/Report/Text.pm b/lib/Devel/Cover/Report/Text.pm
index a98de7e..924ffa4 100644
--- a/lib/Devel/Cover/Report/Text.pm
+++ b/lib/Devel/Cover/Report/Text.pm
@@ -10,7 +10,7 @@ package Devel::Cover::Report::Text;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use Devel::Cover::DB;
 
@@ -268,7 +268,7 @@ Devel::Cover::Report::Text - Text backend for Devel::Cover
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/Report/Text2.pm b/lib/Devel/Cover/Report/Text2.pm
index 5d657ff..49ffab3 100644
--- a/lib/Devel/Cover/Report/Text2.pm
+++ b/lib/Devel/Cover/Report/Text2.pm
@@ -2,7 +2,7 @@ package Devel::Cover::Report::Text2;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use Devel::Cover::DB;
 use Devel::Cover::Truth_Table;
@@ -170,7 +170,7 @@ Devel::Cover::Report::Test2 - Text backend for Devel::Cover
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/Report/Vim.pm b/lib/Devel/Cover/Report/Vim.pm
index 577e83a..6c1da50 100644
--- a/lib/Devel/Cover/Report/Vim.pm
+++ b/lib/Devel/Cover/Report/Vim.pm
@@ -10,7 +10,7 @@ package Devel::Cover::Report::Vim;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 our $LVERSION = do { eval '$VERSION' || "0.001" };  # for development purposes
 
 use Devel::Cover::DB;
@@ -75,7 +75,7 @@ package Devel::Cover::Report::Vim::Template::Provider;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use base "Template::Provider";
 
@@ -303,7 +303,7 @@ Devel::Cover::Report::Vim - Backend for displaying coverage data in Vim
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/Statement.pm b/lib/Devel/Cover/Statement.pm
index 133203d..7d88314 100644
--- a/lib/Devel/Cover/Statement.pm
+++ b/lib/Devel/Cover/Statement.pm
@@ -10,7 +10,7 @@ package Devel::Cover::Statement;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use base "Devel::Cover::Criterion";
 
@@ -33,7 +33,7 @@ Devel::Cover::Statement - Code coverage metrics for Perl
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/Subroutine.pm b/lib/Devel/Cover/Subroutine.pm
index 0a92e8d..3ffc796 100644
--- a/lib/Devel/Cover/Subroutine.pm
+++ b/lib/Devel/Cover/Subroutine.pm
@@ -10,7 +10,7 @@ package Devel::Cover::Subroutine;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use base "Devel::Cover::Criterion";
 
@@ -32,7 +32,7 @@ Devel::Cover::Statement - Code coverage metrics for Perl
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/Test.pm b/lib/Devel/Cover/Test.pm
index 04f03a2..7d1a63f 100644
--- a/lib/Devel/Cover/Test.pm
+++ b/lib/Devel/Cover/Test.pm
@@ -10,7 +10,7 @@ package Devel::Cover::Test;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use Carp;
 
@@ -204,7 +204,7 @@ sub run_test {
     }
 
     my $version = int(($] - 5) * 1000 + 0.5);
-    if ($version % 2 && $version < 18) {
+    if ($version % 2 && $version < 20) {
         Test::plan tests => 1;
         Test::skip("Perl version $] is an obsolete development version", 1);
         return;
@@ -398,7 +398,7 @@ Devel::Cover::Test - Internal module for testing
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 METHODS
 
diff --git a/lib/Devel/Cover/Time.pm b/lib/Devel/Cover/Time.pm
index 306ff6c..31f219e 100644
--- a/lib/Devel/Cover/Time.pm
+++ b/lib/Devel/Cover/Time.pm
@@ -10,7 +10,7 @@ package Devel::Cover::Time;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use base "Devel::Cover::Criterion";
 
@@ -45,7 +45,7 @@ Devel::Cover::Time - Code coverage metrics for Perl
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/Truth_Table.pm b/lib/Devel/Cover/Truth_Table.pm
index 196dd19..5feb8b1 100644
--- a/lib/Devel/Cover/Truth_Table.pm
+++ b/lib/Devel/Cover/Truth_Table.pm
@@ -180,7 +180,7 @@ sub error {
 package Devel::Cover::Truth_Table;
 use warnings;
 use strict;
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 #-------------------------------------------------------------------------------
 # Subroutine : new()
@@ -467,7 +467,7 @@ Devel::Cover::Truth_Table - Truth tables for coverage objects.
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/Tutorial.pod b/lib/Devel/Cover/Tutorial.pod
index 0d0a133..00c426f 100644
--- a/lib/Devel/Cover/Tutorial.pod
+++ b/lib/Devel/Cover/Tutorial.pod
@@ -6,7 +6,7 @@ Devel::Cover::Tutorial - An introduction to code coverage
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 TUTORIAL
 
diff --git a/lib/Devel/Cover/Util.pm b/lib/Devel/Cover/Util.pm
index 7911d0b..47067e7 100644
--- a/lib/Devel/Cover/Util.pm
+++ b/lib/Devel/Cover/Util.pm
@@ -10,7 +10,7 @@ package Devel::Cover::Util;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use Cwd "abs_path";
 use File::Spec;
@@ -56,7 +56,7 @@ Devel::Cover::Util - Utility subroutines for Devel::Cover
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/lib/Devel/Cover/Web.pm b/lib/Devel/Cover/Web.pm
index eeca625..e60ece3 100644
--- a/lib/Devel/Cover/Web.pm
+++ b/lib/Devel/Cover/Web.pm
@@ -12,7 +12,7 @@ package Devel::Cover::Web;
 use strict;
 use warnings;
 
-our $VERSION = '1.14'; # VERSION
+our $VERSION = '1.15'; # VERSION
 
 use Exporter;
 
@@ -79,23 +79,16 @@ th,.h,.hh,.sh,.sv {
     background-color   : #cccccc;
     border             : solid 1px #333333;
     padding            : 0em 0.2em;
-    width              : 2.5em;
     -moz-border-radius : 4px;
 }
 
-.hh {
-    width: 25%;
-}
-
 .sh {
-    width       : 0;
     color       : #CD5555;
     font-weight : bold;
     padding     : 0.2em;
 }
 
 .sv {
-    width       : 0;
     padding     : 0.2em;
 }
 
@@ -904,7 +897,7 @@ Devel::Cover::Web - Files for JavaScript or CSS
 
 =head1 VERSION
 
-version 1.14
+version 1.15
 
 =head1 SYNOPSIS
 
diff --git a/test_output/cover/inc_sub.5.010000 b/test_output/cover/inc_sub.5.010000
deleted file mode 100644
index 5e25089..0000000
--- a/test_output/cover/inc_sub.5.010000
+++ /dev/null
@@ -1,82 +0,0 @@
-Reading database from ...
-
-
------------------------------------------- ------ ------ ------ ------ ------
-File                                         stmt   bran   cond    sub  total
------------------------------------------- ------ ------ ------ ------ ------
-tests/inc_sub                               100.0   75.0    n/a  100.0   96.3
-Total                                       100.0   75.0    n/a  100.0   96.3
------------------------------------------- ------ ------ ------ ------ ------
-
-
-Run: ...
-Perl version: ...
-OS: ...
-Start: ...
-Finish: ...
-
-tests/inc_sub
-
-line  err   stmt   bran   cond    sub   code
-1                                       #!/bin/perl
-2                                       
-3                                       # Copyright 2002-2014, Paul Johnson (paul at pjcj.net)
-4                                       
-5                                       # This software is free.  It is licensed under the same terms as Perl itself.
-6                                       
-7                                       # The latest version of this software should be available from my homepage:
-8                                       # http://www.pjcj.net
-9                                       
-10                                      # __COVER__ skip_test $] < 5.010
-11                                      # __COVER__ skip_reason %+ not available before 5.10
-12                                      
-13             1                    1   use lib ();
-               1                        
-               1                        
-14                                      
-15                                      BEGIN {
-16                                          lib->import(
-17                                              sub {
-18             3                                    print map("[$_]", @_), "\n";
-19             3    100                             return unless $_[1] eq "IncSub.pm";
-20             1                                    my $fh;
-21    ***      1     50                             open $fh, "tests/IncSub.pm" or die $!;
-22             1                                    $fh
-23                                              }
-24                                          )
-25             1                    1   }
-26                                      
-27             1                    1   use IncSub;
-               1                        
-               1                        
-28                                      
-29             1                    1   BEGIN { "x" =~ /((?<x>x))/; print "$+{x}\n" }  # force Tie::Hash::NamedCapture
-               1                    1   
-               1                        
-               1                        
-               1                        
-30                                      
-31             1                        IncSub::check
-
-
-Branches
---------
-
-line  err      %   true  false   branch
------ --- ------ ------ ------   ------
-19           100      2      1   unless $_[1] eq 'IncSub.pm'
-21    ***     50      0      1   unless open $fh, 'tests/IncSub.pm'
-
-
-Covered Subroutines
--------------------
-
-Subroutine Count Location        
----------- ----- ----------------
-BEGIN          1 tests/inc_sub:13
-BEGIN          1 tests/inc_sub:25
-BEGIN          1 tests/inc_sub:27
-BEGIN          1 tests/inc_sub:29
-BEGIN          1 tests/inc_sub:29
-
-
diff --git a/tests/change.t b/tests/change.t
index 07df9a2..76a82ef 100644
--- a/tests/change.t
+++ b/tests/change.t
@@ -53,7 +53,7 @@ my $test = Devel::Cover::Test->new(
     run_test        => $run_test,
     end             => sub { unlink $ft },
     no_report       => 0,
-    delay_after_run => 0.25,
+    delay_after_run => 0.50,
 );
 
 $test->run_test;
diff --git a/tests/inc_sub b/tests/inc_sub
index 66e2c8b..b22018b 100644
--- a/tests/inc_sub
+++ b/tests/inc_sub
@@ -9,6 +9,8 @@
 
 # __COVER__ skip_test $] < 5.010
 # __COVER__ skip_reason %+ not available before 5.10
+# __COVER__ skip_test 1
+# __COVER__ skip_reason depends too much on specific installed perl
 
 use lib ();
 
diff --git a/tests/md5.t b/tests/md5.t
index a75b91f..ed9cb7d 100644
--- a/tests/md5.t
+++ b/tests/md5.t
@@ -45,7 +45,7 @@ my $test = Devel::Cover::Test->new(
     db_name         => "complex_$t",
     run_test        => $run_test,
     end             => sub { unlink $ft },
-    delay_after_run => 0.25,
+    delay_after_run => 0.50,
 );
 
 $test->run_test;
diff --git a/utils/all_versions b/utils/all_versions
index 6999437..174ef63 100755
--- a/utils/all_versions
+++ b/utils/all_versions
@@ -44,8 +44,8 @@ sub get_options {
                 5.14.0 5.14.1 5.14.2 5.14.3 5.14.4
                 5.16.0 5.16.1 5.16.2 5.16.3
                 5.18.0 5.18.1 5.18.2
-                5.19.0 5.19.1 5.19.2 5.19.3 5.19.4  5.19.5
-                5.19.6 5.19.7 5.19.8 5.19.9 5.19.10 5.19.11
+                5.20.0
+                5.21.0
               )
     ] unless @{$Options->{version}};
     $Silent = " >/dev/null 2>&1" if $Options->{silent};
diff --git a/utils/build_cpancover_perl b/utils/build_cpancover_perl
new file mode 100644
index 0000000..6377014
--- /dev/null
+++ b/utils/build_cpancover_perl
@@ -0,0 +1,5 @@
+#!/bin/sh -x
+
+JOBS=16
+perlbrew uninstall cpancover
+perlbrew install perl-5.18.2 --as cpancover -j $JOBS -nf
diff --git a/utils/cpancover_modules b/utils/cpancover_modules
new file mode 100755
index 0000000..b23bbc0
--- /dev/null
+++ b/utils/cpancover_modules
@@ -0,0 +1,394 @@
+# Stuff for Devel::Cover
+.
+Parallel::Iterator
+Test::Pod::Coverage
+PPI::HTML
+
+# My stuff
+Gedcom
+Shell::Source
+
+# Stuff with interest for Devel::Cover
+NetAddr::IP
+
+# There's going to be repetition down here
+
+# Dual-lived core modules
+Archive::Extract
+Archive::Tar
+Attribute::Handlers
+autodie
+AutoLoader
+autouse
+base
+B::Debug
+bignum
+B::Lint
+Carp
+CGI
+Compress::Raw::Bzip2
+Compress::Raw::Zlib
+Config::Perl::V
+constant
+CPAN
+CPAN::Meta
+CPAN::Meta::Requirements
+CPAN::Meta::YAML
+CPANPLUS
+CPANPLUS::Dist::Build
+Data::Dumper
+DB_File
+Devel::PPPort
+Devel::SelfStubber
+Digest
+Digest::MD5
+Digest::SHA
+Dumpvalue
+Encode
+encoding::warnings
+Env
+Exporter
+ExtUtils::CBuilder
+ExtUtils::Command
+ExtUtils::Constant
+ExtUtils::Install
+ExtUtils::MakeMaker
+ExtUtils::Manifest
+ExtUtils::ParseXS
+File::CheckTree
+File::Fetch
+File::Path
+File::Temp
+Filter::Simple
+Filter::Util::Call
+Getopt::Long
+HTTP::Tiny
+I18N::Collate
+I18N::LangTags
+if
+IO
+IO-Compress
+IO::Zlib
+IPC::Cmd
+IPC::SysV
+JSON::PP
+lib
+libnet
+Locale-Codes
+Locale::Maketext
+Locale::Maketext::Simple
+Log::Message
+Log::Message::Simple
+Math::BigInt
+Math::BigInt::FastCalc
+Math::BigRat
+Math::Complex
+Memoize
+MIME::Base64
+Module::Build
+Module::CoreList
+Module::Load
+Module::Load::Conditional
+Module::Loaded
+Module::Metadata
+Module::Pluggable
+Net::Ping
+NEXT
+Object::Accessor
+Package::Constants
+Params::Check
+parent
+Parse::CPAN::Meta
+PathTools
+perlfaq
+PerlIO::via::QuotedPrint
+Perl::OSType
+Pod::Checker
+Pod::Escapes
+Pod::LaTeX
+podlators
+Pod::Parser
+Pod::Perldoc
+Pod::Simple
+Pod::Usage
+Safe
+Scalar-List-Utils
+Search::Dict
+SelfLoader
+Socket
+Storable
+Sys::Syslog
+Term::ANSIColor
+Term::Cap
+Term::Complete
+Term::ReadLine
+Term::UI
+Test
+Test::Harness
+Test::Simple
+Text::Abbrev
+Text::Balanced
+Text::ParseWords
+Text::Soundex
+Text-Tabs+Wrap
+Thread::Queue
+threads
+Thread::Semaphore
+threads::shared
+Tie::File
+Tie::RefHash
+Time::HiRes
+Time::Local
+Time::Piece
+Unicode::Collate
+Unicode::Normalize
+version
+Win32
+Win32API::File
+XSLoader
+
+# Modules with many dependencies
+Task::Kensho
+Task::Plack
+Task::Catalyst
+Task::Dancer
+Mojolicious
+Task::Moose
+Task::Dist::Zilla
+Task::CPAN::SmokeBox
+Task::Perl::Critic
+Task::Toolchain::Test
+Task::Template::Benchmark
+MojoMojo
+Jifty
+Bot::BasicBot
+Dist::Zilla
+
+# Modules with many dependents
+Exporter
+Text::Tabs
+Test::Harness
+Pod::Escapes
+Pod::Simple
+IO
+Getopt::Long
+Pod::Parser
+ExtUtils::MakeMaker
+Test::Simple
+ExtUtils::Manifest
+constant
+Test
+Data::Dumper
+File::Temp
+ExtUtils::Install
+Text::ParseWords
+ExtUtils::CBuilder
+ExtUtils::ParseXS
+Module::Build
+File::Path
+XSLoader
+MIME::Base64
+Digest
+Digest::MD5
+Sub::Uplevel
+URI
+Test::Exception
+HTML::Tagset
+HTML::Parser
+Compress::Raw::Zlib
+Compress::Raw::Bzip2
+Storable
+base
+List::MoreUtils
+Params::Util
+Task::Weaken
+Sub::Install
+Data::OptList
+Sub::Exporter
+Test::Tester
+Test::NoWarnings
+Attribute::Handlers
+Class::Accessor
+Algorithm::C3
+Class::C3
+Sub::Name
+MRO::Compat
+Time::HiRes
+Params::Validate
+Try::Tiny
+Scope::Guard
+Package::Stash
+version
+Tree::DAG_Node
+Test::Warn
+Devel::GlobalDestruction
+Class::MOP
+Moose
+Class::Data::Inheritable
+Test::Deep
+Carp::Clan
+Module::Pluggable
+Variable::Magic
+B::Hooks::EndOfScope
+Sub::Identify
+namespace::clean
+Time::Local
+DBI
+Text::Balanced
+Class::Inspector
+Test::Pod
+Encode
+Path::Class
+Digest::SHA1
+FCGI
+CGI
+MooseX::Types
+XML::NamespaceSupport
+XML::SAX
+Class::Singleton
+Clone
+DateTime::TimeZone
+DateTime::Locale
+YAML
+DateTime
+namespace::autoclean
+IO::String
+Algorithm::Diff
+File::Slurp
+Devel::StackTrace
+
+# Modules which should not fail
+IO
+List::MoreUtils
+Test::Harness
+ExtUtils::MakeMaker
+File::Path
+XML::Parser
+Test::Simple
+HTML::Tree
+Storable
+Net::IP
+DB_File
+XML::LibXML
+Time::HiRes
+Exporter
+Pod::Escapes
+ExtUtils::ParseXS
+Module::Build
+Pod::Parser
+Data::Dumper
+ExtUtils::Install
+IO::Tty
+XML::SAX
+Class::ErrorHandler
+URI
+HTML::Template
+Compress::Raw::Zlib
+Net::DNS
+Test::Pod::Coverage
+XSLoader
+version
+URI::Fetch
+Pod::Simple
+constant
+Test
+File::Temp
+Cache::Cache
+Feed::Find
+HTML::Tagset
+ExtUtils::PkgConfig
+Devel::GlobalDestruction
+PadWalker
+Sub::Name
+Encode
+Test::Base
+Class::DBI::Plugin::Type
+Sub::Identify
+Sub::Uplevel
+Params::Validate
+POE
+Class::Singleton
+Proc::ProcessTable
+Compress::Raw::Bzip2
+Class::MOP
+HTTP::Server::Simple
+Sub::Exporter
+Fuse
+File::HomeDir
+Bot::BasicBot
+# URI::Find::Simple
+base
+# GD
+WWW::Mechanize
+Test::Most
+Sys::Syslog
+File::Slurp
+Tree::DAG_Node
+FCGI
+Params::Util
+Devel::Peek
+DateTime::Format::Mail
+Spiffy
+HTML::TableExtract
+DBD::SQLite
+Class::Accessor::Chained
+DBIx::ContextualFetch
+Test::Tester
+Variable::Magic
+AppConfig
+Class::Accessor
+Want
+XML::Simple
+IO::All
+Number::Format
+Term::ReadKey
+DBI
+Test::Exception
+Data::DPath
+Config::INI::Serializer
+Class::MethodMaker
+PDF::FDF::Simple
+TAP::DOM
+
+# Web stuff
+Authen::Passphrase::BlowfishCrypt
+Carp::Always::Color
+App::cpanoutdated
+Dancer
+Dancer::Logger::Log4perl
+Dancer::Plugin::Auth::Twitter
+Dancer::Plugin::Database
+Dancer::Plugin::DBIC
+Data::Printer
+DBD::SQLite
+DBIx::Class::Schema::Loader
+DBIx::Class::TimeStamp
+DBIx::Log4perl
+Exporter::Lite
+Log::Log4perl
+JSON
+Module::Refresh
+Moose
+MooseX::Declare
+MooseX::StrictConstructor
+MooseX::Types::DateTime::MoreCoercions
+Plack::Middleware::Debug
+Plack::Middleware::Debug::Dancer::Version
+Plack::Middleware::ReverseProxy
+Plack::Middleware::Debug::Dancer::TemplateVariables
+SQL::Translator
+Starman
+Template
+Test::More
+YAML
+
+# Maths stuff
+Math::ODE
+Math::MatrixReal
+
+# Other stuff
+Image::PNG
+Games::Bingo
+Method::Signatures
+Data::Random
+Debuggit
diff --git a/utils/dc b/utils/dc
index 4f399aa..401a5b1 100755
--- a/utils/dc
+++ b/utils/dc
@@ -1,14 +1,96 @@
-#!/usr/bin/zsh
+#!/bin/sh
 
-set -x
+# set -x
+
+export AUTOMATED_TESTING=1
+export NONINTERACTIVE_TESTING=1
+
+WEBDIR=/usr/share/nginx/www
+CPANCOVER_STAGING=~/staging
+CPANCOVER_LATEST=$WEBDIR/latest
+CPANCOVER_DIR=$CPANCOVER_STAGING
+DOCKER=docker
+DOCKER_IMAGE=pjcj/devel-cover-git
 
 case "$1" in
     "update-copyright")
         from="${2:-`date +'%Y' --date='last year'`}"
         to="${3:-`date +'%Y'`}"
         echo Updating copyright from $from to $to
-        perl -pi -e "s/Copyright \d+-\K$from(, Paul Johnson)/$to\$1/" **/*(.)
-        perl -pi -e "s/Copyright $from\K(, Paul Johnson)/-$to\$1/" **/*(.)
+        perl -pi -e "s/Copyright \d+-\K$from(, Paul Johnson)/$to\$1/i" \
+             `git ls-files`
+        perl -pi -e "s/Copyright $from\K(, Paul Johnson)/-$to\$1/i" \
+             `git ls-files`
+        ;;
+    "install_dependencies")
+        shift;
+        cpan -iTf Sereal Digest::MD5 Template Pod::Coverage::CountParents \
+                  Capture::Tiny Parallel::Iterator Template Class::XSAccessor \
+                  Moo namespace::clean CPAN::Releases::Latest . < /dev/null
+        ;;
+    "nice_cpus")
+        shift;
+        perl -Iutils -MDevel::Cover::BuildUtils=nice_cpus -e 'print nice_cpus'
+        ;;
+    "cpancover")
+        shift;
+        jobs=$($0 nice_cpus)
+        perl -Mblib bin/cpancover -results_dir $CPANCOVER_DIR \
+                                  -workers $jobs "$@"
+        ;;
+    "cpancover-compress")
+        find $CPANCOVER_DIR -type f -not -name '*.gz' -not -name '*.json' \
+                            -exec gzip -f9 {} \;
+        ;;
+    "cpancover-latest")
+        $0 cpancover -latest
+        ;;
+    "cpancover-build-module")
+        module="$2"
+        $0 cpancover -local_build -docker $DOCKER -workers 1 "$module"
+        $0 cpancover-compress
+        ;;
+    "cpancover-docker-module")
+        module="$2"
+        name="$3"
+        staging="${4:-$CPANCOVER_DIR}"
+        mkdir -p $staging
+        # echo $name
+        container=$($DOCKER run -d -v=/home/pjcj/g/perl/Devel--Cover:/dc:ro \
+                    -w=/dc --rm=false --name="$name" \
+                    $DOCKER_IMAGE dc cpancover-build-module $module)
+        # https://github.com/dotcloud/docker/issues/3986
+        $DOCKER wait "$name"
+        if [ $? = 0 ]; then
+            $DOCKER logs "$name" > "$staging/$name.out"
+            local_staging="$staging/$name"
+            sudo $DOCKER cp "$name:/staging" "$local_staging"
+            if [ -d "$local_staging" ]; then
+                sudo chmod -R 755 "$local_staging"
+                sudo find "$local_staging" -type f -exec chmod 644 {} \;
+                sudo chown -R pjcj:pjcj "$local_staging"
+                cd "$local_staging"/*
+                for f in *; do
+                    if [ -d $f ]; then
+                        rm -rf "$staging"/$f
+                        mv $f "$staging"
+                    fi
+                done
+                rm -r "$local_staging"
+            fi
+        fi
+        $DOCKER rm "$name"
+        ;;
+    "cpancover-generate-html")
+        $0 cpancover -generate_html
+        $0 cpancover-compress
+        json=$CPANCOVER_DIR/cpancover.json
+        tmp=$json-tmp-$$.gz
+        echo Compressing $json
+        pigz < $json > $tmp && mv $tmp $json.gz
+        ;;
+    "cpancover-kill-docker")
+        docker ps -a | tail -n +2 | awk '{ print $1 }' | xargs -r docker kill
         ;;
     "sereal_each_bug")
         perl="${2:-perl}"
@@ -22,6 +104,9 @@ case "$1" in
         $perl -Mblib bin/cover -report text
         rm tests/change
         ;;
+    "options")
+        perl -nE 'say $1 if /^    "([\w-]+)"\)$/ && $1 !~ /^_/' < $0
+        ;;
     *)
         echo Unknown option "$1"
         ;;
diff --git a/utils/install_modules b/utils/install_modules
deleted file mode 100755
index e63833a..0000000
--- a/utils/install_modules
+++ /dev/null
@@ -1,422 +0,0 @@
-#!/usr/bin/perl
-
-# Copyright 2012-2014, Paul Johnson (paul at pjcj.net)
-
-# This software is free.  It is licensed under the same terms as Perl itself.
-
-# The latest version of this software should be available from my homepage:
-# http://www.pjcj.net
-
-use strict;
-use warnings;
-
-my $modules = <<EOM;
-
-    # Stuff for Devel::Cover
-    # Devel::Cover
-    .
-    Parallel::Iterator
-    Test::Pod::Coverage
-    PPI::HTML
-
-    # My stuff
-    Gedcom
-    Shell::Source
-
-    # Stuff with interest for Devel::Cover
-    NetAddr::IP
-
-    # There's going to be repetition down here
-
-    # Dual-lived core modules
-    Archive::Extract
-    Archive::Tar
-    Attribute::Handlers
-    autodie
-    AutoLoader
-    autouse
-    base
-    B::Debug
-    bignum
-    B::Lint
-    Carp
-    CGI
-    Compress::Raw::Bzip2
-    Compress::Raw::Zlib
-    Config::Perl::V
-    constant
-    CPAN
-    CPAN::Meta
-    CPAN::Meta::Requirements
-    CPAN::Meta::YAML
-    CPANPLUS
-    CPANPLUS::Dist::Build
-    Data::Dumper
-    DB_File
-    Devel::PPPort
-    Devel::SelfStubber
-    Digest
-    Digest::MD5
-    Digest::SHA
-    Dumpvalue
-    Encode
-    encoding::warnings
-    Env
-    Exporter
-    ExtUtils::CBuilder
-    ExtUtils::Command
-    ExtUtils::Constant
-    ExtUtils::Install
-    ExtUtils::MakeMaker
-    ExtUtils::Manifest
-    ExtUtils::ParseXS
-    File::CheckTree
-    File::Fetch
-    File::Path
-    File::Temp
-    Filter::Simple
-    Filter::Util::Call
-    Getopt::Long
-    HTTP::Tiny
-    I18N::Collate
-    I18N::LangTags
-    if
-    IO
-    IO-Compress
-    IO::Zlib
-    IPC::Cmd
-    IPC::SysV
-    JSON::PP
-    lib
-    libnet
-    Locale-Codes
-    Locale::Maketext
-    Locale::Maketext::Simple
-    Log::Message
-    Log::Message::Simple
-    Math::BigInt
-    Math::BigInt::FastCalc
-    Math::BigRat
-    Math::Complex
-    Memoize
-    MIME::Base64
-    Module::Build
-    Module::CoreList
-    Module::Load
-    Module::Load::Conditional
-    Module::Loaded
-    Module::Metadata
-    Module::Pluggable
-    Net::Ping
-    NEXT
-    Object::Accessor
-    Package::Constants
-    Params::Check
-    parent
-    Parse::CPAN::Meta
-    PathTools
-    perlfaq
-    PerlIO::via::QuotedPrint
-    Perl::OSType
-    Pod::Checker
-    Pod::Escapes
-    Pod::LaTeX
-    podlators
-    Pod::Parser
-    Pod::Perldoc
-    Pod::Simple
-    Pod::Usage
-    Safe
-    Scalar-List-Utils
-    Search::Dict
-    SelfLoader
-    Socket
-    Storable
-    Sys::Syslog
-    Term::ANSIColor
-    Term::Cap
-    Term::Complete
-    Term::ReadLine
-    Term::UI
-    Test
-    Test::Harness
-    Test::Simple
-    Text::Abbrev
-    Text::Balanced
-    Text::ParseWords
-    Text::Soundex
-    Text-Tabs+Wrap
-    Thread::Queue
-    threads
-    Thread::Semaphore
-    threads::shared
-    Tie::File
-    Tie::RefHash
-    Time::HiRes
-    Time::Local
-    Time::Piece
-    Unicode::Collate
-    Unicode::Normalize
-    version
-    Win32
-    Win32API::File
-    XSLoader
-
-    # Modules with many dependencies
-    Task::Kensho
-    Task::Plack
-    Task::Catalyst
-    Task::Dancer
-    Mojolicious
-    Task::Moose
-    Task::Dist::Zilla
-    Task::CPAN::SmokeBox
-    Task::Perl::Critic
-    Task::Toolchain::Test
-    Task::Template::Benchmark
-    MojoMojo
-    Jifty
-    Bot::BasicBot
-    Dist::Zilla
-
-    # Modules with many dependents
-    Exporter
-    Text::Tabs
-    Test::Harness
-    Pod::Escapes
-    Pod::Simple
-    IO
-    Getopt::Long
-    Pod::Parser
-    ExtUtils::MakeMaker
-    Test::Simple
-    ExtUtils::Manifest
-    constant
-    Test
-    Data::Dumper
-    File::Temp
-    ExtUtils::Install
-    Text::ParseWords
-    ExtUtils::CBuilder
-    ExtUtils::ParseXS
-    Module::Build
-    File::Path
-    XSLoader
-    MIME::Base64
-    Digest
-    Digest::MD5
-    Sub::Uplevel
-    URI
-    Test::Exception
-    HTML::Tagset
-    HTML::Parser
-    Compress::Raw::Zlib
-    Compress::Raw::Bzip2
-    Storable
-    base
-    List::MoreUtils
-    Params::Util
-    Task::Weaken
-    Sub::Install
-    Data::OptList
-    Sub::Exporter
-    Test::Tester
-    Test::NoWarnings
-    Attribute::Handlers
-    Class::Accessor
-    Algorithm::C3
-    Class::C3
-    Sub::Name
-    MRO::Compat
-    Time::HiRes
-    Params::Validate
-    Try::Tiny
-    Scope::Guard
-    Package::Stash
-    version
-    Tree::DAG_Node
-    Test::Warn
-    Devel::GlobalDestruction
-    Class::MOP
-    Moose
-    Class::Data::Inheritable
-    Test::Deep
-    Carp::Clan
-    Module::Pluggable
-    Variable::Magic
-    B::Hooks::EndOfScope
-    Sub::Identify
-    namespace::clean
-    Time::Local
-    DBI
-    Text::Balanced
-    Class::Inspector
-    Test::Pod
-    Encode
-    Path::Class
-    Digest::SHA1
-    FCGI
-    CGI
-    MooseX::Types
-    XML::NamespaceSupport
-    XML::SAX
-    Class::Singleton
-    Clone
-    DateTime::TimeZone
-    DateTime::Locale
-    YAML
-    DateTime
-    namespace::autoclean
-    IO::String
-    Algorithm::Diff
-    File::Slurp
-    Devel::StackTrace
-
-    # Modules which should not fail
-    IO
-    List::MoreUtils
-    Test::Harness
-    ExtUtils::MakeMaker
-    File::Path
-    XML::Parser
-    Test::Simple
-    HTML::Tree
-    Storable
-    Net::IP
-    DB_File
-    XML::LibXML
-    Time::HiRes
-    Exporter
-    Pod::Escapes
-    ExtUtils::ParseXS
-    Module::Build
-    Pod::Parser
-    Data::Dumper
-    ExtUtils::Install
-    IO::Tty
-    XML::SAX
-    Class::ErrorHandler
-    URI
-    HTML::Template
-    Compress::Raw::Zlib
-    Net::DNS
-    Test::Pod::Coverage
-    XSLoader
-    version
-    URI::Fetch
-    Pod::Simple
-    constant
-    Test
-    File::Temp
-    Cache::Cache
-    Feed::Find
-    HTML::Tagset
-    ExtUtils::PkgConfig
-    Devel::GlobalDestruction
-    PadWalker
-    Sub::Name
-    Encode
-    Test::Base
-    Class::DBI::Plugin::Type
-    Sub::Identify
-    Sub::Uplevel
-    Params::Validate
-    POE
-    Class::Singleton
-    Proc::ProcessTable
-    Compress::Raw::Bzip2
-    Class::MOP
-    HTTP::Server::Simple
-    Sub::Exporter
-    Fuse
-    File::HomeDir
-    Bot::BasicBot
-    # URI::Find::Simple
-    base
-    # GD
-    WWW::Mechanize
-    Test::Most
-    Sys::Syslog
-    File::Slurp
-    Tree::DAG_Node
-    FCGI
-    Params::Util
-    Devel::Peek
-    DateTime::Format::Mail
-    Spiffy
-    HTML::TableExtract
-    DBD::SQLite
-    Class::Accessor::Chained
-    DBIx::ContextualFetch
-    Test::Tester
-    Variable::Magic
-    AppConfig
-    Class::Accessor
-    Want
-    XML::Simple
-    IO::All
-    Number::Format
-    Term::ReadKey
-    DBI
-    Test::Exception
-    Data::DPath
-    Config::INI::Serializer
-    Class::MethodMaker
-    PDF::FDF::Simple
-    TAP::DOM
-
-    # Web stuff
-    Authen::Passphrase::BlowfishCrypt
-    Carp::Always::Color
-    App::cpanoutdated
-    Dancer
-    Dancer::Logger::Log4perl
-    Dancer::Plugin::Auth::Twitter
-    Dancer::Plugin::Database
-    Dancer::Plugin::DBIC
-    Data::Printer
-    DBD::SQLite
-    DBIx::Class::Schema::Loader
-    DBIx::Class::TimeStamp
-    DBIx::Log4perl
-    Exporter::Lite
-    Log::Log4perl
-    JSON
-    Module::Refresh
-    Moose
-    MooseX::Declare
-    MooseX::StrictConstructor
-    MooseX::Types::DateTime::MoreCoercions
-    Plack::Middleware::Debug
-    Plack::Middleware::Debug::Dancer::Version
-    Plack::Middleware::ReverseProxy
-    Plack::Middleware::Debug::Dancer::TemplateVariables
-    SQL::Translator
-    Starman
-    Template
-    Test::More
-    YAML
-
-    # Maths stuff
-    Math::ODE
-    Math::MatrixReal
-
-    # Other stuff
-    Image::PNG
-    Games::Bingo
-    Method::Signatures
-    Data::Random
-    Debuggit
-
-EOM
-
-my @opts = @ARGV;
-
-my @modules = grep /\S/, grep !/^ +#/, split /\n/, $modules;
-s/^ +//, s/ +$// for @modules;
-my %m; @modules = grep !$m{$_}++, @modules;
-
-for my $mod (sort @modules)
-{
-    system "cpanm @opts $mod";
-}
diff --git a/utils/run_cpancover b/utils/run_cpancover
index 4b62985..bda7c81 100755
--- a/utils/run_cpancover
+++ b/utils/run_cpancover
@@ -1,24 +1,23 @@
 #!/bin/sh -x
 
 JOBS=16
-perlbrew uninstall cpancover
-perlbrew install perl-5.18.2 --as cpancover -j $JOBS -nf
 export PATH=$PERLBREW_ROOT/perls/cpancover/bin:$PATH
 rm -rf ~/.cpanm
 rm -rf ~/cpancover
 cpan App::cpanminus
 cpanm -nf .
+cpanm -nf Capture::Tiny Parallel::Iterator Template Class::XSAccessor \
+          Moo namespace::clean
 cpanm -nf App::cpanoutdated
 cpan-outdated | cpanm -nf
-perl utils/install_modules -nf
-CPANCOVER_WORKERS=$JOBS perl utils/cpanmcover
-rm -r /home/pjcj/cpancover/modules/Test-LeakTrace-0.14/cover_db
-cpancover -directory ~/cpancover/modules -outputdir ~/cpancover/results -outputfile index.html -report html_basic -nocollect
-find ~/cpancover/results -type f -exec gzip -9 {} \;
-chmod -R o=g ~/cpancover/results
+perl -Mblib bin/cpancover -force -verbose -results_dir ~/cpancover \
+                          -workers $JOBS -module_file utils/cpancover_modules \
+                          -noempty_cpanm_dir
+find ~/cpancover -type f -exec gzip -9 {} \;
+chmod -R o=g ~/cpancover
 www=/usr/share/nginx/www
 new=$www/`date +%F`
 sudo mv $new $new.$$
-sudo cp -a ~/cpancover/results $new
+sudo cp -a ~/cpancover $new
 sudo rm $www/latest
 sudo ln -s $new $www/latest
diff --git a/utils/setup b/utils/setup
new file mode 100644
index 0000000..aebc90b
--- /dev/null
+++ b/utils/setup
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+# . ./utils/setup
+
+tidy () { echo -n $1 | perl -naF: -e 'print join ":", grep !$s{$_}++ && -e, @F'; }
+dc_home=$PWD
+export PATH=$(tidy $dc_home/utils:$PATH)
+
+if [ ! -z $ZSH_VERSION ]; then
+    _dc() {
+      reply=(`utils/dc options`)
+    }
+    compctl -K _dc dc
+fi

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-perl/packages/libdevel-cover-perl.git



More information about the Pkg-perl-cvs-commits mailing list