The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
CONTRIBUTING 1000
CONTRIBUTING.mkdn 0100
Changes 022
MANIFEST 23
META.json 1112
META.yml 67
Makefile.PL 84
README 1126
cpanfile 54
lib/Path/Tiny.pm 3978
perlcritic.rc 03
t/00-report-prereqs.dd 070
t/00-report-prereqs.t 150122
t/digest.t 26
t/filesystem.t 012
xt/author/00-compile.t 11
xt/author/pod-spell.t 15
17 files changed (This is a version diff) 336475
@@ -1,100 +0,0 @@
-## HOW TO CONTRIBUTE
-
-Thank you for considering contributing to this distribution.  This file
-contains instructions that will help you work with the source code.
-
-The distribution is managed with Dist::Zilla.  This means than many of the
-usual files you might expect are not in the repository, but are generated at
-release time (e.g. Makefile.PL).
-
-Generally, **you do not need Dist::Zilla to contribute patches**.  You do need
-Dist::Zilla to create a tarball and/or install from the repository.  See below
-for guidance.
-
-### Getting dependencies
-
-See the included `cpanfile` file for a list of dependencies.  If you have
-App::cpanminus 1.6 or later installed, you can use `cpanm` to satisfy
-dependencies like this:
-
-    $ cpanm --installdeps .
-
-Otherwise, you can install Module::CPANfile 1.0002 or later and then satisfy
-dependencies with the regular `cpan` client and `cpanfile-dump`:
-
-    $ cpan `cpanfile-dump`
-
-### Running tests
-
-You can run tests directly using the `prove` tool:
-
-    $ prove -l
-    $ prove -lv t/some_test_file.t
-
-For most of my distributions, `prove` is entirely sufficient for you to test any
-patches you have. I use `prove` for 99% of my testing during development.
-
-### Code style and tidying
-
-Please try to match any existing coding style.  If there is a `.perltidyrc`
-file, please install Perl::Tidy and use perltidy before submitting patches.
-
-If there is a `tidyall.ini` file, you can also install Code::TidyAll and run
-`tidyall` on a file or `tidyall -a` to tidy all files.
-
-### Patching documentation
-
-Much of the documentation Pod is generated at release time.  Depending on the
-distribution, some of my documentation may be written in a Pod dialect called
-WikiDoc. (See Pod::WikiDoc on CPAN.)
-
-If you would like to submit a documentation edit, please limit yourself to the
-documentation you see.
-
-If you see typos or documentation issues in the generated docs, please
-email or open a bug ticket instead of patching.
-
-### Installing from the repository
-
-If you want to install directly from the repository, you need to have
-Dist::Zilla installed (see below).  If this is a burden to you, I welcome
-patches against a CPAN tarball instead of the repository.
-
-### Installing and using Dist::Zilla
-
-Dist::Zilla is a very powerful authoring tool, optimized for maintaining a
-large number of distributions with a high degree of automation, but it has a
-large dependency chain, a bit of a learning curve and requires a number of
-author-specific plugins.
-
-To install it from CPAN, I recommend one of the following approaches for
-the quickest installation:
-
-    # using CPAN.pm, but bypassing non-functional pod tests
-    $ cpan TAP::Harness::Restricted
-    $ PERL_MM_USE_DEFAULT=1 HARNESS_CLASS=TAP::Harness::Restricted cpan Dist::Zilla
-
-    # using cpanm, bypassing *all* tests
-    $ cpanm -n Dist::Zilla
-
-In either case, it's probably going to take about 10 minutes.  Go for a walk,
-go get a cup of your favorite beverage, take a bathroom break, or whatever.
-When you get back, Dist::Zilla should be ready for you.
-
-Then you need to install any plugins specific to this distribution:
-
-    $ cpan `dzil authordeps`
-    $ dzil authordeps | cpanm
-
-Once installed, here are some dzil commands you might try:
-
-    $ dzil build
-    $ dzil test
-    $ dzil xtest
-
-To install from the repository, use:
-
-    $ dzil install
-
-You can learn more about Dist::Zilla at http://dzil.org/
-
@@ -0,0 +1,100 @@
+## HOW TO CONTRIBUTE
+
+Thank you for considering contributing to this distribution.  This file
+contains instructions that will help you work with the source code.
+
+The distribution is managed with Dist::Zilla.  This means than many of the
+usual files you might expect are not in the repository, but are generated at
+release time (e.g. Makefile.PL).
+
+Generally, **you do not need Dist::Zilla to contribute patches**.  You do need
+Dist::Zilla to create a tarball and/or install from the repository.  See below
+for guidance.
+
+### Getting dependencies
+
+See the included `cpanfile` file for a list of dependencies.  If you have
+App::cpanminus 1.6 or later installed, you can use `cpanm` to satisfy
+dependencies like this:
+
+    $ cpanm --installdeps .
+
+Otherwise, you can install Module::CPANfile 1.0002 or later and then satisfy
+dependencies with the regular `cpan` client and `cpanfile-dump`:
+
+    $ cpan `cpanfile-dump`
+
+### Running tests
+
+You can run tests directly using the `prove` tool:
+
+    $ prove -l
+    $ prove -lv t/some_test_file.t
+
+For most of my distributions, `prove` is entirely sufficient for you to test any
+patches you have. I use `prove` for 99% of my testing during development.
+
+### Code style and tidying
+
+Please try to match any existing coding style.  If there is a `.perltidyrc`
+file, please install Perl::Tidy and use perltidy before submitting patches.
+
+If there is a `tidyall.ini` file, you can also install Code::TidyAll and run
+`tidyall` on a file or `tidyall -a` to tidy all files.
+
+### Patching documentation
+
+Much of the documentation Pod is generated at release time.  Depending on the
+distribution, some of my documentation may be written in a Pod dialect called
+WikiDoc. (See Pod::WikiDoc on CPAN.)
+
+If you would like to submit a documentation edit, please limit yourself to the
+documentation you see.
+
+If you see typos or documentation issues in the generated docs, please
+email or open a bug ticket instead of patching.
+
+### Installing from the repository
+
+If you want to install directly from the repository, you need to have
+Dist::Zilla installed (see below).  If this is a burden to you, I welcome
+patches against a CPAN tarball instead of the repository.
+
+### Installing and using Dist::Zilla
+
+Dist::Zilla is a very powerful authoring tool, optimized for maintaining a
+large number of distributions with a high degree of automation, but it has a
+large dependency chain, a bit of a learning curve and requires a number of
+author-specific plugins.
+
+To install it from CPAN, I recommend one of the following approaches for
+the quickest installation:
+
+    # using CPAN.pm, but bypassing non-functional pod tests
+    $ cpan TAP::Harness::Restricted
+    $ PERL_MM_USE_DEFAULT=1 HARNESS_CLASS=TAP::Harness::Restricted cpan Dist::Zilla
+
+    # using cpanm, bypassing *all* tests
+    $ cpanm -n Dist::Zilla
+
+In either case, it's probably going to take about 10 minutes.  Go for a walk,
+go get a cup of your favorite beverage, take a bathroom break, or whatever.
+When you get back, Dist::Zilla should be ready for you.
+
+Then you need to install any plugins specific to this distribution:
+
+    $ cpan `dzil authordeps`
+    $ dzil authordeps | cpanm
+
+Once installed, here are some dzil commands you might try:
+
+    $ dzil build
+    $ dzil test
+    $ dzil xtest
+
+To install from the repository, use:
+
+    $ dzil install
+
+You can learn more about Dist::Zilla at http://dzil.org/
+
@@ -1,5 +1,27 @@
 Revision history for Path-Tiny
 
