@@ -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,48 @@
Revision history for Path-Tiny
+0.058 2014-09-23 11:00:24-04:00 America/New_York
+
+ [ADDED]
+
+ - Added a 'sibling' method as a more efficient form of
+ calling $path->parent->child(...).
+
+ [DOCUMENTED]
+
+ - Every method annotated with the version number of the
+ last API change.
+
+0.057 2014-09-19 11:23:05-04:00 America/New_York
+
+ [FIXED]
+
+ - On AIX, reads that default to locking would fail without
+ write permissions, because locking needs write permissions.
+ The fix is only to lock reads if write permissions exist;
+ otherwise locking is skipped.
+
+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.140640",
"license" : [
"apache_2_0"
],
@@ -33,12 +33,12 @@
},
"develop" : {
"requires" : {
- "Dist::Zilla" : "5.015",
+ "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",
+ "Dist::Zilla::PluginBundle::DAGOLDEN" : "0.068",
"File::Spec" : "0",
"File::Temp" : "0",
"IO::Handle" : "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.058"
},
"Path::Tiny::Error" : {
"file" : "lib/Path/Tiny.pm",
- "version" : "0.054"
+ "version" : "0.058"
}
},
"release_status" : "stable",
@@ -116,11 +115,12 @@
"web" : "https://github.com/dagolden/Path-Tiny"
}
},
- "version" : "0.054",
+ "version" : "0.058",
"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.140640'
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.058'
Path::Tiny::Error:
file: lib/Path/Tiny.pm
- version: '0.054'
+ version: '0.058'
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.058'
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.058",
"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.058
SYNOPSIS
use Path::Tiny;
@@ -104,12 +104,16 @@ CONSTRUCTORS
This optimizes copies without proliferating references unexpectedly if a
copy is made by code outside your control.
+ Current API available since 0.017.
+
new
$path = Path::Tiny->new("foo/bar");
This is just like "path", but with method call overhead. (Why would you
do that?)
+ Current API available since 0.001.
+
cwd
$path = Path::Tiny->cwd; # path( Cwd::getcwd )
$path = cwd; # optional export
@@ -120,6 +124,8 @@ CONSTRUCTORS
"cwd" may be exported on request and used as a function instead of as a
method.
+ Current API available since 0.018.
+
rootdir
$path = Path::Tiny->rootdir; # /
$path = rootdir; # optional export
@@ -130,6 +136,8 @@ CONSTRUCTORS
"rootdir" may be exported on request and used as a function instead of
as a method.
+ Current API available since 0.018.
+
tempfile, tempdir
$temp = Path::Tiny->tempfile( @options );
$temp = Path::Tiny->tempdir( @options );
@@ -160,6 +168,8 @@ CONSTRUCTORS
Both "tempfile" and "tempdir" may be exported on request and used as
functions instead of as methods.
+ Current API available since 0.018.
+
METHODS
absolute
$abs = path("foo/bar")->absolute;
@@ -178,6 +188,8 @@ METHODS
On Windows, an absolute path without a volume component will have it
added based on the current drive.
+ Current API available since 0.001.
+
append, append_raw, append_utf8
path("foo.txt")->append(@data);
path("foo.txt")->append(\@data);
@@ -197,6 +209,8 @@ METHODS
":unix:encoding(UTF-8)". If Unicode::UTF8 0.58+ is installed, a raw
append will be done instead on the data encoded with "Unicode::UTF8".
+ Current API available since 0.004.
+
basename
$name = path("foo/bar.txt")->basename; # bar.txt
$name = path("foo.txt")->basename('.txt'); # foo
@@ -209,6 +223,8 @@ METHODS
match at the end of the file portion or last directory portion will be
removed before the result is returned.
+ Current API available since 0.054.
+
canonpath
$canonical = path("foo/bar")->canonpath; # foo\bar on Windows
@@ -216,6 +232,8 @@ METHODS
platform. In particular, this means directory separators will be "\" on
Windows.
+ Current API available since 0.001.
+
child
$file = path("/tmp")->child("foo.txt"); # "/tmp/foo.txt"
$file = path("/tmp")->child(@parts);
@@ -224,6 +242,8 @@ METHODS
"catfile" or "catdir" from File::Spec, but without caring about file or
directories.
+ Current API available since 0.001.
+
children
@paths = path("/tmp")->children;
@paths = path("/tmp")->children( qr/\.txt$/ );
@@ -238,6 +258,8 @@ METHODS
@paths = path("/tmp")->children( qr/^foo/ );
# matches children like the glob foo*
+ Current API available since 0.028.
+
chmod
path("foo.txt")->chmod(0777);
path("foo.txt")->chmod("0755");
@@ -255,26 +277,44 @@ METHODS
allowed and permissions "stugoX" are not supported. (See File::chmod for
more complex needs.)
+ Current API available since 0.053.
+
copy
path("/tmp/foo.txt")->copy("/tmp/bar.txt");
Copies a file using File::Copy's "copy" function.
+ Current API available since 0.001.
+
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. 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.
- 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.
+ 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
+ Current API available since 0.056.
+
+ 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.
+
+ Deprecated in 0.056.
exists, is_file, is_dir
if ( path("/tmp")->exists ) { ... } # -e
@@ -290,6 +330,8 @@ METHODS
Use "-f" instead if you really mean to check for a plain file.
+ Current API available since 0.053.
+
filehandle
$fh = path("/tmp/foo.txt")->filehandle($mode, $binmode);
$fh = path("/tmp/foo.txt")->filehandle({ locked => 1 }, $mode, $binmode);
@@ -306,12 +348,16 @@ METHODS
See "openr", "openw", "openrw", and "opena" for sugar.
+ Current API available since 0.039.
+
is_absolute, is_relative
if ( path("/tmp")->is_absolute ) { ... }
if ( path("/tmp")->is_relative ) { ... }
Booleans for whether the path appears absolute or relative.
+ Current API available since 0.001.
+
is_rootdir
while ( ! $path->is_rootdir ) {
$path = $path->parent;
@@ -326,6 +372,8 @@ METHODS
path("C:/")->is_rootdir; # true
path("//server/share/")->is_rootdir; #true
+ Current API available since 0.038.
+
iterator
$iter = path("/tmp")->iterator( \%options );
@@ -356,6 +404,8 @@ METHODS
For a more powerful, recursive iterator with built-in loop avoidance,
see Path::Iterator::Rule.
+ Current API available since 0.016.
+
lines, lines_raw, lines_utf8
@contents = path("/tmp/foo.txt")->lines;
@contents = path("/tmp/foo.txt")->lines(\%options);
@@ -385,6 +435,8 @@ METHODS
":encoding(UTF-8)", though a bit memory intensive. If memory use is a
concern, consider "openr_utf8" and iterating directly on the handle.
+ Current API available since 0.048.
+
mkpath
path("foo/bar/baz")->mkpath;
path("foo/bar/baz")->mkpath( \%options );
@@ -394,11 +446,15 @@ METHODS
thrown. Returns the list of directories created or an empty list if the
directories already exist, just like "make_path".
+ Current API available since 0.001.
+
move
path("foo.txt")->move("bar.txt");
Just like "rename".
+ Current API available since 0.001.
+
openr, openw, openrw, opena
$fh = path("foo.txt")->openr($binmode); # read
$fh = path("foo.txt")->openr_raw;
@@ -430,6 +486,8 @@ METHODS
See "filehandle" for more on locking.
+ Current API available since 0.011.
+
parent
$parent = path("foo/bar/baz")->parent; # foo/bar
$parent = path("foo/wibble.txt")->parent; # foo
@@ -441,6 +499,8 @@ METHODS
the number of parent directories upwards to return. "parent" by itself
is equivalent to parent(1).
+ Current API available since 0.014.
+
realpath
$real = path("/baz/foo/../bar")->realpath;
$real = path("foo/../bar")->realpath;
@@ -454,19 +514,24 @@ METHODS
$real = path("doesnt_exist/foo")->realpath; # dies
+ Current API available since 0.001.
+
relative
$rel = path("/tmp/foo/bar")->relative("/tmp"); # foo/bar
Returns a "Path::Tiny" object with a relative path name. Given the
trickiness of this, it's a thin wrapper around "File::Spec->abs2rel()".
+ Current API available since 0.001.
+
remove
path("foo.txt")->remove;
- Note: as of 0.012, remove only works on files.
+ 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.
- This is just like "unlink", except if the path does not exist, it
- returns false rather than throwing an exception.
+ Current API available since 0.012.
remove_tree
# directory
@@ -484,6 +549,19 @@ METHODS
rmdir path("foo/bar/baz/");
+ Current API available since 0.013.
+
+ sibling
+ $foo = path("/tmp/foo.txt");
+ $sib = $foo->sibling("bar.txt"); # /tmp/bar.txt
+ $sib = $foo->sibling("baz", "bam.txt"); # /tmp/baz/bam.txt
+
+ Returns a new "Path::Tiny" object relative to the parent of the
+ original. This is slightly more efficient than
+ "$path->parent->child(...)".
+
+ Current API available since 0.058.
+
slurp, slurp_raw, slurp_utf8
$data = path("foo.txt")->slurp;
$data = path("foo.txt")->slurp( {binmode => ":raw"} );
@@ -503,6 +581,8 @@ METHODS
This is just as strict and is roughly an order of magnitude faster than
using ":encoding(UTF-8)".
+ Current API available since 0.004.
+
spew, spew_raw, spew_utf8
path("foo.txt")->spew(@data);
path("foo.txt")->spew(\@data);
@@ -523,12 +603,16 @@ METHODS
If Unicode::UTF8 0.58+ is installed, a raw spew will be done instead on
the data encoded with "Unicode::UTF8".
+ Current API available since 0.011.
+
stat, lstat
$stat = path("foo.txt")->stat;
$stat = path("/some/symlink")->lstat;
Like calling "stat" or "lstat" from File::stat.
+ Current API available since 0.001.
+
stringify
$path = path("foo.txt");
say $path->stringify; # same as "$path"
@@ -537,6 +621,8 @@ METHODS
method returns the path standardized with Unix-style "/" directory
separators.
+ Current API available since 0.001.
+
subsumes
path("foo/bar")->subsumes("foo/bar/baz"); # true
path("/foo/bar")->subsumes("/foo/baz"); # false
@@ -555,6 +641,8 @@ METHODS
my $p2 = path("foo/bar/../baz")->realpath;
if ( $p1->subsumes($p2) ) { ... }
+ Current API available since 0.048.
+
touch
path("foo.txt")->touch;
path("foo.txt")->touch($epoch_secs);
@@ -567,6 +655,8 @@ METHODS
path("foo.txt")->touch->spew( $content );
+ Current API available since 0.015.
+
touchpath
path("bar/baz/foo.txt")->touchpath;
@@ -574,6 +664,8 @@ METHODS
doesn't exist, before touching the file. Returns the path object like
"touch" does.
+ Current API available since 0.022.
+
volume
$vol = path("/tmp/foo.txt")->volume; # ""
$vol = path("C:/tmp/foo.txt")->volume; # "C:"
@@ -583,6 +675,8 @@ METHODS
empty string on Unix-like operating systems or the drive letter for an
absolute path on "MSWin32".
+ Current API available since 0.001.
+
EXCEPTION HANDLING
Simple usage errors will generally croak. Failures of underlying Perl
unctions will be thrown as exceptions in the class "Path::Tiny::Error".
@@ -620,7 +714,8 @@ CAVEATS
AIX and locking
AIX requires a write handle for locking. Therefore, calls that normally
open a read handle and take a shared lock instead will open a read-write
- handle and take an exclusive lock.
+ handle and take an exclusive lock. If the user does not have write
+ permission, no lock will be used.
utf8 vs UTF-8
All the *_utf8 methods use ":encoding(UTF-8)" -- either as
@@ -706,8 +801,18 @@ AUTHOR
CONTRIBUTORS
* Chris Williams <bingos@cpan.org>
+ * Michael G. Schwern <mschwern@cpan.org>
+
+ * Smylers <Smylers@stripey.com>
+
+ * Toby Inkster <tobyink@cpan.org>
+
+ * 김도형 - Keedi Kim <keedi@cpan.org>
+
* David Steinbrunner <dsteinbrunner@pobox.com>
+ * Doug Bell <madcityzen@gmail.com>
+
* Gabor Szabo <szabgab@cpan.org>
* Gabriel Andrade <gabiruh@gmail.com>
@@ -722,12 +827,6 @@ CONTRIBUTORS
* Martin Kjeldsen <mk@bluepipe.dk>
- * Michael G. Schwern <mschwern@cpan.org>
-
- * Toby Inkster <tobyink@cpan.org>
-
- * 김도형 - Keedi Kim <keedi@cpan.org>
-
COPYRIGHT AND LICENSE
This software is Copyright (c) 2013 by David Golden.
@@ -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,12 +39,12 @@ 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";
requires "Dist::Zilla::Plugin::RemovePrereqs" => "0";
- requires "Dist::Zilla::PluginBundle::DAGOLDEN" => "0.060";
+ requires "Dist::Zilla::PluginBundle::DAGOLDEN" => "0.068";
requires "File::Spec" => "0";
requires "File::Temp" => "0";
requires "IO::Handle" => "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";
};
@@ -5,7 +5,7 @@ copyright_holder = David Golden
copyright_year = 2013
[@DAGOLDEN]
-:version = 0.060
+:version = 0.068
-remove = MinimumPerlFast
stopwords = AIX
stopwords = BENCHMARKING
@@ -4,7 +4,7 @@ use warnings;
package Path::Tiny;
# ABSTRACT: File path utility
-our $VERSION = '0.054'; # VERSION
+our $VERSION = '0.058'; # VERSION
# Dependencies
use Config;
@@ -191,6 +191,8 @@ sub _get_args {
#pod This optimizes copies without proliferating references unexpectedly if a copy is
#pod made by code outside your control.
#pod
+#pod Current API available since 0.017.
+#pod
#pod =cut
sub path {
@@ -203,7 +205,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 +214,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 +238,6 @@ sub path {
$path =~ s{^(~[^/]*)}{$homedir};
}
- # and we're finally done
bless [ $path, $cpath ], __PACKAGE__;
}
@@ -248,6 +248,8 @@ sub path {
#pod This is just like C<path>, but with method call overhead. (Why would you
#pod do that?)
#pod
+#pod Current API available since 0.001.
+#pod
#pod =cut
sub new { shift; path(@_) }
@@ -263,6 +265,8 @@ sub new { shift; path(@_) }
#pod C<cwd> may be exported on request and used as a function instead of as a
#pod method.
#pod
+#pod Current API available since 0.018.
+#pod
#pod =cut
sub cwd {
@@ -281,6 +285,8 @@ sub cwd {
#pod C<rootdir> may be exported on request and used as a function instead of as a
#pod method.
#pod
+#pod Current API available since 0.018.
+#pod
#pod =cut
sub rootdir { path( File::Spec->rootdir ) }
@@ -315,10 +321,12 @@ sub rootdir { path( File::Spec->rootdir ) }
#pod Both C<tempfile> and C<tempdir> may be exported on request and used as
#pod functions instead of as methods.
#pod
+#pod Current API available since 0.018.
+#pod
#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 +335,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;
}
@@ -386,6 +394,8 @@ sub _splitpath {
#pod On Windows, an absolute path without a volume component will have it added
#pod based on the current drive.
#pod
+#pod Current API available since 0.001.
+#pod
#pod =cut
sub absolute {
@@ -431,6 +441,8 @@ sub absolute {
#pod C<:unix:encoding(UTF-8)>. If L<Unicode::UTF8> 0.58+ is installed, a raw
#pod append will be done instead on the data encoded with C<Unicode::UTF8>.
#pod
+#pod Current API available since 0.004.
+#pod
#pod =cut
sub append {
@@ -470,6 +482,8 @@ sub append_utf8 {
#pod the end of the file portion or last directory portion will be removed before
#pod the result is returned.
#pod
+#pod Current API available since 0.054.
+#pod
#pod =cut
sub basename {
@@ -491,6 +505,8 @@ sub basename {
#pod the platform. In particular, this means directory separators
#pod will be C<\> on Windows.
#pod
+#pod Current API available since 0.001.
+#pod
#pod =cut
sub canonpath { $_[0]->[CANON] }
@@ -504,6 +520,8 @@ sub canonpath { $_[0]->[CANON] }
#pod like C<catfile> or C<catdir> from File::Spec, but without caring about
#pod file or directories.
#pod
+#pod Current API available since 0.001.
+#pod
#pod =cut
sub child {
@@ -526,6 +544,8 @@ sub child {
#pod @paths = path("/tmp")->children( qr/^foo/ );
#pod # matches children like the glob foo*
#pod
+#pod Current API available since 0.028.
+#pod
#pod =cut
sub children {
@@ -565,6 +585,8 @@ sub children {
#pod are required for each clause, multiple ops are not allowed and permissions
#pod C<stugoX> are not supported. (See L<File::chmod> for more complex needs.)
#pod
+#pod Current API available since 0.053.
+#pod
#pod =cut
sub chmod {
@@ -592,6 +614,8 @@ sub chmod {
#pod
#pod Copies a file using L<File::Copy>'s C<copy> function.
#pod
+#pod Current API available since 0.001.
+#pod
#pod =cut
# XXX do recursively for directories?
@@ -606,28 +630,52 @@ 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. 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 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 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 Current API available since 0.056.
#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 Deprecated in 0.056.
#pod
#pod =cut
@@ -652,6 +700,7 @@ sub dirname {
#pod
#pod Use C<-f> instead if you really mean to check for a plain file.
#pod
+#pod Current API available since 0.053.
#pod
#pod =cut
@@ -678,6 +727,8 @@ sub is_dir { -d $_[0]->[PATH] }
#pod
#pod See C<openr>, C<openw>, C<openrw>, and C<opena> for sugar.
#pod
+#pod Current API available since 0.039.
+#pod
#pod =cut
# Note: must put binmode on open line, not subsequent binmode() call, so things
@@ -728,9 +779,14 @@ sub filehandle {
$trunc = 1;
}
elsif ( $^O eq 'aix' && $opentype eq "<" ) {
- # AIX can only lock write handles, so upgrade to RW and LOCK_EX
- $opentype = "+<";
- $lock = Fcntl::LOCK_EX();
+ # AIX can only lock write handles, so upgrade to RW and LOCK_EX if
+ # the file is writable; otherwise give up on locking. N.B.
+ # checking -w before open to determine the open mode is an
+ # unavoidable race condition
+ if ( -w $self->[PATH] ) {
+ $opentype = "+<";
+ $lock = Fcntl::LOCK_EX();
+ }
}
else {
$lock = $opentype eq "<" ? Fcntl::LOCK_SH() : Fcntl::LOCK_EX();
@@ -755,6 +811,8 @@ sub filehandle {
#pod
#pod Booleans for whether the path appears absolute or relative.
#pod
+#pod Current API available since 0.001.
+#pod
#pod =cut
sub is_absolute { substr( $_[0]->dirname, 0, 1 ) eq '/' }
@@ -776,6 +834,8 @@ sub is_relative { substr( $_[0]->dirname, 0, 1 ) ne '/' }
#pod path("C:/")->is_rootdir; # true
#pod path("//server/share/")->is_rootdir; #true
#pod
+#pod Current API available since 0.038.
+#pod
#pod =cut
sub is_rootdir {
@@ -815,6 +875,8 @@ sub is_rootdir {
#pod For a more powerful, recursive iterator with built-in loop avoidance, see
#pod L<Path::Iterator::Rule>.
#pod
+#pod Current API available since 0.016.
+#pod
#pod =cut
sub iterator {
@@ -892,6 +954,8 @@ sub iterator {
#pod intensive. If memory use is a concern, consider C<openr_utf8> and
#pod iterating directly on the handle.
#pod
+#pod Current API available since 0.048.
+#pod
#pod =cut
sub lines {
@@ -956,6 +1020,8 @@ sub lines_utf8 {
#pod thrown. Returns the list of directories created or an empty list if
#pod the directories already exist, just like C<make_path>.
#pod
+#pod Current API available since 0.001.
+#pod
#pod =cut
sub mkpath {
@@ -978,6 +1044,8 @@ sub mkpath {
#pod
#pod Just like C<rename>.
#pod
+#pod Current API available since 0.001.
+#pod
#pod =cut
sub move {
@@ -1018,6 +1086,8 @@ sub move {
#pod
#pod See L</filehandle> for more on locking.
#pod
+#pod Current API available since 0.011.
+#pod
#pod =cut
# map method names to corresponding open mode
@@ -1066,6 +1136,8 @@ while ( my ( $k, $v ) = each %opens ) {
#pod of parent directories upwards to return. C<parent> by itself is equivalent to
#pod C<parent(1)>.
#pod
+#pod Current API available since 0.014.
+#pod
#pod =cut
# XXX this is ugly and coverage is incomplete. I think it's there for windows
@@ -1119,6 +1191,8 @@ sub _non_empty {
#pod
#pod $real = path("doesnt_exist/foo")->realpath; # dies
#pod
+#pod Current API available since 0.001.
+#pod
#pod =cut
sub realpath {
@@ -1140,6 +1214,8 @@ sub realpath {
#pod Given the trickiness of this, it's a thin wrapper around
#pod C<< File::Spec->abs2rel() >>.
#pod
+#pod Current API available since 0.001.
+#pod
#pod =cut
# Easy to get wrong, so wash it through File::Spec (sigh)
@@ -1149,10 +1225,11 @@ sub relative { path( File::Spec->abs2rel( $_[0]->[PATH], $_[1] ) ) }
#pod
#pod path("foo.txt")->remove;
#pod
-#pod B<Note: as of 0.012, remove only works on files>.
+#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 This is just like C<unlink>, except if the path does not exist, it returns
-#pod false rather than throwing an exception.
+#pod Current API available since 0.012.
#pod
#pod =cut
@@ -1161,7 +1238,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
@@ -1181,6 +1258,8 @@ sub remove {
#pod
#pod rmdir path("foo/bar/baz/");
#pod
+#pod Current API available since 0.013.
+#pod
#pod =cut
sub remove_tree {
@@ -1200,6 +1279,24 @@ sub remove_tree {
return $count;
}
+#pod =method sibling
+#pod
+#pod $foo = path("/tmp/foo.txt");
+#pod $sib = $foo->sibling("bar.txt"); # /tmp/bar.txt
+#pod $sib = $foo->sibling("baz", "bam.txt"); # /tmp/baz/bam.txt
+#pod
+#pod Returns a new C<Path::Tiny> object relative to the parent of the original.
+#pod This is slightly more efficient than C<< $path->parent->child(...) >>.
+#pod
+#pod Current API available since 0.058.
+#pod
+#pod =cut
+
+sub sibling {
+ my $self = shift;
+ return path( $self->parent->[PATH], @_ );
+}
+
#pod =method slurp, slurp_raw, slurp_utf8
#pod
#pod $data = path("foo.txt")->slurp;
@@ -1220,6 +1317,8 @@ sub remove_tree {
#pod This is just as strict and is roughly an order of magnitude faster than
#pod using C<:encoding(UTF-8)>.
#pod
+#pod Current API available since 0.004.
+#pod
#pod =cut
sub slurp {
@@ -1273,6 +1372,8 @@ sub slurp_utf8 {
#pod If L<Unicode::UTF8> 0.58+ is installed, a raw spew will be done instead on
#pod the data encoded with C<Unicode::UTF8>.
#pod
+#pod Current API available since 0.011.
+#pod
#pod =cut
# XXX add "unsafe" option to disable flocking and atomic? Check benchmarks on append() first.
@@ -1315,6 +1416,8 @@ sub spew_utf8 {
#pod
#pod Like calling C<stat> or C<lstat> from L<File::stat>.
#pod
+#pod Current API available since 0.001.
+#pod
#pod =cut
# XXX break out individual stat() components as subs?
@@ -1338,6 +1441,8 @@ sub lstat {
#pod Returns a string representation of the path. Unlike C<canonpath>, this method
#pod returns the path standardized with Unix-style C</> directory separators.
#pod
+#pod Current API available since 0.001.
+#pod
#pod =cut
sub stringify { $_[0]->[PATH] }
@@ -1361,6 +1466,8 @@ sub stringify { $_[0]->[PATH] }
#pod my $p2 = path("foo/bar/../baz")->realpath;
#pod if ( $p1->subsumes($p2) ) { ... }
#pod
+#pod Current API available since 0.048.
+#pod
#pod =cut
sub subsumes {
@@ -1412,6 +1519,8 @@ sub subsumes {
#pod
#pod path("foo.txt")->touch->spew( $content );
#pod
+#pod Current API available since 0.015.
+#pod
#pod =cut
sub touch {
@@ -1433,6 +1542,8 @@ sub touch {
#pod Combines C<mkpath> and C<touch>. Creates the parent directory if it doesn't exist,
#pod before touching the file. Returns the path object like C<touch> does.
#pod
+#pod Current API available since 0.022.
+#pod
#pod =cut
sub touchpath {
@@ -1452,6 +1563,8 @@ sub touchpath {
#pod usually is the empty string on Unix-like operating systems or the
#pod drive letter for an absolute path on C<MSWin32>.
#pod
+#pod Current API available since 0.001.
+#pod
#pod =cut
sub volume {
@@ -1490,7 +1603,7 @@ Path::Tiny - File path utility
=head1 VERSION
-version 0.054
+version 0.058
=head1 SYNOPSIS
@@ -1596,6 +1709,8 @@ stringified copy is made.
This optimizes copies without proliferating references unexpectedly if a copy is
made by code outside your control.
+Current API available since 0.017.
+
=head2 new
$path = Path::Tiny->new("foo/bar");
@@ -1603,6 +1718,8 @@ made by code outside your control.
This is just like C<path>, but with method call overhead. (Why would you
do that?)
+Current API available since 0.001.
+
=head2 cwd
$path = Path::Tiny->cwd; # path( Cwd::getcwd )
@@ -1614,6 +1731,8 @@ This is slightly faster than C<< path(".")->absolute >>.
C<cwd> may be exported on request and used as a function instead of as a
method.
+Current API available since 0.018.
+
=head2 rootdir
$path = Path::Tiny->rootdir; # /
@@ -1625,6 +1744,8 @@ picky for C<path("/")>.
C<rootdir> may be exported on request and used as a function instead of as a
method.
+Current API available since 0.018.
+
=head2 tempfile, tempdir
$temp = Path::Tiny->tempfile( @options );
@@ -1655,6 +1776,8 @@ C<< File::Temp->newdir >> instead.
Both C<tempfile> and C<tempdir> may be exported on request and used as
functions instead of as methods.
+Current API available since 0.018.
+
=head1 METHODS
=head2 absolute
@@ -1674,6 +1797,8 @@ resolved, you must call the more expensive C<realpath> method instead.
On Windows, an absolute path without a volume component will have it added
based on the current drive.
+Current API available since 0.001.
+
=head2 append, append_raw, append_utf8
path("foo.txt")->append(@data);
@@ -1693,6 +1818,8 @@ C<append_utf8> is like C<append> with a C<binmode> of
C<:unix:encoding(UTF-8)>. If L<Unicode::UTF8> 0.58+ is installed, a raw
append will be done instead on the data encoded with C<Unicode::UTF8>.
+Current API available since 0.004.
+
=head2 basename
$name = path("foo/bar.txt")->basename; # bar.txt
@@ -1706,6 +1833,8 @@ Given a list of suffixes as strings or regular expressions, any that match at
the end of the file portion or last directory portion will be removed before
the result is returned.
+Current API available since 0.054.
+
=head2 canonpath
$canonical = path("foo/bar")->canonpath; # foo\bar on Windows
@@ -1714,6 +1843,8 @@ Returns a string with the canonical format of the path name for
the platform. In particular, this means directory separators
will be C<\> on Windows.
+Current API available since 0.001.
+
=head2 child
$file = path("/tmp")->child("foo.txt"); # "/tmp/foo.txt"
@@ -1723,6 +1854,8 @@ Returns a new C<Path::Tiny> object relative to the original. Works
like C<catfile> or C<catdir> from File::Spec, but without caring about
file or directories.
+Current API available since 0.001.
+
=head2 children
@paths = path("/tmp")->children;
@@ -1738,6 +1871,8 @@ for matching:
@paths = path("/tmp")->children( qr/^foo/ );
# matches children like the glob foo*
+Current API available since 0.028.
+
=head2 chmod
path("foo.txt")->chmod(0777);
@@ -1755,29 +1890,46 @@ match C<< qr/\A([augo]+)([=+-])([rwx]+)\z/ >>, which defines "who", "op" and
are required for each clause, multiple ops are not allowed and permissions
C<stugoX> are not supported. (See L<File::chmod> for more complex needs.)
+Current API available since 0.053.
+
=head2 copy
path("/tmp/foo.txt")->copy("/tmp/bar.txt");
Copies a file using L<File::Copy>'s C<copy> function.
+Current API available since 0.001.
+
=head2 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. 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.
-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.
+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
+Current API available since 0.056.
+
+=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.
+
+Deprecated in 0.056.
=head2 exists, is_file, is_dir
@@ -1794,6 +1946,8 @@ read just like files.
Use C<-f> instead if you really mean to check for a plain file.
+Current API available since 0.053.
+
=head2 filehandle
$fh = path("/tmp/foo.txt")->filehandle($mode, $binmode);
@@ -1811,6 +1965,8 @@ acquired.
See C<openr>, C<openw>, C<openrw>, and C<opena> for sugar.
+Current API available since 0.039.
+
=head2 is_absolute, is_relative
if ( path("/tmp")->is_absolute ) { ... }
@@ -1818,6 +1974,8 @@ See C<openr>, C<openw>, C<openrw>, and C<opena> for sugar.
Booleans for whether the path appears absolute or relative.
+Current API available since 0.001.
+
=head2 is_rootdir
while ( ! $path->is_rootdir ) {
@@ -1833,6 +1991,8 @@ This works even on C<MSWin32> with drives and UNC volumes:
path("C:/")->is_rootdir; # true
path("//server/share/")->is_rootdir; #true
+Current API available since 0.038.
+
=head2 iterator
$iter = path("/tmp")->iterator( \%options );
@@ -1864,6 +2024,8 @@ The default is the same as:
For a more powerful, recursive iterator with built-in loop avoidance, see
L<Path::Iterator::Rule>.
+Current API available since 0.016.
+
=head2 lines, lines_raw, lines_utf8
@contents = path("/tmp/foo.txt")->lines;
@@ -1895,6 +2057,8 @@ actually faster than relying on C<:encoding(UTF-8)>, though a bit memory
intensive. If memory use is a concern, consider C<openr_utf8> and
iterating directly on the handle.
+Current API available since 0.048.
+
=head2 mkpath
path("foo/bar/baz")->mkpath;
@@ -1905,12 +2069,16 @@ is passed through to C<make_path>. Errors will be trapped and an exception
thrown. Returns the list of directories created or an empty list if
the directories already exist, just like C<make_path>.
+Current API available since 0.001.
+
=head2 move
path("foo.txt")->move("bar.txt");
Just like C<rename>.
+Current API available since 0.001.
+
=head2 openr, openw, openrw, opena
$fh = path("foo.txt")->openr($binmode); # read
@@ -1942,6 +2110,8 @@ locked with C<LOCK_EX>; otherwise, they are locked for C<LOCK_SH>.
See L</filehandle> for more on locking.
+Current API available since 0.011.
+
=head2 parent
$parent = path("foo/bar/baz")->parent; # foo/bar
@@ -1954,6 +2124,8 @@ original directory or file. An optional positive integer argument is the number
of parent directories upwards to return. C<parent> by itself is equivalent to
C<parent(1)>.
+Current API available since 0.014.
+
=head2 realpath
$real = path("/baz/foo/../bar")->realpath;
@@ -1968,6 +2140,8 @@ an exception will be thrown:
$real = path("doesnt_exist/foo")->realpath; # dies
+Current API available since 0.001.
+
=head2 relative
$rel = path("/tmp/foo/bar")->relative("/tmp"); # foo/bar
@@ -1976,14 +2150,17 @@ Returns a C<Path::Tiny> object with a relative path name.
Given the trickiness of this, it's a thin wrapper around
C<< File::Spec->abs2rel() >>.
+Current API available since 0.001.
+
=head2 remove
path("foo.txt")->remove;
-B<Note: as of 0.012, remove only works on files>.
+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.
-This is just like C<unlink>, except if the path does not exist, it returns
-false rather than throwing an exception.
+Current API available since 0.012.
=head2 remove_tree
@@ -2002,6 +2179,19 @@ C<rmdir> function instead.
rmdir path("foo/bar/baz/");
+Current API available since 0.013.
+
+=head2 sibling
+
+ $foo = path("/tmp/foo.txt");
+ $sib = $foo->sibling("bar.txt"); # /tmp/bar.txt
+ $sib = $foo->sibling("baz", "bam.txt"); # /tmp/baz/bam.txt
+
+Returns a new C<Path::Tiny> object relative to the parent of the original.
+This is slightly more efficient than C<< $path->parent->child(...) >>.
+
+Current API available since 0.058.
+
=head2 slurp, slurp_raw, slurp_utf8
$data = path("foo.txt")->slurp;
@@ -2022,6 +2212,8 @@ slurp will be done instead and the result decoded with C<Unicode::UTF8>.
This is just as strict and is roughly an order of magnitude faster than
using C<:encoding(UTF-8)>.
+Current API available since 0.004.
+
=head2 spew, spew_raw, spew_utf8
path("foo.txt")->spew(@data);
@@ -2042,6 +2234,8 @@ C<spew_utf8> is like C<spew> with a C<binmode> of C<:unix:encoding(UTF-8)>.
If L<Unicode::UTF8> 0.58+ is installed, a raw spew will be done instead on
the data encoded with C<Unicode::UTF8>.
+Current API available since 0.011.
+
=head2 stat, lstat
$stat = path("foo.txt")->stat;
@@ -2049,6 +2243,8 @@ the data encoded with C<Unicode::UTF8>.
Like calling C<stat> or C<lstat> from L<File::stat>.
+Current API available since 0.001.
+
=head2 stringify
$path = path("foo.txt");
@@ -2057,6 +2253,8 @@ 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.
+Current API available since 0.001.
+
=head2 subsumes
path("foo/bar")->subsumes("foo/bar/baz"); # true
@@ -2076,6 +2274,8 @@ the filesystem with C<realpath>:
my $p2 = path("foo/bar/../baz")->realpath;
if ( $p1->subsumes($p2) ) { ... }
+Current API available since 0.048.
+
=head2 touch
path("foo.txt")->touch;
@@ -2089,6 +2289,8 @@ Returns the path object so it can be easily chained with spew:
path("foo.txt")->touch->spew( $content );
+Current API available since 0.015.
+
=head2 touchpath
path("bar/baz/foo.txt")->touchpath;
@@ -2096,6 +2298,8 @@ Returns the path object so it can be easily chained with spew:
Combines C<mkpath> and C<touch>. Creates the parent directory if it doesn't exist,
before touching the file. Returns the path object like C<touch> does.
+Current API available since 0.022.
+
=head2 volume
$vol = path("/tmp/foo.txt")->volume; # ""
@@ -2106,6 +2310,8 @@ equivalent to what L<File::Spec> would give from C<splitpath> and thus
usually is the empty string on Unix-like operating systems or the
drive letter for an absolute path on C<MSWin32>.
+Current API available since 0.001.
+
=for Pod::Coverage openr_utf8 opena_utf8 openw_utf8 openrw_utf8
openr_raw opena_raw openw_raw openrw_raw
IS_BSD IS_WIN32 FREEZE THAW TO_JSON
@@ -2163,7 +2369,8 @@ category:
AIX requires a write handle for locking. Therefore, calls that normally
open a read handle and take a shared lock instead will open a read-write
-handle and take an exclusive lock.
+handle and take an exclusive lock. If the user does not have write
+permission, no lock will be used.
=head2 utf8 vs UTF-8
@@ -2276,6 +2483,8 @@ David Golden <dagolden@cpan.org>
=head1 CONTRIBUTORS
+=for stopwords Chris Williams Michael G. Schwern Smylers Toby Inkster 김도형 - Keedi Kim David Steinbrunner Doug Bell Gabor Szabo Gabriel Andrade George Hartzell Geraud Continsouzas Goro Fuji Karen Etheridge Martin Kjeldsen
+
=over 4
=item *
@@ -2284,47 +2493,55 @@ Chris Williams <bingos@cpan.org>
=item *
-David Steinbrunner <dsteinbrunner@pobox.com>
+Michael G. Schwern <mschwern@cpan.org>
=item *
-Gabor Szabo <szabgab@cpan.org>
+Smylers <Smylers@stripey.com>
=item *
-Gabriel Andrade <gabiruh@gmail.com>
+Toby Inkster <tobyink@cpan.org>
=item *
-George Hartzell <hartzell@cpan.org>
+김도형 - Keedi Kim <keedi@cpan.org>
=item *
-Geraud Continsouzas <geraud@scsi.nc>
+David Steinbrunner <dsteinbrunner@pobox.com>
=item *
-Goro Fuji <gfuji@cpan.org>
+Doug Bell <madcityzen@gmail.com>
=item *
-Karen Etheridge <ether@cpan.org>
+Gabor Szabo <szabgab@cpan.org>
=item *
-Martin Kjeldsen <mk@bluepipe.dk>
+Gabriel Andrade <gabiruh@gmail.com>
=item *
-Michael G. Schwern <mschwern@cpan.org>
+George Hartzell <hartzell@cpan.org>
=item *
-Toby Inkster <tobyink@cpan.org>
+Geraud Continsouzas <geraud@scsi.nc>
=item *
-김도형 - Keedi Kim <keedi@cpan.org>
+Goro Fuji <gfuji@cpan.org>
+
+=item *
+
+Karen Etheridge <ether@cpan.org>
+
+=item *
+
+Martin Kjeldsen <mk@bluepipe.dk>
=back
@@ -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.068',
+ '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,172 @@
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.019
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';
+# 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;
+
+# Add static includes into a fake section
+for my $mod (@include) {
+ $req_hash->{other}{modules}{$mod} = 0;
+}
+
+for my $phase ( qw(configure build test runtime develop other) ) {
+ next unless $req_hash->{$phase};
+ next if ($phase eq 'develop' and not $ENV{AUTHOR_TESTING});
+
+ for my $type ( qw(requires recommends suggests conflicts modules) ) {
+ 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";
- 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)";
- }
+ 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];
+
+ 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;
@@ -51,6 +51,10 @@ is $cat, '/tmp/foo';
isa_ok $cat, 'Path::Tiny';
is $cat->basename, 'foo';
+my $sib = $cat->sibling('bar');
+is $sib, '/tmp/bar';
+isa_ok $sib, 'Path::Tiny';
+
my $file = path('/foo//baz/./foo');
is $file, '/foo/baz/foo';
is $file->dirname, '/foo/baz/';
@@ -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.046
use Test::More tests => 1 + ($ENV{AUTHOR_TESTING} ? 1 : 0);
@@ -48,6 +48,6 @@ for my $lib (@module_files)
-is(scalar(@warnings), 0, 'no warnings found') if $ENV{AUTHOR_TESTING};
+is(scalar(@warnings), 0, 'no warnings found') or diag 'got warnings: ', explain \@warnings if $ENV{AUTHOR_TESTING};
@@ -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