Hello community, here is the log from the commit of package perl-Path-Tiny for openSUSE:Factory checked in at 2016-03-16 10:24:54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/perl-Path-Tiny (Old) and /work/SRC/openSUSE:Factory/.perl-Path-Tiny.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "perl-Path-Tiny" Changes: -------- --- /work/SRC/openSUSE:Factory/perl-Path-Tiny/perl-Path-Tiny.changes 2015-11-22 11:02:46.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.perl-Path-Tiny.new/perl-Path-Tiny.changes 2016-03-16 10:24:55.000000000 +0100 @@ -1,0 +2,62 @@ +Tue Mar 8 10:48:07 UTC 2016 - [email protected] + +- updated to 0.084 + see /usr/share/doc/packages/perl-Path-Tiny/Changes + + 0.084 2016-03-04 07:17:49-05:00 America/New_York + + [Fixes] + + - Fixed relative() for the case with regex metacharacters in the path + + 0.082 2016-03-01 18:23:26-05:00 America/New_York + + [!!! INCOMPATIBLE CHANGES !!!] + + - (This warning repeated from 0.079-TRIAL) The relative() method no + longer uses File::Spec's buggy rel2bs method. The new Path::Tiny + algorithm should be comparable and passes File::Spec rel2abs test + cases, except that it correctly accounts for symlinks. For common + use, you are not likely to notice any difference. For uncommon use, + this should be an improvement. As a side benefit, this change drops + the minimum File::Spec version required, allowing Path::Tiny to be + fatpacked if desired. + + [Changes] + + - no other changes from 0.081 + + 0.081 2016-02-18 16:55:37-05:00 America/New_York (TRIAL RELEASE) + + [Fixed] + + - Fixed lines_utf8+chomp and relative() bugs on Windows + + 0.079 2016-02-15 20:52:10-07:00 America/Mazatlan (TRIAL RELEASE) + + [!!! INCOMPATIBLE CHANGES !!!] + + - The relative() method no longer uses File::Spec's buggy rel2bs + method. The new Path::Tiny algorithm should be comparable and passes + File::Spec rel2abs test cases, except that it correctly accounts for + symlinks. For common use, you are not likely to notice any + difference. For uncommon use, this should be an improvement. As a + side benefit, this change drops the minimum File::Spec version + required, allowing Path::Tiny to be fatpacked if desired. + + [FIXED] + + - Fixed lines_utf8() with chomping for repeated empty lines. + + [DOCS] + + - Documented that subclassing is not supported + + 0.077 2016-02-10 14:17:32-07:00 America/Mazatlan (TRIAL RELEASE) + + [ADDED] + + - Added 'edit' and 'edit_lines' plus _utf8 and _raw variants; this + is similar to perl's -i flag (though without backups) + +------------------------------------------------------------------- Old: ---- Path-Tiny-0.076.tar.gz New: ---- Path-Tiny-0.084.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ perl-Path-Tiny.spec ++++++ --- /var/tmp/diff_new_pack.xa4SMS/_old 2016-03-16 10:24:56.000000000 +0100 +++ /var/tmp/diff_new_pack.xa4SMS/_new 2016-03-16 10:24:56.000000000 +0100 @@ -1,7 +1,7 @@ # # spec file for package perl-Path-Tiny # -# Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,7 +17,7 @@ Name: perl-Path-Tiny -Version: 0.076 +Version: 0.084 Release: 0 %define cpan_name Path-Tiny Summary: File path utility @@ -32,12 +32,10 @@ BuildRequires: perl-macros BuildRequires: perl(Digest::SHA) >= 5.45 BuildRequires: perl(File::Path) >= 2.070000 -BuildRequires: perl(File::Spec) >= 3.40 BuildRequires: perl(File::Temp) >= 0.19 BuildRequires: perl(Test::More) >= 0.96 Requires: perl(Digest::SHA) >= 5.45 Requires: perl(File::Path) >= 2.070000 -Requires: perl(File::Spec) >= 3.40 Requires: perl(File::Temp) >= 0.19 Recommends: perl(Unicode::UTF8) >= 0.58 %{perl_requires} ++++++ Path-Tiny-0.076.tar.gz -> Path-Tiny-0.084.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Path-Tiny-0.076/Changes new/Path-Tiny-0.084/Changes --- old/Path-Tiny-0.076/Changes 2015-11-16 16:47:43.000000000 +0100 +++ new/Path-Tiny-0.084/Changes 2016-03-04 13:18:09.000000000 +0100 @@ -1,5 +1,61 @@ Revision history for Path-Tiny +0.084 2016-03-04 07:17:49-05:00 America/New_York + + [Fixes] + + - Fixed relative() for the case with regex metacharacters in the path + +0.082 2016-03-01 18:23:26-05:00 America/New_York + + [!!! INCOMPATIBLE CHANGES !!!] + + - (This warning repeated from 0.079-TRIAL) The relative() method no + longer uses File::Spec's buggy rel2bs method. The new Path::Tiny + algorithm should be comparable and passes File::Spec rel2abs test + cases, except that it correctly accounts for symlinks. For common + use, you are not likely to notice any difference. For uncommon use, + this should be an improvement. As a side benefit, this change drops + the minimum File::Spec version required, allowing Path::Tiny to be + fatpacked if desired. + + [Changes] + + - no other changes from 0.081 + +0.081 2016-02-18 16:55:37-05:00 America/New_York (TRIAL RELEASE) + + [Fixed] + + - Fixed lines_utf8+chomp and relative() bugs on Windows + +0.079 2016-02-15 20:52:10-07:00 America/Mazatlan (TRIAL RELEASE) + + [!!! INCOMPATIBLE CHANGES !!!] + + - The relative() method no longer uses File::Spec's buggy rel2bs + method. The new Path::Tiny algorithm should be comparable and passes + File::Spec rel2abs test cases, except that it correctly accounts for + symlinks. For common use, you are not likely to notice any + difference. For uncommon use, this should be an improvement. As a + side benefit, this change drops the minimum File::Spec version + required, allowing Path::Tiny to be fatpacked if desired. + + [FIXED] + + - Fixed lines_utf8() with chomping for repeated empty lines. + + [DOCS] + + - Documented that subclassing is not supported + +0.077 2016-02-10 14:17:32-07:00 America/Mazatlan (TRIAL RELEASE) + + [ADDED] + + - Added 'edit' and 'edit_lines' plus _utf8 and _raw variants; this + is similar to perl's -i flag (though without backups) + 0.076 2015-11-16 10:47:24-05:00 America/New_York - no changes from 0.075 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Path-Tiny-0.076/MANIFEST new/Path-Tiny-0.084/MANIFEST --- old/Path-Tiny-0.076/MANIFEST 2015-11-16 16:47:43.000000000 +0100 +++ new/Path-Tiny-0.084/MANIFEST 2016-03-04 13:18:09.000000000 +0100 @@ -1,4 +1,4 @@ -# This file was automatically generated by Dist::Zilla::Plugin::Manifest v5.041. +# This file was automatically generated by Dist::Zilla::Plugin::Manifest v5.043. CONTRIBUTING.mkdn Changes LICENSE diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Path-Tiny-0.076/META.json new/Path-Tiny-0.084/META.json --- old/Path-Tiny-0.076/META.json 2015-11-16 16:47:43.000000000 +0100 +++ new/Path-Tiny-0.084/META.json 2016-03-04 13:18:09.000000000 +0100 @@ -4,7 +4,7 @@ "David Golden <[email protected]>" ], "dynamic_config" : 0, - "generated_by" : "Dist::Zilla version 5.041, CPAN::Meta::Converter version 2.150001", + "generated_by" : "Dist::Zilla version 5.043, CPAN::Meta::Converter version 2.150001", "license" : [ "apache_2_0" ], @@ -30,6 +30,9 @@ "requires" : { "ExtUtils::MakeMaker" : "6.17", "perl" : "5.008001" + }, + "suggests" : { + "JSON::PP" : "2.27300" } }, "develop" : { @@ -71,7 +74,7 @@ "File::Copy" : "0", "File::Glob" : "0", "File::Path" : "2.07", - "File::Spec" : "3.40", + "File::Spec" : "0.86", "File::Temp" : "0.19", "File::stat" : "0", "constant" : "0", @@ -91,7 +94,7 @@ "requires" : { "ExtUtils::MakeMaker" : "0", "File::Basename" : "0", - "File::Spec" : "3.40", + "File::Spec" : "0.86", "File::Spec::Functions" : "0", "File::Spec::Unix" : "0", "File::Temp" : "0.19", @@ -105,11 +108,11 @@ "provides" : { "Path::Tiny" : { "file" : "lib/Path/Tiny.pm", - "version" : "0.076" + "version" : "0.084" }, "Path::Tiny::Error" : { "file" : "lib/Path/Tiny.pm", - "version" : "0.076" + "version" : "0.084" } }, "release_status" : "stable", @@ -124,7 +127,7 @@ "web" : "https://github.com/dagolden/Path-Tiny" } }, - "version" : "0.076", + "version" : "0.084", "x_authority" : "cpan:DAGOLDEN", "x_contributors" : [ "Alex Efros <[email protected]>", @@ -139,10 +142,12 @@ "Goro Fuji <[email protected]>", "Graham Knop <[email protected]>", "James Hunt <[email protected]>", + "John Karr <[email protected]>", "Karen Etheridge <[email protected]>", "Mark Ellis <[email protected]>", "Martin Kjeldsen <[email protected]>", "Michael G. Schwern <[email protected]>", + "Nigel Gregoire <[email protected]>", "Philippe Bruhat (BooK) <[email protected]>", "Regina Verbae <[email protected]>", "Roy Ivy III <[email protected]>", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Path-Tiny-0.076/META.yml new/Path-Tiny-0.084/META.yml --- old/Path-Tiny-0.076/META.yml 2015-11-16 16:47:43.000000000 +0100 +++ new/Path-Tiny-0.084/META.yml 2016-03-04 13:18:09.000000000 +0100 @@ -5,7 +5,7 @@ build_requires: ExtUtils::MakeMaker: '0' File::Basename: '0' - File::Spec: '3.40' + File::Spec: '0.86' File::Spec::Functions: '0' File::Spec::Unix: '0' File::Temp: '0.19' @@ -17,7 +17,7 @@ ExtUtils::MakeMaker: '6.17' perl: '5.008001' dynamic_config: 0 -generated_by: 'Dist::Zilla version 5.041, CPAN::Meta::Converter version 2.150001' +generated_by: 'Dist::Zilla version 5.043, CPAN::Meta::Converter version 2.150001' license: apache meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html @@ -35,10 +35,10 @@ provides: Path::Tiny: file: lib/Path/Tiny.pm - version: '0.076' + version: '0.084' Path::Tiny::Error: file: lib/Path/Tiny.pm - version: '0.076' + version: '0.084' recommends: Unicode::UTF8: '0.58' requires: @@ -51,7 +51,7 @@ File::Copy: '0' File::Glob: '0' File::Path: '2.07' - File::Spec: '3.40' + File::Spec: '0.86' File::Temp: '0.19' File::stat: '0' constant: '0' @@ -64,7 +64,7 @@ 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.076' +version: '0.084' x_authority: cpan:DAGOLDEN x_contributors: - 'Alex Efros <[email protected]>' @@ -79,10 +79,12 @@ - 'Goro Fuji <[email protected]>' - 'Graham Knop <[email protected]>' - 'James Hunt <[email protected]>' + - 'John Karr <[email protected]>' - 'Karen Etheridge <[email protected]>' - 'Mark Ellis <[email protected]>' - 'Martin Kjeldsen <[email protected]>' - 'Michael G. Schwern <[email protected]>' + - 'Nigel Gregoire <[email protected]>' - 'Philippe Bruhat (BooK) <[email protected]>' - 'Regina Verbae <[email protected]>' - 'Roy Ivy III <[email protected]>' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Path-Tiny-0.076/Makefile.PL new/Path-Tiny-0.084/Makefile.PL --- old/Path-Tiny-0.076/Makefile.PL 2015-11-16 16:47:43.000000000 +0100 +++ new/Path-Tiny-0.084/Makefile.PL 2016-03-04 13:18:09.000000000 +0100 @@ -1,4 +1,4 @@ -# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v5.041. +# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v5.043. use strict; use warnings; @@ -26,7 +26,7 @@ "File::Copy" => 0, "File::Glob" => 0, "File::Path" => "2.07", - "File::Spec" => "3.40", + "File::Spec" => "0.86", "File::Temp" => "0.19", "File::stat" => 0, "constant" => 0, @@ -38,7 +38,7 @@ "TEST_REQUIRES" => { "ExtUtils::MakeMaker" => 0, "File::Basename" => 0, - "File::Spec" => "3.40", + "File::Spec" => "0.86", "File::Spec::Functions" => 0, "File::Spec::Unix" => 0, "File::Temp" => "0.19", @@ -46,7 +46,7 @@ "lib" => 0, "open" => 0 }, - "VERSION" => "0.076", + "VERSION" => "0.084", "test" => { "TESTS" => "t/*.t" } @@ -65,7 +65,7 @@ "File::Copy" => 0, "File::Glob" => 0, "File::Path" => "2.07", - "File::Spec" => "3.40", + "File::Spec" => "0.86", "File::Spec::Functions" => 0, "File::Spec::Unix" => 0, "File::Temp" => "0.19", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Path-Tiny-0.076/README new/Path-Tiny-0.084/README --- old/Path-Tiny-0.076/README 2015-11-16 16:47:43.000000000 +0100 +++ new/Path-Tiny-0.084/README 2016-03-04 13:18:09.000000000 +0100 @@ -2,7 +2,7 @@ Path::Tiny - File path utility VERSION - version 0.076 + version 0.084 SYNOPSIS use Path::Tiny; @@ -178,6 +178,10 @@ of what "Path::Tiny" gives you to be just a temporary file name that gets cleaned up. + Note 2: if you don't want these cleaned up automatically when the object + is destroyed, File::Temp requires different options for directories and + files. Use "CLEANUP => 0" for directories and "UNLINK => 0" for files. + Current API available since 0.018. METHODS @@ -347,6 +351,46 @@ Deprecated in 0.056. + edit, edit_raw, edit_utf8 + path("foo.txt")->edit( \&callback, $options ); + path("foo.txt")->edit_utf8( \&callback ); + path("foo.txt")->edit_raw( \&callback ); + + These are convenience methods that allow "editing" a file using a single + callback argument. They slurp the file using "slurp", place the contents + inside a localized $_ variable, call the callback function (without + arguments), and then write $_ (presumably mutated) back to the file with + "spew". + + An optional hash reference may be used to pass options. The only option + is "binmode", which is passed to "slurp" and "spew". + + "edit_utf8" and "edit_raw" act like their respective "slurp_*" and + "spew_*" methods. + + Current API available since 0.077. + + edit_lines, edit_lines_utf8, edit_lines_raw + path("foo.txt")->edit_lines( \&callback, $options ); + path("foo.txt")->edit_lines_utf8( \&callback ); + path("foo.txt")->edit_lines_raw( \&callback ); + + These are convenience methods that allow "editing" a file's lines using + a single callback argument. They iterate over the file: for each line, + the line is put into a localized $_ variable, the callback function is + executed (without arguments) and then $_ is written to a temporary file. + When iteration is finished, the temporary file is atomically renamed + over the original. + + An optional hash reference may be used to pass options. The only option + is "binmode", which is passed to the method that open handles for + reading and writing. + + "edit_lines_utf8" and "edit_lines_raw" act like their respective + "slurp_*" and "spew_*" methods. + + Current API available since 0.077. + exists, is_file, is_dir if ( path("/tmp")->exists ) { ... } # -e if ( path("/tmp")->is_dir ) { ... } # -d @@ -576,10 +620,46 @@ 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()". + Returns a "Path::Tiny" object with a path relative to a new base path + given as an argument. If no argument is given, the current directory + will be used as the new base path. - Current API available since 0.001. + If either path is already relative, it will be made absolute based on + the current directly before determining the new relative path. + + The algorithm is roughly as follows: + + * If the original and new base path are on different volumes, an + exception will be thrown. + + * If the original and new base are identical, the relative path is + ".". + + * If the new base subsumes the original, the relative path is the + original path with the new base chopped off the front + + * If the new base does not subsume the original, a common prefix path + is determined (possibly the root directory) and the relative path + will consist of updirs ("..") to reach the common prefix, followed + by the original path less the common prefix. + + Unlike "File::Spec::rel2abs", in the last case above, the calculation + based on a common prefix takes into account symlinks that could affect + the updir process. Given an original path "/A/B" and a new base "/A/C", + (where "A", "B" and "C" could each have multiple path components): + + * Symlinks in "A" don't change the result unless the last component of + A is a symlink and the first component of "C" is an updir. + + * Symlinks in "B" don't change the result and will exist in the result + as given. + + * Symlinks and updirs in "C" must be resolved to actual paths, taking + into account the possibility that not all path components might + exist on the filesystem. + + Current API available since 0.001. New algorithm (that accounts for + symlinks) available since 0.079. remove path("foo.txt")->remove; @@ -625,9 +705,10 @@ $data = path("foo.txt")->slurp_raw; $data = path("foo.txt")->slurp_utf8; - Reads file contents into a scalar. Takes an optional hash reference may - be used to pass options. The only option is "binmode", which is passed - to "binmode()" on the handle used for reading. + Reads file contents into a scalar. Takes an optional hash reference + which may be used to pass options. The only available option is + "binmode", which is passed to "binmode()" on the handle used for + reading. "slurp_raw" is like "slurp" with a "binmode" of ":unix" for a fast, unbuffered, raw read. @@ -791,9 +872,9 @@ $vol = path("/tmp/foo.txt")->volume; # "" $vol = path("C:/tmp/foo.txt")->volume; # "C:" - Returns the volume portion of the path. This is equivalent equivalent to - what File::Spec would give from "splitpath" and thus usually is the - empty string on Unix-like operating systems or the drive letter for an + Returns the volume portion of the path. This is equivalent to what + File::Spec would give from "splitpath" and thus usually is the empty + string on Unix-like operating systems or the drive letter for an absolute path on "MSWin32". Current API available since 0.001. @@ -818,6 +899,11 @@ Exception objects will stringify as the "msg" field. CAVEATS + Subclassing not supported + For speed, this class is implemented as an array based object and uses + many direction function calls internally. You must not subclass it and + expect things to work properly. + File locking If flock is not supported on a platform, it will not be used, even if locking is requested. @@ -944,6 +1030,8 @@ * James Hunt <[email protected]> + * John Karr <[email protected]> + * Karen Etheridge <[email protected]> * Mark Ellis <[email protected]> @@ -952,6 +1040,8 @@ * Michael G. Schwern <[email protected]> + * Nigel Gregoire <[email protected]> + * Philippe Bruhat (BooK) <[email protected]> * Regina Verbae <[email protected]> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Path-Tiny-0.076/cpanfile new/Path-Tiny-0.084/cpanfile --- old/Path-Tiny-0.076/cpanfile 2015-11-16 16:47:43.000000000 +0100 +++ new/Path-Tiny-0.084/cpanfile 2016-03-04 13:18:09.000000000 +0100 @@ -7,7 +7,7 @@ requires "File::Copy" => "0"; requires "File::Glob" => "0"; requires "File::Path" => "2.07"; -requires "File::Spec" => "3.40"; +requires "File::Spec" => "0.86"; requires "File::Temp" => "0.19"; requires "File::stat" => "0"; requires "constant" => "0"; @@ -21,7 +21,7 @@ on 'test' => sub { requires "ExtUtils::MakeMaker" => "0"; requires "File::Basename" => "0"; - requires "File::Spec" => "3.40"; + requires "File::Spec" => "0.86"; requires "File::Spec::Functions" => "0"; requires "File::Spec::Unix" => "0"; requires "File::Temp" => "0.19"; @@ -42,6 +42,10 @@ requires "perl" => "5.008001"; }; +on 'configure' => sub { + suggests "JSON::PP" => "2.27300"; +}; + on 'develop' => sub { requires "Dist::Zilla" => "5"; requires "Dist::Zilla::Plugin::MinimumPerl" => "0"; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Path-Tiny-0.076/lib/Path/Tiny.pm new/Path-Tiny-0.084/lib/Path/Tiny.pm --- old/Path-Tiny-0.076/lib/Path/Tiny.pm 2015-11-16 16:47:43.000000000 +0100 +++ new/Path-Tiny-0.084/lib/Path/Tiny.pm 2016-03-04 13:18:09.000000000 +0100 @@ -5,12 +5,12 @@ package Path::Tiny; # ABSTRACT: File path utility -our $VERSION = '0.076'; +our $VERSION = '0.084'; # Dependencies use Config; use Exporter 5.57 (qw/import/); -use File::Spec 3.40 (); +use File::Spec 0.86 (); # shipped with 5.8.1 use Carp (); our @EXPORT = qw/path/; @@ -73,6 +73,10 @@ return IS_WIN32() ? ( $_[0] =~ /^$WIN32_ROOT$/ ) : ( $_[0] eq '/' ); } +BEGIN { + *_same = IS_WIN32() ? sub { lc( $_[0] ) eq lc( $_[1] ) } : sub { $_[0] eq $_[1] }; +} + # mode bits encoded for chmod in symbolic mode my %MODEBITS = ( om => 0007, gm => 0070, um => 0700 ); ## no critic { my $m = 0; $MODEBITS{$_} = ( 1 << $m++ ) for qw/ox ow or gx gw gr ux uw ur/ }; @@ -223,6 +227,7 @@ # 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 $path eq '/..'; # for old File::Spec $path .= "/" if IS_WIN32() && $path =~ m{^$UNC_VOL$}; # root paths must always have a trailing slash, but other paths must not @@ -330,6 +335,11 @@ #pod C<Path::Tiny> gives you to be just a temporary file B<name> that gets cleaned #pod up. #pod +#pod B<Note 2>: if you don't want these cleaned up automatically when the object +#pod is destroyed, File::Temp requires different options for directories and +#pod files. Use C<< CLEANUP => 0 >> for directories and C<< UNLINK => 0 >> for +#pod files. +#pod #pod Current API available since 0.018. #pod #pod =cut @@ -748,6 +758,121 @@ return length $self->[DIR] ? $self->[DIR] : "."; } +#pod =method edit, edit_raw, edit_utf8 +#pod +#pod path("foo.txt")->edit( \&callback, $options ); +#pod path("foo.txt")->edit_utf8( \&callback ); +#pod path("foo.txt")->edit_raw( \&callback ); +#pod +#pod These are convenience methods that allow "editing" a file using a single +#pod callback argument. They slurp the file using C<slurp>, place the contents +#pod inside a localized C<$_> variable, call the callback function (without +#pod arguments), and then write C<$_> (presumably mutated) back to the +#pod file with C<spew>. +#pod +#pod An optional hash reference may be used to pass options. The only option is +#pod C<binmode>, which is passed to C<slurp> and C<spew>. +#pod +#pod C<edit_utf8> and C<edit_raw> act like their respective C<slurp_*> and +#pod C<spew_*> methods. +#pod +#pod Current API available since 0.077. +#pod +#pod =cut + +sub edit { + my $self = shift; + my $cb = shift; + my $args = _get_args( shift, qw/binmode/ ); + Carp::croak("Callback for edit() must be a code reference") + unless defined($cb) && ref($cb) eq 'CODE'; + + local $_ = + $self->slurp( exists( $args->{binmode} ) ? { binmode => $args->{binmode} } : () ); + $cb->(); + $self->spew( $args, $_ ); + + return; +} + +# this is done long-hand to benefit from slurp_utf8 optimizations +sub edit_utf8 { + my ( $self, $cb ) = @_; + Carp::croak("Callback for edit_utf8() must be a code reference") + unless defined($cb) && ref($cb) eq 'CODE'; + + local $_ = $self->slurp_utf8; + $cb->(); + $self->spew_utf8($_); + + return; +} + +sub edit_raw { $_[2] = { binmode => ":unix" }; goto &edit } + +#pod =method edit_lines, edit_lines_utf8, edit_lines_raw +#pod +#pod path("foo.txt")->edit_lines( \&callback, $options ); +#pod path("foo.txt")->edit_lines_utf8( \&callback ); +#pod path("foo.txt")->edit_lines_raw( \&callback ); +#pod +#pod These are convenience methods that allow "editing" a file's lines using a +#pod single callback argument. They iterate over the file: for each line, the +#pod line is put into a localized C<$_> variable, the callback function is +#pod executed (without arguments) and then C<$_> is written to a temporary file. +#pod When iteration is finished, the temporary file is atomically renamed over +#pod the original. +#pod +#pod An optional hash reference may be used to pass options. The only option is +#pod C<binmode>, which is passed to the method that open handles for reading and +#pod writing. +#pod +#pod C<edit_lines_utf8> and C<edit_lines_raw> act like their respective +#pod C<slurp_*> and C<spew_*> methods. +#pod +#pod Current API available since 0.077. +#pod +#pod =cut + +sub edit_lines { + my $self = shift; + my $cb = shift; + my $args = _get_args( shift, qw/binmode/ ); + Carp::croak("Callback for edit_lines() must be a code reference") + unless defined($cb) && ref($cb) eq 'CODE'; + + my $binmode = $args->{binmode}; + # get default binmode from caller's lexical scope (see "perldoc open") + $binmode = ( ( caller(0) )[10] || {} )->{'open>'} unless defined $binmode; + + # writing need to follow the link and create the tempfile in the same + # dir for later atomic rename + my $resolved_path = $self->[PATH]; + $resolved_path = readlink $resolved_path while -l $resolved_path; + my $temp = path( $resolved_path . $$ . int( rand( 2**31 ) ) ); + + my $temp_fh = $temp->filehandle( { exclusive => 1, locked => 1 }, ">", $binmode ); + my $in_fh = $self->filehandle( { locked => 1 }, '<', $binmode ); + + local $_; + while (<$in_fh>) { + $cb->(); + $temp_fh->print($_); + } + + close $temp_fh or $self->_throw( 'close', $temp ); + close $in_fh or $self->_throw('close'); + + return $temp->move($resolved_path); +} + +sub edit_lines_raw { $_[2] = { binmode => ":unix" }; goto &edit_lines } + +sub edit_lines_utf8 { + $_[2] = { binmode => ":raw:encoding(UTF-8)" }; + goto &edit_lines; +} + #pod =method exists, is_file, is_dir #pod #pod if ( path("/tmp")->exists ) { ... } # -e @@ -1080,6 +1205,8 @@ } } +my $CRLF = qr/(?:\x{0d}?\x{0a}|\x{0d})/; + sub lines_utf8 { my $self = shift; my $args = _get_args( shift, qw/binmode chomp count/ ); @@ -1087,7 +1214,9 @@ && $args->{chomp} && !$args->{count} ) { - return split /(?:\x{0d}?\x{0a}|\x{0d})/, slurp_utf8($self); ## no critic + my $slurp = slurp_utf8($self); + $slurp =~ s/$CRLF$//; # like chomp, but full CR?LF|CR + return split $CRLF, $slurp, -1; ## no critic } else { $args->{binmode} = ":raw:encoding(UTF-8)"; @@ -1294,6 +1423,10 @@ # doesn't throw an error resolving non-existent basename sub realpath { my $self = shift; + while ( -l $self->[PATH] ) { + my $resolved = readlink $self->[PATH] or $self->_throw( 'readlink', $self->[PATH] ); + $self = path($resolved); + } require Cwd; $self->_splitpath if !defined $self->[FILE]; my $check_parent = @@ -1313,16 +1446,139 @@ #pod #pod $rel = path("/tmp/foo/bar")->relative("/tmp"); # foo/bar #pod -#pod Returns a C<Path::Tiny> object with a relative path name. -#pod Given the trickiness of this, it's a thin wrapper around -#pod C<< File::Spec->abs2rel() >>. +#pod Returns a C<Path::Tiny> object with a path relative to a new base path +#pod given as an argument. If no argument is given, the current directory will +#pod be used as the new base path. #pod -#pod Current API available since 0.001. +#pod If either path is already relative, it will be made absolute based on the +#pod current directly before determining the new relative path. +#pod +#pod The algorithm is roughly as follows: +#pod +#pod =for :list +#pod * If the original and new base path are on different volumes, an exception +#pod will be thrown. +#pod * If the original and new base are identical, the relative path is C<".">. +#pod * If the new base subsumes the original, the relative path is the original +#pod path with the new base chopped off the front +#pod * If the new base does not subsume the original, a common prefix path is +#pod determined (possibly the root directory) and the relative path will +#pod consist of updirs (C<"..">) to reach the common prefix, followed by the +#pod original path less the common prefix. +#pod +#pod Unlike C<File::Spec::rel2abs>, in the last case above, the calculation based +#pod on a common prefix takes into account symlinks that could affect the updir +#pod process. Given an original path "/A/B" and a new base "/A/C", +#pod (where "A", "B" and "C" could each have multiple path components): +#pod +#pod =for :list +#pod * Symlinks in "A" don't change the result unless the last component of A is +#pod a symlink and the first component of "C" is an updir. +#pod * Symlinks in "B" don't change the result and will exist in the result as +#pod given. +#pod * Symlinks and updirs in "C" must be resolved to actual paths, taking into +#pod account the possibility that not all path components might exist on the +#pod filesystem. +#pod +#pod Current API available since 0.001. New algorithm (that accounts for +#pod symlinks) available since 0.079. #pod #pod =cut -# Easy to get wrong, so wash it through File::Spec (sigh) -sub relative { path( File::Spec->abs2rel( $_[0]->[PATH], $_[1] ) ) } +sub relative { + my ( $self, $base ) = @_; + $base = path( defined $base && length $base ? $base : '.' ); + + # relative paths must be converted to absolute first + $self = $self->absolute if $self->is_relative; + $base = $base->absolute if $base->is_relative; + + # normalize volumes if they exist + $self = $self->absolute if !length $self->volume && length $base->volume; + $base = $base->absolute if length $self->volume && !length $base->volume; + + # can't make paths relative across volumes + if ( !_same( $self->volume, $base->volume ) ) { + Carp::croak("relative() can't cross volumes: '$self' vs '$base'"); + } + + # if same absolute path, relative is current directory + return path(".") if _same( $self->[PATH], $base->[PATH] ); + + # if base is a prefix of self, chop prefix off self + if ( $base->subsumes($self) ) { + $base = "" if $base->is_rootdir; + my $relative = "$self"; + $relative =~ s{\A\Q$base/}{}; + return path($relative); + } + + # base is not a prefix, so must find a common prefix (even if root) + my ( @common, @self_parts, @base_parts ); + @base_parts = split /\//, $base->_just_filepath; + + # if self is rootdir, then common directory is root (shown as empty + # string for later joins); otherwise, must be computed from path parts. + if ( $self->is_rootdir ) { + @common = (""); + shift @base_parts; + } + else { + @self_parts = split /\//, $self->_just_filepath; + + while ( @self_parts && @base_parts && _same( $self_parts[0], $base_parts[0] ) ) { + push @common, shift @base_parts; + shift @self_parts; + } + } + + # if there are any symlinks from common to base, we have a problem, as + # you can't guarantee that updir from base reaches the common prefix; + # we must resolve symlinks and try again; likewise, any updirs are + # a problem as it throws off calculation of updirs needed to get from + # self's path to the common prefix. + if ( my $new_base = $self->_resolve_between( \@common, \@base_parts ) ) { + return $self->relative($new_base); + } + + # otherwise, symlinks in common or from common to A don't matter as + # those don't involve updirs + my @new_path = ( ("..") x ( 0+ @base_parts ), @self_parts ); + return path(@new_path); +} + +sub _just_filepath { + my $self = shift; + my $self_vol = $self->volume; + return "$self" if !length $self_vol; + + ( my $self_path = "$self" ) =~ s{\A\Q$self_vol}{}; + + return $self_path; +} + +sub _resolve_between { + my ( $self, $common, $base ) = @_; + my $path = $self->volume . join( "/", @$common ); + my $changed = 0; + for my $p (@$base) { + $path .= "/$p"; + if ( $p eq '..' ) { + $changed = 1; + if ( -e $path ) { + $path = path($path)->realpath->[PATH]; + } + else { + $path =~ s{/[^/]+/..$}{/}; + } + } + if ( -l $path ) { + $changed = 1; + $path = path($path)->realpath->[PATH]; + } + } + return $changed ? path($path) : undef; +} #pod =method remove #pod @@ -1407,9 +1663,9 @@ #pod $data = path("foo.txt")->slurp_raw; #pod $data = path("foo.txt")->slurp_utf8; #pod -#pod Reads file contents into a scalar. Takes an optional hash reference may be -#pod used to pass options. The only option is C<binmode>, which is passed to -#pod C<binmode()> on the handle used for reading. +#pod Reads file contents into a scalar. Takes an optional hash reference which may +#pod be used to pass options. The only available option is C<binmode>, which is +#pod passed to C<binmode()> on the handle used for reading. #pod #pod C<slurp_raw> is like C<slurp> with a C<binmode> of C<:unix> for #pod a fast, unbuffered, raw read. @@ -1744,7 +2000,7 @@ #pod $vol = path("C:/tmp/foo.txt")->volume; # "C:" #pod #pod Returns the volume portion of the path. This is equivalent -#pod equivalent to what L<File::Spec> would give from C<splitpath> and thus +#pod to what L<File::Spec> would give from C<splitpath> and thus #pod usually is the empty string on Unix-like operating systems or the #pod drive letter for an absolute path on C<MSWin32>. #pod @@ -1788,7 +2044,7 @@ =head1 VERSION -version 0.076 +version 0.084 =head1 SYNOPSIS @@ -1971,6 +2227,11 @@ C<Path::Tiny> gives you to be just a temporary file B<name> that gets cleaned up. +B<Note 2>: if you don't want these cleaned up automatically when the object +is destroyed, File::Temp requires different options for directories and +files. Use C<< CLEANUP => 0 >> for directories and C<< UNLINK => 0 >> for +files. + Current API available since 0.018. =head1 METHODS @@ -2156,6 +2417,48 @@ Deprecated in 0.056. +=head2 edit, edit_raw, edit_utf8 + + path("foo.txt")->edit( \&callback, $options ); + path("foo.txt")->edit_utf8( \&callback ); + path("foo.txt")->edit_raw( \&callback ); + +These are convenience methods that allow "editing" a file using a single +callback argument. They slurp the file using C<slurp>, place the contents +inside a localized C<$_> variable, call the callback function (without +arguments), and then write C<$_> (presumably mutated) back to the +file with C<spew>. + +An optional hash reference may be used to pass options. The only option is +C<binmode>, which is passed to C<slurp> and C<spew>. + +C<edit_utf8> and C<edit_raw> act like their respective C<slurp_*> and +C<spew_*> methods. + +Current API available since 0.077. + +=head2 edit_lines, edit_lines_utf8, edit_lines_raw + + path("foo.txt")->edit_lines( \&callback, $options ); + path("foo.txt")->edit_lines_utf8( \&callback ); + path("foo.txt")->edit_lines_raw( \&callback ); + +These are convenience methods that allow "editing" a file's lines using a +single callback argument. They iterate over the file: for each line, the +line is put into a localized C<$_> variable, the callback function is +executed (without arguments) and then C<$_> is written to a temporary file. +When iteration is finished, the temporary file is atomically renamed over +the original. + +An optional hash reference may be used to pass options. The only option is +C<binmode>, which is passed to the method that open handles for reading and +writing. + +C<edit_lines_utf8> and C<edit_lines_raw> act like their respective +C<slurp_*> and C<spew_*> methods. + +Current API available since 0.077. + =head2 exists, is_file, is_dir if ( path("/tmp")->exists ) { ... } # -e @@ -2395,11 +2698,58 @@ $rel = path("/tmp/foo/bar")->relative("/tmp"); # foo/bar -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() >>. +Returns a C<Path::Tiny> object with a path relative to a new base path +given as an argument. If no argument is given, the current directory will +be used as the new base path. -Current API available since 0.001. +If either path is already relative, it will be made absolute based on the +current directly before determining the new relative path. + +The algorithm is roughly as follows: + +=over 4 + +=item * + +If the original and new base path are on different volumes, an exception will be thrown. + +=item * + +If the original and new base are identical, the relative path is C<".">. + +=item * + +If the new base subsumes the original, the relative path is the original path with the new base chopped off the front + +=item * + +If the new base does not subsume the original, a common prefix path is determined (possibly the root directory) and the relative path will consist of updirs (C<"..">) to reach the common prefix, followed by the original path less the common prefix. + +=back + +Unlike C<File::Spec::rel2abs>, in the last case above, the calculation based +on a common prefix takes into account symlinks that could affect the updir +process. Given an original path "/A/B" and a new base "/A/C", +(where "A", "B" and "C" could each have multiple path components): + +=over 4 + +=item * + +Symlinks in "A" don't change the result unless the last component of A is a symlink and the first component of "C" is an updir. + +=item * + +Symlinks in "B" don't change the result and will exist in the result as given. + +=item * + +Symlinks and updirs in "C" must be resolved to actual paths, taking into account the possibility that not all path components might exist on the filesystem. + +=back + +Current API available since 0.001. New algorithm (that accounts for +symlinks) available since 0.079. =head2 remove @@ -2448,9 +2798,9 @@ $data = path("foo.txt")->slurp_raw; $data = path("foo.txt")->slurp_utf8; -Reads file contents into a scalar. Takes an optional hash reference may be -used to pass options. The only option is C<binmode>, which is passed to -C<binmode()> on the handle used for reading. +Reads file contents into a scalar. Takes an optional hash reference which may +be used to pass options. The only available option is C<binmode>, which is +passed to C<binmode()> on the handle used for reading. C<slurp_raw> is like C<slurp> with a C<binmode> of C<:unix> for a fast, unbuffered, raw read. @@ -2617,7 +2967,7 @@ $vol = path("C:/tmp/foo.txt")->volume; # "C:" Returns the volume portion of the path. This is equivalent -equivalent to what L<File::Spec> would give from C<splitpath> and thus +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>. @@ -2625,7 +2975,7 @@ =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 +IS_BSD IS_WIN32 FREEZE THAW TO_JSON abs2rel =head1 EXCEPTION HANDLING @@ -2659,6 +3009,12 @@ =head1 CAVEATS +=head2 Subclassing not supported + +For speed, this class is implemented as an array based object and uses many +direction function calls internally. You must not subclass it and expect +things to work properly. + =head2 File locking If flock is not supported on a platform, it will not be used, even if @@ -2794,7 +3150,7 @@ =head1 CONTRIBUTORS -=for stopwords Alex Efros Chris Williams David Golden Steinbrunner Doug Bell Gabor Szabo Gabriel Andrade George Hartzell Geraud Continsouzas Goro Fuji Graham Knop James Hunt Karen Etheridge Mark Ellis Martin Kjeldsen Michael G. Schwern Philippe Bruhat (BooK) Regina Verbae Roy Ivy III Shlomi Fish Smylers Tatsuhiko Miyagawa Toby Inkster Yanick Champoux 김도형 - Keedi Kim +=for stopwords Alex Efros Chris Williams David Golden Steinbrunner Doug Bell Gabor Szabo Gabriel Andrade George Hartzell Geraud Continsouzas Goro Fuji Graham Knop James Hunt John Karr Karen Etheridge Mark Ellis Martin Kjeldsen Michael G. Schwern Nigel Gregoire Philippe Bruhat (BooK) Regina Verbae Roy Ivy III Shlomi Fish Smylers Tatsuhiko Miyagawa Toby Inkster Yanick Champoux 김도형 - Keedi Kim =over 4 @@ -2848,6 +3204,10 @@ =item * +John Karr <[email protected]> + +=item * + Karen Etheridge <[email protected]> =item * @@ -2864,6 +3224,10 @@ =item * +Nigel Gregoire <[email protected]> + +=item * + Philippe Bruhat (BooK) <[email protected]> =item * diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Path-Tiny-0.076/t/00-report-prereqs.dd new/Path-Tiny-0.084/t/00-report-prereqs.dd --- old/Path-Tiny-0.076/t/00-report-prereqs.dd 2015-11-16 16:47:43.000000000 +0100 +++ new/Path-Tiny-0.084/t/00-report-prereqs.dd 2016-03-04 13:18:09.000000000 +0100 @@ -3,6 +3,9 @@ 'requires' => { 'ExtUtils::MakeMaker' => '6.17', 'perl' => '5.008001' + }, + 'suggests' => { + 'JSON::PP' => '2.27300' } }, 'develop' => { @@ -44,7 +47,7 @@ 'File::Copy' => '0', 'File::Glob' => '0', 'File::Path' => '2.07', - 'File::Spec' => '3.40', + 'File::Spec' => '0.86', 'File::Temp' => '0.19', 'File::stat' => '0', 'constant' => '0', @@ -64,7 +67,7 @@ 'requires' => { 'ExtUtils::MakeMaker' => '0', 'File::Basename' => '0', - 'File::Spec' => '3.40', + 'File::Spec' => '0.86', 'File::Spec::Functions' => '0', 'File::Spec::Unix' => '0', 'File::Temp' => '0.19', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Path-Tiny-0.076/t/00-report-prereqs.t new/Path-Tiny-0.084/t/00-report-prereqs.t --- old/Path-Tiny-0.076/t/00-report-prereqs.t 2015-11-16 16:47:43.000000000 +0100 +++ new/Path-Tiny-0.084/t/00-report-prereqs.t 2016-03-04 13:18:09.000000000 +0100 @@ -3,7 +3,7 @@ use strict; use warnings; -# This test was generated by Dist::Zilla::Plugin::Test::ReportPrereqs 0.021 +# This test was generated by Dist::Zilla::Plugin::Test::ReportPrereqs 0.024 use Test::More tests => 1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Path-Tiny-0.076/t/basic.t new/Path-Tiny-0.084/t/basic.t --- old/Path-Tiny-0.076/t/basic.t 2015-11-16 16:47:43.000000000 +0100 +++ new/Path-Tiny-0.084/t/basic.t 2016-03-04 13:18:09.000000000 +0100 @@ -106,6 +106,9 @@ $file = path('one/two/three'); is $file->relative('one'), 'two/three'; + + $file = path('/one[0/two'); + is $file->relative( '/one[0' ), 'two', 'path with regex special char'; } { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Path-Tiny-0.076/t/filesystem.t new/Path-Tiny-0.084/t/filesystem.t --- old/Path-Tiny-0.076/t/filesystem.t 2015-11-16 16:47:43.000000000 +0100 +++ new/Path-Tiny-0.084/t/filesystem.t 2016-03-04 13:18:09.000000000 +0100 @@ -347,6 +347,8 @@ skip "symlink unavailable", 1 if $@; ok( $link->lstat->size, "lstat" ); + is( $link->realpath, $file->realpath, "realpath resolves symlinks" ); + ok $link->remove, 'remove symbolic link'; ok $file->remove; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Path-Tiny-0.076/t/input_output.t new/Path-Tiny-0.084/t/input_output.t --- old/Path-Tiny-0.076/t/input_output.t 2015-11-16 16:47:43.000000000 +0100 +++ new/Path-Tiny-0.084/t/input_output.t 2016-03-04 13:18:09.000000000 +0100 @@ -198,6 +198,13 @@ join( '', @exp[ 1 .. 2 ] ), "lines" ); }; +subtest "spew -> lines (chomp, only newlines)" => sub { + my $file = Path::Tiny->tempfile; + ok( $file->spew( "\n" x 5 ), "spew" ); + my @exp = ('') x 5; + is( join( '|', $file->lines_utf8( { chomp => 1 } ) ), join( '|', @exp ), "lines" ); +}; + subtest "spew -> lines (chomp, UTF-8)" => sub { my $file = Path::Tiny->tempfile; ok( $file->spew_utf8(_utf8_lines), "spew" ); @@ -485,6 +492,57 @@ is( $got, join( '', _lines ), "openr & read" ); }; +subtest "edit_utf8" => sub { + my $file = Path::Tiny->tempfile; + $file->spew_utf8(_utf8_lines); + $file->edit_utf8( sub { s/^Line/Row/gm; } ); + my $line3 = "\302\261\n"; + utf8::decode($line3); + is( $file->slurp_utf8, ("Row1\r\nRow2\n$line3"), "edit_utf8", ); +}; + +subtest "edit_raw" => sub { + my $file = Path::Tiny->tempfile; + $file->spew_raw("Foo Bar\nClam Bar\n"); + $file->edit_raw( sub { s/Bar/Mangle/; } ); + is( $file->slurp_raw, "Foo Mangle\nClam Bar\n", "edit_raw", ); +}; + +subtest "edit" => sub { + my $file = Path::Tiny->tempfile; + $file->spew_raw("One line\nTwo lines\nThree lines\n"); + $file->edit( sub { s/line/row/; }, { binmode => ':raw' }, ); + is( + $file->slurp_raw, + "One row\nTwo lines\nThree lines\n", + "edit() was successful.", + ); +}; + +subtest "edit_lines_utf8" => sub { + my $file = Path::Tiny->tempfile; + $file->spew_utf8("Foo\nBar\nBaz\nQuux\n"); + $file->edit_lines_utf8( sub { s/\A/prefix = /gm; } ); + is( $file->slurp_utf8, ("prefix = Foo\nprefix = Bar\nprefix = Baz\nprefix = Quux\n"), + "edit_lines_utf8", ); +}; + +subtest "edit_lines_raw" => sub { + my $file = Path::Tiny->tempfile; + $file->spew_raw("Foo\nBar\nBaz\nQuux\n"); + $file->edit_lines_raw( sub { s/\A/prefix = /gm; } ); + is( $file->slurp_raw, ("prefix = Foo\nprefix = Bar\nprefix = Baz\nprefix = Quux\n"), + "edit_lines_utf8", ); +}; + +subtest "edit_lines" => sub { + my $file = Path::Tiny->tempfile; + $file->spew_raw("Foo\nBar\nBaz\nQuux\n"); + $file->edit_lines( sub { s/a/[replacement]/; }, { binmode => ':raw' } ); + is( $file->slurp_raw, ("Foo\nB[replacement]r\nB[replacement]z\nQuux\n"), + "edit_lines", ); +}; + done_testing; # # This file is part of Path-Tiny diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Path-Tiny-0.076/t/lib/TestUtils.pm new/Path-Tiny-0.084/t/lib/TestUtils.pm --- old/Path-Tiny-0.076/t/lib/TestUtils.pm 2015-11-16 16:47:43.000000000 +0100 +++ new/Path-Tiny-0.084/t/lib/TestUtils.pm 2016-03-04 13:18:09.000000000 +0100 @@ -12,6 +12,7 @@ our @ISA = qw/Exporter/; our @EXPORT = qw( exception + pushd tempd ); @@ -30,9 +31,14 @@ } sub tempd { + return pushd( File::Temp->newdir ); +} + +sub pushd { + my $temp = shift; my $guard = TestUtils::_Guard->new( { - temp => File::Temp->newdir, + temp => $temp, origin => getcwd(), code => sub { chdir $_[0]{origin} }, } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Path-Tiny-0.076/t/recurse.t new/Path-Tiny-0.084/t/recurse.t --- old/Path-Tiny-0.076/t/recurse.t 2015-11-16 16:47:43.000000000 +0100 +++ new/Path-Tiny-0.084/t/recurse.t 2016-03-04 13:18:09.000000000 +0100 @@ -139,15 +139,14 @@ } is_deeply( [ sort @files ], [ sort @follow ], "Follow symlinks" ) or diag explain \@files; - }, + }; subtest 'visit' => sub { my @files; path(".") ->visit( sub { push @files, "$_[0]" }, { recurse => 1, follow_symlinks => 1 }, ); is_deeply( [ sort @files ], [ sort @follow ], "Follow symlinks" ) or diag explain \@files; - }, - ; + }; }; }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Path-Tiny-0.076/t/rel-abs.t new/Path-Tiny-0.084/t/rel-abs.t --- old/Path-Tiny-0.076/t/rel-abs.t 2015-11-16 16:47:43.000000000 +0100 +++ new/Path-Tiny-0.084/t/rel-abs.t 2016-03-04 13:18:09.000000000 +0100 @@ -4,10 +4,12 @@ use Test::More 0.96; use lib 't/lib'; -use TestUtils qw/exception/; +use TestUtils qw/exception pushd tempd/; use Path::Tiny; +# absolute() tests + my $rel1 = path("."); my $abs1 = $rel1->absolute; is( $abs1->absolute, $abs1, "absolute of absolute is identity" ); @@ -17,6 +19,209 @@ is( $rel2->absolute($abs1), $abs2, "absolute on base" ); +# Note: in following relative() tests, capital 'A', 'B' denotes absolute path +# and lower case 'a', 'b' denotes relative paths. 'R' denotes the root +# directory. When there are multiple +# letters together, they indicate how paths relate in the hierarchy: +# A subsumes AB, ABC and ABD have a common prefix (referred to as AB). +# The presence of an underscore indicates a symlink somewhere in that segment +# of a path: ABC_D indicates a symlink somewhere between ABC and ABC_D. + +my @symlink_free_cases = ( + # identical (absolute and relative cases) + [ "A->rel(A)", "/foo/bar", "/foo/bar", "." ], + [ "a->rel(a)", "foo/bar", "foo/bar", "." ], + # descends -- absolute + [ "AB->rel(A)", "/foo/bar/baz", "/", "foo/bar/baz" ], + [ "AB->rel(A)", "/foo/bar/baz", "/foo", "bar/baz" ], + [ "AB->rel(A)", "/foo/bar/baz", "/foo/bar", "baz" ], + # descends -- relative + [ "ab->rel(a)", "foo/bar/baz", "", "foo/bar/baz" ], + [ "ab->rel(a)", "foo/bar/baz", ".", "foo/bar/baz" ], + [ "ab->rel(a)", "foo/bar/baz", "foo", "bar/baz" ], + [ "ab->rel(a)", "foo/bar/baz", "foo/bar", "baz" ], + # common prefix -- absolute (same volume) + [ "R->rel(A)", "/", "/bam", ".." ], + [ "R->rel(AB)", "/", "/bam/baz", "../.." ], + [ "ABC->rel(D)", "/foo/bar/baz", "/bam", "../foo/bar/baz" ], + [ "ABC->rel(AD)", "/foo/bar/baz", "/foo/bam", "../bar/baz" ], + [ "ABC->rel(ABD)", "/foo/bar/baz", "/foo/bar/bam", "../baz" ], + [ "ABC->rel(DE)", "/foo/bar/baz", "/bim/bam", "../../foo/bar/baz" ], + [ "ABC->rel(ADE)", "/foo/bar/baz", "/foo/bim/bam", "../../bar/baz" ], + [ "ABC->rel(ABDE)", "/foo/bar/baz", "/foo/bar/bim/bam", "../../baz" ], + # common prefix -- relative (same volume) + [ "abc->rel(d)", "foo/bar/baz", "bam", "../foo/bar/baz" ], + [ "abc->rel(ad)", "foo/bar/baz", "foo/bam", "../bar/baz" ], + [ "abc->rel(abd)", "foo/bar/baz", "foo/bar/bam", "../baz" ], + [ "abc->rel(de)", "foo/bar/baz", "bim/bam", "../../foo/bar/baz" ], + [ "abc->rel(ade)", "foo/bar/baz", "foo/bim/bam", "../../bar/baz" ], + [ "abc->rel(abde)", "foo/bar/baz", "foo/bar/bim/bam", "../../baz" ], + # both paths relative (not identical) + [ "ab->rel(a)", "foo/bar", "foo", "bar" ], + [ "abc->rel(ab)", "foo/bar/baz", "foo/bim", "../bar/baz" ], + [ "a->rel(b)", "foo", "bar", "../foo" ], +); + +for my $c (@symlink_free_cases) { + my ( $label, $path, $base, $result ) = @$c; + is( path($path)->relative($base), $result, $label ); +} + +my @one_rel_from_root = ( + [ "A->rel(b) from rootdir", "/foo/bar", "baz", "../foo/bar" ], + [ "a->rel(B) from rootdir", "foo/bar", "/baz", "../foo/bar" ], +); + +{ + my $wd = pushd("/"); + for my $c (@one_rel_from_root) { + my ( $label, $path, $base, $result ) = @$c; + is( path($path)->relative($base), $result, $label ); + } +} + +{ + my $wd = tempd("/"); + my $cwd = Path::Tiny::cwd->realpath; + + # A->rel(b) from tmpdir -- need to find updir from ./b to root + my $base = $cwd->child("baz"); + my ( undef, @parts ) = split "/", $base; + my $up_to_root = path( "../" x @parts ); + is( + path("/foo/bar")->relative("baz"), + $up_to_root->child("foo/bar"), + "A->rel(b) from tmpdir" + ); + + # a->rel(B) from tempdir -- path is .. + cwd + a + is( + path("foo/bar")->relative("/baz"), + path( "..", $cwd->_just_filepath, "foo/bar" ), + "a->rel(B) from tmpdir" + ); + +} + +subtest "relative on absolute paths with symlinks" => sub { + my $wd = tempd; + my $cwd = path(".")->realpath; + my $deep = $cwd->child("foo/bar/baz/bam/bim/buz/wiz/was/woz"); + $deep->mkpath(); + + eval { symlink "foo/bar/baz", "baz" }; + plan skip_all => "No symlink support" + if $@; + + my ( $path, $base, $expect ); + + # (a) symlink in common path + # + # A_BCD->rel(A_BEF) - common point A_BC - result: ../../C/D + # + $cwd->child("A")->mkpath; + symlink $deep, "A/B" or die "$!"; + $path = $cwd->child("A/B/C/D"); + $path->mkpath; + is( $path->relative( $cwd->child("A/B/E/F") ), "../../C/D", "A_BCD->rel(A_BEF)" ); + $cwd->child("A")->remove_tree; + $deep->remove_tree; + $deep->mkpath; + + # (b) symlink in path from common to original path + # + # ABC_DE->rel(ABFG) - common point AB - result: ../../C/D/E + # + $cwd->child("A/B/C")->mkpath; + symlink $deep, "A/B/C/D" or die "$!"; + $path = $cwd->child("A/B/C/D/E"); + $path->mkpath; + is( $path->relative( $cwd->child("A/B/F/G") ), "../../C/D/E", + "ABC_DE->rel(ABC_FG)" ); + $cwd->child("A")->remove_tree; + $deep->remove_tree; + $deep->mkpath; + + # (c) symlink in path from common to new base; all path exist + # + # ABCD->rel(ABE_FG) - common point AB - result depends on E_F resolution + # + $path = $cwd->child("A/B/C/D"); + $path->mkpath; + $cwd->child("A/B/E")->mkpath; + symlink $deep, "A/B/E/F" or die $!; + $base = $cwd->child("A/B/E/F/G"); + $base->mkpath; + $expect = $path->relative( $deep->child("G") ); + is( $path->relative($base), $expect, "ABCD->rel(ABE_FG) [real paths]" ); + $cwd->child("A")->remove_tree; + $deep->remove_tree; + $deep->mkpath; + + # (d) symlink in path from common to new base; paths after symlink + # don't exist + # + # ABCD->rel(ABE_FGH) - common point AB - result depends on E_F resolution + # + $path = $cwd->child("A/B/C/D"); + $path->mkpath; + $cwd->child("A/B/E")->mkpath; + symlink $deep, "A/B/E/F" or die $!; + $base = $cwd->child("A/B/E/F/G/H"); + $expect = $path->relative( $deep->child("G/H") ); + is( $path->relative($base), $expect, "ABCD->rel(ABE_FGH) [unreal paths]" ); + $cwd->child("A")->remove_tree; + $deep->remove_tree; + $deep->mkpath; + + # (e) symlink at end of common, with updir at start of new base + # + # AB_CDE->rel(AB_C..FG) - common point really AB - result depends on + # symlink resolution + # + $cwd->child("A/B")->mkpath; + symlink $deep, "A/B/C" or die "$!"; + $path = $cwd->child("A/B/C/D/E"); + $path->mkpath; + $base = $cwd->child("A/B/C/../F/G"); + $base->mkpath; + $expect = $path->relative( $deep->parent->child("F/G")->realpath ); + is( $path->relative($base), $expect, "AB_CDE->rel(AB_C..FG)" ); + $cwd->child("A")->remove_tree; + $deep->remove_tree; + $deep->mkpath; + + # (f) updirs in new base [files exist] + # + # ABCDE->rel(ABF..GH) - common point AB - result ../../C/D/E + # + $path = $cwd->child("A/B/C/D/E"); + $path->mkpath; + $cwd->child("A/B/F")->mkpath; + $cwd->child("A/B/G/H")->mkpath; + $base = $cwd->child("A/B/F/../G/H"); + $expect = "../../C/D/E"; + is( $path->relative($base), $expect, "ABCDE->rel(ABF..GH) [real paths]" ); + $cwd->child("A")->remove_tree; + + # (f) updirs in new base [files don't exist] + # + # ABCDE->rel(ABF..GH) - common point AB - result ../../C/D/E + # + $path = $cwd->child("A/B/C/D/E"); + $base = $cwd->child("A/B/F/../G/H"); + $expect = "../../C/D/E"; + is( $path->relative($base), $expect, "ABCDE->rel(ABF..GH) [unreal paths]" ); + $cwd->child("A")->remove_tree; + +}; + +# XXX need to test common prefix case where both are abs but one +# has volume and one doesn't. (Win32: UNC and drive letters) + +# XXX need to test A->rel(B) where A and B are different volumes, +# including UNC and drive letters + done_testing; # # This file is part of Path-Tiny diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Path-Tiny-0.076/xt/author/pod-spell.t new/Path-Tiny-0.084/xt/author/pod-spell.t --- old/Path-Tiny-0.076/xt/author/pod-spell.t 2015-11-16 16:47:43.000000000 +0100 +++ new/Path-Tiny-0.084/xt/author/pod-spell.t 2016-03-04 13:18:09.000000000 +0100 @@ -69,6 +69,9 @@ James Hunt james +John +Karr +brainbuz Karen Etheridge ether @@ -81,6 +84,9 @@ Michael Schwern mschwern +Nigel +Gregoire +nigelgregoire Philippe Bruhat BooK