+0.056     2014-08-07 15:08:41-04:00 America/New_York
+
+    [*** DEPRECATIONS ***]
+
+    - The 'dirname' method is deprecated due to exposing File::Spec
+      inconsistencies
+
+    [ADDED]
+
+    - The 'digest' method now takes a 'chunk_size' option to avoid
+      slurping files entirely into memory.
+
+    [FIXED]
+
+    - Fixed problem throwing errors from 'remove'
+
+0.055     2014-06-30 10:29:28-04:00 America/New_York
+
+    [FIXED]
+
+    - tempfile/tempdir won't warn if used as functions without arguments
+
 0.054     2014-05-04 13:56:11-04:00 America/New_York
 
     [ADDED]
@@ -1,5 +1,5 @@
-# This file was automatically generated by Dist::Zilla::Plugin::Manifest v5.015.
-CONTRIBUTING
+# This file was automatically generated by Dist::Zilla::Plugin::Manifest v5.020.
+CONTRIBUTING.mkdn
 Changes
 LICENSE
 MANIFEST
@@ -11,6 +11,7 @@ cpanfile
 dist.ini
 lib/Path/Tiny.pm
 perlcritic.rc
+t/00-report-prereqs.dd
 t/00-report-prereqs.t
 t/README
 t/basename.t
@@ -4,7 +4,7 @@
       "David Golden <dagolden@cpan.org>"
    ],
    "dynamic_config" : 0,
-   "generated_by" : "Dist::Zilla version 5.015, CPAN::Meta::Converter version 2.141170",
+   "generated_by" : "Dist::Zilla version 5.020, CPAN::Meta::Converter version 2.142060",
    "license" : [
       "apache_2_0"
    ],
@@ -33,7 +33,7 @@
       },
       "develop" : {
          "requires" : {
-            "Dist::Zilla" : "5.015",
+            "Dist::Zilla" : "5",
             "Dist::Zilla::Plugin::MinimumPerl" : "0",
             "Dist::Zilla::Plugin::OnlyCorePrereqs" : "0",
             "Dist::Zilla::Plugin::Prereqs" : "0",
@@ -47,7 +47,8 @@
             "Test::CPAN::Meta" : "0",
             "Test::More" : "0",
             "Test::Pod" : "1.41",
-            "Test::Pod::Coverage" : "1.08"
+            "Test::Pod::Coverage" : "1.08",
+            "Test::Spelling" : "0.12"
          }
       },
       "runtime" : {
@@ -76,32 +77,30 @@
       },
       "test" : {
          "recommends" : {
-            "CPAN::Meta" : "0",
-            "CPAN::Meta::Requirements" : "2.120900",
+            "CPAN::Meta" : "2.120900",
             "Test::FailWarnings" : "0"
          },
          "requires" : {
             "ExtUtils::MakeMaker" : "0",
             "File::Basename" : "0",
+            "File::Spec" : "3.40",
             "File::Spec::Functions" : "0",
             "File::Spec::Unix" : "0",
             "File::Temp" : "0.19",
-            "List::Util" : "0",
             "Test::More" : "0.96",
             "lib" : "0",
-            "open" : "0",
-            "version" : "0"
+            "open" : "0"
          }
       }
    },
    "provides" : {
       "Path::Tiny" : {
          "file" : "lib/Path/Tiny.pm",
-         "version" : "0.054"
+         "version" : "0.056"
       },
       "Path::Tiny::Error" : {
          "file" : "lib/Path/Tiny.pm",
-         "version" : "0.054"
+         "version" : "0.056"
       }
    },
    "release_status" : "stable",
@@ -116,11 +115,12 @@
          "web" : "https://github.com/dagolden/Path-Tiny"
       }
    },
-   "version" : "0.054",
+   "version" : "0.056",
    "x_authority" : "cpan:DAGOLDEN",
    "x_contributors" : [
       "Chris Williams <bingos@cpan.org>",
       "David Steinbrunner <dsteinbrunner@pobox.com>",
+      "Doug Bell <madcityzen@gmail.com>",
       "Gabor Szabo <szabgab@cpan.org>",
       "Gabriel Andrade <gabiruh@gmail.com>",
       "George Hartzell <hartzell@cpan.org>",
@@ -129,6 +129,7 @@
       "Karen Etheridge <ether@cpan.org>",
       "Martin Kjeldsen <mk@bluepipe.dk>",
       "Michael G. Schwern <mschwern@cpan.org>",
+      "Smylers <Smylers@stripey.com>",
       "Toby Inkster <tobyink@cpan.org>",
       "김도형 - Keedi Kim <keedi@cpan.org>"
    ]
@@ -5,18 +5,17 @@ author:
 build_requires:
   ExtUtils::MakeMaker: '0'
   File::Basename: '0'
+  File::Spec: '3.40'
   File::Spec::Functions: '0'
   File::Spec::Unix: '0'
   File::Temp: '0.19'
-  List::Util: '0'
   Test::More: '0.96'
   lib: '0'
   open: '0'
