The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
Changes 045
MANIFEST 03
META.json 117
META.yml 85
Makefile.PL 12
README 526
cpanfile 11
dist.ini 01
lib/Path/Tiny.pm 2690
t/00-report-prereqs.t 22
t/input_output.t 44
t/mutable_tree_while_iterating.t 036
t/subsumes.t 0105
t/zzz-spec.t 22
xt/author/00-compile.t 24
xt/author/pod-spell.t 44
xt/release/distmeta.t 01
xt/release/pod-coverage.t 01
xt/release/pod-syntax.t 01
19 files changed (This is a version diff) 66340
@@ -1,5 +1,50 @@
 Revision history for Path-Tiny
 
+0.052     2014-01-14 15:58:03-05:00 America/New_York
+
+    [FIXED]
+
+    - Backslash-to-slash conversion now only happens on Windows
+      (since backslash is legal on Unix, we must allow it)
+
+0.051     2013-12-20 07:34:14 America/New_York
+
+    [FIXED]
+
+    - Fixed file order bug in the new test file
+
+0.050     2013-12-20 07:27:20 America/New_York
+
+    [FIXED]
+
+    - Recursive iteration won't throw an exception if a directory is
+      removed or unreadable during iteration.
+
+0.049     2013-12-12 00:48:01 America/New_York
+
+    [FIXED]
+
+    - Generates filename for atomic writes independent of thread-ID.
+      Fixes crashing bug on Win32 when fork() is called.
+
+0.048     2013-12-11 21:56:23 America/New_York
+
+    [ADDED]
+
+    - Added 'subsumes' method
+
+    [CHANGED]
+
+    - The 'chomp' option for 'lines' will remove any end-of-line sequences
+      fully instead of just chomping the last character
+
+    - The 'flock' package will no longer indexed by PAUSE
+
+    [FIXED]
+
+    - Hides warnings and fixes possible fatal errors from pure-perl Cwd,
+      particularly on MSWin32
+
 0.047     2013-11-26 15:11:13 America/New_York
 
     [FIXED]
@@ -1,3 +1,4 @@
+# This file was automatically generated by Dist::Zilla::Plugin::Manifest v5.011.
 CONTRIBUTING
 Changes
 LICENSE
@@ -23,11 +24,13 @@ t/input_output_no_UU.t
 t/lib/TestUtils.pm
 t/locking.t
 t/mkpath.t
+t/mutable_tree_while_iterating.t
 t/normalize.t
 t/overloading.t
 t/parent.t
 t/recurse.t
 t/rel-abs.t
+t/subsumes.t
 t/temp.t
 t/zzz-spec.t
 tidyall.ini
@@ -4,7 +4,7 @@
       "David Golden <dagolden@cpan.org>"
    ],
    "dynamic_config" : 0,
-   "generated_by" : "Dist::Zilla version 5.006, CPAN::Meta::Converter version 2.132830",
+   "generated_by" : "Dist::Zilla version 5.011, CPAN::Meta::Converter version 2.133380",
    "license" : [
       "apache_2_0"
    ],
@@ -21,7 +21,8 @@
          "corpus"
       ],
       "package" : [
-         "DB"
+         "DB",
+         "flock"
       ]
    },
    "prereqs" : {
@@ -32,7 +33,7 @@
       },
       "develop" : {
          "requires" : {
-            "Dist::Zilla" : "5.006",
+            "Dist::Zilla" : "5.011",
             "Dist::Zilla::Plugin::MakeMaker" : "0",
             "Dist::Zilla::Plugin::OnlyCorePrereqs" : "0",
             "Dist::Zilla::Plugin::Prereqs" : "0",
@@ -95,15 +96,11 @@
    "provides" : {
       "Path::Tiny" : {
          "file" : "lib/Path/Tiny.pm",
-         "version" : "0.047"
+         "version" : "0.052"
       },
       "Path::Tiny::Error" : {
          "file" : "lib/Path/Tiny.pm",
-         "version" : "0.047"
-      },
-      "flock" : {
-         "file" : "lib/Path/Tiny.pm",
-         "version" : "0.047"
+         "version" : "0.052"
       }
    },
    "release_status" : "stable",
@@ -118,7 +115,7 @@
          "web" : "https://github.com/dagolden/Path-Tiny"
       }
    },
