Major refactoring of code into separate Stow and Stow::Util Perl modules

This commit is contained in:
Adam Spiers 2011-11-24 16:28:09 +00:00
parent 1365c4c4f1
commit dc61da22d4
20 changed files with 2439 additions and 1980 deletions

1
.gitignore vendored
View file

@ -9,3 +9,4 @@ stamp-vti
stow.info stow.info
t/target/ t/target/
version.texi version.texi
lib/Stow.pm

View file

@ -4,6 +4,8 @@ bin_SCRIPTS = stow chkstow
info_TEXINFOS = stow.texi info_TEXINFOS = stow.texi
dist_man_MANS = stow.8 dist_man_MANS = stow.8
dist_doc_DATA = README dist_doc_DATA = README
pmdir = $(libdir)/perl5
pm_DATA = lib/Stow.pm lib/Stow/Util.pm
TESTS_ENVIRONMENT=$(PERL) -I $(top_srcdir) TESTS_ENVIRONMENT=$(PERL) -I $(top_srcdir)
TESTS = \ TESTS = \
@ -21,7 +23,7 @@ TESTS = \
t/chkstow.t t/chkstow.t
AUTOMAKE_OPTIONS = dist-shar AUTOMAKE_OPTIONS = dist-shar
EXTRA_DIST = $(TESTS) t/util.pm stow.in EXTRA_DIST = $(TESTS) t/testutil.pm
CLEANFILES = $(bin_SCRIPTS) CLEANFILES = $(bin_SCRIPTS)
# clean up files left behind by test suite # clean up files left behind by test suite
@ -30,7 +32,6 @@ clean-local:
# this is more explicit and reliable than the config file trick # this is more explicit and reliable than the config file trick
edit = sed -e 's|[@]PERL[@]|$(PERL)|g' \ edit = sed -e 's|[@]PERL[@]|$(PERL)|g' \
-e 's|[@]PACKAGE[@]|$(PACKAGE)|g' \
-e 's|[@]VERSION[@]|$(VERSION)|g' -e 's|[@]VERSION[@]|$(VERSION)|g'
stow: stow.in Makefile stow: stow.in Makefile
@ -41,6 +42,9 @@ chkstow: chkstow.in Makefile
$(edit) < $< > $@ $(edit) < $< > $@
chmod +x $@ chmod +x $@
lib/Stow.pm: lib/Stow.pm.in
$(edit) < $< > $@
# The rules for manual.html and manual.texi are only used by # The rules for manual.html and manual.texi are only used by
# the developer # the developer
manual.html: manual.texi manual.html: manual.texi
@ -51,5 +55,7 @@ manual.texi: stow.texi
-rm -f $@ -rm -f $@
cp $< $@ cp $< $@
test: stow chkstow MODULES = lib/Stow.pm lib/Stow/Util.pm
perl -MTest::Harness -e 'runtests(@ARGV)' t/*.t
test: stow chkstow $(MODULES)
perl -MTest::Harness -Ilib -It -Ibin -e 'runtests(@ARGV)' t/*.t

2
TODO
View file

@ -1,5 +1,3 @@
* Split core code into Stow.pm
* Add use strict / warnings to tests
* Honour .no-stow-folding and --no-folding * Honour .no-stow-folding and --no-folding
* Support ignore lists in files * Support ignore lists in files
*** Implement. *** Implement.

View file

@ -15,5 +15,11 @@ then
AC_MSG_WARN([WARNING: Perl not found; you must edit line 1 of 'stow']) AC_MSG_WARN([WARNING: Perl not found; you must edit line 1 of 'stow'])
fi fi
AC_ARG_WITH(
pmdir,
[ --with-pmdir=DIR perl modules are in DIR [[LIBDIR/perl5]]],
[PMDIR=${withval}], [PMDIR=${libdir}/perl5]
)
AC_CONFIG_FILES([Makefile]) AC_CONFIG_FILES([Makefile])
AC_OUTPUT AC_OUTPUT

1675
lib/Stow.pm.in Executable file

File diff suppressed because it is too large Load diff

202
lib/Stow/Util.pm Normal file
View file

@ -0,0 +1,202 @@
package Stow::Util;
=head1 NAME
Stow::Util - general utilities
=head1 SYNOPSIS
use Stow::Util qw(debug set_debug_level error ...);
=head1 DESCRIPTION
Supporting utility routines for L<Stow>.
=cut
use strict;
use warnings;
use POSIX qw(getcwd);
use base qw(Exporter);
our @EXPORT_OK = qw(
error debug set_debug_level set_test_mode
join_paths parent canon_path restore_cwd
);
our $ProgramName = 'stow';
#############################################################################
#
# General Utilities: nothing stow specific here.
#
#############################################################################
=head1 IMPORTABLE SUBROUTINES
=head2 error($format, @args)
Outputs an error message in a consistent form and then dies.
=cut
sub error {
my ($format, @args) = @_;
die "$ProgramName: ERROR: " . sprintf($format, @args) . " ($!)\n";
}
=head2 set_debug_level($level)
Sets verbosity level for C<debug()>.
=cut
our $debug_level = 0;
sub set_debug_level {
my ($level) = @_;
$debug_level = $level;
}
=head2 set_test_mode($on_or_off)
Sets testmode on or off.
=cut
our $test_mode = 0;
sub set_test_mode {
my ($on_or_off) = @_;
if ($on_or_off) {
$test_mode = 1;
}
else {
$test_mode = 0;
}
}
=head2 debug($level, $msg)
Logs to STDERR based on C<$debug_level> setting. C<$level> is the
minimum verbosity level required to output C<$msg>. All output is to
STDERR to preserve backward compatibility, except for in test mode,
when STDOUT is used instead. In test mode, the verbosity can be
overridden via the C<TEST_VERBOSE> environment variable.
Verbosity rules:
=over 4
=item 0: errors only
=item >= 1: print operations: LINK/UNLINK/MKDIR/RMDIR
=item >= 2: print trace: stow/unstow package/contents/node
=item >= 3: print trace detail: "_this_ already points to _that_"
=item >= 4: debug helper routines
=back
=cut
sub debug {
my ($level, $msg) = @_;
if ($debug_level >= $level) {
if ($test_mode) {
print "# $msg\n";
}
else {
warn "$msg\n";
}
}
}
#===== METHOD ===============================================================
# Name : join_paths()
# Purpose : concatenates given paths
# Parameters: path1, path2, ... => paths
# Returns : concatenation of given paths
# Throws : n/a
# Comments : factors out redundant path elements:
# : '//' => '/' and 'a/b/../c' => 'a/c'
#============================================================================
sub join_paths {
my @paths = @_;
# weed out empty components and concatenate
my $result = join '/', grep {!/\A\z/} @paths;
# factor out back references and remove redundant /'s)
my @result = ();
PART:
for my $part (split m{/+}, $result) {
next PART if $part eq '.';
if (@result && $part eq '..' && $result[-1] ne '..') {
pop @result;
}
else {
push @result, $part;
}
}
return join '/', @result;
}
#===== METHOD ===============================================================
# Name : parent
# Purpose : find the parent of the given path
# Parameters: @path => components of the path
# Returns : returns a path string
# Throws : n/a
# Comments : allows you to send multiple chunks of the path
# : (this feature is currently not used)
#============================================================================
sub parent {
my @path = @_;
my $path = join '/', @_;
my @elts = split m{/+}, $path;
pop @elts;
return join '/', @elts;
}
#===== METHOD ===============================================================
# Name : canon_path
# Purpose : find absolute canonical path of given path
# Parameters: $path
# Returns : absolute canonical path
# Throws : n/a
# Comments : is this significantly different from File::Spec->rel2abs?
#============================================================================
sub canon_path {
my ($path) = @_;
my $cwd = getcwd();
chdir($path) or error("canon_path: cannot chdir to $path from $cwd");
my $canon_path = getcwd();
restore_cwd($cwd);
return $canon_path;
}
sub restore_cwd {
my ($prev) = @_;
chdir($prev) or error("Your current directory $prev seems to have vanished");
}
=head1 BUGS
=head1 SEE ALSO
=cut
1;
# Local variables:
# mode: perl
# cperl-indent-level: 4
# end:
# vim: ft=perl

1657
stow.in

File diff suppressed because it is too large Load diff

View file

@ -4,22 +4,18 @@
# Testing cleanup_invalid_links() # Testing cleanup_invalid_links()
# #
# load as a library use strict;
BEGIN { use warnings;
use lib qw(.);
require "t/util.pm"; use testutil;
require "chkstow"; require "chkstow";
}
use Test::More tests => 7; use Test::More tests => 7;
use Test::Output; use Test::Output;
use English qw(-no_match_vars); use English qw(-no_match_vars);
### setup make_fresh_stow_and_target_dirs();
eval { remove_dir('t/target'); }; cd('t/target');
make_dir('t/target');
chdir 't/target';
# setup stow directory # setup stow directory
make_dir('stow'); make_dir('stow');
@ -111,5 +107,6 @@ stdout_like(
@ARGV = ('-b',); @ARGV = ('-b',);
process_options(); process_options();
ok($::Target == q{/usr/local}, our $Target;
ok($Target == q{/usr/local},
"Default target is /usr/local/"); "Default target is /usr/local/");

View file

@ -4,64 +4,55 @@
# Testing cleanup_invalid_links() # Testing cleanup_invalid_links()
# #
# load as a library use strict;
BEGIN { use lib qw(.); require "t/util.pm"; require "stow"; } use warnings;
use Test::More tests => 3; use Test::More tests => 6;
use English qw(-no_match_vars); use English qw(-no_match_vars);
### setup use testutil;
eval { remove_dir('t/target'); };
eval { remove_dir('t/stow'); };
make_dir('t/target');
make_dir('t/stow');
chdir 't/target'; make_fresh_stow_and_target_dirs();
$Stow_Path= '../stow'; cd('t/target');
my $stow;
# Note that each of the following tests use a distinct set of files # Note that each of the following tests use a distinct set of files
# #
# nothing to clean in a simple tree # nothing to clean in a simple tree
# #
reset_state();
make_dir('../stow/pkg1/bin1'); make_dir('../stow/pkg1/bin1');
make_file('../stow/pkg1/bin1/file1'); make_file('../stow/pkg1/bin1/file1');
make_link('bin1','../stow/pkg1/bin1'); make_link('bin1','../stow/pkg1/bin1');
cleanup_invalid_links('./'); $stow = new_Stow();
$stow->cleanup_invalid_links('./');
is( is(
scalar @Tasks, 0 scalar($stow->get_tasks), 0
=> 'nothing to clean' => 'nothing to clean'
); );
# #
# cleanup a bad link in a simple tree # cleanup a bad link in a simple tree
# #
reset_state();
make_dir('bin2'); make_dir('bin2');
make_dir('../stow/pkg2/bin2'); make_dir('../stow/pkg2/bin2');
make_file('../stow/pkg2/bin2/file2a'); make_file('../stow/pkg2/bin2/file2a');
make_link('bin2/file2a','../../stow/pkg2/bin2/file2a'); make_link('bin2/file2a','../../stow/pkg2/bin2/file2a');
make_link('bin2/file2b','../../stow/pkg2/bin2/file2b'); make_link('bin2/file2b','../../stow/pkg2/bin2/file2b');
cleanup_invalid_links('bin2'); $stow = new_Stow();
ok( $stow->cleanup_invalid_links('bin2');
scalar(@Conflicts) == 0 && is(scalar($stow->get_conflicts), 0, 'no conflicts cleaning up bad link');
scalar @Tasks == 1 && is(scalar($stow->get_tasks), 1, 'one task cleaning up bad link');
$Link_Task_For{'bin2/file2b'}->{'action'} eq 'remove' is($stow->link_task_action('bin2/file2b'), 'remove', 'removal task for bad link');
=> 'cleanup a bad link'
);
#use Data::Dumper;
#print Dumper(\@Tasks,\%Link_Task_For,\%Dir_Task_For);
# #
# dont cleanup a bad link not owned by stow # dont cleanup a bad link not owned by stow
# #
reset_state();
make_dir('bin3'); make_dir('bin3');
make_dir('../stow/pkg3/bin3'); make_dir('../stow/pkg3/bin3');
@ -69,11 +60,7 @@ make_file('../stow/pkg3/bin3/file3a');
make_link('bin3/file3a','../../stow/pkg3/bin3/file3a'); make_link('bin3/file3a','../../stow/pkg3/bin3/file3a');
make_link('bin3/file3b','../../empty'); make_link('bin3/file3b','../../empty');
cleanup_invalid_links('bin3'); $stow = new_Stow();
ok( $stow->cleanup_invalid_links('bin3');
scalar(@Conflicts) == 0 && is(scalar($stow->get_conflicts), 0, 'no conflicts cleaning up bad link not owned by stow');
scalar @Tasks == 0 is(scalar($stow->get_tasks), 0, 'no tasks cleaning up bad link not owned by stow');
=> 'dont cleanup a bad link not owned by stow'
);

24
t/defer.t Normal file → Executable file
View file

@ -4,19 +4,23 @@
# Testing defer(). # Testing defer().
# #
# load as a library use strict;
BEGIN { use lib qw(. ..); require "stow"; } use warnings;
use testutil;
use Test::More tests => 4; use Test::More tests => 4;
$Option{'defer'} = [ 'man' ]; my $stow;
ok(defer('man/man1/file.1') => 'simple success');
$Option{'defer'} = [ 'lib' ]; $stow = new_Stow(defer => [ 'man' ]);
ok(!defer('man/man1/file.1') => 'simple failure'); ok($stow->defer('man/man1/file.1') => 'simple success');
$Option{'defer'} = [ 'lib', 'man', 'share' ]; $stow = new_Stow(defer => [ 'lib' ]);
ok(defer('man/man1/file.1') => 'complex success'); ok(! $stow->defer('man/man1/file.1') => 'simple failure');
$Option{'defer'} = [ 'lib', 'man', 'share' ]; $stow = new_Stow(defer => [ 'lib', 'man', 'share' ]);
ok(!defer('bin/file') => 'complex failure'); ok($stow->defer('man/man1/file.1') => 'complex success');
$stow = new_Stow(defer => [ 'lib', 'man', 'share' ]);
ok(! $stow->defer('bin/file') => 'complex failure');

View file

@ -4,18 +4,18 @@
# Testing examples from the documentation # Testing examples from the documentation
# #
# load as a library use strict;
BEGIN { use lib qw(.); require "t/util.pm"; require "stow"; } use warnings;
use Test::More tests => 4; use testutil;
use Test::More tests => 10;
use English qw(-no_match_vars); use English qw(-no_match_vars);
### setup make_fresh_stow_and_target_dirs();
eval { remove_dir('t/target'); }; cd('t/target');
make_dir('t/target/stow');
chdir 't/target'; my $stow;
$Stow_Path= 'stow';
## set up some fake packages to stow ## set up some fake packages to stow
@ -42,8 +42,6 @@ make_file('stow/emacs/man/man1/emacs.1');
# #
# stow perl into an empty target # stow perl into an empty target
# #
reset_state();
make_dir('stow/perl/bin'); make_dir('stow/perl/bin');
make_file('stow/perl/bin/perl'); make_file('stow/perl/bin/perl');
make_file('stow/perl/bin/a2p'); make_file('stow/perl/bin/a2p');
@ -52,10 +50,11 @@ make_dir('stow/perl/lib/perl');
make_dir('stow/perl/man/man1'); make_dir('stow/perl/man/man1');
make_file('stow/perl/man/man1/perl.1'); make_file('stow/perl/man/man1/perl.1');
stow_contents('stow/perl','./','stow/perl'); $stow = new_Stow(dir => 'stow');
process_tasks(); $stow->plan_stow('perl');
$stow->process_tasks();
ok( ok(
scalar(@Conflicts) == 0 && scalar($stow->get_conflicts) == 0 &&
-l 'bin' && -l 'info' && -l 'lib' && -l 'man' && -l 'bin' && -l 'info' && -l 'lib' && -l 'man' &&
readlink('bin') eq 'stow/perl/bin' && readlink('bin') eq 'stow/perl/bin' &&
readlink('info') eq 'stow/perl/info' && readlink('info') eq 'stow/perl/info' &&
@ -64,11 +63,9 @@ ok(
=> 'stow perl into an empty target' => 'stow perl into an empty target'
); );
# #
# stow perl into a non-empty target # stow perl into a non-empty target
# #
reset_state();
# clean up previous stow # clean up previous stow
remove_link('bin'); remove_link('bin');
@ -80,10 +77,11 @@ make_dir('bin');
make_dir('lib'); make_dir('lib');
make_dir('man/man1'); make_dir('man/man1');
stow_contents('stow/perl','./','stow/perl'); $stow = new_Stow(dir => 'stow');
process_tasks(); $stow->plan_stow('perl');
$stow->process_tasks();
ok( ok(
scalar(@Conflicts) == 0 && scalar($stow->get_conflicts) == 0 &&
-d 'bin' && -d 'lib' && -d 'man' && -d 'man/man1' && -d 'bin' && -d 'lib' && -d 'man' && -d 'man/man1' &&
-l 'info' && -l 'bin/perl' && -l 'bin/a2p' && -l 'info' && -l 'bin/perl' && -l 'bin/a2p' &&
-l 'lib/perl' && -l 'man/man1/perl.1' && -l 'lib/perl' && -l 'man/man1/perl.1' &&
@ -99,7 +97,6 @@ ok(
# #
# Install perl into an empty target and then install emacs # Install perl into an empty target and then install emacs
# #
reset_state();
# clean up previous stow # clean up previous stow
remove_link('info'); remove_link('info');
@ -107,11 +104,11 @@ remove_dir('bin');
remove_dir('lib'); remove_dir('lib');
remove_dir('man'); remove_dir('man');
stow_contents('stow/perl', './','stow/perl'); $stow = new_Stow(dir => 'stow');
stow_contents('stow/emacs','./','stow/emacs'); $stow->plan_stow('perl', 'emacs');
process_tasks(); $stow->process_tasks();
is(scalar($stow->get_conflicts), 0, 'no conflicts');
ok( ok(
scalar(@Conflicts) == 0 &&
-d 'bin' && -d 'bin' &&
-l 'bin/perl' && -l 'bin/perl' &&
-l 'bin/emacs' && -l 'bin/emacs' &&
@ -151,30 +148,22 @@ ok(
# Q. the original empty directory should remain # Q. the original empty directory should remain
# behaviour is the same as if the empty directory had nothing to do with stow # behaviour is the same as if the empty directory had nothing to do with stow
# #
reset_state();
make_dir('stow/pkg1a/bin1'); make_dir('stow/pkg1a/bin1');
make_dir('stow/pkg1b/bin1'); make_dir('stow/pkg1b/bin1');
make_file('stow/pkg1b/bin1/file1b'); make_file('stow/pkg1b/bin1/file1b');
stow_contents('stow/pkg1a', './', 'stow/pkg1a'); $stow = new_Stow(dir => 'stow');
stow_contents('stow/pkg1b', './', 'stow/pkg1b'); $stow->plan_stow('pkg1a', 'pkg1b');
unstow_contents('stow/pkg1b', './', 'stow/pkg1b'); $stow->plan_unstow('pkg1b');
process_tasks(); $stow->process_tasks();
is(scalar($stow->get_conflicts), 0, 'no conflicts stowing empty dirs');
ok( ok(-d 'bin1' => 'bug 1: stowing empty dirs');
scalar(@Conflicts) == 0 &&
-d 'bin1'
=> 'bug 1: stowing empty dirs'
);
# #
# BUG 2: split open tree-folding symlinks pointing inside different stow # BUG 2: split open tree-folding symlinks pointing inside different stow
# directories # directories
# #
reset_state();
make_dir('stow2a/pkg2a/bin2'); make_dir('stow2a/pkg2a/bin2');
make_file('stow2a/pkg2a/bin2/file2a'); make_file('stow2a/pkg2a/bin2/file2a');
make_file('stow2a/.stow'); make_file('stow2a/.stow');
@ -182,8 +171,15 @@ make_dir('stow2b/pkg2b/bin2');
make_file('stow2b/pkg2b/bin2/file2b'); make_file('stow2b/pkg2b/bin2/file2b');
make_file('stow2b/.stow'); make_file('stow2b/.stow');
stow_contents('stow2a/pkg2a','./', 'stow2a/pkg2a'); $stow = new_Stow(dir => 'stow2a');
stow_contents('stow2b/pkg2b','./', 'stow2b/pkg2b'); $stow->plan_stow('pkg2a');
process_tasks(); $stow->set_stow_dir('stow2b');
$stow->plan_stow('pkg2b');
$stow->process_tasks();
is(scalar($stow->get_conflicts), 0, 'no conflicts splitting tree-folding symlinks');
ok(-d 'bin2' => 'tree got split by packages from multiple stow directories');
ok(-f 'bin2/file2a' => 'file from 1st stow dir');
ok(-f 'bin2/file2b' => 'file from 2nd stow dir');
## Finish this test ## Finish this test

40
t/find_stowed_path.t Normal file → Executable file
View file

@ -4,39 +4,43 @@
# Testing find_stowed_path() # Testing find_stowed_path()
# #
BEGIN { require "t/util.pm"; require "stow"; } use strict;
use warnings;
use Test::More tests => 5; use testutil;
eval { remove_dir('t/target'); }; use Test::More tests => 6;
eval { remove_dir('t/stow'); };
make_dir('t/target'); make_fresh_stow_and_target_dirs();
make_dir('t/stow');
my $stow = new_Stow(dir => 't/stow');
$Stow_Path = 't/stow';
is( is(
find_stowed_path('t/target/a/b/c', '../../../stow/a/b/c'), $stow->find_stowed_path('t/target/a/b/c', '../../../stow/a/b/c'),
't/stow/a/b/c', 't/stow/a/b/c',
=> 'from root' => 'from root'
); );
$Stow_Path = '../stow'; cd('t/target');
$stow->set_stow_dir('../stow');
is( is(
find_stowed_path('a/b/c','../../../stow/a/b/c'), $stow->find_stowed_path('a/b/c','../../../stow/a/b/c'),
'../stow/a/b/c', '../stow/a/b/c',
=> 'from target directory' => 'from target directory'
); );
$Stow_Path = 't/target/stow'; make_dir('stow');
cd('../..');
$stow->set_stow_dir('t/target/stow');
is( is(
find_stowed_path('t/target/a/b/c', '../../stow/a/b/c'), $stow->find_stowed_path('t/target/a/b/c', '../../stow/a/b/c'),
't/target/stow/a/b/c', 't/target/stow/a/b/c',
=> 'stow is subdir of target directory' => 'stow is subdir of target directory'
); );
is( is(
find_stowed_path('t/target/a/b/c','../../empty'), $stow->find_stowed_path('t/target/a/b/c','../../empty'),
'', '',
=> 'target is not stowed' => 'target is not stowed'
); );
@ -45,7 +49,15 @@ make_dir('t/target/stow2');
make_file('t/target/stow2/.stow'); make_file('t/target/stow2/.stow');
is( is(
find_stowed_path('t/target/a/b/c','../../stow2/a/b/c'), $stow->find_stowed_path('t/target/a/b/c','../../stow2/a/b/c'),
't/target/stow2/a/b/c' 't/target/stow2/a/b/c'
=> q(detect alternate stow directory) => q(detect alternate stow directory)
); );
# Possible corner case with rogue symlink pointing to ancestor of
# stow dir.
is(
$stow->find_stowed_path('t/target/a/b/c','../../..'),
''
=> q(corner case - link points to ancestor of stow dir)
);

View file

@ -4,21 +4,18 @@
# Testing foldable() # Testing foldable()
# #
# load as a library use strict;
BEGIN { use lib qw(.); require "t/util.pm"; require "stow"; } use warnings;
use testutil;
use Test::More tests => 4; use Test::More tests => 4;
use English qw(-no_match_vars); use English qw(-no_match_vars);
### setup make_fresh_stow_and_target_dirs();
# be very careful with these cd('t/target');
eval { remove_dir('t/target'); };
eval { remove_dir('t/stow'); };
make_dir('t/target');
make_dir('t/stow');
chdir 't/target'; my $stow = new_Stow(dir => '../stow');
$Stow_Path= '../stow';
# Note that each of the following tests use a distinct set of files # Note that each of the following tests use a distinct set of files
@ -31,7 +28,7 @@ make_file('../stow/pkg1/bin1/file1');
make_dir('bin1'); make_dir('bin1');
make_link('bin1/file1','../../stow/pkg1/bin1/file1'); make_link('bin1/file1','../../stow/pkg1/bin1/file1');
is( foldable('bin1'), '../stow/pkg1/bin1' => q(can fold a simple tree) ); is( $stow->foldable('bin1'), '../stow/pkg1/bin1' => q(can fold a simple tree) );
# #
# can't fold an empty directory # can't fold an empty directory
@ -41,7 +38,7 @@ make_dir('../stow/pkg2/bin2');
make_file('../stow/pkg2/bin2/file2'); make_file('../stow/pkg2/bin2/file2');
make_dir('bin2'); make_dir('bin2');
is( foldable('bin2'), '' => q(can't fold an empty directory) ); is( $stow->foldable('bin2'), '' => q(can't fold an empty directory) );
# #
# can't fold if dir contains a non-link # can't fold if dir contains a non-link
@ -53,7 +50,7 @@ make_dir('bin3');
make_link('bin3/file3','../../stow/pkg3/bin3/file3'); make_link('bin3/file3','../../stow/pkg3/bin3/file3');
make_file('bin3/non-link'); make_file('bin3/non-link');
is( foldable('bin3'), '' => q(can't fold a dir containing non-links) ); is( $stow->foldable('bin3'), '' => q(can't fold a dir containing non-links) );
# #
# can't fold if links point to different directories # can't fold if links point to different directories
@ -67,4 +64,4 @@ make_dir('../stow/pkg4b/bin4');
make_file('../stow/pkg4b/bin4/file4b'); make_file('../stow/pkg4b/bin4/file4b');
make_link('bin4/file4b','../../stow/pkg4b/bin4/file4b'); make_link('bin4/file4b','../../stow/pkg4b/bin4/file4b');
is( foldable('bin4'), '' => q(can't fold if links point to different dirs) ); is( $stow->foldable('bin4'), '' => q(can't fold if links point to different dirs) );

6
t/join_paths.t Normal file → Executable file
View file

@ -4,8 +4,10 @@
# Testing join_paths(); # Testing join_paths();
# #
# load as a library use strict;
BEGIN { use lib qw(. ..); require "stow"; } use warnings;
use Stow::Util qw(join_paths);
use Test::More tests => 13; use Test::More tests => 13;

6
t/parent.t Normal file → Executable file
View file

@ -4,8 +4,10 @@
# Testing parent() # Testing parent()
# #
# load as a library use strict;
BEGIN { use lib qw(. ..); require "stow"; } use warnings;
use Stow::Util qw(parent);
use Test::More tests => 5; use Test::More tests => 5;

View file

@ -4,11 +4,17 @@
# Testing core application # Testing core application
# #
# load as a library use strict;
BEGIN { use lib qw(.); require "t/util.pm"; require "stow"; } use warnings;
use Test::More tests => 10; use Test::More tests => 10;
use testutil;
require 'stow';
make_fresh_stow_and_target_dirs();
local @ARGV = ( local @ARGV = (
'-v', '-v',
'-d t/stow', '-d t/stow',
@ -16,23 +22,19 @@ local @ARGV = (
'dummy' 'dummy'
); );
### setup my ($options, $pkgs_to_delete, $pkgs_to_stow) = process_options();
eval { remove_dir('t/target'); };
eval { remove_dir('t/stow'); };
make_dir('t/target');
make_dir('t/stow');
ok eval {process_options(); 1} => 'process options'; is($options->{verbose}, 1, 'verbose option');
ok eval {set_stow_path(); 1} => 'set stow path'; is($options->{dir}, 't/stow', 'stow dir option');
is($Stow_Path,"../stow" => 'stow dir'); my $stow = new_Stow(%$options);
is_deeply(\@Pkgs_To_Stow, [ 'dummy' ] => 'default to stow');
is($stow->{stow_path}, "../stow" => 'stow dir');
is_deeply($pkgs_to_stow, [ 'dummy' ] => 'default to stow');
# #
# Check mixed up package options # Check mixed up package options
# #
%Option=();
local @ARGV = ( local @ARGV = (
'-v', '-v',
'-D', 'd1', 'd2', '-D', 'd1', 'd2',
@ -43,55 +45,53 @@ local @ARGV = (
'-R', 'r2', '-R', 'r2',
); );
@Pkgs_To_Stow = (); ($options, $pkgs_to_delete, $pkgs_to_stow) = process_options();
@Pkgs_To_Delete = (); is_deeply($pkgs_to_delete, [ 'd1', 'd2', 'r1', 'd3', 'r2' ] => 'mixed deletes');
process_options(); is_deeply($pkgs_to_stow, [ 's1', 'r1', 's2', 's3', 'r2' ] => 'mixed stows');
is_deeply(\@Pkgs_To_Delete, [ 'd1', 'd2', 'r1', 'd3', 'r2' ] => 'mixed deletes');
is_deeply(\@Pkgs_To_Stow, [ 's1', 'r1', 's2', 's3', 'r2' ] => 'mixed stows');
# #
# Check setting defered paths # Check setting deferred paths
# #
%Option=();
local @ARGV = ( local @ARGV = (
'--defer=man', '--defer=man',
'--defer=info' '--defer=info',
'dummy'
); );
process_options(); ($options, $pkgs_to_delete, $pkgs_to_stow) = process_options();
is_deeply($Option{'defer'}, [ qr(\Aman), qr(\Ainfo) ] => 'defer man and info'); is_deeply($options->{'defer'}, [ qr(\Aman), qr(\Ainfo) ] => 'defer man and info');
# #
# Check setting override paths # Check setting override paths
# #
%Option=();
local @ARGV = ( local @ARGV = (
'--override=man', '--override=man',
'--override=info' '--override=info',
'dummy'
); );
process_options(); ($options, $pkgs_to_delete, $pkgs_to_stow) = process_options();
is_deeply($Option{'override'}, [qr(\Aman), qr(\Ainfo)] => 'override man and info'); is_deeply($options->{'override'}, [qr(\Aman), qr(\Ainfo)] => 'override man and info');
# #
# Check stripping any matched quotes # Check stripping any matched quotes
# #
%Option=();
local @ARGV = ( local @ARGV = (
"--override='man'", "--override='man'",
'--override="info"', '--override="info"',
'dummy'
); );
process_options(); ($options, $pkgs_to_delete, $pkgs_to_stow) = process_options();
is_deeply($Option{'override'}, [qr(\Aman), qr(\Ainfo)] => 'strip shell quoting'); is_deeply($options->{'override'}, [qr(\Aman), qr(\Ainfo)] => 'strip shell quoting');
# #
# Check setting ignored paths # Check setting ignored paths
# #
%Option=();
local @ARGV = ( local @ARGV = (
'--ignore="~"', '--ignore="~"',
'--ignore="\.#.*"' '--ignore="\.#.*"',
'dummy'
); );
process_options(); ($options, $pkgs_to_delete, $pkgs_to_stow) = process_options();
is_deeply($Option{'ignore'}, [ qr(~\z), qr(\.#.*\z) ] => 'ignore temp files'); is_deeply($options->{'ignore'}, [ qr(~\z), qr(\.#.*\z) ] => 'ignore temp files');
# vim:ft=perl # vim:ft=perl

View file

@ -1,36 +1,37 @@
#!/usr/local/bin/perl #!/usr/local/bin/perl
# #
# Testing # Testing stow_contents()
# #
# load as a library use strict;
BEGIN { use lib qw(.); require "t/util.pm"; require "stow"; } use warnings;
use Test::More tests => 16; use Test::More tests => 19;
use Test::Output; use Test::Output;
use English qw(-no_match_vars); use English qw(-no_match_vars);
### setup use testutil;
eval { remove_dir('t/target'); };
eval { remove_dir('t/stow'); };
make_dir('t/target');
make_dir('t/stow');
chdir 't/target'; make_fresh_stow_and_target_dirs();
$Stow_Path= '../stow'; cd('t/target');
my $stow;
my @conflicts;
# Note that each of the following tests use a distinct set of files # Note that each of the following tests use a distinct set of files
# #
# stow a simple tree minimally # stow a simple tree minimally
# #
reset_state(); $stow = new_Stow(dir => '../stow');
make_dir('../stow/pkg1/bin1'); make_dir('../stow/pkg1/bin1');
make_file('../stow/pkg1/bin1/file1'); make_file('../stow/pkg1/bin1/file1');
stow_contents('../stow/pkg1', './', '../stow/pkg1');
process_tasks(); $stow->plan_stow('pkg1');
$stow->process_tasks();
is($stow->get_conflicts(), 0, 'no conflicts with minimal stow');
is( is(
readlink('bin1'), readlink('bin1'),
'../stow/pkg1/bin1', '../stow/pkg1/bin1',
@ -40,13 +41,13 @@ is(
# #
# stow a simple tree into an existing directory # stow a simple tree into an existing directory
# #
reset_state(); $stow = new_Stow();
make_dir('../stow/pkg2/lib2'); make_dir('../stow/pkg2/lib2');
make_file('../stow/pkg2/lib2/file2'); make_file('../stow/pkg2/lib2/file2');
make_dir('lib2'); make_dir('lib2');
stow_contents('../stow/pkg2', '.', '../stow/pkg2'); $stow->plan_stow('pkg2');
process_tasks(); $stow->process_tasks();
is( is(
readlink('lib2/file2'), readlink('lib2/file2'),
'../../stow/pkg2/lib2/file2', '../../stow/pkg2/lib2/file2',
@ -56,7 +57,7 @@ is(
# #
# unfold existing tree # unfold existing tree
# #
reset_state(); $stow = new_Stow();
make_dir('../stow/pkg3a/bin3'); make_dir('../stow/pkg3a/bin3');
make_file('../stow/pkg3a/bin3/file3a'); make_file('../stow/pkg3a/bin3/file3a');
@ -64,8 +65,8 @@ make_link('bin3' => '../stow/pkg3a/bin3'); # emulate stow
make_dir('../stow/pkg3b/bin3'); make_dir('../stow/pkg3b/bin3');
make_file('../stow/pkg3b/bin3/file3b'); make_file('../stow/pkg3b/bin3/file3b');
stow_contents('../stow/pkg3b', './', '../stow/pkg3b'); $stow->plan_stow('pkg3b');
process_tasks(); $stow->process_tasks();
ok( ok(
-d 'bin3' && -d 'bin3' &&
readlink('bin3/file3a') eq '../../stow/pkg3a/bin3/file3a' && readlink('bin3/file3a') eq '../../stow/pkg3a/bin3/file3a' &&
@ -74,42 +75,45 @@ ok(
); );
# #
# Link to a new dir conflicts with existing non-dir (can't unfold) # Link to a new dir conflicts with existing non-dir (can't unfold)
# #
reset_state(); $stow = new_Stow();
make_file('bin4'); # this is a file but named like a directory make_file('bin4'); # this is a file but named like a directory
make_dir('../stow/pkg4/bin4'); make_dir('../stow/pkg4/bin4');
make_file('../stow/pkg4/bin4/file4'); make_file('../stow/pkg4/bin4/file4');
stow_contents('../stow/pkg4', './', '../stow/pkg4'); $stow->plan_stow('pkg4');
like( @conflicts = $stow->get_conflicts();
$Conflicts[-1], qr(CONFLICT:.*existing target is neither a link nor a directory) like(
$conflicts[-1], qr(CONFLICT:.*existing target is neither a link nor a directory)
=> 'link to new dir conflicts with existing non-directory' => 'link to new dir conflicts with existing non-directory'
); );
# #
# Target already exists but is not owned by stow # Target already exists but is not owned by stow
# #
reset_state(); $stow = new_Stow();
make_dir('bin5'); make_dir('bin5');
make_link('bin5/file5','../../empty'); make_link('bin5/file5','../../empty');
make_dir('../stow/pkg5/bin5/file5'); make_dir('../stow/pkg5/bin5/file5');
stow_contents('../stow/pkg5', './', '../stow/pkg5'); $stow->plan_stow('pkg5');
@conflicts = $stow->get_conflicts();
like( like(
$Conflicts[-1], qr(CONFLICT:.*not owned by stow) $conflicts[-1], qr(CONFLICT:.*not owned by stow)
=> 'target already exists but is not owned by stow' => 'target already exists but is not owned by stow'
); );
# #
# Replace existing but invalid target # Replace existing but invalid target
# #
reset_state(); $stow = new_Stow();
make_link('file6','../stow/path-does-not-exist'); make_link('file6','../stow/path-does-not-exist');
make_dir('../stow/pkg6'); make_dir('../stow/pkg6');
make_file('../stow/pkg6/file6'); make_file('../stow/pkg6/file6');
eval{ stow_contents('../stow/pkg6', './', '../stow/pkg6'); process_tasks() }; $stow->plan_stow('pkg6');
$stow->process_tasks();
is( is(
readlink('file6'), readlink('file6'),
'../stow/pkg6/file6' '../stow/pkg6/file6'
@ -120,7 +124,7 @@ is(
# Target already exists, is owned by stow, but points to a non-directory # Target already exists, is owned by stow, but points to a non-directory
# (can't unfold) # (can't unfold)
# #
reset_state(); $stow = new_Stow();
make_dir('bin7'); make_dir('bin7');
make_dir('../stow/pkg7a/bin7'); make_dir('../stow/pkg7a/bin7');
@ -128,16 +132,17 @@ make_file('../stow/pkg7a/bin7/node7');
make_link('bin7/node7','../../stow/pkg7a/bin7/node7'); make_link('bin7/node7','../../stow/pkg7a/bin7/node7');
make_dir('../stow/pkg7b/bin7/node7'); make_dir('../stow/pkg7b/bin7/node7');
make_file('../stow/pkg7b/bin7/node7/file7'); make_file('../stow/pkg7b/bin7/node7/file7');
stow_contents('../stow/pkg7b', './', '../stow/pkg7b'); $stow->plan_stow('pkg7b');
like( @conflicts = $stow->get_conflicts();
$Conflicts[-1], qr(CONFLICT:.*existing target is stowed to a different package) like(
$conflicts[-1], qr(CONFLICT:.*existing target is stowed to a different package)
=> 'link to new dir conflicts with existing stowed non-directory' => 'link to new dir conflicts with existing stowed non-directory'
); );
# #
# stowing directories named 0 # stowing directories named 0
# #
reset_state(); $stow = new_Stow();
make_dir('../stow/pkg8a/0'); make_dir('../stow/pkg8a/0');
make_file('../stow/pkg8a/0/file8a'); make_file('../stow/pkg8a/0/file8a');
@ -145,10 +150,10 @@ make_link('0' => '../stow/pkg8a/0'); # emulate stow
make_dir('../stow/pkg8b/0'); make_dir('../stow/pkg8b/0');
make_file('../stow/pkg8b/0/file8b'); make_file('../stow/pkg8b/0/file8b');
stow_contents('../stow/pkg8b', './', '../stow/pkg8b'); $stow->plan_stow('pkg8b');
process_tasks(); $stow->process_tasks();
ok( ok(
scalar(@Conflicts) == 0 && scalar($stow->get_conflicts) == 0 &&
-d '0' && -d '0' &&
readlink('0/file8a') eq '../../stow/pkg8a/0/file8a' && readlink('0/file8a') eq '../../stow/pkg8a/0/file8a' &&
readlink('0/file8b') eq '../../stow/pkg8b/0/file8b' readlink('0/file8b') eq '../../stow/pkg8b/0/file8b'
@ -158,8 +163,7 @@ ok(
# #
# overriding already stowed documentation # overriding already stowed documentation
# #
reset_state(); $stow = new_Stow(override => ['man9', 'info9']);
$Option{'override'} = ['man9', 'info9'];
make_dir('../stow/pkg9a/man9/man1'); make_dir('../stow/pkg9a/man9/man1');
make_file('../stow/pkg9a/man9/man1/file9.1'); make_file('../stow/pkg9a/man9/man1/file9.1');
@ -168,10 +172,10 @@ make_link('man9/man1/file9.1' => '../../../stow/pkg9a/man9/man1/file9.1'); # emu
make_dir('../stow/pkg9b/man9/man1'); make_dir('../stow/pkg9b/man9/man1');
make_file('../stow/pkg9b/man9/man1/file9.1'); make_file('../stow/pkg9b/man9/man1/file9.1');
stow_contents('../stow/pkg9b', './', '../stow/pkg9b'); $stow->plan_stow('pkg9b');
process_tasks(); $stow->process_tasks();
ok( ok(
scalar(@Conflicts) == 0 && scalar($stow->get_conflicts) == 0 &&
readlink('man9/man1/file9.1') eq '../../../stow/pkg9b/man9/man1/file9.1' readlink('man9/man1/file9.1') eq '../../../stow/pkg9b/man9/man1/file9.1'
=> 'overriding existing documentation files' => 'overriding existing documentation files'
); );
@ -179,8 +183,7 @@ ok(
# #
# deferring to already stowed documentation # deferring to already stowed documentation
# #
reset_state(); $stow = new_Stow(defer => ['man10', 'info10']);
$Option{'defer'} = ['man10', 'info10'];
make_dir('../stow/pkg10a/man10/man1'); make_dir('../stow/pkg10a/man10/man1');
make_file('../stow/pkg10a/man10/man1/file10.1'); make_file('../stow/pkg10a/man10/man1/file10.1');
@ -189,14 +192,15 @@ make_link('man10/man1/file10.1' => '../../../stow/pkg10a/man10/man1/file10.1');
make_dir('../stow/pkg10b/man10/man1'); make_dir('../stow/pkg10b/man10/man1');
make_file('../stow/pkg10b/man10/man1/file10.1'); make_file('../stow/pkg10b/man10/man1/file10.1');
stow_contents('../stow/pkg10b', './', '../stow/pkg10b'); $stow->plan_stow('pkg10b');
stderr_like( stderr_like(
sub { process_tasks(); }, sub { $stow->process_tasks(); },
qr/There are no outstanding operations to perform/, qr/There are no outstanding operations to perform/,
'no tasks to process' 'no tasks to process'
); );
ok( ok(
scalar(@Conflicts) == 0 && scalar($stow->get_conflicts) == 0 &&
readlink('man10/man1/file10.1') eq '../../../stow/pkg10a/man10/man1/file10.1' readlink('man10/man1/file10.1') eq '../../../stow/pkg10a/man10/man1/file10.1'
=> 'defer to existing documentation files' => 'defer to existing documentation files'
); );
@ -204,8 +208,7 @@ ok(
# #
# Ignore temp files # Ignore temp files
# #
reset_state(); $stow = new_Stow(ignore => ['~', '\.#.*']);
$Option{'ignore'} = ['~', '\.#.*'];
make_dir('../stow/pkg11/man11/man1'); make_dir('../stow/pkg11/man11/man1');
make_file('../stow/pkg11/man11/man1/file11.1'); make_file('../stow/pkg11/man11/man1/file11.1');
@ -213,10 +216,10 @@ make_file('../stow/pkg11/man11/man1/file11.1~');
make_file('../stow/pkg11/man11/man1/.#file11.1'); make_file('../stow/pkg11/man11/man1/.#file11.1');
make_dir('man11/man1'); make_dir('man11/man1');
stow_contents('../stow/pkg11', './', '../stow/pkg11'); $stow->plan_stow('pkg11');
process_tasks(); $stow->process_tasks();
ok( ok(
scalar(@Conflicts) == 0 && scalar($stow->get_conflicts) == 0 &&
readlink('man11/man1/file11.1') eq '../../../stow/pkg11/man11/man1/file11.1' && readlink('man11/man1/file11.1') eq '../../../stow/pkg11/man11/man1/file11.1' &&
!-e 'man11/man1/file11.1~' && !-e 'man11/man1/file11.1~' &&
!-e 'man11/man1/.#file11.1' !-e 'man11/man1/.#file11.1'
@ -226,17 +229,17 @@ ok(
# #
# stowing links library files # stowing links library files
# #
reset_state(); $stow = new_Stow();
make_dir('../stow/pkg12/lib12/'); make_dir('../stow/pkg12/lib12/');
make_file('../stow/pkg12/lib12/lib.so'); make_file('../stow/pkg12/lib12/lib.so');
make_link('../stow/pkg12/lib12/lib.so.1','lib.so'); make_link('../stow/pkg12/lib12/lib.so.1','lib.so');
make_dir('lib12/'); make_dir('lib12/');
stow_contents('../stow/pkg12', './', '../stow/pkg12'); $stow->plan_stow('pkg12');
process_tasks(); $stow->process_tasks();
ok( ok(
scalar(@Conflicts) == 0 && scalar($stow->get_conflicts) == 0 &&
readlink('lib12/lib.so.1') eq '../../stow/pkg12/lib12/lib.so.1' readlink('lib12/lib.so.1') eq '../../stow/pkg12/lib12/lib.so.1'
=> 'stow links to libraries' => 'stow links to libraries'
); );
@ -244,7 +247,7 @@ ok(
# #
# unfolding to stow links to library files # unfolding to stow links to library files
# #
reset_state(); $stow = new_Stow();
make_dir('../stow/pkg13a/lib13/'); make_dir('../stow/pkg13a/lib13/');
make_file('../stow/pkg13a/lib13/liba.so'); make_file('../stow/pkg13a/lib13/liba.so');
@ -255,10 +258,10 @@ make_dir('../stow/pkg13b/lib13/');
make_file('../stow/pkg13b/lib13/libb.so'); make_file('../stow/pkg13b/lib13/libb.so');
make_link('../stow/pkg13b/lib13/libb.so.1', 'libb.so'); make_link('../stow/pkg13b/lib13/libb.so.1', 'libb.so');
stow_contents('../stow/pkg13b', './', '../stow/pkg13b'); $stow->plan_stow('pkg13b');
process_tasks(); $stow->process_tasks();
ok( ok(
scalar(@Conflicts) == 0 && scalar($stow->get_conflicts) == 0 &&
readlink('lib13/liba.so.1') eq '../../stow/pkg13a/lib13/liba.so.1' && readlink('lib13/liba.so.1') eq '../../stow/pkg13a/lib13/liba.so.1' &&
readlink('lib13/libb.so.1') eq '../../stow/pkg13b/lib13/libb.so.1' readlink('lib13/libb.so.1') eq '../../stow/pkg13b/lib13/libb.so.1'
=> 'unfolding to stow links to libraries' => 'unfolding to stow links to libraries'
@ -267,20 +270,38 @@ ok(
# #
# stowing to stow dir should fail # stowing to stow dir should fail
# #
reset_state(); make_dir('stow');
$Stow_Path= 'stow'; $stow = new_Stow(dir => 'stow');
make_dir('stow/pkg14/stow/pkg15'); make_dir('stow/pkg14/stow/pkg15');
make_file('stow/pkg14/stow/pkg15/node15'); make_file('stow/pkg14/stow/pkg15/node15');
stow_contents('stow/pkg14', '.', 'stow/pkg14'); $stow->plan_stow('pkg14');
stderr_like( stderr_like(
sub { process_tasks(); }, sub { $stow->process_tasks(); },
qr/There are no outstanding operations to perform/, qr/There are no outstanding operations to perform/,
'no tasks to process' 'no tasks to process'
); );
ok( ok(
scalar(@Conflicts) == 0 && scalar($stow->get_conflicts) == 0 &&
! -l 'stow/pkg15' ! -l 'stow/pkg15'
=> "stowing to stow dir should fail" => "stowing to stow dir should fail"
); );
#
# stow a simple tree minimally when cwd isn't target
#
cd('../..');
$stow = new_Stow(dir => 't/stow', target => 't/target');
make_dir('t/stow/pkg16/bin16');
make_file('t/stow/pkg16/bin16/file16');
$stow->plan_stow('pkg16');
$stow->process_tasks();
is($stow->get_conflicts(), 0, 'no conflicts with minimal stow');
is(
readlink('t/target/bin16'),
'../stow/pkg16/bin16',
=> 'minimal stow of a simple tree'
);

View file

@ -7,22 +7,31 @@
use strict; use strict;
use warnings; use warnings;
use Stow;
use Stow::Util qw(parent);
#===== SUBROUTINE =========================================================== sub make_fresh_stow_and_target_dirs {
# Name : reset_state() die "t/ didn't exist; are you running the tests from the root of the tree?\n"
# Purpose : reset internal state machine unless -d 't';
# Parameters: none
# Returns : n/a for my $dir ('t/target', 't/stow') {
# Throws : n/a eval { remove_dir($dir); };
# Comments : none make_dir($dir);
#============================================================================ }
sub reset_state { }
@::Tasks = ();
@::Conflicts = (); sub new_Stow {
%::Link_Task_For = (); my %opts = @_;
%::Dir_Task_For = (); $opts{dir} ||= '../stow';
%::Option = ( testmode => 1 ); $opts{target} ||= '.';
return; $opts{test_mode} = 1;
return new Stow(%opts);
}
sub new_compat_Stow {
my %opts = @_;
$opts{compat} = 1;
return new_Stow(%opts);
} }
#===== SUBROUTINE =========================================================== #===== SUBROUTINE ===========================================================
@ -38,13 +47,13 @@ sub make_link {
my ($target, $source) = @_; my ($target, $source) = @_;
if (-l $target) { if (-l $target) {
my $old_source = readlink join('/',parent($target),$source) my $old_source = readlink join('/', parent($target), $source)
or die "could not read link $target/$source"; or die "could not read link $target/$source";
if ($old_source ne $source) { if ($old_source ne $source) {
die "$target already exists but points elsewhere\n"; die "$target already exists but points elsewhere\n";
} }
} }
elsif (-e $target ) { elsif (-e $target) {
die "$target already exists and is not a link\n"; die "$target already exists and is not a link\n";
} }
else { else {
@ -56,7 +65,7 @@ sub make_link {
#===== SUBROUTINE =========================================================== #===== SUBROUTINE ===========================================================
# Name : make_dir() # Name : make_dir()
# Purpose : create a directory and any requiste parents # Purpose : create a directory and any requisite parents
# Parameters: $dir => path to the new directory # Parameters: $dir => path to the new directory
# Returns : n/a # Returns : n/a
# Throws : fatal error if the directory or any of its parents cannot be # Throws : fatal error if the directory or any of its parents cannot be
@ -174,4 +183,23 @@ sub remove_dir {
return; return;
} }
#===== SUBROUTINE ===========================================================
# Name : cd()
# Purpose : wrapper around chdir
# Parameters: $dir => path to chdir to
# Returns : n/a
# Throws : fatal error if the chdir fails
# Comments : none
#============================================================================
sub cd {
my ($dir) = @_;
chdir $dir or die "Failed to chdir($dir): $!\n";
}
1; 1;
# Local variables:
# mode: perl
# cperl-indent-level: 4
# end:
# vim: ft=perl

View file

@ -4,38 +4,36 @@
# Testing unstow_contents() # Testing unstow_contents()
# #
# load as a library use strict;
BEGIN { use lib qw(.); require "t/util.pm"; require "stow"; } use warnings;
use Test::More tests => 20; use testutil;
use Test::More tests => 21;
use Test::Output; use Test::Output;
use English qw(-no_match_vars); use English qw(-no_match_vars);
### setup make_fresh_stow_and_target_dirs();
eval { remove_dir('t/target'); }; cd('t/target');
eval { remove_dir('t/stow'); };
make_dir('t/target');
make_dir('t/stow');
chdir 't/target';
$Stow_Path= '../stow';
# Note that each of the following tests use a distinct set of files # Note that each of the following tests use a distinct set of files
my $stow;
my @conflicts;
# #
# unstow a simple tree minimally # unstow a simple tree minimally
# #
$stow = new_Stow();
reset_state();
make_dir('../stow/pkg1/bin1'); make_dir('../stow/pkg1/bin1');
make_file('../stow/pkg1/bin1/file1'); make_file('../stow/pkg1/bin1/file1');
make_link('bin1','../stow/pkg1/bin1'); make_link('bin1', '../stow/pkg1/bin1');
unstow_contents('../stow/pkg1','.'); $stow->plan_unstow('pkg1');
process_tasks(); $stow->process_tasks();
ok( ok(
scalar(@Conflicts) == 0 && scalar($stow->get_conflicts) == 0 &&
-f '../stow/pkg1/bin1/file1' && ! -e 'bin1' -f '../stow/pkg1/bin1/file1' && ! -e 'bin1'
=> 'unstow a simple tree' => 'unstow a simple tree'
); );
@ -43,16 +41,16 @@ ok(
# #
# unstow a simple tree from an existing directory # unstow a simple tree from an existing directory
# #
reset_state(); $stow = new_Stow();
make_dir('lib2'); make_dir('lib2');
make_dir('../stow/pkg2/lib2'); make_dir('../stow/pkg2/lib2');
make_file('../stow/pkg2/lib2/file2'); make_file('../stow/pkg2/lib2/file2');
make_link('lib2/file2', '../../stow/pkg2/lib2/file2'); make_link('lib2/file2', '../../stow/pkg2/lib2/file2');
unstow_contents('../stow/pkg2','.'); $stow->plan_unstow('pkg2');
process_tasks(); $stow->process_tasks();
ok( ok(
scalar(@Conflicts) == 0 && scalar($stow->get_conflicts) == 0 &&
-f '../stow/pkg2/lib2/file2' && -d 'lib2' -f '../stow/pkg2/lib2/file2' && -d 'lib2'
=> 'unstow simple tree from a pre-existing directory' => 'unstow simple tree from a pre-existing directory'
); );
@ -60,7 +58,7 @@ ok(
# #
# fold tree after unstowing # fold tree after unstowing
# #
reset_state(); $stow = new_Stow();
make_dir('bin3'); make_dir('bin3');
@ -71,10 +69,10 @@ make_link('bin3/file3a' => '../../stow/pkg3a/bin3/file3a'); # emulate stow
make_dir('../stow/pkg3b/bin3'); make_dir('../stow/pkg3b/bin3');
make_file('../stow/pkg3b/bin3/file3b'); make_file('../stow/pkg3b/bin3/file3b');
make_link('bin3/file3b' => '../../stow/pkg3b/bin3/file3b'); # emulate stow make_link('bin3/file3b' => '../../stow/pkg3b/bin3/file3b'); # emulate stow
unstow_contents('../stow/pkg3b', '.'); $stow->plan_unstow('pkg3b');
process_tasks(); $stow->process_tasks();
ok( ok(
scalar(@Conflicts) == 0 && scalar($stow->get_conflicts) == 0 &&
-l 'bin3' && -l 'bin3' &&
readlink('bin3') eq '../stow/pkg3a/bin3' readlink('bin3') eq '../stow/pkg3a/bin3'
=> 'fold tree after unstowing' => 'fold tree after unstowing'
@ -83,17 +81,17 @@ ok(
# #
# existing link is owned by stow but is invalid so it gets removed anyway # existing link is owned by stow but is invalid so it gets removed anyway
# #
reset_state(); $stow = new_Stow();
make_dir('bin4'); make_dir('bin4');
make_dir('../stow/pkg4/bin4'); make_dir('../stow/pkg4/bin4');
make_file('../stow/pkg4/bin4/file4'); make_file('../stow/pkg4/bin4/file4');
make_link('bin4/file4', '../../stow/pkg4/bin4/does-not-exist'); make_link('bin4/file4', '../../stow/pkg4/bin4/does-not-exist');
unstow_contents('../stow/pkg4', '.'); $stow->plan_unstow('pkg4');
process_tasks(); $stow->process_tasks();
ok( ok(
scalar(@Conflicts) == 0 && scalar($stow->get_conflicts) == 0 &&
! -e 'bin4/file4' ! -e 'bin4/file4'
=> q(remove invalid link owned by stow) => q(remove invalid link owned by stow)
); );
@ -101,20 +99,22 @@ ok(
# #
# Existing link is not owned by stow # Existing link is not owned by stow
# #
reset_state(); $stow = new_Stow();
make_dir('../stow/pkg5/bin5'); make_dir('../stow/pkg5/bin5');
make_link('bin5', '../not-stow'); make_link('bin5', '../not-stow');
unstow_contents('../stow/pkg5', '.'); $stow->plan_unstow('pkg5');
@conflicts = $stow->get_conflicts;
like( like(
$Conflicts[-1], qr(CONFLICT:.*existing target is not owned by stow) $conflicts[-1], qr(CONFLICT:.*existing target is not owned by stow)
=> q(existing link not owned by stow) => q(existing link not owned by stow)
); );
# #
# Target already exists, is owned by stow, but points to a different package # Target already exists, is owned by stow, but points to a different package
# #
reset_state(); $stow = new_Stow();
make_dir('bin6'); make_dir('bin6');
make_dir('../stow/pkg6a/bin6'); make_dir('../stow/pkg6a/bin6');
@ -124,10 +124,10 @@ make_link('bin6/file6', '../../stow/pkg6a/bin6/file6');
make_dir('../stow/pkg6b/bin6'); make_dir('../stow/pkg6b/bin6');
make_file('../stow/pkg6b/bin6/file6'); make_file('../stow/pkg6b/bin6/file6');
unstow_contents('../stow/pkg6b', '.'); $stow->plan_unstow('pkg6b');
ok( ok(
scalar(@Conflicts) == 0 && scalar($stow->get_conflicts) == 0 &&
-l 'bin6/file6' && -l 'bin6/file6' &&
readlink('bin6/file6') eq '../../stow/pkg6a/bin6/file6' readlink('bin6/file6') eq '../../stow/pkg6a/bin6/file6'
=> q(ignore existing link that points to a different package) => q(ignore existing link that points to a different package)
); );
@ -135,24 +135,22 @@ ok(
# #
# Don't unlink anything under the stow directory # Don't unlink anything under the stow directory
# #
reset_state();
make_dir('stow'); # make out stow dir a subdir of target make_dir('stow'); # make out stow dir a subdir of target
$Stow_Path = 'stow'; $stow = new_Stow(dir => 'stow');
# emulate stowing into ourself (bizarre corner case or accident) # emulate stowing into ourself (bizarre corner case or accident)
make_dir('stow/pkg7a/stow/pkg7b'); make_dir('stow/pkg7a/stow/pkg7b');
make_file('stow/pkg7a/stow/pkg7b/file7b'); make_file('stow/pkg7a/stow/pkg7b/file7b');
make_link('stow/pkg7b', '../stow/pkg7a/stow/pkg7b'); make_link('stow/pkg7b', '../stow/pkg7a/stow/pkg7b');
unstow_contents('stow/pkg7b', '.'); $stow->plan_unstow('pkg7b');
stderr_like( stderr_like(
sub { process_tasks(); }, sub { $stow->process_tasks(); },
qr/There are no outstanding operations to perform/, qr/There are no outstanding operations to perform/,
'no tasks to process when unstowing pkg7b' 'no tasks to process when unstowing pkg7b'
); );
ok( ok(
scalar(@Conflicts) == 0 && scalar($stow->get_conflicts) == 0 &&
-l 'stow/pkg7b' && -l 'stow/pkg7b' &&
readlink('stow/pkg7b') eq '../stow/pkg7a/stow/pkg7b' readlink('stow/pkg7b') eq '../stow/pkg7a/stow/pkg7b'
=> q(don't unlink any nodes under the stow directory) => q(don't unlink any nodes under the stow directory)
@ -161,10 +159,7 @@ ok(
# #
# Don't unlink any nodes under another stow directory # Don't unlink any nodes under another stow directory
# #
reset_state(); $stow = new_Stow(dir => 'stow');
make_dir('stow'); # make out stow dir a subdir of target
$Stow_Path = 'stow';
make_dir('stow2'); # make our alternate stow dir a subdir of target make_dir('stow2'); # make our alternate stow dir a subdir of target
make_file('stow2/.stow'); make_file('stow2/.stow');
@ -174,14 +169,14 @@ make_dir('stow/pkg8a/stow2/pkg8b');
make_file('stow/pkg8a/stow2/pkg8b/file8b'); make_file('stow/pkg8a/stow2/pkg8b/file8b');
make_link('stow2/pkg8b', '../stow/pkg8a/stow2/pkg8b'); make_link('stow2/pkg8b', '../stow/pkg8a/stow2/pkg8b');
unstow_contents('stow/pkg8a', '.'); $stow->plan_unstow('pkg8a');
stderr_like( stderr_like(
sub { process_tasks(); }, sub { $stow->process_tasks(); },
qr/There are no outstanding operations to perform/, qr/There are no outstanding operations to perform/,
'no tasks to process when unstowing pkg8a' 'no tasks to process when unstowing pkg8a'
); );
ok( ok(
scalar(@Conflicts) == 0 && scalar($stow->get_conflicts) == 0 &&
-l 'stow2/pkg8b' && -l 'stow2/pkg8b' &&
readlink('stow2/pkg8b') eq '../stow/pkg8a/stow2/pkg8b' readlink('stow2/pkg8b') eq '../stow/pkg8a/stow2/pkg8b'
=> q(don't unlink any nodes under another stow directory) => q(don't unlink any nodes under another stow directory)
@ -190,10 +185,8 @@ ok(
# #
# overriding already stowed documentation # overriding already stowed documentation
# #
reset_state(); $stow = new_Stow(override => ['man9', 'info9']);
make_file('stow/.stow'); make_file('stow/.stow');
$Stow_Path = '../stow';
$Option{'override'} = ['man9', 'info9'];
make_dir('../stow/pkg9a/man9/man1'); make_dir('../stow/pkg9a/man9/man1');
make_file('../stow/pkg9a/man9/man1/file9.1'); make_file('../stow/pkg9a/man9/man1/file9.1');
@ -202,10 +195,10 @@ make_link('man9/man1/file9.1' => '../../../stow/pkg9a/man9/man1/file9.1'); # emu
make_dir('../stow/pkg9b/man9/man1'); make_dir('../stow/pkg9b/man9/man1');
make_file('../stow/pkg9b/man9/man1/file9.1'); make_file('../stow/pkg9b/man9/man1/file9.1');
unstow_contents('../stow/pkg9b', '.'); $stow->plan_unstow('pkg9b');
process_tasks(); $stow->process_tasks();
ok( ok(
scalar(@Conflicts) == 0 && scalar($stow->get_conflicts) == 0 &&
!-l 'man9/man1/file9.1' !-l 'man9/man1/file9.1'
=> 'overriding existing documentation files' => 'overriding existing documentation files'
); );
@ -213,8 +206,7 @@ ok(
# #
# deferring to already stowed documentation # deferring to already stowed documentation
# #
reset_state(); $stow = new_Stow(defer => ['man10', 'info10']);
$Option{'defer'} = ['man10', 'info10'];
make_dir('../stow/pkg10a/man10/man1'); make_dir('../stow/pkg10a/man10/man1');
make_file('../stow/pkg10a/man10/man1/file10a.1'); make_file('../stow/pkg10a/man10/man1/file10a.1');
@ -229,14 +221,14 @@ make_link('man10/man1/file10b.1' => '../../../stow/pkg10b/man10/man1/file10b.1'
make_dir('../stow/pkg10c/man10/man1'); make_dir('../stow/pkg10c/man10/man1');
make_file('../stow/pkg10c/man10/man1/file10a.1'); make_file('../stow/pkg10c/man10/man1/file10a.1');
unstow_contents('../stow/pkg10c', '.'); $stow->plan_unstow('pkg10c');
stderr_like( stderr_like(
sub { process_tasks(); }, sub { $stow->process_tasks(); },
qr/There are no outstanding operations to perform/, qr/There are no outstanding operations to perform/,
'no tasks to process when unstowing pkg10c' 'no tasks to process when unstowing pkg10c'
); );
ok( ok(
scalar(@Conflicts) == 0 && scalar($stow->get_conflicts) == 0 &&
readlink('man10/man1/file10a.1') eq '../../../stow/pkg10a/man10/man1/file10a.1' readlink('man10/man1/file10a.1') eq '../../../stow/pkg10a/man10/man1/file10a.1'
=> 'defer to existing documentation files' => 'defer to existing documentation files'
); );
@ -244,8 +236,7 @@ ok(
# #
# Ignore temp files # Ignore temp files
# #
reset_state(); $stow = new_Stow(ignore => ['~', '\.#.*']);
$Option{'ignore'} = ['~', '\.#.*'];
make_dir('../stow/pkg12/man12/man1'); make_dir('../stow/pkg12/man12/man1');
make_file('../stow/pkg12/man12/man1/file12.1'); make_file('../stow/pkg12/man12/man1/file12.1');
@ -254,10 +245,10 @@ make_file('../stow/pkg12/man12/man1/.#file12.1');
make_dir('man12/man1'); make_dir('man12/man1');
make_link('man12/man1/file12.1' => '../../../stow/pkg12/man12/man1/file12.1'); make_link('man12/man1/file12.1' => '../../../stow/pkg12/man12/man1/file12.1');
unstow_contents('../stow/pkg12', '.'); $stow->plan_unstow('pkg12');
process_tasks(); $stow->process_tasks();
ok( ok(
scalar(@Conflicts) == 0 && scalar($stow->get_conflicts) == 0 &&
!-e 'man12/man1/file12.1' !-e 'man12/man1/file12.1'
=> 'ignore temp files' => 'ignore temp files'
); );
@ -265,15 +256,15 @@ ok(
# #
# Unstow an already unstowed package # Unstow an already unstowed package
# #
reset_state(); $stow = new_Stow();
unstow_contents('../stow/pkg12', '.'); $stow->plan_unstow('pkg12');
stderr_like( stderr_like(
sub { process_tasks(); }, sub { $stow->process_tasks(); },
qr/There are no outstanding operations to perform/, qr/There are no outstanding operations to perform/,
'no tasks to process when unstowing pkg12' 'no tasks to process when unstowing pkg12'
); );
ok( ok(
scalar(@Conflicts) == 0 scalar($stow->get_conflicts) == 0
=> 'unstow already unstowed package pkg12' => 'unstow already unstowed package pkg12'
); );
@ -284,15 +275,15 @@ ok(
eval { remove_dir('t/target'); }; eval { remove_dir('t/target'); };
mkdir('t/target'); mkdir('t/target');
reset_state(); $stow = new_Stow();
unstow_contents('../stow/pkg12', '.'); $stow->plan_unstow('pkg12');
stderr_like( stderr_like(
sub { process_tasks(); }, sub { $stow->process_tasks(); },
qr/There are no outstanding operations to perform/, qr/There are no outstanding operations to perform/,
'no tasks to process when unstowing pkg12 which was never stowed' 'no tasks to process when unstowing pkg12 which was never stowed'
); );
ok( ok(
scalar(@Conflicts) == 0 scalar($stow->get_conflicts) == 0
=> 'unstow never stowed package pkg12' => 'unstow never stowed package pkg12'
); );
@ -301,19 +292,38 @@ ok(
# #
make_file('man12/man1/file12.1'); make_file('man12/man1/file12.1');
reset_state(); $stow = new_Stow();
unstow_contents('../stow/pkg12', '.'); $stow->plan_unstow('pkg12');
stderr_like( stderr_like(
sub { process_tasks(); }, sub { $stow->process_tasks(); },
qr/There are no outstanding operations to perform/, qr/There are no outstanding operations to perform/,
'no tasks to process when unstowing pkg12 for third time' 'no tasks to process when unstowing pkg12 for third time'
); );
@conflicts = $stow->get_conflicts;
ok( ok(
scalar(@Conflicts) == 1 && @conflicts == 1 &&
$Conflicts[0] =~ m!existing target is neither a link nor a directory: man12/man1/file12\.1! $conflicts[0] =~ m!existing target is neither a link nor a directory: man12/man1/file12\.1!
=> 'unstow pkg12 for third time' => 'unstow pkg12 for third time'
); );
#
# unstow a simple tree minimally when cwd isn't target
#
cd('../..');
$stow = new_Stow(dir => 't/stow', target => 't/target');
make_dir('t/stow/pkg13/bin13');
make_file('t/stow/pkg13/bin13/file13');
make_link('t/target/bin13', '../stow/pkg13/bin13');
$stow->plan_unstow('pkg13');
$stow->process_tasks();
ok(
scalar($stow->get_conflicts) == 0 &&
-f 't/stow/pkg13/bin13/file13' && ! -e 't/target/bin13'
=> 'unstow a simple tree'
);
# Todo # Todo
# #

View file

@ -4,38 +4,37 @@
# Testing unstow_contents_orig() # Testing unstow_contents_orig()
# #
# load as a library use strict;
BEGIN { use lib qw(.); require "t/util.pm"; require "stow"; } use warnings;
use Test::More tests => 20; use testutil;
use Test::More tests => 21;
use Test::Output; use Test::Output;
use English qw(-no_match_vars); use English qw(-no_match_vars);
### setup make_fresh_stow_and_target_dirs();
eval { remove_dir('t/target'); }; cd('t/target');
eval { remove_dir('t/stow'); };
make_dir('t/target');
make_dir('t/stow');
chdir 't/target';
$Stow_Path= '../stow';
# Note that each of the following tests use a distinct set of files # Note that each of the following tests use a distinct set of files
my $stow;
my @conflicts;
# #
# unstow a simple tree minimally # unstow a simple tree minimally
# #
reset_state(); $stow = new_compat_Stow();
make_dir('../stow/pkg1/bin1'); make_dir('../stow/pkg1/bin1');
make_file('../stow/pkg1/bin1/file1'); make_file('../stow/pkg1/bin1/file1');
make_link('bin1','../stow/pkg1/bin1'); make_link('bin1', '../stow/pkg1/bin1');
unstow_contents_orig('../stow/pkg1','.'); $stow->plan_unstow('pkg1');
process_tasks(); $stow->process_tasks();
ok( ok(
scalar(@Conflicts) == 0 && scalar($stow->get_conflicts) == 0 &&
-f '../stow/pkg1/bin1/file1' && ! -e 'bin1' -f '../stow/pkg1/bin1/file1' && ! -e 'bin1'
=> 'unstow a simple tree' => 'unstow a simple tree'
); );
@ -43,16 +42,16 @@ ok(
# #
# unstow a simple tree from an existing directory # unstow a simple tree from an existing directory
# #
reset_state(); $stow = new_compat_Stow();
make_dir('lib2'); make_dir('lib2');
make_dir('../stow/pkg2/lib2'); make_dir('../stow/pkg2/lib2');
make_file('../stow/pkg2/lib2/file2'); make_file('../stow/pkg2/lib2/file2');
make_link('lib2/file2', '../../stow/pkg2/lib2/file2'); make_link('lib2/file2', '../../stow/pkg2/lib2/file2');
unstow_contents_orig('../stow/pkg2','.'); $stow->plan_unstow('pkg2');
process_tasks(); $stow->process_tasks();
ok( ok(
scalar(@Conflicts) == 0 && scalar($stow->get_conflicts) == 0 &&
-f '../stow/pkg2/lib2/file2' && -d 'lib2' -f '../stow/pkg2/lib2/file2' && -d 'lib2'
=> 'unstow simple tree from a pre-existing directory' => 'unstow simple tree from a pre-existing directory'
); );
@ -60,7 +59,7 @@ ok(
# #
# fold tree after unstowing # fold tree after unstowing
# #
reset_state(); $stow = new_compat_Stow();
make_dir('bin3'); make_dir('bin3');
@ -71,10 +70,10 @@ make_link('bin3/file3a' => '../../stow/pkg3a/bin3/file3a'); # emulate stow
make_dir('../stow/pkg3b/bin3'); make_dir('../stow/pkg3b/bin3');
make_file('../stow/pkg3b/bin3/file3b'); make_file('../stow/pkg3b/bin3/file3b');
make_link('bin3/file3b' => '../../stow/pkg3b/bin3/file3b'); # emulate stow make_link('bin3/file3b' => '../../stow/pkg3b/bin3/file3b'); # emulate stow
unstow_contents_orig('../stow/pkg3b', '.'); $stow->plan_unstow('pkg3b');
process_tasks(); $stow->process_tasks();
ok( ok(
scalar(@Conflicts) == 0 && scalar($stow->get_conflicts) == 0 &&
-l 'bin3' && -l 'bin3' &&
readlink('bin3') eq '../stow/pkg3a/bin3' readlink('bin3') eq '../stow/pkg3a/bin3'
=> 'fold tree after unstowing' => 'fold tree after unstowing'
@ -83,17 +82,17 @@ ok(
# #
# existing link is owned by stow but is invalid so it gets removed anyway # existing link is owned by stow but is invalid so it gets removed anyway
# #
reset_state(); $stow = new_compat_Stow();
make_dir('bin4'); make_dir('bin4');
make_dir('../stow/pkg4/bin4'); make_dir('../stow/pkg4/bin4');
make_file('../stow/pkg4/bin4/file4'); make_file('../stow/pkg4/bin4/file4');
make_link('bin4/file4', '../../stow/pkg4/bin4/does-not-exist'); make_link('bin4/file4', '../../stow/pkg4/bin4/does-not-exist');
unstow_contents_orig('../stow/pkg4', '.'); $stow->plan_unstow('pkg4');
process_tasks(); $stow->process_tasks();
ok( ok(
scalar(@Conflicts) == 0 && scalar($stow->get_conflicts) == 0 &&
! -e 'bin4/file4' ! -e 'bin4/file4'
=> q(remove invalid link owned by stow) => q(remove invalid link owned by stow)
); );
@ -101,12 +100,12 @@ ok(
# #
# Existing link is not owned by stow # Existing link is not owned by stow
# #
reset_state(); $stow = new_compat_Stow();
make_dir('../stow/pkg5/bin5'); make_dir('../stow/pkg5/bin5');
make_link('bin5', '../not-stow'); make_link('bin5', '../not-stow');
unstow_contents_orig('../stow/pkg5', '.'); $stow->plan_unstow('pkg5');
#like( #like(
# $Conflicts[-1], qr(CONFLICT:.*can't unlink.*not owned by stow) # $Conflicts[-1], qr(CONFLICT:.*can't unlink.*not owned by stow)
# => q(existing link not owned by stow) # => q(existing link not owned by stow)
@ -115,10 +114,11 @@ ok(
-l 'bin5' && readlink('bin5') eq '../not-stow' -l 'bin5' && readlink('bin5') eq '../not-stow'
=> q(existing link not owned by stow) => q(existing link not owned by stow)
); );
# #
# Target already exists, is owned by stow, but points to a different package # Target already exists, is owned by stow, but points to a different package
# #
reset_state(); $stow = new_compat_Stow();
make_dir('bin6'); make_dir('bin6');
make_dir('../stow/pkg6a/bin6'); make_dir('../stow/pkg6a/bin6');
@ -128,9 +128,9 @@ make_link('bin6/file6', '../../stow/pkg6a/bin6/file6');
make_dir('../stow/pkg6b/bin6'); make_dir('../stow/pkg6b/bin6');
make_file('../stow/pkg6b/bin6/file6'); make_file('../stow/pkg6b/bin6/file6');
unstow_contents_orig('../stow/pkg6b', '.'); $stow->plan_unstow('pkg6b');
ok( ok(
scalar(@Conflicts) == 0 && scalar($stow->get_conflicts) == 0 &&
-l 'bin6/file6' && -l 'bin6/file6' &&
readlink('bin6/file6') eq '../../stow/pkg6a/bin6/file6' readlink('bin6/file6') eq '../../stow/pkg6a/bin6/file6'
=> q(ignore existing link that points to a different package) => q(ignore existing link that points to a different package)
@ -139,24 +139,22 @@ ok(
# #
# Don't unlink anything under the stow directory # Don't unlink anything under the stow directory
# #
reset_state();
make_dir('stow'); # make out stow dir a subdir of target make_dir('stow'); # make out stow dir a subdir of target
$Stow_Path = 'stow'; $stow = new_compat_Stow(dir => 'stow');
# emulate stowing into ourself (bizarre corner case or accident) # emulate stowing into ourself (bizarre corner case or accident)
make_dir('stow/pkg7a/stow/pkg7b'); make_dir('stow/pkg7a/stow/pkg7b');
make_file('stow/pkg7a/stow/pkg7b/file7b'); make_file('stow/pkg7a/stow/pkg7b/file7b');
make_link('stow/pkg7b', '../stow/pkg7a/stow/pkg7b'); make_link('stow/pkg7b', '../stow/pkg7a/stow/pkg7b');
unstow_contents_orig('stow/pkg7b', '.'); $stow->plan_unstow('pkg7b');
stderr_like( stderr_like(
sub { process_tasks(); }, sub { $stow->process_tasks(); },
qr/There are no outstanding operations to perform/, qr/There are no outstanding operations to perform/,
'no tasks to process when unstowing pkg7b' 'no tasks to process when unstowing pkg7b'
); );
ok( ok(
scalar(@Conflicts) == 0 && scalar($stow->get_conflicts) == 0 &&
-l 'stow/pkg7b' && -l 'stow/pkg7b' &&
readlink('stow/pkg7b') eq '../stow/pkg7a/stow/pkg7b' readlink('stow/pkg7b') eq '../stow/pkg7a/stow/pkg7b'
=> q(don't unlink any nodes under the stow directory) => q(don't unlink any nodes under the stow directory)
@ -165,10 +163,7 @@ ok(
# #
# Don't unlink any nodes under another stow directory # Don't unlink any nodes under another stow directory
# #
reset_state(); $stow = new_compat_Stow(dir => 'stow');
make_dir('stow'); # make out stow dir a subdir of target
$Stow_Path = 'stow';
make_dir('stow2'); # make our alternate stow dir a subdir of target make_dir('stow2'); # make our alternate stow dir a subdir of target
make_file('stow2/.stow'); make_file('stow2/.stow');
@ -178,14 +173,14 @@ make_dir('stow/pkg8a/stow2/pkg8b');
make_file('stow/pkg8a/stow2/pkg8b/file8b'); make_file('stow/pkg8a/stow2/pkg8b/file8b');
make_link('stow2/pkg8b', '../stow/pkg8a/stow2/pkg8b'); make_link('stow2/pkg8b', '../stow/pkg8a/stow2/pkg8b');
unstow_contents_orig('stow/pkg8a', '.'); $stow->plan_unstow('pkg8a');
stderr_like( stderr_like(
sub { process_tasks(); }, sub { $stow->process_tasks(); },
qr/There are no outstanding operations to perform/, qr/There are no outstanding operations to perform/,
'no tasks to process when unstowing pkg8a' 'no tasks to process when unstowing pkg8a'
); );
ok( ok(
scalar(@Conflicts) == 0 && scalar($stow->get_conflicts) == 0 &&
-l 'stow2/pkg8b' && -l 'stow2/pkg8b' &&
readlink('stow2/pkg8b') eq '../stow/pkg8a/stow2/pkg8b' readlink('stow2/pkg8b') eq '../stow/pkg8a/stow2/pkg8b'
=> q(don't unlink any nodes under another stow directory) => q(don't unlink any nodes under another stow directory)
@ -194,10 +189,8 @@ ok(
# #
# overriding already stowed documentation # overriding already stowed documentation
# #
reset_state(); $stow = new_compat_Stow(override => ['man9', 'info9']);
make_file('stow/.stow'); make_file('stow/.stow');
$Stow_Path = '../stow';
$Option{'override'} = ['man9', 'info9'];
make_dir('../stow/pkg9a/man9/man1'); make_dir('../stow/pkg9a/man9/man1');
make_file('../stow/pkg9a/man9/man1/file9.1'); make_file('../stow/pkg9a/man9/man1/file9.1');
@ -206,10 +199,10 @@ make_link('man9/man1/file9.1' => '../../../stow/pkg9a/man9/man1/file9.1'); # emu
make_dir('../stow/pkg9b/man9/man1'); make_dir('../stow/pkg9b/man9/man1');
make_file('../stow/pkg9b/man9/man1/file9.1'); make_file('../stow/pkg9b/man9/man1/file9.1');
unstow_contents_orig('../stow/pkg9b', '.'); $stow->plan_unstow('pkg9b');
process_tasks(); $stow->process_tasks();
ok( ok(
scalar(@Conflicts) == 0 && scalar($stow->get_conflicts) == 0 &&
!-l 'man9/man1/file9.1' !-l 'man9/man1/file9.1'
=> 'overriding existing documentation files' => 'overriding existing documentation files'
); );
@ -217,8 +210,7 @@ ok(
# #
# deferring to already stowed documentation # deferring to already stowed documentation
# #
reset_state(); $stow = new_compat_Stow(defer => ['man10', 'info10']);
$Option{'defer'} = ['man10', 'info10'];
make_dir('../stow/pkg10a/man10/man1'); make_dir('../stow/pkg10a/man10/man1');
make_file('../stow/pkg10a/man10/man1/file10a.1'); make_file('../stow/pkg10a/man10/man1/file10a.1');
@ -233,14 +225,14 @@ make_link('man10/man1/file10b.1' => '../../../stow/pkg10b/man10/man1/file10b.1'
make_dir('../stow/pkg10c/man10/man1'); make_dir('../stow/pkg10c/man10/man1');
make_file('../stow/pkg10c/man10/man1/file10a.1'); make_file('../stow/pkg10c/man10/man1/file10a.1');
unstow_contents_orig('../stow/pkg10c', '.'); $stow->plan_unstow('pkg10c');
stderr_like( stderr_like(
sub { process_tasks(); }, sub { $stow->process_tasks(); },
qr/There are no outstanding operations to perform/, qr/There are no outstanding operations to perform/,
'no tasks to process when unstowing pkg10c' 'no tasks to process when unstowing pkg10c'
); );
ok( ok(
scalar(@Conflicts) == 0 && scalar($stow->get_conflicts) == 0 &&
readlink('man10/man1/file10a.1') eq '../../../stow/pkg10a/man10/man1/file10a.1' readlink('man10/man1/file10a.1') eq '../../../stow/pkg10a/man10/man1/file10a.1'
=> 'defer to existing documentation files' => 'defer to existing documentation files'
); );
@ -248,8 +240,7 @@ ok(
# #
# Ignore temp files # Ignore temp files
# #
reset_state(); $stow = new_compat_Stow(ignore => ['~', '\.#.*']);
$Option{'ignore'} = ['~', '\.#.*'];
make_dir('../stow/pkg12/man12/man1'); make_dir('../stow/pkg12/man12/man1');
make_file('../stow/pkg12/man12/man1/file12.1'); make_file('../stow/pkg12/man12/man1/file12.1');
@ -258,10 +249,10 @@ make_file('../stow/pkg12/man12/man1/.#file12.1');
make_dir('man12/man1'); make_dir('man12/man1');
make_link('man12/man1/file12.1' => '../../../stow/pkg12/man12/man1/file12.1'); make_link('man12/man1/file12.1' => '../../../stow/pkg12/man12/man1/file12.1');
unstow_contents_orig('../stow/pkg12', '.'); $stow->plan_unstow('pkg12');
process_tasks(); $stow->process_tasks();
ok( ok(
scalar(@Conflicts) == 0 && scalar($stow->get_conflicts) == 0 &&
!-e 'man12/man1/file12.1' !-e 'man12/man1/file12.1'
=> 'ignore temp files' => 'ignore temp files'
); );
@ -269,15 +260,15 @@ ok(
# #
# Unstow an already unstowed package # Unstow an already unstowed package
# #
reset_state(); $stow = new_compat_Stow();
unstow_contents_orig('../stow/pkg12', '.'); $stow->plan_unstow('pkg12');
stderr_like( stderr_like(
sub { process_tasks(); }, sub { $stow->process_tasks(); },
qr/There are no outstanding operations to perform/, qr/There are no outstanding operations to perform/,
'no tasks to process when unstowing pkg12' 'no tasks to process when unstowing pkg12'
); );
ok( ok(
scalar(@Conflicts) == 0 scalar($stow->get_conflicts) == 0
=> 'unstow already unstowed package pkg12' => 'unstow already unstowed package pkg12'
); );
@ -288,15 +279,15 @@ ok(
eval { remove_dir('t/target'); }; eval { remove_dir('t/target'); };
mkdir('t/target'); mkdir('t/target');
reset_state(); $stow = new_compat_Stow();
unstow_contents_orig('../stow/pkg12', '.'); $stow->plan_unstow('pkg12');
stderr_like( stderr_like(
sub { process_tasks(); }, sub { $stow->process_tasks(); },
qr/There are no outstanding operations to perform/, qr/There are no outstanding operations to perform/,
'no tasks to process when unstowing pkg12 which was never stowed' 'no tasks to process when unstowing pkg12 which was never stowed'
); );
ok( ok(
scalar(@Conflicts) == 0 scalar($stow->get_conflicts) == 0
=> 'unstow never stowed package pkg12' => 'unstow never stowed package pkg12'
); );
@ -305,19 +296,38 @@ ok(
# #
make_file('man12/man1/file12.1'); make_file('man12/man1/file12.1');
reset_state(); $stow = new_compat_Stow();
unstow_contents('../stow/pkg12', '.'); $stow->plan_unstow('pkg12');
stderr_like( stderr_like(
sub { process_tasks(); }, sub { $stow->process_tasks(); },
qr/There are no outstanding operations to perform/, qr/There are no outstanding operations to perform/,
'no tasks to process when unstowing pkg12 for third time' 'no tasks to process when unstowing pkg12 for third time'
); );
@conflicts = $stow->get_conflicts;
ok( ok(
scalar(@Conflicts) == 1 && @conflicts == 1 &&
$Conflicts[0] =~ m!existing target is neither a link nor a directory: man12/man1/file12\.1! $conflicts[0] =~ m!existing target is neither a link nor a directory: man12/man1/file12\.1!
=> 'unstow pkg12 for third time' => 'unstow pkg12 for third time'
); );
#
# unstow a simple tree minimally when cwd isn't target
#
cd('../..');
$stow = new_Stow(dir => 't/stow', target => 't/target');
make_dir('t/stow/pkg13/bin13');
make_file('t/stow/pkg13/bin13/file13');
make_link('t/target/bin13', '../stow/pkg13/bin13');
$stow->plan_unstow('pkg13');
$stow->process_tasks();
ok(
scalar($stow->get_conflicts) == 0 &&
-f 't/stow/pkg13/bin13/file13' && ! -e 't/target/bin13'
=> 'unstow a simple tree'
);
# Todo # Todo
# #