-  version: '0'
 configure_requires:
   ExtUtils::MakeMaker: '6.17'
 dynamic_config: 0
-generated_by: 'Dist::Zilla version 5.015, CPAN::Meta::Converter version 2.141170'
+generated_by: 'Dist::Zilla version 5.020, CPAN::Meta::Converter version 2.142060'
 license: apache
 meta-spec:
   url: http://module-build.sourceforge.net/META-spec-v1.4.html
@@ -34,10 +33,10 @@ no_index:
 provides:
   Path::Tiny:
     file: lib/Path/Tiny.pm
-    version: '0.054'
+    version: '0.056'
   Path::Tiny::Error:
     file: lib/Path/Tiny.pm
-    version: '0.054'
+    version: '0.056'
 recommends:
   Unicode::UTF8: '0.58'
 requires:
@@ -62,11 +61,12 @@ resources:
   bugtracker: https://github.com/dagolden/Path-Tiny/issues
   homepage: https://github.com/dagolden/Path-Tiny
   repository: https://github.com/dagolden/Path-Tiny.git
-version: '0.054'
+version: '0.056'
 x_authority: cpan:DAGOLDEN
 x_contributors:
   - 'Chris Williams <bingos@cpan.org>'
   - 'David Steinbrunner <dsteinbrunner@pobox.com>'
+  - 'Doug Bell <madcityzen@gmail.com>'
   - 'Gabor Szabo <szabgab@cpan.org>'
   - 'Gabriel Andrade <gabiruh@gmail.com>'
   - 'George Hartzell <hartzell@cpan.org>'
@@ -75,5 +75,6 @@ x_contributors:
   - 'Karen Etheridge <ether@cpan.org>'
   - 'Martin Kjeldsen <mk@bluepipe.dk>'
   - 'Michael G. Schwern <mschwern@cpan.org>'
+  - 'Smylers <Smylers@stripey.com>'
   - 'Toby Inkster <tobyink@cpan.org>'
   - '김도형 - Keedi Kim <keedi@cpan.org>'
@@ -1,5 +1,5 @@
 
-# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v5.015.
+# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v5.020.
 use strict;
 use warnings;
 