-   "version" : "0.047",
+   "version" : "0.052",
    "x_authority" : "cpan:DAGOLDEN",
    "x_contributors" : [
       "Chris Williams <bingos@cpan.org>",
@@ -129,7 +126,6 @@
       "Geraud Continsouzas <geraud@scsi.nc>",
       "Goro Fuji <gfuji@cpan.org>",
       "Karen Etheridge <ether@cpan.org>",
-      "Keedi Kim <keedi@cpan.org>",
       "Martin Kjeldsen <mk@bluepipe.dk>",
       "Michael G. Schwern <mschwern@cpan.org>",
       "Toby Inkster <tobyink@cpan.org>",
@@ -15,7 +15,7 @@ build_requires:
 configure_requires:
   ExtUtils::MakeMaker: 6.17
 dynamic_config: 0
-generated_by: 'Dist::Zilla version 5.006, CPAN::Meta::Converter version 2.132830'
+generated_by: 'Dist::Zilla version 5.011, CPAN::Meta::Converter version 2.133380'
 license: apache
 meta-spec:
   url: http://module-build.sourceforge.net/META-spec-v1.4.html
@@ -29,16 +29,14 @@ no_index:
     - corpus
   package:
     - DB
+    - flock
 provides:
   Path::Tiny:
     file: lib/Path/Tiny.pm
-    version: 0.047
+    version: 0.052
   Path::Tiny::Error:
     file: lib/Path/Tiny.pm
-    version: 0.047
-  flock:
-    file: lib/Path/Tiny.pm
-    version: 0.047
+    version: 0.052
 recommends:
   Unicode::UTF8: 0.58
 requires:
@@ -63,7 +61,7 @@ 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.047
+version: 0.052
 x_authority: cpan:DAGOLDEN
 x_contributors:
   - 'Chris Williams <bingos@cpan.org>'
@@ -74,7 +72,6 @@ x_contributors:
   - 'Geraud Continsouzas <geraud@scsi.nc>'
   - 'Goro Fuji <gfuji@cpan.org>'
   - 'Karen Etheridge <ether@cpan.org>'
-  - 'Keedi Kim <keedi@cpan.org>'
   - 'Martin Kjeldsen <mk@bluepipe.dk>'
   - 'Michael G. Schwern <mschwern@cpan.org>'
   - 'Toby Inkster <tobyink@cpan.org>'
@@ -1,4 +1,5 @@
 
+# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v5.011.
 use strict;
 use warnings;
 
@@ -48,7 +49,7 @@ my %WriteMakefileArgs = (
     "lib" => 0,
     "open" => 0
   },
-  "VERSION" => "0.047",
+  "VERSION" => "0.052",
   "test" => {
     "TESTS" => "t/*.t"
   }
@@ -2,7 +2,7 @@ NAME
     Path::Tiny - File path utility
 
 VERSION
-    version 0.047
+    version 0.052
 
 SYNOPSIS
       use Path::Tiny;
@@ -298,7 +298,8 @@ METHODS
     If the "recurse" option is true, the iterator will walk the directory
     recursively, breadth-first. If the "follow_symlinks" option is also
     true, directory links will be followed recursively. There is no
-    protection against loops when following links.
+    protection against loops when following links. If a directory is not
+    readable, it will not be followed.
 
     The default is the same as:
 
@@ -322,7 +323,8 @@ METHODS
     of options. Valid options are "binmode", "count" and "chomp". If
     "binmode" is provided, it will be set on the handle prior to reading. If
     "count" is provided, up to that many lines will be returned. If "chomp"
-    is set, lines will be chomped before being returned.
+    is set, any end-of-line character sequences ("CR", "CRLF", or "LF") will
+    be removed from the lines returned.
 
     Because the return is a list, "lines" in scalar context will return the
     number of lines (and throw away the data).
@@ -490,6 +492,24 @@ METHODS
     method returns the path standardized with Unix-style "/" directory
     separators.
 
+  subsumes
+        path("foo/bar")->subsumes("foo/bar/baz"); # true
+        path("/foo/bar")->subsumes("/foo/baz");   # false
+
+    Returns true if the first path is a prefix of the second path at a
+    directory boundary.
+
+    This does not resolve parent directory entries ("..") or symlinks:
+
+        path("foo/bar")->subsumes("foo/bar/../baz"); # true
+
+    If such things are important to you, ensure that both paths are resolved
+    to the filesystem with "realpath":
+
+        my $p1 = path("foo/bar")->realpath;
+        my $p2 = path("foo/bar/../baz")->realpath;
+        if ( $p1->subsumes($p2) ) { ... }
+
   touch
         path("foo.txt")->touch;
         path("foo.txt")->touch($epoch_secs);
@@ -614,6 +634,9 @@ SEE ALSO
     There are probably comparable, non-Tiny tools. Let me know if you want
     me to add a module to the list.
 
+    This module was featured in the 2013 Perl Advent Calendar
+    <http://www.perladvent.org/2013/2013-12-18.html>.
+
 SUPPORT
   Bugs / Feature Requests
     Please report any bugs or feature requests through the issue tracker at
@@ -648,8 +671,6 @@ CONTRIBUTORS
 
     *   Karen Etheridge <ether@cpan.org>
 
-    *   Keedi Kim <keedi@cpan.org>
-
     *   Martin Kjeldsen <mk@bluepipe.dk>
 
     *   Michael G. Schwern <mschwern@cpan.org>
@@ -40,7 +40,7 @@ on 'configure' => sub {
 };
 
 on 'develop' => sub {
-  requires "Dist::Zilla" => "5.006";
+  requires "Dist::Zilla" => "5.011";
   requires "Dist::Zilla::Plugin::MakeMaker" => "0";
   requires "Dist::Zilla::Plugin::OnlyCorePrereqs" => "0";
   requires "Dist::Zilla::Plugin::Prereqs" => "0";
@@ -30,6 +30,7 @@ stopwords = touchpath
 stopwords = UNC
 stopwords = unlinked
 stopwords = utf
+MetaNoIndex.package = flock
 
 [MakeMaker]
 eumm_version = 6.17
@@ -4,7 +4,7 @@ use warnings;
 
 package Path::Tiny;
 # ABSTRACT: File path utility
-our $VERSION = '0.047'; # VERSION
+our $VERSION = '0.052'; # VERSION
 
 # Dependencies
 use Config;
@@ -32,13 +32,7 @@ use overload (
     fallback => 1,
 );
 
-# if cloning, threads should already be loaded, but Win32 pseudoforks
-# don't do that so we have to be sure it's loaded anyway
-my $TID = 0; # for thread safe atomic writes
-
-sub CLONE { require threads; $TID = threads->tid }
-
-my $HAS_UU;  # has Unicode::UTF8; lazily populated
+my $HAS_UU; # has Unicode::UTF8; lazily populated
 
 sub _check_UU {
     eval { require Unicode::UTF8; Unicode::UTF8->VERSION(0.58); 1 };
@@ -56,10 +50,10 @@ my $WIN32_ROOT = qr{(?: $UNC_VOL $SLASH | $DRV_VOL $SLASH | $SLASH )}x;
 sub _win32_vol {
     my ( $path, $drv ) = @_;
     require Cwd;
-    my $dcwd = Cwd::getdcwd($drv); # C: -> C:\some\cwd
+    my $dcwd = eval { Cwd::getdcwd($drv) }; # C: -> C:\some\cwd
     # getdcwd on non-existent drive returns empty string
     # so just use the original drive Z: -> Z:
-    $dcwd = "$drv" unless length $dcwd;
+    $dcwd = "$drv" unless defined $dcwd && length $dcwd;
     # normalize dwcd to end with a slash: might be C:\some\cwd or D:\ or Z:
     $dcwd =~ s{$SLASH?$}{/};
     # make the path absolute with dcwd
@@ -147,7 +141,7 @@ sub path {
 
     # canonicalize paths
     my $cpath = $path = File::Spec->canonpath($path); # ugh, but probably worth it
-    $path =~ tr[\\][/];                               # unix convention enforced
+    $path =~ tr[\\][/] if IS_WIN32();                 # unix convention enforced
     $path .= "/" if IS_WIN32() && $path =~ m{^$UNC_VOL$}; # canonpath strips it
 
     # hack to make splitpath give us a basename; root paths must always have
@@ -244,7 +238,9 @@ sub absolute {
         # add missing volume
         if ( $self->is_absolute ) {
             require Cwd;
-            my ($drv) = Cwd::getdcwd() =~ /^($DRV_VOL | $UNC_VOL)/x;
+            # use Win32::GetCwd not Cwd::getdcwd because we're sure
+            # to have the former but not necessarily the latter
+            my ($drv) = Win32::GetCwd() =~ /^($DRV_VOL | $UNC_VOL)/x;
             return path( $drv . $self->[PATH] );
         }
     }
@@ -441,6 +437,15 @@ sub iterator {
         my $next;
         while (@dirs) {
             if ( ref $dirs[0] eq 'Path::Tiny' ) {
+                if ( !-r $dirs[0] ) {
+                    # Directory is missing or not readable, so skip it.  There
+                    # is still a race condition possible between the check and
+                    # the opendir, but we can't easily differentiate between
+                    # error cases that are OK to skip and those that we want
+                    # to be exceptions, so we live with the race and let opendir
+                    # be fatal.
+                    shift @dirs and next;
+                }
                 $current = $dirs[0];
                 my $dh;
                 opendir( $dh, $current->[PATH] )
@@ -479,14 +484,14 @@ sub lines {
     if ( $args->{count} ) {
         my ( @result, $counter );
         while ( my $line = <$fh> ) {
-            chomp $line if $chomp;
+            $line =~ s/(?:\x{0d}?\x{0a}|\x{0d})$// if $chomp;
             push @result, $line;
             last if ++$counter == $args->{count};
         }
         return @result;
     }
     elsif ($chomp) {
-        return map { chomp; $_ } <$fh>;
+        return map { s/(?:\x{0d}?\x{0a}|\x{0d})$//; $_ } <$fh>; ## no critic
     }
     else {
         return wantarray ? <$fh> : ( my $count =()= <$fh> );
@@ -497,7 +502,7 @@ sub lines_raw {
     my $self = shift;
     my $args = _get_args( shift, qw/binmode chomp count/ );
     if ( $args->{chomp} && !$args->{count} ) {
-        return split /\n/, slurp_raw($self); ## no critic
+        return split /\n/, slurp_raw($self);                    ## no critic
     }
     else {
         $args->{binmode} = ":raw";
@@ -512,7 +517,7 @@ sub lines_utf8 {
         && $args->{chomp}
         && !$args->{count} )
     {
-        return split /\n/, slurp_utf8($self); ## no critic
+        return split /(?:\x{0d}?\x{0a}|\x{0d})/, slurp_utf8($self); ## no critic
     }
     else {
         $args->{binmode} = ":raw:encoding(UTF-8)";
@@ -620,7 +625,10 @@ sub _non_empty {
 sub realpath {
     my $self = shift;
     require Cwd;
-    my $realpath = eval { Cwd::realpath( $self->[PATH] ) };
+    my $realpath = eval {
+        local $SIG{__WARN__} = sub { }; # (sigh) pure-perl CWD can carp
+        Cwd::realpath( $self->[PATH] );
+    };
     $self->_throw("resolving realpath") unless defined $realpath and length $realpath;
     return path($realpath);
 }
@@ -697,7 +705,7 @@ sub spew {
     my $binmode = $args->{binmode};
     # get default binmode from caller's lexical scope (see "perldoc open")
     $binmode = ( ( caller(0) )[10] || {} )->{'open>'} unless defined $binmode;
-    my $temp = path( $self->[PATH] . $TID . $$ );
+    my $temp = path( $self->[PATH] . $$ . int( rand( 2**31 ) ) );
     my $fh = $temp->filehandle( { locked => 1 }, ">", $binmode );
     print {$fh} map { ref eq 'ARRAY' ? @$_ : $_ } @data;
     close $fh or $self->_throw( 'close', $temp->[PATH] );
@@ -740,6 +748,43 @@ sub lstat {
 sub stringify { $_[0]->[PATH] }
 
 
+sub subsumes {
+    my $self = shift;
+    Carp::croak("subsumes() requires a defined, positive-length argument")
+      unless defined $_[0];
+    my $other = path(shift);
+
+    # normalize absolute vs relative
+    if ( $self->is_absolute && !$other->is_absolute ) {
+        $other = $other->absolute;
+    }
+    elsif ( $other->is_absolute && !$self->is_absolute ) {
+        $self = $self->absolute;
+    }
+
+    # normalize volume vs non-volume; do this after absolute path
+    # adjustments above since that might add volumes already
+    if ( length $self->volume && !length $other->volume ) {
+        $other = $other->absolute;
+    }
+    elsif ( length $other->volume && !length $self->volume ) {
+        $self = $self->absolute;
+    }
+
+    if ( $self->[PATH] eq '.' ) {
+        return !!1; # cwd subsumes everything relative
+    }
+    elsif ( $self->is_rootdir ) {
+        # a root directory ("/", "c:/") already ends with a separator
+        return $other->[PATH] =~ m{^\Q$self->[PATH]\E};
+    }
+    else {
+        # exact match or prefix breaking at a separator
+        return $other->[PATH] =~ m{^\Q$self->[PATH]\E(?:/|$)};
+    }
+}
+
+
 sub touch {
     my ( $self, $epoch ) = @_;
     if ( !-e $self->[PATH] ) {
@@ -797,7 +842,7 @@ Path::Tiny - File path utility
 
 =head1 VERSION
 
-version 0.047
+version 0.052
 
 =head1 SYNOPSIS
 
@@ -1113,7 +1158,8 @@ be included.
 If the C<recurse> option is true, the iterator will walk the directory
 recursively, breadth-first.  If the C<follow_symlinks> option is also true,
 directory links will be followed recursively.  There is no protection against
-loops when following links.
+loops when following links. If a directory is not readable, it will not be
+followed.
 
 The default is the same as:
 
@@ -1137,8 +1183,9 @@ L<Path::Iterator::Rule>.
 Returns a list of lines from a file.  Optionally takes a hash-reference of
 options.  Valid options are C<binmode>, C<count> and C<chomp>.  If C<binmode>
 is provided, it will be set on the handle prior to reading.  If C<count> is
-provided, up to that many lines will be returned. If C<chomp> is set, lines
-will be chomped before being returned.
+provided, up to that many lines will be returned. If C<chomp> is set, any
+end-of-line character sequences (C<CR>, C<CRLF>, or C<LF>) will be removed
+from the lines returned.
 
 Because the return is a list, C<lines> in scalar context will return the number
 of lines (and throw away the data).
@@ -1317,6 +1364,25 @@ Like calling C<stat> or C<lstat> from L<File::stat>.
 Returns a string representation of the path.  Unlike C<canonpath>, this method
 returns the path standardized with Unix-style C</> directory separators.
 
+=head2 subsumes
+
+    path("foo/bar")->subsumes("foo/bar/baz"); # true
+    path("/foo/bar")->subsumes("/foo/baz");   # false
+
+Returns true if the first path is a prefix of the second path at a directory
+boundary.
+
+This B<does not> resolve parent directory entries (C<..>) or symlinks:
+
+    path("foo/bar")->subsumes("foo/bar/../baz"); # true
+
+If such things are important to you, ensure that both paths are resolved to
+the filesystem with C<realpath>:
+
+    my $p1 = path("foo/bar")->realpath;
+    my $p2 = path("foo/bar/../baz")->realpath;
+    if ( $p1->subsumes($p2) ) { ... }
+
 =head2 touch
 
     path("foo.txt")->touch;
@@ -1484,6 +1550,8 @@ L<File::Next>
 There are probably comparable, non-Tiny tools.  Let me know if you want me to
 add a module to the list.
 
+This module was featured in the L<2013 Perl Advent Calendar|http://www.perladvent.org/2013/2013-12-18.html>.
+
 =for :stopwords cpan testmatrix url annocpan anno bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan
 
 =head1 SUPPORT
@@ -1545,10 +1613,6 @@ Karen Etheridge <ether@cpan.org>
 
 =item *
 
-Keedi Kim <keedi@cpan.org>
-
-=item *
-
 Martin Kjeldsen <mk@bluepipe.dk>
 
 =item *
@@ -3,7 +3,7 @@
 use strict;
 use warnings;
 
-# This test was generated by Dist::Zilla::Plugin::Test::ReportPrereqs 0.010
+# This test was generated by Dist::Zilla::Plugin::Test::ReportPrereqs 0.012
 
 use Test::More tests => 1;
 
@@ -70,7 +70,7 @@ if ( -f $source && eval "require $cpan_meta" ) { ## no critic
       $prereqs = $meta->effective_prereqs; # get the object, not the hash
       if (eval "require $cpan_meta_req; 1") { ## no critic
         $all_requires = $cpan_meta_req->new;
-        for my $phase ( qw/configure build test runtime/ ) {
+        for my $phase ( qw/configure build test runtime develop/ ) {
           $all_requires->add_requirements(
             $prereqs->requirements_for($phase, 'requires')
           );
@@ -11,7 +11,7 @@ use Path::Tiny;
 my $tmp = Path::Tiny->tempdir;
 
 sub _lines {
-    return ( "Line1\n", "Line2\n" );
+    return ( "Line1\r\n", "Line2\n" );
 }
 
 sub _utf8_lines {
@@ -125,7 +125,7 @@ subtest "spew -> lines (count, more than)" => sub {
 subtest "spew -> lines (count, chomp)" => sub {
     my $file = Path::Tiny->tempfile;
     ok( $file->spew(_lines), "spew" );
-    my @exp = map { chomp; $_ } _lines;
+    my @exp = map { s/[\r\n]+//; $_ } _lines;
     is( join( '', $file->lines( { chomp => 1, count => 2 } ) ),
         join( '', @exp[ 0 .. 1 ] ), "lines" );
 };
@@ -140,7 +140,7 @@ subtest "spew -> lines (count, UTF-8)" => sub {
 subtest "spew -> lines (count, chomp, UTF-8)" => sub {
     my $file = Path::Tiny->tempfile;
     ok( $file->spew_utf8(_utf8_lines), "spew" );
-    my @exp = map { chomp; $_ } _utf8_lines;
+    my @exp = map { s/[\r\n]+//; $_ } _utf8_lines;
     is( join( '', $file->lines_utf8( { chomp => 1, count => 2 } ) ),
         join( '', @exp[ 0 .. 1 ] ), "lines" );
 };
@@ -148,7 +148,7 @@ subtest "spew -> lines (count, chomp, UTF-8)" => sub {
 subtest "spew -> lines (chomp, UTF-8)" => sub {
     my $file = Path::Tiny->tempfile;
     ok( $file->spew_utf8(_utf8_lines), "spew" );
-    my @exp = map { chomp; $_ } _utf8_lines;
+    my @exp = map { s/[\r\n]+//; $_ } _utf8_lines;
     is( join( '', $file->lines_utf8( { chomp => 1 } ) ), join( '', @exp ), "lines" );
 };
 
@@ -0,0 +1,36 @@
+use strict;
+use warnings;
+use Test::More 0.88;
+use Path::Tiny;
+
+use lib 't/lib';
+use TestUtils qw/exception tempd/;
+use Path::Tiny;
+
+my $wd = tempd;
+
+my @tree = qw(
+  base/Bethlehem/XDG/gift_list.txt
+  base/Vancouver/ETHER/.naughty
+  base/Vancouver/ETHER/gift_list.txt
+  base/New_York/XDG/gift_list.txt
+);
+path($_)->touchpath for @tree;
+
+my @files;
+my $iter = path('base')->iterator( { recurse => 1 } );
+my $exception = exception {
+    while ( my $path = $iter->() ) {
+        $path->remove_tree if $path->child('.naughty')->is_file;
+        push @files, $path if $path->is_file;
+    }
+};
+
+is( $exception, '', 'can remove directories while traversing' );
+is_deeply(
+    [ sort @files ],
+    [ 'base/Bethlehem/XDG/gift_list.txt', 'base/New_York/XDG/gift_list.txt' ],
+    'remaining files',
+);
+
+done_testing;
@@ -0,0 +1,105 @@
+use 5.008001;
+use strict;
+use warnings;
+use Test::More 0.96;
+
+use lib 't/lib';
+use TestUtils qw/exception/;
+
+use Path::Tiny;
+use Cwd;
+
+my $IS_WIN32 = $^O eq 'MSWin32';
+
+my @cases = (
+    # path1 => path2 => path1->subsumes(path2)
+
+    "identity always subsumes" => [
+        [ '.'     => '.'     => 1 ],
+        [ '/'     => '/'     => 1 ],
+        [ '..'    => '..'    => 1 ],
+        [ '../..' => '../..' => 1 ],
+        [ '/foo/' => '/foo'  => 1 ],
+        [ 'foo/'  => 'foo'   => 1 ],
+        [ './foo' => 'foo'   => 1 ],
+        [ 'foo/.' => 'foo'   => 1 ],
+    ],
+
+    "absolute v. absolute" => [
+        [ '/foo'     => '/foo/bar'      => 1 ],
+        [ '/foo'     => '/foo/bar/baz'  => 1 ],
+        [ '/foo'     => '/foo/bar/baz/' => 1 ],
+        [ '/'        => '/foo'          => 1 ],
+        [ '/foo'     => '/bar'          => 0 ],
+        [ '/foo/bar' => '/foo/baz'      => 0 ],
+    ],
+
+    "relative v. relative" => [
+        [ '.'         => 'foo'         => 1 ],
+        [ 'foo'       => 'foo/baz'     => 1 ],
+        [ './foo/bar' => 'foo/bar/baz' => 1 ],
+        [ './foo/bar' => './foo/bar'   => 1 ],
+        [ './foo/bar' => 'foo/bar'     => 1 ],
+        [ 'foo/bar'   => './foo/bar'   => 1 ],
+        [ 'foo/bar'   => 'foo/baz'     => 0 ],
+    ],
+
+    "relative v. absolute" => [
+        [ path(".")->absolute   => 't'                 => 1 ],
+        [ "."                   => path('t')->absolute => 1 ],
+        [ "foo"                 => path('t')->absolute => 0 ],
+        [ path("..")->realpath  => 't'                 => 1 ],
+        [ path("lib")->absolute => 't'                 => 0 ],
+    ],
+
+    "updirs in paths" => [
+        [ '/foo'        => '/foo/bar/baz/..' => 1 ],
+        [ '/foo/bar'    => '/foo/bar/../baz' => $IS_WIN32 ? 0 : 1 ],
+        [ '/foo/../bar' => '/bar'            => $IS_WIN32 ? 1 : 0 ],
+        [ '..'          => '../bar'          => 1 ],
+    ],
+
+);
+
+if ($IS_WIN32) {
+    my $vol = path( Win32::GetCwd() )->volume . "/";
+    my $other = $vol ne 'Z:/' ? 'Z:/' : 'Y:/';
+    push @cases, 'Win32 cases',
+      [
+        [ "C:/foo"    => "C:/foo"    => 1 ],
+        [ "C:/foo"    => "C:/bar"    => 0 ],
+        [ "C:/"       => "C:/foo"    => 1 ],
+        [ "C:/"       => "D:/"       => 0 ],
+        [ "${vol}foo" => "/foo"      => 1 ],
+        [ $vol        => "/foo"      => 1 ],
+        [ $vol        => $other      => 0 ],
+        [ "/"         => $vol        => 1 ],
+        [ "/"         => $other      => 0 ],
+        [ "/foo"      => "${vol}foo" => 1 ],
+      ];
+}
+
+while (@cases) {
+    my ( $subtest, $tests ) = splice( @cases, 0, 2 );
+    subtest $subtest => sub {
+        for my $t (@$tests) {
+            my ( $path1, $path2, $subsumes ) = @$t;
+            my $label =
+              join( " ", $path1, ( $subsumes ? "subsumes" : "does not subsume" ), $path2 );
+            ok( !!path($path1)->subsumes($path2) eq !!$subsumes, $label )
+              or diag "PATH 1:\n", explain( path($path1) ), "\nPATH2:\n",
+              explain( path($path2) );
+        }
+    };
+}
+
+done_testing;
+#
+# This file is part of Path-Tiny
+#
+# This software is Copyright (c) 2013 by David Golden.
+#
+# This is free software, licensed under:
+#
+#   The Apache License, Version 2.0, January 2004
+#
@@ -63,7 +63,7 @@ my @tests = (
     [ "path('..')->absolute('/t1/t2/t3')",           '/t1/t2/t3/..',    '/t1/t2' ],
     [ "path('../t4')->absolute('/t1/t2/t3')",        '/t1/t2/t3/../t4', '/t1/t2/t4' ],
     # need to wash through rootdir->absolute->child to pick up volume on Windows
-    [ "path('/t1')->absolute('/t1/t2/t3')",  Path::Tiny->rootdir->absolute->child("t1") ],
+    [ "path('/t1')->absolute('/t1/t2/t3')", Path::Tiny->rootdir->absolute->child("t1") ],
 );
 
 my @win32_tests;
@@ -119,7 +119,7 @@ if ($IS_WIN32) {
         [ "path('/../')",                  '/' ],
         [ "path('d1/../foo')",             'foo' ],
         # if there's no C drive, getdcwd will probably return '', so fake it
-        [ "path('C:')", path( Cwd::getdcwd("C:") || "C:/" ) ],
+        [ "path('C:')", path( eval { Cwd::getdcwd("C:") } || "C:/" ) ],
         [ "path('\\\\server\\share\\')", '//server/share/' ],
         [ "path('\\\\server\\share')",   '//server/share/' ],
         [ "path('//server/share/')",     '//server/share/' ],
@@ -1,7 +1,8 @@
+use 5.006;
 use strict;
 use warnings;
 
-# this test was generated with Dist::Zilla::Plugin::Test::Compile 2.037
+# this test was generated with Dist::Zilla::Plugin::Test::Compile 2.039
 
 use Test::More  tests => 1 + ($ENV{AUTHOR_TESTING} ? 1 : 0);
 
@@ -24,11 +25,12 @@ use File::Spec;
 use IPC::Open3;
 use IO::Handle;
 
+open my $stdin, '<', File::Spec->devnull or die "can't open devnull: $!";
+
 my @warnings;
 for my $lib (@module_files)
 {
     # see L<perlfaq8/How can I capture STDERR from an external command?>
-    open my $stdin, '<', File::Spec->devnull or die "can't open devnull: $!";
     my $stderr = IO::Handle->new;
 
     my $pid = open3($stdin, '>&STDERR', $stderr, $^X, $inc_switch, '-e', "require q[$lib]");
@@ -2,7 +2,7 @@ use strict;
 use warnings;
 use Test::More;
 
-# generated by Dist::Zilla::Plugin::Test::PodSpelling 2.006001
+# generated by Dist::Zilla::Plugin::Test::PodSpelling 2.006002
 use Test::Spelling 0.12;
 use Pod::Wordlist;
 
@@ -59,9 +59,6 @@ gfuji
 Karen
 Etheridge
 ether
-Keedi
-Kim
-keedi
 Martin
 Kjeldsen
 mk
@@ -72,6 +69,9 @@ Toby
 Inkster
 tobyink
 κΉ€λ„ν˜•
+Keedi
+Kim
+keedi
 lib
 Path
 Tiny
@@ -1,4 +1,5 @@
 #!perl
+# This file was automatically generated by Dist::Zilla::Plugin::MetaTests.
 
 use Test::More;
 
@@ -1,4 +1,5 @@
 #!perl
+# This file was automatically generated by Dist::Zilla::Plugin::PodCoverageTests.
 
 use Test::More;
 
@@ -1,4 +1,5 @@
 #!perl
+# This file was automatically generated by Dist::Zilla::Plugin::PodSyntaxTests.
 use Test::More;
 
 eval "use Test::Pod 1.41";