@@ -12,7 +12,6 @@ use ExtUtils::MakeMaker 6.17;
 my %WriteMakefileArgs = (
   "ABSTRACT" => "File path utility",
   "AUTHOR" => "David Golden <dagolden\@cpan.org>",
-  "BUILD_REQUIRES" => {},
   "CONFIGURE_REQUIRES" => {
     "ExtUtils::MakeMaker" => "6.17"
   },
@@ -41,16 +40,15 @@ my %WriteMakefileArgs = (
   "TEST_REQUIRES" => {
     "ExtUtils::MakeMaker" => 0,
     "File::Basename" => 0,
+    "File::Spec" => "3.40",
     "File::Spec::Functions" => 0,
     "File::Spec::Unix" => 0,
     "File::Temp" => "0.19",
-    "List::Util" => 0,
     "Test::More" => "0.96",
     "lib" => 0,
-    "open" => 0,
-    "version" => 0
+    "open" => 0
   },
-  "VERSION" => "0.054",
+  "VERSION" => "0.056",
   "test" => {
     "TESTS" => "t/*.t"
   }
@@ -73,7 +71,6 @@ my %FallbackPrereqs = (
   "File::Spec::Unix" => 0,
   "File::Temp" => "0.19",
   "File::stat" => 0,
-  "List::Util" => 0,
   "Test::More" => "0.96",
   "constant" => 0,
   "if" => 0,
@@ -81,7 +78,6 @@ my %FallbackPrereqs = (
   "open" => 0,
   "overload" => 0,
   "strict" => 0,
-  "version" => 0,
   "warnings" => 0
 );
 
@@ -2,7 +2,7 @@ NAME
     Path::Tiny - File path utility
 
 VERSION
-    version 0.054
+    version 0.056
 
 SYNOPSIS
       use Path::Tiny;
@@ -263,18 +263,28 @@ METHODS
   digest
         $obj = path("/tmp/foo.txt")->digest;        # SHA-256
         $obj = path("/tmp/foo.txt")->digest("MD5"); # user-selected
+        $obj = path("/tmp/foo.txt")->digest( { chunk_size => 1e6 }, "MD5" );
 
-    Returns a hexadecimal digest for a file. Any arguments are passed to the
-    constructor for Digest to select an algorithm. If no arguments are
-    given, the default is SHA-256.
+    Returns a hexadecimal digest for a file. An optional hash reference of
+    options may be given. The only option is "chunk_size". If "chunk_size"
+    is given, that many bytes will be read at a time. If not provided, the
+    entire file will be slurped into memory to compute the digest.
 
-  dirname
+    Any subsequent arguments are passed to the constructor for Digest to
+    select an algorithm. If no arguments are given, the default is SHA-256.
+
+  dirname (deprecated)
         $name = path("/tmp/foo.txt")->dirname; # "/tmp/"
 
-    Returns the directory name portion of the path. This is roughly
-    equivalent to what File::Spec would give from "splitpath" and thus
-    usually has the trailing slash. If that's not desired, stringify
-    directories or call "parent" on files.
+    Returns the directory portion you would get from calling
+    "File::Spec->splitpath( $path->stringify )" or "." for a path without a
+    parent directory portion. Because File::Spec is inconsistent, the result
+    might or might not have a trailing slash. Because of this, this method
+    is deprecated.
+
+    A better, more consistently approach is likely
+    "$path->parent->stringify", which will not have a trailing slash except
+    for a root directory.
 
   exists, is_file, is_dir
         if ( path("/tmp")->exists ) { ... }     # -e
@@ -465,8 +475,9 @@ METHODS
 
     Note: as of 0.012, remove only works on files.
 
-    This is just like "unlink", except if the path does not exist, it
-    returns false rather than throwing an exception.
+    This is just like "unlink", except for its error handling: if the path
+    does not exist, it returns false; if deleting the file fails, it throws
+    an exception.
 
   remove_tree
         # directory
@@ -708,6 +719,8 @@ CONTRIBUTORS
 
     *   David Steinbrunner <dsteinbrunner@pobox.com>
 
+    *   Doug Bell <madcityzen@gmail.com>
+
     *   Gabor Szabo <szabgab@cpan.org>
 
     *   Gabriel Andrade <gabiruh@gmail.com>
@@ -724,6 +737,8 @@ CONTRIBUTORS
 
     *   Michael G. Schwern <mschwern@cpan.org>
 
+    *   Smylers <Smylers@stripey.com>
+
     *   Toby Inkster <tobyink@cpan.org>
 
     *   김도형 - Keedi Kim <keedi@cpan.org>
@@ -20,19 +20,17 @@ recommends "Unicode::UTF8" => "0.58";
 on 'test' => sub {
   requires "ExtUtils::MakeMaker" => "0";
   requires "File::Basename" => "0";
+  requires "File::Spec" => "3.40";
   requires "File::Spec::Functions" => "0";
   requires "File::Spec::Unix" => "0";
   requires "File::Temp" => "0.19";
-  requires "List::Util" => "0";
   requires "Test::More" => "0.96";
   requires "lib" => "0";
   requires "open" => "0";
-  requires "version" => "0";
 };
 
 on 'test' => sub {
-  recommends "CPAN::Meta" => "0";
-  recommends "CPAN::Meta::Requirements" => "2.120900";
+  recommends "CPAN::Meta" => "2.120900";
   recommends "Test::FailWarnings" => "0";
 };
 
@@ -41,7 +39,7 @@ on 'configure' => sub {
 };
 
 on 'develop' => sub {
-  requires "Dist::Zilla" => "5.015";
+  requires "Dist::Zilla" => "5";
   requires "Dist::Zilla::Plugin::MinimumPerl" => "0";
   requires "Dist::Zilla::Plugin::OnlyCorePrereqs" => "0";
   requires "Dist::Zilla::Plugin::Prereqs" => "0";
@@ -56,4 +54,5 @@ on 'develop' => sub {
   requires "Test::More" => "0";
   requires "Test::Pod" => "1.41";
   requires "Test::Pod::Coverage" => "1.08";
+  requires "Test::Spelling" => "0.12";
 };
@@ -4,7 +4,7 @@ use warnings;
 
 package Path::Tiny;
 # ABSTRACT: File path utility
-our $VERSION = '0.054'; # VERSION
+our $VERSION = '0.056'; # VERSION
 
 # Dependencies
 use Config;
@@ -203,7 +203,7 @@ sub path {
         return $path;
     }
 
-    # stringify initial path
+    # stringify objects
     $path = "$path";
 
     # expand relative volume paths on windows; put trailing slash on UNC root
@@ -212,18 +212,17 @@ sub path {
         $path .= "/" if $path =~ m{^$UNC_VOL$};
     }
 
-    # concatenate more arguments (stringifies any objects, too)
+    # concatenations stringifies objects, too
     if (@_) {
         $path .= ( _is_root($path) ? "" : "/" ) . join( "/", @_ );
     }
 
-    # canonicalize paths
-    my $cpath = $path = File::Spec->canonpath($path); # ugh, but probably worth it
-    $path =~ tr[\\][/] if IS_WIN32();                 # unix convention enforced
-    $path .= "/" if IS_WIN32() && $path =~ m{^$UNC_VOL$}; # canonpath strips it
+    # canonicalize, but with unix slashes and put back trailing volume slash
+    my $cpath = $path = File::Spec->canonpath($path);
+    $path =~ tr[\\][/] if IS_WIN32();
+    $path .= "/" if IS_WIN32() && $path =~ m{^$UNC_VOL$};
 
-    # hack to make splitpath give us a basename; root paths must always have
-    # a trailing slash, but other paths must not
+    # root paths must always have a trailing slash, but other paths must not
     if ( _is_root($path) ) {
         $path =~ s{/?$}{/};
     }
@@ -237,7 +236,6 @@ sub path {
         $path =~ s{^(~[^/]*)}{$homedir};
     }
 
-    # and we're finally done
     bless [ $path, $cpath ], __PACKAGE__;
 }
 
@@ -318,7 +316,7 @@ sub rootdir { path( File::Spec->rootdir ) }
 #pod =cut
 
 sub tempfile {
-    shift if $_[0] eq 'Path::Tiny'; # called as method
+    shift if @_ && $_[0] eq 'Path::Tiny'; # called as method
     my ( $maybe_template, $args ) = _parse_file_temp_args(@_);
     # File::Temp->new demands TEMPLATE
     $args->{TEMPLATE} = $maybe_template->[0] if @$maybe_template;
@@ -327,19 +325,19 @@ sub tempfile {
     my $temp = File::Temp->new( TMPDIR => 1, %$args );
     close $temp;
     my $self = path($temp)->absolute;
-    $self->[TEMP] = $temp;          # keep object alive while we are
+    $self->[TEMP] = $temp;                # keep object alive while we are
     return $self;
 }
 
 sub tempdir {
-    shift if $_[0] eq 'Path::Tiny'; # called as method
+    shift if @_ && $_[0] eq 'Path::Tiny'; # called as method
     my ( $maybe_template, $args ) = _parse_file_temp_args(@_);
 
     # File::Temp->newdir demands leading template
     require File::Temp;
     my $temp = File::Temp->newdir( @$maybe_template, TMPDIR => 1, %$args );
     my $self = path($temp)->absolute;
-    $self->[TEMP] = $temp;          # keep object alive while we are
+    $self->[TEMP] = $temp;                # keep object alive while we are
     return $self;
 }
 
@@ -606,28 +604,48 @@ sub copy {
 #pod
 #pod     $obj = path("/tmp/foo.txt")->digest;        # SHA-256
 #pod     $obj = path("/tmp/foo.txt")->digest("MD5"); # user-selected
+#pod     $obj = path("/tmp/foo.txt")->digest( { chunk_size => 1e6 }, "MD5" );
 #pod
-#pod Returns a hexadecimal digest for a file.  Any arguments are passed to the
-#pod constructor for L<Digest> to select an algorithm.  If no arguments are given,
-#pod the default is SHA-256.
+#pod Returns a hexadecimal digest for a file.  An optional hash reference of options may
+#pod be given.  The only option is C<chunk_size>.  If C<chunk_size> is given, that many
+#pod bytes will be read at a time.  If not provided, the entire file will be slurped
+#pod into memory to compute the digest.
+#pod
+#pod Any subsequent arguments are passed to the constructor for L<Digest> to select
+#pod an algorithm.  If no arguments are given, the default is SHA-256.
 #pod
 #pod =cut
 
 sub digest {
-    my ( $self, $alg, @args ) = @_;
-    $alg = 'SHA-256' unless defined $alg;
+    my ( $self, @opts ) = @_;
+    my $args = ( @opts && ref $opts[0] eq 'HASH' ) ? shift @opts : {};
+    $args = _get_args( $args, qw/chunk_size/ );
+    unshift @opts, 'SHA-256' unless @opts;
     require Digest;
-    return Digest->new( $alg, @args )->add( $self->slurp_raw )->hexdigest;
+    my $digest = Digest->new(@opts);
+    if ( $args->{chunk_size} ) {
+        my $fh = $self->filehandle( { locked => 1 }, "<", ":unix" );
+        my $buf;
+        $digest->add($buf) while read $fh, $buf, $args->{chunk_size};
+    }
+    else {
+        $digest->add( $self->slurp_raw );
+    }
+    return $digest->hexdigest;
 }
 
-#pod =method dirname
+#pod =method dirname (deprecated)
 #pod
 #pod     $name = path("/tmp/foo.txt")->dirname; # "/tmp/"
 #pod
-#pod Returns the directory name portion of the path.  This is roughly
-#pod equivalent to what L<File::Spec> would give from C<splitpath> and thus
-#pod usually has the trailing slash. If that's not desired, stringify directories
-#pod or call C<parent> on files.
+#pod Returns the directory portion you would get from calling
+#pod C<< File::Spec->splitpath( $path->stringify ) >> or C<"."> for a path without a
+#pod parent directory portion.  Because L<File::Spec> is inconsistent, the result
+#pod might or might not have a trailing slash.  Because of this, this method is
+#pod B<deprecated>.
+#pod
+#pod A better, more consistently approach is likely C<< $path->parent->stringify >>,
+#pod which will not have a trailing slash except for a root directory.
 #pod
 #pod =cut
 
@@ -1151,8 +1169,9 @@ sub relative { path( File::Spec->abs2rel( $_[0]->[PATH], $_[1] ) ) }
 #pod
 #pod B<Note: as of 0.012, remove only works on files>.
 #pod
-#pod This is just like C<unlink>, except if the path does not exist, it returns
-#pod false rather than throwing an exception.
+#pod This is just like C<unlink>, except for its error handling: if the path does
+#pod not exist, it returns false; if deleting the file fails, it throws an
+#pod exception.
 #pod
 #pod =cut
 
@@ -1161,7 +1180,7 @@ sub remove {
 
     return 0 if !-e $self->[PATH] && !-l $self->[PATH];
 
-    return unlink $self->[PATH] || $self->_throw('unlink');
+    return unlink( $self->[PATH] ) || $self->_throw('unlink');
 }
 
 #pod =method remove_tree
@@ -1490,7 +1509,7 @@ Path::Tiny - File path utility
 
 =head1 VERSION
 
-version 0.054
+version 0.056
 
 =head1 SYNOPSIS
 
@@ -1765,19 +1784,28 @@ Copies a file using L<File::Copy>'s C<copy> function.
 
     $obj = path("/tmp/foo.txt")->digest;        # SHA-256
     $obj = path("/tmp/foo.txt")->digest("MD5"); # user-selected
+    $obj = path("/tmp/foo.txt")->digest( { chunk_size => 1e6 }, "MD5" );
 
-Returns a hexadecimal digest for a file.  Any arguments are passed to the
-constructor for L<Digest> to select an algorithm.  If no arguments are given,
-the default is SHA-256.
+Returns a hexadecimal digest for a file.  An optional hash reference of options may
+be given.  The only option is C<chunk_size>.  If C<chunk_size> is given, that many
+bytes will be read at a time.  If not provided, the entire file will be slurped
+into memory to compute the digest.
 
-=head2 dirname
+Any subsequent arguments are passed to the constructor for L<Digest> to select
+an algorithm.  If no arguments are given, the default is SHA-256.
+
+=head2 dirname (deprecated)
 
     $name = path("/tmp/foo.txt")->dirname; # "/tmp/"
 
-Returns the directory name portion of the path.  This is roughly
-equivalent to what L<File::Spec> would give from C<splitpath> and thus
-usually has the trailing slash. If that's not desired, stringify directories
-or call C<parent> on files.
+Returns the directory portion you would get from calling
+C<< File::Spec->splitpath( $path->stringify ) >> or C<"."> for a path without a
+parent directory portion.  Because L<File::Spec> is inconsistent, the result
+might or might not have a trailing slash.  Because of this, this method is
+B<deprecated>.
+
+A better, more consistently approach is likely C<< $path->parent->stringify >>,
+which will not have a trailing slash except for a root directory.
 
 =head2 exists, is_file, is_dir
 
@@ -1982,8 +2010,9 @@ C<< File::Spec->abs2rel() >>.
 
 B<Note: as of 0.012, remove only works on files>.
 
-This is just like C<unlink>, except if the path does not exist, it returns
-false rather than throwing an exception.
+This is just like C<unlink>, except for its error handling: if the path does
+not exist, it returns false; if deleting the file fails, it throws an
+exception.
 
 =head2 remove_tree
 
@@ -2276,6 +2305,8 @@ David Golden <dagolden@cpan.org>
 
 =head1 CONTRIBUTORS
 
+=for stopwords Chris Williams David Steinbrunner Doug Bell Gabor Szabo Gabriel Andrade George Hartzell Geraud Continsouzas Goro Fuji Karen Etheridge Martin Kjeldsen Michael G. Schwern Smylers Toby Inkster 김도형 - Keedi Kim
+
 =over 4
 
 =item *
@@ -2288,6 +2319,10 @@ David Steinbrunner <dsteinbrunner@pobox.com>
 
 =item *
 
+Doug Bell <madcityzen@gmail.com>
+
+=item *
+
 Gabor Szabo <szabgab@cpan.org>
 
 =item *
@@ -2320,6 +2355,10 @@ Michael G. Schwern <mschwern@cpan.org>
 
 =item *
 
+Smylers <Smylers@stripey.com>
+
+=item *
+
 Toby Inkster <tobyink@cpan.org>
 
 =item *
@@ -7,6 +7,9 @@ allow = $@ $!
 [TestingAndDebugging::ProhibitNoStrict]
 allow = refs
 
+[Variables::ProhibitEvilVariables]
+variables = $DB::single
+
 # Turn these off
 [-BuiltinFunctions::ProhibitStringyEval]
 [-ControlStructures::ProhibitPostfixControls]
@@ -0,0 +1,70 @@
+do { my $x = {
+       'configure' => {
+                        'requires' => {
+                                        'ExtUtils::MakeMaker' => '6.17'
+                                      }
+                      },
+       'develop' => {
+                      'requires' => {
+                                      'Dist::Zilla' => '5',
+                                      'Dist::Zilla::Plugin::MinimumPerl' => '0',
+                                      'Dist::Zilla::Plugin::OnlyCorePrereqs' => '0',
+                                      'Dist::Zilla::Plugin::Prereqs' => '0',
+                                      'Dist::Zilla::Plugin::RemovePrereqs' => '0',
+                                      'Dist::Zilla::PluginBundle::DAGOLDEN' => '0.060',
+                                      'File::Spec' => '0',
+                                      'File::Temp' => '0',
+                                      'IO::Handle' => '0',
+                                      'IPC::Open3' => '0',
+                                      'Pod::Coverage::TrustPod' => '0',
+                                      'Test::CPAN::Meta' => '0',
+                                      'Test::More' => '0',
+                                      'Test::Pod' => '1.41',
+                                      'Test::Pod::Coverage' => '1.08',
+                                      'Test::Spelling' => '0.12'
+                                    }
+                    },
+       'runtime' => {
+                      'recommends' => {
+                                        'Unicode::UTF8' => '0.58'
+                                      },
+                      'requires' => {
+                                      'Carp' => '0',
+                                      'Cwd' => '0',
+                                      'Digest' => '1.03',
+                                      'Digest::SHA' => '5.45',
+                                      'Exporter' => '5.57',
+                                      'Fcntl' => '0',
+                                      'File::Copy' => '0',
+                                      'File::Path' => '2.07',
+                                      'File::Spec' => '3.40',
+                                      'File::Temp' => '0.19',
+                                      'File::stat' => '0',
+                                      'constant' => '0',
+                                      'if' => '0',
+                                      'overload' => '0',
+                                      'perl' => '5.008001',
+                                      'strict' => '0',
+                                      'warnings' => '0'
+                                    }
+                    },
+       'test' => {
+                   'recommends' => {
+                                     'CPAN::Meta' => '2.120900',
+                                     'Test::FailWarnings' => '0'
+                                   },
+                   'requires' => {
+                                   'ExtUtils::MakeMaker' => '0',
+                                   'File::Basename' => '0',
+                                   'File::Spec' => '3.40',
+                                   'File::Spec::Functions' => '0',
+                                   'File::Spec::Unix' => '0',
+                                   'File::Temp' => '0.19',
+                                   'Test::More' => '0.96',
+                                   'lib' => '0',
+                                   'open' => '0'
+                                 }
+                 }
+     };
+  $x;
+ }
\ No newline at end of file
@@ -3,201 +3,173 @@
 use strict;
 use warnings;
 
-# This test was generated by Dist::Zilla::Plugin::Test::ReportPrereqs 0.013
+# This test was generated by Dist::Zilla::Plugin::Test::ReportPrereqs 0.018
 
 use Test::More tests => 1;
 
 use ExtUtils::MakeMaker;
-use File::Spec::Functions;
-use List::Util qw/max/;
-use version;
+use File::Spec;
+
+# from $version::LAX
+my $lax_version_re =
+    qr/(?: undef | (?: (?:[0-9]+) (?: \. | (?:\.[0-9]+) (?:_[0-9]+)? )?
+            |
+            (?:\.[0-9]+) (?:_[0-9]+)?
+        ) | (?:
+            v (?:[0-9]+) (?: (?:\.[0-9]+)+ (?:_[0-9]+)? )?
+            |
+            (?:[0-9]+)? (?:\.[0-9]+){2,} (?:_[0-9]+)?
+        )
+    )/x;
 
 # hide optional CPAN::Meta modules from prereq scanner
 # and check if they are available
 my $cpan_meta = "CPAN::Meta";
-my $cpan_meta_req = "CPAN::Meta::Requirements";
-my $HAS_CPAN_META = eval "require $cpan_meta"; ## no critic
-my $HAS_CPAN_META_REQ = eval "require $cpan_meta_req; $cpan_meta_req->VERSION('2.120900')";
+my $cpan_meta_pre = "CPAN::Meta::Prereqs";
+my $HAS_CPAN_META = eval "require $cpan_meta; $cpan_meta->VERSION('2.120900')" && eval "require $cpan_meta_pre"; ## no critic
 
 # Verify requirements?
 my $DO_VERIFY_PREREQS = 1;
 
-sub _merge_requires {
+sub _max {
+    my $max = shift;
+    $max = ( $_ > $max ) ? $_ : $max for @_;
+    return $max;
+}
+
+sub _merge_prereqs {
     my ($collector, $prereqs) = @_;
-    for my $phase ( qw/configure build test runtime develop/ ) {
-        next unless exists $prereqs->{$phase};
-        if ( my $req = $prereqs->{$phase}{'requires'} ) {
-            my $cmr = CPAN::Meta::Requirements->from_string_hash( $req );
-            $collector->add_requirements( $cmr );
+
+    # CPAN::Meta::Prereqs object
+    if (ref $collector eq $cpan_meta_pre) {
+        return $collector->with_merged_prereqs(
+            CPAN::Meta::Prereqs->new( $prereqs )
+        );
+    }
+
+    # Raw hashrefs
+    for my $phase ( keys %$prereqs ) {
+        for my $type ( keys %{ $prereqs->{$phase} } ) {
+            for my $module ( keys %{ $prereqs->{$phase}{$type} } ) {
+                $collector->{$phase}{$type}{$module} = $prereqs->{$phase}{$type}{$module};
+            }
         }
     }
+
+    return $collector;
 }
 
-my %include = map {; $_ => 1 } qw(
+my @include = qw(
 
 );
 
-my %exclude = map {; $_ => 1 } qw(
+my @exclude = qw(
 
 );
 
 # Add static prereqs to the included modules list
-my $static_prereqs = do { my $x = {
-       'configure' => {
-                        'requires' => {
-                                        'ExtUtils::MakeMaker' => '6.17'
-                                      }
-                      },
-       'develop' => {
-                      'requires' => {
-                                      'Dist::Zilla' => '5.015',
-                                      'Dist::Zilla::Plugin::MinimumPerl' => '0',
-                                      'Dist::Zilla::Plugin::OnlyCorePrereqs' => '0',
-                                      'Dist::Zilla::Plugin::Prereqs' => '0',
-                                      'Dist::Zilla::Plugin::RemovePrereqs' => '0',
-                                      'Dist::Zilla::PluginBundle::DAGOLDEN' => '0.060',
-                                      'File::Spec' => '0',
-                                      'File::Temp' => '0',
-                                      'IO::Handle' => '0',
-                                      'IPC::Open3' => '0',
-                                      'Pod::Coverage::TrustPod' => '0',
-                                      'Test::CPAN::Meta' => '0',
-                                      'Test::More' => '0',
-                                      'Test::Pod' => '1.41',
-                                      'Test::Pod::Coverage' => '1.08'
-                                    }
-                    },
-       'runtime' => {
-                      'recommends' => {
-                                        'Unicode::UTF8' => '0.58'
-                                      },
-                      'requires' => {
-                                      'Carp' => '0',
-                                      'Cwd' => '0',
-                                      'Digest' => '1.03',
-                                      'Digest::SHA' => '5.45',
-                                      'Exporter' => '5.57',
-                                      'Fcntl' => '0',
-                                      'File::Copy' => '0',
-                                      'File::Path' => '2.07',
-                                      'File::Spec' => '3.40',
-                                      'File::Temp' => '0.19',
-                                      'File::stat' => '0',
-                                      'constant' => '0',
-                                      'if' => '0',
-                                      'overload' => '0',
-                                      'perl' => '5.008001',
-                                      'strict' => '0',
-                                      'warnings' => '0'
-                                    }
-                    },
-       'test' => {
-                   'recommends' => {
-                                     'CPAN::Meta' => '0',
-                                     'CPAN::Meta::Requirements' => '2.120900',
-                                     'Test::FailWarnings' => '0'
-                                   },
-                   'requires' => {
-                                   'ExtUtils::MakeMaker' => '0',
-                                   'File::Basename' => '0',
-                                   'File::Spec::Functions' => '0',
-                                   'File::Spec::Unix' => '0',
-                                   'File::Temp' => '0.19',
-                                   'List::Util' => '0',
-                                   'Test::More' => '0.96',
-                                   'lib' => '0',
-                                   'open' => '0',
-                                   'version' => '0'
-                                 }
-                 }
-     };
-  $x;
- };
-
-delete $static_prereqs->{develop} if not $ENV{AUTHOR_TESTING};
-$include{$_} = 1 for map { keys %$_ } map { values %$_ } values %$static_prereqs;
-
-# Merge requirements for major phases (if we can)
-my $all_requires;
-if ( $DO_VERIFY_PREREQS && $HAS_CPAN_META_REQ ) {
-    $all_requires = $cpan_meta_req->new;
-    _merge_requires($all_requires, $static_prereqs);
+my $static_prereqs = do 't/00-report-prereqs.dd';
+
+### XXX: Assume these are Runtime Requires
+my $static_prereqs_requires = $static_prereqs->{runtime}{requires};
+for my $mod (@include) {
+    $static_prereqs_requires->{$mod} = 0 unless exists $static_prereqs_requires->{$mod};
 }
 
+# Merge all prereqs (either with ::Prereqs or a hashref)
+my $full_prereqs = _merge_prereqs(
+    ( $HAS_CPAN_META ? $cpan_meta_pre->new : {} ),
+    $static_prereqs
+);
 
 # Add dynamic prereqs to the included modules list (if we can)
 my ($source) = grep { -f } 'MYMETA.json', 'MYMETA.yml';
 if ( $source && $HAS_CPAN_META ) {
-  if ( my $meta = eval { CPAN::Meta->load_file($source) } ) {
-    my $dynamic_prereqs = $meta->prereqs;
-    delete $dynamic_prereqs->{develop} if not $ENV{AUTHOR_TESTING};
-    $include{$_} = 1 for map { keys %$_ } map { values %$_ } values %$dynamic_prereqs;
-
-    if ( $DO_VERIFY_PREREQS && $HAS_CPAN_META_REQ ) {
-        _merge_requires($all_requires, $dynamic_prereqs);
+    if ( my $meta = eval { CPAN::Meta->load_file($source) } ) {
+        $full_prereqs = _merge_prereqs($full_prereqs, $meta->prereqs);
     }
-  }
 }
 else {
-  $source = 'static metadata';
+    $source = 'static metadata';
 }
 
-my @modules = sort grep { ! $exclude{$_} } keys %include;
-my @reports = [qw/Version Module/];
+my @full_reports;
 my @dep_errors;
-my $req_hash = defined($all_requires) ? $all_requires->as_string_hash : {};
-
-for my $mod ( @modules ) {
-  next if $mod eq 'perl';
-  my $file = $mod;
-  $file =~ s{::}{/}g;
-  $file .= ".pm";
-  my ($prefix) = grep { -e catfile($_, $file) } @INC;
-  if ( $prefix ) {
-    my $ver = MM->parse_version( catfile($prefix, $file) );
-    $ver = "undef" unless defined $ver; # Newer MM should do this anyway
-    push @reports, [$ver, $mod];
-
-    if ( $DO_VERIFY_PREREQS && $all_requires ) {
-      my $req = $req_hash->{$mod};
-      if ( defined $req && length $req ) {
-        if ( ! defined eval { version->parse($ver) } ) {
-          push @dep_errors, "$mod version '$ver' cannot be parsed (version '$req' required)";
-        }
-        elsif ( ! $all_requires->accepts_module( $mod => $ver ) ) {
-          push @dep_errors, "$mod version '$ver' is not in required range '$req'";
+my $req_hash = $HAS_CPAN_META ? $full_prereqs->as_string_hash : $full_prereqs;
+
+for my $phase ( qw(configure build test runtime develop) ) {
+    next unless $req_hash->{$phase};
+    next if ($phase eq 'develop' and not $ENV{AUTHOR_TESTING});
+
+    for my $type ( qw(requires recommends suggests conflicts) ) {
+        next unless $req_hash->{$phase}{$type};
+
+        my $title = ucfirst($phase).' '.ucfirst($type);
+        my @reports = [qw/Module Want Have/];
+
+        for my $mod ( sort keys %{ $req_hash->{$phase}{$type} } ) {
+            next if $mod eq 'perl';
+            next if grep { $_ eq $mod } @exclude;
+
+            my $file = $mod;
+            $file =~ s{::}{/}g;
+            $file .= ".pm";
+            my ($prefix) = grep { -e File::Spec->catfile($_, $file) } @INC;
+
+            my $want = $req_hash->{$phase}{$type}{$mod};
+            $want = "undef" unless defined $want;
+            $want = "any" if !$want && $want == 0;
+
+            my $req_string = $want eq 'any' ? 'any version required' : "version '$want' required";
+
+            if ($prefix) {
+                my $have = MM->parse_version( File::Spec->catfile($prefix, $file) );
+                $have = "undef" unless defined $have;
+                push @reports, [$mod, $want, $have];
+
+                if ( $DO_VERIFY_PREREQS && $HAS_CPAN_META && $type eq 'requires' ) {
+                    if ( $have !~ /\A$lax_version_re\z/ ) {
+                        push @dep_errors, "$mod version '$have' cannot be parsed ($req_string)";
+                    }
+                    elsif ( ! $full_prereqs->requirements_for( $phase, $type )->accepts_module( $mod => $have ) ) {
+                        push @dep_errors, "$mod version '$have' is not in required range '$want'";
+                    }
+                }
+            }
+            else {
+                push @reports, [$mod, $want, "missing"];
+
+                if ( $DO_VERIFY_PREREQS && $type eq 'requires' ) {
+                    push @dep_errors, "$mod is not installed ($req_string)";
+                }
+            }
         }
-      }
-    }
 
-  }
-  else {
-    push @reports, ["missing", $mod];
+        if ( @reports ) {
+            push @full_reports, "=== $title ===\n\n";
+
+            my $ml = _max( map { length $_->[0] } @reports );
+            my $wl = _max( map { length $_->[1] } @reports );
+            my $hl = _max( map { length $_->[2] } @reports );
+            splice @reports, 1, 0, ["-" x $ml, "-" x $wl, "-" x $hl];
 
-    if ( $DO_VERIFY_PREREQS && $all_requires ) {
-      my $req = $req_hash->{$mod};
-      if ( defined $req && length $req ) {
-        push @dep_errors, "$mod is not installed (version '$req' required)";
-      }
+            push @full_reports, map { sprintf("    %*s %*s %*s\n", -$ml, $_->[0], $wl, $_->[1], $hl, $_->[2]) } @reports;
+            push @full_reports, "\n";
+        }
     }
-  }
 }
 
-if ( @reports ) {
-  my $vl = max map { length $_->[0] } @reports;
-  my $ml = max map { length $_->[1] } @reports;
-  splice @reports, 1, 0, ["-" x $vl, "-" x $ml];
-  diag "\nVersions for all modules listed in $source (including optional ones):\n",
-    map {sprintf("  %*s %*s\n",$vl,$_->[0],-$ml,$_->[1])} @reports;
+if ( @full_reports ) {
+    diag "\nVersions for all modules listed in $source (including optional ones):\n\n", @full_reports;
 }
 
 if ( @dep_errors ) {
-  diag join("\n",
-    "\n*** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ***\n",
-    "The following REQUIRED prerequisites were not satisfied:\n",
-    @dep_errors,
-    "\n"
-  );
+    diag join("\n",
+        "\n*** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ***\n",
+        "The following REQUIRED prerequisites were not satisfied:\n",
+        @dep_errors,
+        "\n"
+    );
 }
 
 pass;
@@ -23,7 +23,9 @@ is(
 
 my $sha = Digest->new('SHA-256');
 $sha->add($chunk);
-is( $file->digest, $sha->hexdigest, 'digest SHA-256', );
+my $sha_hex = $sha->hexdigest;
+is( $file->digest, $sha_hex, 'digest SHA-256' );
+is( $file->digest( { chunk_size => 10 } ), $sha_hex, 'digest SHA-256 (chunked)' );
 
 is(
     $file->digest('MD5'),
@@ -33,7 +35,9 @@ is(
 
 my $md5 = Digest->new('MD5');
 $md5->add($chunk);
-is( $file->digest('MD5'), $md5->hexdigest, 'digest MD5', );
+my $md5_hex = $md5->hexdigest;
+is( $file->digest('MD5'), $md5_hex, 'digest MD5', );
+is( $file->digest( { chunk_size => 10 }, 'MD5' ), $md5_hex, 'digest MD5 (chunked)' );
 
 done_testing;
 #
@@ -176,6 +176,18 @@ my $tmpdir = Path::Tiny->tempdir;
     ok( $file->remove, "removing file" );
     ok !-e $file, "file is gone";
     ok !$file->remove, "removing file again returns false";
+
+    my $subdir = $tmpdir->child('subdir');
+    ok $subdir->mkpath;
+    ok exception { $subdir->remove }, "calling 'remove' on a directory throws";
+    ok rmdir $subdir;
+
+    my $orig = Path::Tiny->cwd;
+    ok chdir $tmpdir;
+    my $zero_file = path '0';
+    ok $zero_file->openw;
+    ok $zero_file->remove, "removing file called '0'";
+    ok chdir $orig;
 }
 
 {
@@ -2,7 +2,7 @@ use 5.006;
 use strict;
 use warnings;
 
-# this test was generated with Dist::Zilla::Plugin::Test::Compile 2.040
+# this test was generated with Dist::Zilla::Plugin::Test::Compile 2.045
 
 use Test::More  tests => 1 + ($ENV{AUTHOR_TESTING} ? 1 : 0);
 
@@ -2,7 +2,7 @@ use strict;
 use warnings;
 use Test::More;
 
-# generated by Dist::Zilla::Plugin::Test::PodSpelling 2.006007
+# generated by Dist::Zilla::Plugin::Test::PodSpelling 2.006008
 use Test::Spelling 0.12;
 use Pod::Wordlist;
 
@@ -41,6 +41,9 @@ Williams
 bingos
 Steinbrunner
 dsteinbrunner
+Doug
+Bell
+madcityzen
 Gabor
 Szabo
 szabgab
@@ -65,6 +68,7 @@ mk
 Michael
 Schwern
 mschwern
+Smylers
 Toby
 Inkster
 tobyink