Initial Import
This commit is contained in:
commit
38dcdcb08c
42 changed files with 24923 additions and 0 deletions
115
t/chkstow.t
Executable file
115
t/chkstow.t
Executable file
|
@ -0,0 +1,115 @@
|
|||
#!/usr/local/bin/perl
|
||||
|
||||
#
|
||||
# Testing cleanup_invalid_links()
|
||||
#
|
||||
|
||||
# load as a library
|
||||
BEGIN {
|
||||
use lib qw(.);
|
||||
require "t/util.pm";
|
||||
require "chkstow";
|
||||
}
|
||||
|
||||
use Test::More tests => 7;
|
||||
use Test::Output;
|
||||
use English qw(-no_match_vars);
|
||||
|
||||
### setup
|
||||
eval { remove_dir('t/target'); };
|
||||
make_dir('t/target');
|
||||
|
||||
chdir 't/target';
|
||||
|
||||
# setup stow directory
|
||||
make_dir('stow');
|
||||
make_file('stow/.stow');
|
||||
# perl
|
||||
make_dir('stow/perl/bin');
|
||||
make_file('stow/perl/bin/perl');
|
||||
make_file('stow/perl/bin/a2p');
|
||||
make_dir('stow/perl/info');
|
||||
make_file('stow/perl/info/perl');
|
||||
make_dir('stow/perl/lib/perl');
|
||||
make_dir('stow/perl/man/man1');
|
||||
make_file('stow/perl/man/man1/perl.1');
|
||||
# emacs
|
||||
make_dir('stow/emacs/bin');
|
||||
make_file('stow/emacs/bin/emacs');
|
||||
make_file('stow/emacs/bin/etags');
|
||||
make_dir('stow/emacs/info');
|
||||
make_file('stow/emacs/info/emacs');
|
||||
make_dir('stow/emacs/libexec/emacs');
|
||||
make_dir('stow/emacs/man/man1');
|
||||
make_file('stow/emacs/man/man1/emacs.1');
|
||||
|
||||
#setup target directory
|
||||
make_dir('bin');
|
||||
make_link('bin/a2p', '../stow/perl/bin/a2p');
|
||||
make_link('bin/emacs', '../stow/emacs/bin/emacs');
|
||||
make_link('bin/etags', '../stow/emacs/bin/etags');
|
||||
make_link('bin/perl', '../stow/perl/bin/perl');
|
||||
|
||||
make_dir('info');
|
||||
make_link('info/emacs', '../stow/emacs/info/emacs');
|
||||
make_link('info/perl', '../stow/perl/info/perl');
|
||||
|
||||
make_link('lib', 'stow/perl/lib');
|
||||
make_link('libexec', 'stow/emacs/libexec');
|
||||
|
||||
make_dir('man');
|
||||
make_dir('man/man1');
|
||||
make_link('man/man1/emacs', '../../stow/emacs/man/man1/emacs.1');
|
||||
make_link('man/man1/perl', '../../stow/perl/man/man1/perl.1');
|
||||
|
||||
sub run_chkstow() {
|
||||
process_options();
|
||||
check_stow();
|
||||
}
|
||||
|
||||
local @ARGV = ('-t', '.', '-b',);
|
||||
stderr_like(
|
||||
\&run_chkstow,
|
||||
qr{\Askipping .*stow.*\z}xms,
|
||||
"Skip directories containing .stow");
|
||||
|
||||
# squelch warn so that check_stow doesn't carp about skipping .stow all the time
|
||||
$SIG{'__WARN__'} = sub { };
|
||||
|
||||
@ARGV = ('-t', '.', '-l',);
|
||||
stdout_like(
|
||||
\&run_chkstow,
|
||||
qr{emacs$perl$stow}xms,
|
||||
"List packages");
|
||||
|
||||
@ARGV = ('-t', '.', '-b',);
|
||||
stdout_like(
|
||||
\&run_chkstow,
|
||||
qr{\A\z}xms,
|
||||
"No bogus links exist");
|
||||
|
||||
@ARGV = ('-t', '.', '-a',);
|
||||
stdout_like(
|
||||
\&run_chkstow,
|
||||
qr{\A\z}xms,
|
||||
"No aliens exist");
|
||||
|
||||
# Create an alien
|
||||
make_file('bin/alien');
|
||||
@ARGV = ('-t', '.', '-a',);
|
||||
stdout_like(
|
||||
\&run_chkstow,
|
||||
qr{Unstowed\ file:\ ./bin/alien}xms,
|
||||
"Aliens exist");
|
||||
|
||||
make_link('bin/link', 'ireallyhopethisfiledoesn/t.exist');
|
||||
@ARGV = ('-t', '.', '-b',);
|
||||
stdout_like(
|
||||
\&run_chkstow,
|
||||
qr{Bogus\ link:\ ./bin/link}xms,
|
||||
"Bogus links exist");
|
||||
|
||||
@ARGV = ('-b',);
|
||||
process_options();
|
||||
ok($Target == q{/usr/local},
|
||||
"Default target is /usr/local/");
|
92
t/cleanup_invalid_links.t
Normal file
92
t/cleanup_invalid_links.t
Normal file
|
@ -0,0 +1,92 @@
|
|||
#!/usr/local/bin/perl
|
||||
|
||||
#
|
||||
# Testing cleanup_invalid_links()
|
||||
#
|
||||
|
||||
# load as a library
|
||||
BEGIN { use lib qw(.); require "t/util.pm"; require "stow"; }
|
||||
|
||||
use Test::More tests => 3;
|
||||
use English qw(-no_match_vars);
|
||||
|
||||
# local utility
|
||||
sub reset_state {
|
||||
@Tasks = ();
|
||||
@Conflicts = ();
|
||||
%Link_Task_For = ();
|
||||
%Dir_Task_For = ();
|
||||
%Options = ();
|
||||
return;
|
||||
}
|
||||
|
||||
### setup
|
||||
eval { remove_dir('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
|
||||
|
||||
#
|
||||
# nothing to clean in a simple tree
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 1;
|
||||
|
||||
make_dir('../stow/pkg1/bin1');
|
||||
make_file('../stow/pkg1/bin1/file1');
|
||||
make_link('bin1','../stow/pkg1/bin1');
|
||||
|
||||
cleanup_invalid_links('./');
|
||||
is(
|
||||
scalar @Tasks, 0
|
||||
=> 'nothing to clean'
|
||||
);
|
||||
|
||||
#
|
||||
# cleanup a bad link in a simple tree
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('bin2');
|
||||
make_dir('../stow/pkg2/bin2');
|
||||
make_file('../stow/pkg2/bin2/file2a');
|
||||
make_link('bin2/file2a','../../stow/pkg2/bin2/file2a');
|
||||
make_link('bin2/file2b','../../stow/pkg2/bin2/file2b');
|
||||
|
||||
cleanup_invalid_links('bin2');
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
scalar @Tasks == 1 &&
|
||||
$Link_Task_For{'bin2/file2b'}->{'action'} eq 'remove'
|
||||
=> '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
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('bin3');
|
||||
make_dir('../stow/pkg3/bin3');
|
||||
make_file('../stow/pkg3/bin3/file3a');
|
||||
make_link('bin3/file3a','../../stow/pkg3/bin3/file3a');
|
||||
make_link('bin3/file3b','../../empty');
|
||||
|
||||
cleanup_invalid_links('bin3');
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
scalar @Tasks == 0
|
||||
=> 'dont cleanup a bad link not owned by stow'
|
||||
);
|
||||
|
||||
|
22
t/defer.t
Normal file
22
t/defer.t
Normal file
|
@ -0,0 +1,22 @@
|
|||
#!/usr/local/bin/perl
|
||||
|
||||
#
|
||||
# Testing defer().
|
||||
#
|
||||
|
||||
# load as a library
|
||||
BEGIN { use lib qw(. ..); require "stow"; }
|
||||
|
||||
use Test::More tests => 4;
|
||||
|
||||
$Option{'defer'} = [ 'man' ];
|
||||
ok(defer('man/man1/file.1') => 'simple success');
|
||||
|
||||
$Option{'defer'} = [ 'lib' ];
|
||||
ok(!defer('man/man1/file.1') => 'simple failure');
|
||||
|
||||
$Option{'defer'} = [ 'lib', 'man', 'share' ];
|
||||
ok(defer('man/man1/file.1') => 'complex success');
|
||||
|
||||
$Option{'defer'} = [ 'lib', 'man', 'share' ];
|
||||
ok(!defer('bin/file') => 'complex failure');
|
204
t/examples.t
Normal file
204
t/examples.t
Normal file
|
@ -0,0 +1,204 @@
|
|||
#!/usr/local/bin/perl
|
||||
|
||||
#
|
||||
# Testing examples from the documentation
|
||||
#
|
||||
|
||||
# load as a library
|
||||
BEGIN { use lib qw(.); require "t/util.pm"; require "stow"; }
|
||||
|
||||
use Test::More tests => 4;
|
||||
use English qw(-no_match_vars);
|
||||
|
||||
# local utility
|
||||
sub reset_state {
|
||||
@Tasks = ();
|
||||
@Conflicts = ();
|
||||
%Link_Task_For = ();
|
||||
%Dir_Task_For = ();
|
||||
%Options = ();
|
||||
return;
|
||||
}
|
||||
|
||||
### setup
|
||||
eval { remove_dir('t/target'); };
|
||||
make_dir('t/target/stow');
|
||||
|
||||
chdir 't/target';
|
||||
$Stow_Path= 'stow';
|
||||
|
||||
## set up some fake packages to stow
|
||||
|
||||
# perl
|
||||
make_dir('stow/perl/bin');
|
||||
make_file('stow/perl/bin/perl');
|
||||
make_file('stow/perl/bin/a2p');
|
||||
make_dir('stow/perl/info');
|
||||
make_file('stow/perl/info/perl');
|
||||
make_dir('stow/perl/lib/perl');
|
||||
make_dir('stow/perl/man/man1');
|
||||
make_file('stow/perl/man/man1/perl.1');
|
||||
|
||||
# emacs
|
||||
make_dir('stow/emacs/bin');
|
||||
make_file('stow/emacs/bin/emacs');
|
||||
make_file('stow/emacs/bin/etags');
|
||||
make_dir('stow/emacs/info');
|
||||
make_file('stow/emacs/info/emacs');
|
||||
make_dir('stow/emacs/libexec/emacs');
|
||||
make_dir('stow/emacs/man/man1');
|
||||
make_file('stow/emacs/man/man1/emacs.1');
|
||||
|
||||
#
|
||||
# stow perl into an empty target
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('stow/perl/bin');
|
||||
make_file('stow/perl/bin/perl');
|
||||
make_file('stow/perl/bin/a2p');
|
||||
make_dir('stow/perl/info');
|
||||
make_dir('stow/perl/lib/perl');
|
||||
make_dir('stow/perl/man/man1');
|
||||
make_file('stow/perl/man/man1/perl.1');
|
||||
|
||||
stow_contents('stow/perl','./','stow/perl');
|
||||
process_tasks();
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
-l 'bin' && -l 'info' && -l 'lib' && -l 'man' &&
|
||||
readlink('bin') eq 'stow/perl/bin' &&
|
||||
readlink('info') eq 'stow/perl/info' &&
|
||||
readlink('lib') eq 'stow/perl/lib' &&
|
||||
readlink('man') eq 'stow/perl/man'
|
||||
=> 'stow perl into an empty target'
|
||||
);
|
||||
|
||||
|
||||
#
|
||||
# stow perl into a non-empty target
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
# clean up previous stow
|
||||
remove_link('bin');
|
||||
remove_link('info');
|
||||
remove_link('lib');
|
||||
remove_link('man');
|
||||
|
||||
make_dir('bin');
|
||||
make_dir('lib');
|
||||
make_dir('man/man1');
|
||||
|
||||
stow_contents('stow/perl','./','stow/perl');
|
||||
process_tasks();
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
-d 'bin' && -d 'lib' && -d 'man' && -d 'man/man1' &&
|
||||
-l 'info' && -l 'bin/perl' && -l 'bin/a2p' &&
|
||||
-l 'lib/perl' && -l 'man/man1/perl.1' &&
|
||||
readlink('info') eq 'stow/perl/info' &&
|
||||
readlink('bin/perl') eq '../stow/perl/bin/perl' &&
|
||||
readlink('bin/a2p') eq '../stow/perl/bin/a2p' &&
|
||||
readlink('lib/perl') eq '../stow/perl/lib/perl' &&
|
||||
readlink('man/man1/perl.1') eq '../../stow/perl/man/man1/perl.1'
|
||||
=> 'stow perl into a non-empty target'
|
||||
);
|
||||
|
||||
|
||||
#
|
||||
# Install perl into an empty target and then install emacs
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
# clean up previous stow
|
||||
remove_link('info');
|
||||
remove_dir('bin');
|
||||
remove_dir('lib');
|
||||
remove_dir('man');
|
||||
|
||||
stow_contents('stow/perl', './','stow/perl');
|
||||
stow_contents('stow/emacs','./','stow/emacs');
|
||||
process_tasks();
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
-d 'bin' &&
|
||||
-l 'bin/perl' &&
|
||||
-l 'bin/emacs' &&
|
||||
-l 'bin/a2p' &&
|
||||
-l 'bin/etags' &&
|
||||
readlink('bin/perl') eq '../stow/perl/bin/perl' &&
|
||||
readlink('bin/a2p') eq '../stow/perl/bin/a2p' &&
|
||||
readlink('bin/emacs') eq '../stow/emacs/bin/emacs' &&
|
||||
readlink('bin/etags') eq '../stow/emacs/bin/etags' &&
|
||||
|
||||
-d 'info' &&
|
||||
-l 'info/perl' &&
|
||||
-l 'info/emacs' &&
|
||||
readlink('info/perl') eq '../stow/perl/info/perl' &&
|
||||
readlink('info/emacs') eq '../stow/emacs/info/emacs' &&
|
||||
|
||||
-d 'man' &&
|
||||
-d 'man/man1' &&
|
||||
-l 'man/man1/perl.1' &&
|
||||
-l 'man/man1/emacs.1' &&
|
||||
readlink('man/man1/perl.1') eq '../../stow/perl/man/man1/perl.1' &&
|
||||
readlink('man/man1/emacs.1') eq '../../stow/emacs/man/man1/emacs.1' &&
|
||||
|
||||
-l 'lib' &&
|
||||
-l 'libexec' &&
|
||||
readlink('lib') eq 'stow/perl/lib' &&
|
||||
readlink('libexec') eq 'stow/emacs/libexec' &&
|
||||
1
|
||||
=> 'stow perl into an empty target, then stow emacs'
|
||||
);
|
||||
|
||||
#
|
||||
# BUG 1:
|
||||
# 1. stowing a package with an empty directory
|
||||
# 2. stow another package with the same directory but non empty
|
||||
# 3. unstow the second package
|
||||
# Q. the original empty directory should remain
|
||||
# behaviour is the same as if the empty directory had nothing to do with stow
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('stow/pkg1a/bin1');
|
||||
make_dir('stow/pkg1b/bin1');
|
||||
make_file('stow/pkg1b/bin1/file1b');
|
||||
|
||||
stow_contents('stow/pkg1a', './', 'stow/pkg1a');
|
||||
stow_contents('stow/pkg1b', './', 'stow/pkg1b');
|
||||
unstow_contents('stow/pkg1b', './', 'stow/pkg1b');
|
||||
process_tasks();
|
||||
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
-d 'bin1'
|
||||
=> 'bug 1: stowing empty dirs'
|
||||
);
|
||||
|
||||
|
||||
#
|
||||
# BUG 2: split open tree-folding symlinks pointing inside different stow
|
||||
# directories
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('stow2a/pkg2a/bin2');
|
||||
make_file('stow2a/pkg2a/bin2/file2a');
|
||||
make_file('stow2a/.stow');
|
||||
make_dir('stow2b/pkg2b/bin2');
|
||||
make_file('stow2b/pkg2b/bin2/file2b');
|
||||
make_file('stow2b/.stow');
|
||||
|
||||
stow_contents('stow2a/pkg2a','./', 'stow2a/pkg2a');
|
||||
stow_contents('stow2b/pkg2b','./', 'stow2b/pkg2b');
|
||||
process_tasks();
|
||||
|
||||
## Finish this test
|
51
t/find_stowed_path.t
Normal file
51
t/find_stowed_path.t
Normal file
|
@ -0,0 +1,51 @@
|
|||
#!/usr/local/bin/perl
|
||||
|
||||
#
|
||||
# Testing find_stowed_path()
|
||||
#
|
||||
|
||||
BEGIN { require "t/util.pm"; require "stow"; }
|
||||
|
||||
use Test::More tests => 5;
|
||||
|
||||
eval { remove_dir('t/target'); };
|
||||
eval { remove_dir('t/stow'); };
|
||||
make_dir('t/target');
|
||||
make_dir('t/stow');
|
||||
|
||||
$Stow_Path = 't/stow';
|
||||
is(
|
||||
find_stowed_path('t/target/a/b/c', '../../../stow/a/b/c'),
|
||||
't/stow/a/b/c',
|
||||
=> 'from root'
|
||||
);
|
||||
|
||||
$Stow_Path = '../stow';
|
||||
is(
|
||||
find_stowed_path('a/b/c','../../../stow/a/b/c'),
|
||||
'../stow/a/b/c',
|
||||
=> 'from target directory'
|
||||
);
|
||||
|
||||
$Stow_Path = 't/target/stow';
|
||||
|
||||
is(
|
||||
find_stowed_path('t/target/a/b/c', '../../stow/a/b/c'),
|
||||
't/target/stow/a/b/c',
|
||||
=> 'stow is subdir of target directory'
|
||||
);
|
||||
|
||||
is(
|
||||
find_stowed_path('t/target/a/b/c','../../empty'),
|
||||
'',
|
||||
=> 'target is not stowed'
|
||||
);
|
||||
|
||||
make_dir('t/target/stow2');
|
||||
make_file('t/target/stow2/.stow');
|
||||
|
||||
is(
|
||||
find_stowed_path('t/target/a/b/c','../../stow2/a/b/c'),
|
||||
't/target/stow2/a/b/c'
|
||||
=> q(detect alternate stow directory)
|
||||
);
|
74
t/foldable.t
Normal file
74
t/foldable.t
Normal file
|
@ -0,0 +1,74 @@
|
|||
#!/usr/local/bin/perl
|
||||
|
||||
#
|
||||
# Testing foldable()
|
||||
#
|
||||
|
||||
# load as a library
|
||||
BEGIN { use lib qw(.); require "t/util.pm"; require "stow"; }
|
||||
|
||||
use Test::More tests => 4;
|
||||
use English qw(-no_match_vars);
|
||||
|
||||
### setup
|
||||
# be very careful with these
|
||||
eval { remove_dir('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
|
||||
|
||||
#
|
||||
# can fold a simple tree
|
||||
#
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('../stow/pkg1/bin1');
|
||||
make_file('../stow/pkg1/bin1/file1');
|
||||
make_dir('bin1');
|
||||
make_link('bin1/file1','../../stow/pkg1/bin1/file1');
|
||||
|
||||
is( foldable('bin1'), '../stow/pkg1/bin1' => q(can fold a simple tree) );
|
||||
|
||||
#
|
||||
# can't fold an empty directory
|
||||
#
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('../stow/pkg2/bin2');
|
||||
make_file('../stow/pkg2/bin2/file2');
|
||||
make_dir('bin2');
|
||||
|
||||
is( foldable('bin2'), '' => q(can't fold an empty directory) );
|
||||
|
||||
#
|
||||
# can't fold if dir contains a non-link
|
||||
#
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('../stow/pkg3/bin3');
|
||||
make_file('../stow/pkg3/bin3/file3');
|
||||
make_dir('bin3');
|
||||
make_link('bin3/file3','../../stow/pkg3/bin3/file3');
|
||||
make_file('bin3/non-link');
|
||||
|
||||
is( foldable('bin3'), '' => q(can't fold a dir containing non-links) );
|
||||
|
||||
#
|
||||
# can't fold if links point to different directories
|
||||
#
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('bin4');
|
||||
make_dir('../stow/pkg4a/bin4');
|
||||
make_file('../stow/pkg4a/bin4/file4a');
|
||||
make_link('bin4/file4a','../../stow/pkg4a/bin4/file4a');
|
||||
make_dir('../stow/pkg4b/bin4');
|
||||
make_file('../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) );
|
89
t/join_paths.t
Normal file
89
t/join_paths.t
Normal file
|
@ -0,0 +1,89 @@
|
|||
#!/usr/local/bin/perl
|
||||
|
||||
#
|
||||
# Testing join_paths();
|
||||
#
|
||||
|
||||
# load as a library
|
||||
BEGIN { use lib qw(. ..); require "stow"; }
|
||||
|
||||
use Test::More tests => 13;
|
||||
|
||||
is(
|
||||
join_paths('a/b/c', 'd/e/f'),
|
||||
'a/b/c/d/e/f',
|
||||
=> 'simple'
|
||||
);
|
||||
|
||||
is(
|
||||
join_paths('/a/b/c', '/d/e/f'),
|
||||
'/a/b/c/d/e/f',
|
||||
=> 'leading /'
|
||||
);
|
||||
|
||||
is(
|
||||
join_paths('/a/b/c/', '/d/e/f/'),
|
||||
'/a/b/c/d/e/f',
|
||||
=> 'trailing /'
|
||||
);
|
||||
|
||||
is(
|
||||
join_paths('///a/b///c//', '/d///////e/f'),
|
||||
'/a/b/c/d/e/f',
|
||||
=> 'mltiple /\'s'
|
||||
);
|
||||
|
||||
is(
|
||||
join_paths('', 'a/b/c'),
|
||||
'a/b/c',
|
||||
=> 'first empty'
|
||||
);
|
||||
|
||||
is(
|
||||
join_paths('a/b/c', ''),
|
||||
'a/b/c',
|
||||
=> 'second empty'
|
||||
);
|
||||
|
||||
is(
|
||||
join_paths('/', 'a/b/c'),
|
||||
'/a/b/c',
|
||||
=> 'first is /'
|
||||
);
|
||||
|
||||
is(
|
||||
join_paths('a/b/c', '/'),
|
||||
'a/b/c',
|
||||
=> 'second is /'
|
||||
);
|
||||
|
||||
is(
|
||||
join_paths('///a/b///c//', '/d///////e/f'),
|
||||
'/a/b/c/d/e/f',
|
||||
=> 'multiple /\'s'
|
||||
);
|
||||
|
||||
|
||||
is(
|
||||
join_paths('../a1/b1/../c1/', '/a2/../b2/e2'),
|
||||
'../a1/c1/b2/e2',
|
||||
=> 'simple deref ".."'
|
||||
);
|
||||
|
||||
is(
|
||||
join_paths('../a1/b1/../c1/d1/e1', '../a2/../b2/c2/d2/../e2'),
|
||||
'../a1/c1/d1/b2/c2/e2',
|
||||
=> 'complex deref ".."'
|
||||
);
|
||||
|
||||
is(
|
||||
join_paths('../a1/../../c1', 'a2/../../'),
|
||||
'../..',
|
||||
=> 'too many ".."'
|
||||
);
|
||||
|
||||
is(
|
||||
join_paths('./a1', '../../a2'),
|
||||
'../a2',
|
||||
=> 'drop any "./"'
|
||||
);
|
41
t/parent.t
Normal file
41
t/parent.t
Normal file
|
@ -0,0 +1,41 @@
|
|||
#!/usr/local/bin/perl
|
||||
|
||||
#
|
||||
# Testing parent()
|
||||
#
|
||||
|
||||
# load as a library
|
||||
BEGIN { use lib qw(. ..); require "stow"; }
|
||||
|
||||
use Test::More tests => 5;
|
||||
|
||||
is(
|
||||
parent('a/b/c'),
|
||||
'a/b',
|
||||
=> 'no leading or trailing /'
|
||||
);
|
||||
|
||||
is(
|
||||
parent('/a/b/c'),
|
||||
'/a/b',
|
||||
=> 'leading /'
|
||||
);
|
||||
|
||||
is(
|
||||
parent('a/b/c/'),
|
||||
'a/b',
|
||||
=> 'trailing /'
|
||||
);
|
||||
|
||||
is(
|
||||
parent('/////a///b///c///'),
|
||||
'/a/b',
|
||||
=> 'multiple /'
|
||||
);
|
||||
|
||||
is (
|
||||
parent('a'),
|
||||
''
|
||||
=> 'empty parent'
|
||||
);
|
||||
|
41
t/relative_path.t
Normal file
41
t/relative_path.t
Normal file
|
@ -0,0 +1,41 @@
|
|||
#!/usr/local/bin/perl
|
||||
|
||||
#
|
||||
# Testing relative_path();
|
||||
#
|
||||
|
||||
# load as a library
|
||||
BEGIN { use lib qw(. ..); require "stow"; }
|
||||
|
||||
use Test::More tests => 5;
|
||||
|
||||
is(
|
||||
relative_path('a/b/c', 'a/b/d'),
|
||||
'../d',
|
||||
=> 'diferent branches'
|
||||
);
|
||||
|
||||
is(
|
||||
relative_path('/a/b/c', '/a/b/c/d'),
|
||||
'd',
|
||||
=> 'lower same branch'
|
||||
);
|
||||
|
||||
is(
|
||||
relative_path('a/b/c', 'a/b'),
|
||||
'..',
|
||||
=> 'higher, same branch'
|
||||
);
|
||||
|
||||
is(
|
||||
relative_path('/a/b/c', '/d/e/f'),
|
||||
'../../../d/e/f',
|
||||
=> 'common parent is /'
|
||||
);
|
||||
|
||||
is(
|
||||
relative_path('///a//b//c////', '/a////b/c/d////'),
|
||||
'd',
|
||||
=> 'extra /\'s '
|
||||
);
|
||||
|
97
t/stow.t
Normal file
97
t/stow.t
Normal file
|
@ -0,0 +1,97 @@
|
|||
#!/usr/local/bin/perl
|
||||
|
||||
#
|
||||
# Testing core application
|
||||
#
|
||||
|
||||
# load as a library
|
||||
BEGIN { use lib qw(.); require "t/util.pm"; require "stow"; }
|
||||
|
||||
use Test::More tests => 10;
|
||||
|
||||
local @ARGV = (
|
||||
'-v',
|
||||
'-d t/stow',
|
||||
'-t t/target',
|
||||
'dummy'
|
||||
);
|
||||
|
||||
### setup
|
||||
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';
|
||||
ok eval {set_stow_path(); 1} => 'set stow path';
|
||||
|
||||
is($Stow_Path,"../stow" => 'stow dir');
|
||||
is_deeply(\@Pkgs_To_Stow, [ 'dummy' ] => 'default to stow');
|
||||
|
||||
|
||||
#
|
||||
# Check mixed up package options
|
||||
#
|
||||
%Option=();
|
||||
local @ARGV = (
|
||||
'-v',
|
||||
'-D', 'd1', 'd2',
|
||||
'-S', 's1',
|
||||
'-R', 'r1',
|
||||
'-D', 'd3',
|
||||
'-S', 's2', 's3',
|
||||
'-R', 'r2',
|
||||
);
|
||||
|
||||
@Pkgs_To_Stow = ();
|
||||
@Pkgs_To_Delete = ();
|
||||
process_options();
|
||||
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
|
||||
#
|
||||
%Option=();
|
||||
local @ARGV = (
|
||||
'--defer=man',
|
||||
'--defer=info'
|
||||
);
|
||||
process_options();
|
||||
is_deeply($Option{'defer'}, [ qr(\Aman), qr(\Ainfo) ] => 'defer man and info');
|
||||
|
||||
#
|
||||
# Check setting override paths
|
||||
#
|
||||
%Option=();
|
||||
local @ARGV = (
|
||||
'--override=man',
|
||||
'--override=info'
|
||||
);
|
||||
process_options();
|
||||
is_deeply($Option{'override'}, [qr(\Aman), qr(\Ainfo)] => 'override man and info');
|
||||
|
||||
#
|
||||
# Check stripping any matched quotes
|
||||
#
|
||||
%Option=();
|
||||
local @ARGV = (
|
||||
"--override='man'",
|
||||
'--override="info"',
|
||||
);
|
||||
process_options();
|
||||
is_deeply($Option{'override'}, [qr(\Aman), qr(\Ainfo)] => 'strip shell quoting');
|
||||
|
||||
#
|
||||
# Check setting ignored paths
|
||||
#
|
||||
%Option=();
|
||||
local @ARGV = (
|
||||
'--ignore="~"',
|
||||
'--ignore="\.#.*'
|
||||
);
|
||||
process_options();
|
||||
is_deeply($Option{'ignore'}, [ qr(~\z), qr(\.#.*\z) ] => 'ignore temp files');
|
||||
|
||||
|
||||
# vim:ft=perl
|
283
t/stow_contents.t
Normal file
283
t/stow_contents.t
Normal file
|
@ -0,0 +1,283 @@
|
|||
#!/usr/local/bin/perl
|
||||
|
||||
#
|
||||
# Testing
|
||||
#
|
||||
|
||||
# load as a library
|
||||
BEGIN { use lib qw(.); require "t/util.pm"; require "stow"; }
|
||||
|
||||
use Test::More tests => 13;
|
||||
use English qw(-no_match_vars);
|
||||
|
||||
# local utility
|
||||
sub reset_state {
|
||||
@Tasks = ();
|
||||
@Conflicts = ();
|
||||
%Link_Task_For = ();
|
||||
%Dir_Task_For = ();
|
||||
%Options = ();
|
||||
return;
|
||||
}
|
||||
|
||||
### setup
|
||||
eval { remove_dir('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
|
||||
|
||||
#
|
||||
# stow a simple tree minimally
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('../stow/pkg1/bin1');
|
||||
make_file('../stow/pkg1/bin1/file1');
|
||||
stow_contents('../stow/pkg1', './', '../stow/pkg1');
|
||||
process_tasks();
|
||||
is(
|
||||
readlink('bin1'),
|
||||
'../stow/pkg1/bin1',
|
||||
=> 'minimal stow of a simple tree'
|
||||
);
|
||||
|
||||
#
|
||||
# stow a simple tree into an existing directory
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('../stow/pkg2/lib2');
|
||||
make_file('../stow/pkg2/lib2/file2');
|
||||
make_dir('lib2');
|
||||
stow_contents('../stow/pkg2', './', '../stow/pkg2');
|
||||
process_tasks();
|
||||
is(
|
||||
readlink('lib2/file2'),
|
||||
'../../stow/pkg2/lib2/file2',
|
||||
=> 'stow simple tree to existing directory'
|
||||
);
|
||||
|
||||
#
|
||||
# unfold existing tree
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('../stow/pkg3a/bin3');
|
||||
make_file('../stow/pkg3a/bin3/file3a');
|
||||
make_link('bin3' => '../stow/pkg3a/bin3'); # emulate stow
|
||||
|
||||
make_dir('../stow/pkg3b/bin3');
|
||||
make_file('../stow/pkg3b/bin3/file3b');
|
||||
stow_contents('../stow/pkg3b', './', '../stow/pkg3b');
|
||||
process_tasks();
|
||||
ok(
|
||||
-d 'bin3' &&
|
||||
readlink('bin3/file3a') eq '../../stow/pkg3a/bin3/file3a' &&
|
||||
readlink('bin3/file3b') eq '../../stow/pkg3b/bin3/file3b'
|
||||
=> 'target already has 1 stowed package'
|
||||
);
|
||||
|
||||
#
|
||||
# Link to a new dir conflicts with existing non-dir (can't unfold)
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_file('bin4'); # this is a file but named like a directory
|
||||
make_dir('../stow/pkg4/bin4');
|
||||
make_file('../stow/pkg4/bin4/file4');
|
||||
stow_contents('../stow/pkg4', './', '../stow/pkg4');
|
||||
like(
|
||||
$Conflicts[-1], qr(CONFLICT:.*existing target is neither a link nor a directory)
|
||||
=> 'link to new dir conflicts with existing non-directory'
|
||||
);
|
||||
|
||||
#
|
||||
# Target already exists but is not owned by stow
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('bin5');
|
||||
make_link('bin5/file5','../../empty');
|
||||
make_dir('../stow/pkg5/bin5/file5');
|
||||
stow_contents('../stow/pkg5', './', '../stow/pkg5');
|
||||
like(
|
||||
$Conflicts[-1], qr(CONFLICT:.*not owned by stow)
|
||||
=> 'target already exists but is not owned by stow'
|
||||
);
|
||||
|
||||
#
|
||||
# Replace existing but invalid target
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_link('file6','../stow/path-does-not-exist');
|
||||
make_dir('../stow/pkg6');
|
||||
make_file('../stow/pkg6/file6');
|
||||
eval{ stow_contents('../stow/pkg6', './', '../stow/pkg6'); process_tasks() };
|
||||
is(
|
||||
readlink('file6'),
|
||||
'../stow/pkg6/file6'
|
||||
=> 'replace existing but invalid target'
|
||||
);
|
||||
|
||||
#
|
||||
# Target already exists, is owned by stow, but points to a non-directory
|
||||
# (can't unfold)
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('bin7');
|
||||
make_dir('../stow/pkg7a/bin7');
|
||||
make_file('../stow/pkg7a/bin7/node7');
|
||||
make_link('bin7/node7','../../stow/pkg7a/bin7/node7');
|
||||
make_dir('../stow/pkg7b/bin7/node7');
|
||||
make_file('../stow/pkg7b/bin7/node7/file7');
|
||||
stow_contents('../stow/pkg7b', './', '../stow/pkg7b');
|
||||
like(
|
||||
$Conflicts[-1], qr(CONFLICT:.*existing target is stowed to a different package)
|
||||
=> 'link to new dir conflicts with existing stowed non-directory'
|
||||
);
|
||||
|
||||
#
|
||||
# stowing directories named 0
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('../stow/pkg8a/0');
|
||||
make_file('../stow/pkg8a/0/file8a');
|
||||
make_link('0' => '../stow/pkg8a/0'); # emulate stow
|
||||
|
||||
make_dir('../stow/pkg8b/0');
|
||||
make_file('../stow/pkg8b/0/file8b');
|
||||
stow_contents('../stow/pkg8b', './', '../stow/pkg8b');
|
||||
process_tasks();
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
-d '0' &&
|
||||
readlink('0/file8a') eq '../../stow/pkg8a/0/file8a' &&
|
||||
readlink('0/file8b') eq '../../stow/pkg8b/0/file8b'
|
||||
=> 'stowing directories named 0'
|
||||
);
|
||||
|
||||
#
|
||||
# overriding already stowed documentation
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
$Option{'override'} = ['man9', 'info9'];
|
||||
|
||||
make_dir('../stow/pkg9a/man9/man1');
|
||||
make_file('../stow/pkg9a/man9/man1/file9.1');
|
||||
make_dir('man9/man1');
|
||||
make_link('man9/man1/file9.1' => '../../../stow/pkg9a/man9/man1/file9.1'); # emulate stow
|
||||
|
||||
make_dir('../stow/pkg9b/man9/man1');
|
||||
make_file('../stow/pkg9b/man9/man1/file9.1');
|
||||
stow_contents('../stow/pkg9b', './', '../stow/pkg9b');
|
||||
process_tasks();
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
readlink('man9/man1/file9.1') eq '../../../stow/pkg9b/man9/man1/file9.1'
|
||||
=> 'overriding existing documentation files'
|
||||
);
|
||||
|
||||
#
|
||||
# deferring to already stowed documentation
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
$Option{'defer'} = ['man10', 'info10'];
|
||||
|
||||
make_dir('../stow/pkg10a/man10/man1');
|
||||
make_file('../stow/pkg10a/man10/man1/file10.1');
|
||||
make_dir('man10/man1');
|
||||
make_link('man10/man1/file10.1' => '../../../stow/pkg10a/man10/man1/file10.1'); # emulate stow
|
||||
|
||||
make_dir('../stow/pkg10b/man10/man1');
|
||||
make_file('../stow/pkg10b/man10/man1/file10.1');
|
||||
stow_contents('../stow/pkg10b', './', '../stow/pkg10b');
|
||||
process_tasks();
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
readlink('man10/man1/file10.1') eq '../../../stow/pkg10a/man10/man1/file10.1'
|
||||
=> 'defer to existing documentation files'
|
||||
);
|
||||
|
||||
#
|
||||
# Ignore temp files
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
$Option{'ignore'} = ['~', '\.#.*'];
|
||||
|
||||
make_dir('../stow/pkg11/man11/man1');
|
||||
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');
|
||||
|
||||
stow_contents('../stow/pkg11', './', '../stow/pkg11');
|
||||
process_tasks();
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
readlink('man11/man1/file11.1') eq '../../../stow/pkg11/man11/man1/file11.1' &&
|
||||
!-e 'man11/man1/file11.1~' &&
|
||||
!-e 'man11/man1/.#file11.1'
|
||||
=> 'ignore temp files'
|
||||
);
|
||||
|
||||
#
|
||||
# stowing links library files
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('../stow/pkg12/lib12/');
|
||||
make_file('../stow/pkg12/lib12/lib.so');
|
||||
make_link('../stow/pkg12/lib12/lib.so.1','lib.so');
|
||||
|
||||
make_dir('lib12/');
|
||||
stow_contents('../stow/pkg12', './', '../stow/pkg12');
|
||||
process_tasks();
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
readlink('lib12/lib.so.1') eq '../../stow/pkg12/lib12/lib.so.1'
|
||||
=> 'stow links to libraries'
|
||||
);
|
||||
|
||||
#
|
||||
# unfolding to stow links to library files
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('../stow/pkg13a/lib13/');
|
||||
make_file('../stow/pkg13a/lib13/liba.so');
|
||||
make_link('../stow/pkg13a/lib13/liba.so.1', 'liba.so');
|
||||
make_link('lib13','../stow/pkg13a/lib13');
|
||||
|
||||
make_dir('../stow/pkg13b/lib13/');
|
||||
make_file('../stow/pkg13b/lib13/libb.so');
|
||||
make_link('../stow/pkg13b/lib13/libb.so.1', 'libb.so');
|
||||
|
||||
stow_contents('../stow/pkg13b', './', '../stow/pkg13b');
|
||||
process_tasks();
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
readlink('lib13/liba.so.1') eq '../../stow/pkg13a/lib13/liba.so.1' &&
|
||||
readlink('lib13/libb.so.1') eq '../../stow/pkg13b/lib13/libb.so.1'
|
||||
=> 'unfolding to stow links to libraries'
|
||||
);
|
276
t/unstow_contents.t
Normal file
276
t/unstow_contents.t
Normal file
|
@ -0,0 +1,276 @@
|
|||
#!/usr/local/bin/perl
|
||||
|
||||
#
|
||||
# Testing unstow_contents()
|
||||
#
|
||||
|
||||
# load as a library
|
||||
BEGIN { use lib qw(.); require "t/util.pm"; require "stow"; }
|
||||
|
||||
use Test::More tests => 11;
|
||||
use English qw(-no_match_vars);
|
||||
|
||||
# local utility
|
||||
sub reset_state {
|
||||
@Tasks = ();
|
||||
@Conflicts = ();
|
||||
%Link_Task_For = ();
|
||||
%Dir_Task_For = ();
|
||||
%Options = ();
|
||||
return;
|
||||
}
|
||||
|
||||
### setup
|
||||
eval { remove_dir('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
|
||||
|
||||
#
|
||||
# unstow a simple tree minimally
|
||||
#
|
||||
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('../stow/pkg1/bin1');
|
||||
make_file('../stow/pkg1/bin1/file1');
|
||||
make_link('bin1','../stow/pkg1/bin1');
|
||||
|
||||
unstow_contents('../stow/pkg1','./');
|
||||
process_tasks();
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
-f '../stow/pkg1/bin1/file1' && ! -e 'bin1'
|
||||
=> 'unstow a simple tree'
|
||||
);
|
||||
|
||||
#
|
||||
# unstow a simple tree from an existing directory
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('lib2');
|
||||
make_dir('../stow/pkg2/lib2');
|
||||
make_file('../stow/pkg2/lib2/file2');
|
||||
make_link('lib2/file2', '../../stow/pkg2/lib2/file2');
|
||||
unstow_contents('../stow/pkg2','./');
|
||||
process_tasks();
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
-f '../stow/pkg2/lib2/file2' && -d 'lib2'
|
||||
=> 'unstow simple tree from a pre-existing directory'
|
||||
);
|
||||
|
||||
#
|
||||
# fold tree after unstowing
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('bin3');
|
||||
|
||||
make_dir('../stow/pkg3a/bin3');
|
||||
make_file('../stow/pkg3a/bin3/file3a');
|
||||
make_link('bin3/file3a' => '../../stow/pkg3a/bin3/file3a'); # emulate stow
|
||||
|
||||
make_dir('../stow/pkg3b/bin3');
|
||||
make_file('../stow/pkg3b/bin3/file3b');
|
||||
make_link('bin3/file3b' => '../../stow/pkg3b/bin3/file3b'); # emulate stow
|
||||
unstow_contents('../stow/pkg3b', './');
|
||||
process_tasks();
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
-l 'bin3' &&
|
||||
readlink('bin3') eq '../stow/pkg3a/bin3'
|
||||
=> 'fold tree after unstowing'
|
||||
);
|
||||
|
||||
#
|
||||
# existing link is owned by stow but is invalid so it gets removed anyway
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('bin4');
|
||||
make_dir('../stow/pkg4/bin4');
|
||||
make_file('../stow/pkg4/bin4/file4');
|
||||
make_link('bin4/file4', '../../stow/pkg4/bin4/does-not-exist');
|
||||
|
||||
unstow_contents('../stow/pkg4', './');
|
||||
process_tasks();
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
! -e 'bin4/file4'
|
||||
=> q(remove invalid link owned by stow)
|
||||
);
|
||||
|
||||
#
|
||||
# Existing link is not owned by stow
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('../stow/pkg5/bin5');
|
||||
make_link('bin5', '../not-stow');
|
||||
|
||||
unstow_contents('../stow/pkg5', './');
|
||||
like(
|
||||
$Conflicts[-1], qr(CONFLICT:.*existing target is not owned by stow)
|
||||
=> q(existing link not owned by stow)
|
||||
);
|
||||
#
|
||||
# Target already exists, is owned by stow, but points to a different package
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('bin6');
|
||||
make_dir('../stow/pkg6a/bin6');
|
||||
make_file('../stow/pkg6a/bin6/file6');
|
||||
make_link('bin6/file6', '../../stow/pkg6a/bin6/file6');
|
||||
|
||||
make_dir('../stow/pkg6b/bin6');
|
||||
make_file('../stow/pkg6b/bin6/file6');
|
||||
|
||||
unstow_contents('../stow/pkg6b', './');
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
-l 'bin6/file6' &&
|
||||
readlink('bin6/file6') eq '../../stow/pkg6a/bin6/file6'
|
||||
=> q(ignore existing link that points to a different package)
|
||||
);
|
||||
|
||||
#
|
||||
# Don't unlink anything under the stow directory
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('stow'); # make out stow dir a subdir of target
|
||||
$Stow_Path = 'stow';
|
||||
|
||||
# emulate stowing into ourself (bizzare corner case or accident)
|
||||
make_dir('stow/pkg7a/stow/pkg7b');
|
||||
make_file('stow/pkg7a/stow/pkg7b/file7b');
|
||||
make_link('stow/pkg7b', '../stow/pkg7a/stow/pkg7b');
|
||||
|
||||
unstow_contents('stow/pkg7b', './');
|
||||
process_tasks();
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
-l 'stow/pkg7b' &&
|
||||
readlink('stow/pkg7b') eq '../stow/pkg7a/stow/pkg7b'
|
||||
=> q(don't unlink any nodes under the stow directory)
|
||||
);
|
||||
|
||||
#
|
||||
# Don't unlink any nodes under another stow directory
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
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_file('stow2/.stow');
|
||||
|
||||
# emulate stowing into ourself (bizzare corner case or accident)
|
||||
make_dir('stow/pkg8a/stow2/pkg8b');
|
||||
make_file('stow/pkg8a/stow2/pkg8b/file8b');
|
||||
make_link('stow2/pkg8b', '../stow/pkg8a/stow2/pkg8b');
|
||||
|
||||
unstow_contents('stow/pkg8a', './');
|
||||
process_tasks();
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
-l 'stow2/pkg8b' &&
|
||||
readlink('stow2/pkg8b') eq '../stow/pkg8a/stow2/pkg8b'
|
||||
=> q(don't unlink any nodes under another stow directory)
|
||||
);
|
||||
|
||||
#
|
||||
# overriding already stowed documentation
|
||||
#
|
||||
reset_state();
|
||||
$Stow_Path = '../stow';
|
||||
$Option{'verbose'} = 0;
|
||||
$Option{'override'} = ['man9', 'info9'];
|
||||
|
||||
make_dir('../stow/pkg9a/man9/man1');
|
||||
make_file('../stow/pkg9a/man9/man1/file9.1');
|
||||
make_dir('man9/man1');
|
||||
make_link('man9/man1/file9.1' => '../../../stow/pkg9a/man9/man1/file9.1'); # emulate stow
|
||||
|
||||
make_dir('../stow/pkg9b/man9/man1');
|
||||
make_file('../stow/pkg9b/man9/man1/file9.1');
|
||||
unstow_contents('../stow/pkg9b', './');
|
||||
process_tasks();
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
!-l 'man9/man1/file9.1'
|
||||
=> 'overriding existing documentation files'
|
||||
);
|
||||
|
||||
#
|
||||
# deferring to already stowed documentation
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
$Option{'defer'} = ['man10', 'info10'];
|
||||
|
||||
make_dir('../stow/pkg10a/man10/man1');
|
||||
make_file('../stow/pkg10a/man10/man1/file10a.1');
|
||||
make_dir('man10/man1');
|
||||
make_link('man10/man1/file10a.1' => '../../../stow/pkg10a/man10/man1/file10a.1');
|
||||
|
||||
# need this to block folding
|
||||
make_dir('../stow/pkg10b/man10/man1');
|
||||
make_file('../stow/pkg10b/man10/man1/file10b.1');
|
||||
make_link('man10/man1/file10b.1' => '../../../stow/pkg10b/man10/man1/file10b.1');
|
||||
|
||||
|
||||
make_dir('../stow/pkg10c/man10/man1');
|
||||
make_file('../stow/pkg10c/man10/man1/file10a.1');
|
||||
unstow_contents('../stow/pkg10c', './');
|
||||
process_tasks();
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
readlink('man10/man1/file10a.1') eq '../../../stow/pkg10a/man10/man1/file10a.1'
|
||||
=> 'defer to existing documentation files'
|
||||
);
|
||||
|
||||
#
|
||||
# Ignore temp files
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
$Option{'ignore'} = ['~', '\.#.*'];
|
||||
|
||||
make_dir('../stow/pkg12/man12/man1');
|
||||
make_file('../stow/pkg12/man12/man1/file12.1');
|
||||
make_file('../stow/pkg12/man12/man1/file12.1~');
|
||||
make_file('../stow/pkg12/man12/man1/.#file12.1');
|
||||
make_dir('man12/man1');
|
||||
make_link('man12/man1/file12.1' => '../../../stow/pkg12/man12/man1/file12.1');
|
||||
|
||||
unstow_contents('../stow/pkg12', './');
|
||||
process_tasks();
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
!-e 'man12/man1/file12.1'
|
||||
=> 'ignore temp files'
|
||||
);
|
||||
|
||||
|
||||
# Todo
|
||||
#
|
||||
# Test cleaning up subdirs with --paranoid option
|
||||
|
277
t/unstow_contents_orig.t
Normal file
277
t/unstow_contents_orig.t
Normal file
|
@ -0,0 +1,277 @@
|
|||
#!/usr/local/bin/perl
|
||||
|
||||
#
|
||||
# Testing unstow_contents_orig()
|
||||
#
|
||||
|
||||
# load as a library
|
||||
BEGIN { use lib qw(.); require "t/util.pm"; require "stow"; }
|
||||
|
||||
use Test::More tests => 11;
|
||||
use English qw(-no_match_vars);
|
||||
|
||||
# local utility
|
||||
sub reset_state {
|
||||
@Tasks = ();
|
||||
@Conflicts = ();
|
||||
%Link_Task_For = ();
|
||||
%Dir_Task_For = ();
|
||||
%Options = ();
|
||||
return;
|
||||
}
|
||||
|
||||
### setup
|
||||
eval { remove_dir('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
|
||||
|
||||
#
|
||||
# unstow a simple tree minimally
|
||||
#
|
||||
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('../stow/pkg1/bin1');
|
||||
make_file('../stow/pkg1/bin1/file1');
|
||||
make_link('bin1','../stow/pkg1/bin1');
|
||||
|
||||
unstow_contents_orig('../stow/pkg1','./');
|
||||
process_tasks();
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
-f '../stow/pkg1/bin1/file1' && ! -e 'bin1'
|
||||
=> 'unstow a simple tree'
|
||||
);
|
||||
|
||||
#
|
||||
# unstow a simple tree from an existing directory
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('lib2');
|
||||
make_dir('../stow/pkg2/lib2');
|
||||
make_file('../stow/pkg2/lib2/file2');
|
||||
make_link('lib2/file2', '../../stow/pkg2/lib2/file2');
|
||||
unstow_contents_orig('../stow/pkg2','./');
|
||||
process_tasks();
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
-f '../stow/pkg2/lib2/file2' && -d 'lib2'
|
||||
=> 'unstow simple tree from a pre-existing directory'
|
||||
);
|
||||
|
||||
#
|
||||
# fold tree after unstowing
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('bin3');
|
||||
|
||||
make_dir('../stow/pkg3a/bin3');
|
||||
make_file('../stow/pkg3a/bin3/file3a');
|
||||
make_link('bin3/file3a' => '../../stow/pkg3a/bin3/file3a'); # emulate stow
|
||||
|
||||
make_dir('../stow/pkg3b/bin3');
|
||||
make_file('../stow/pkg3b/bin3/file3b');
|
||||
make_link('bin3/file3b' => '../../stow/pkg3b/bin3/file3b'); # emulate stow
|
||||
unstow_contents_orig('../stow/pkg3b', './');
|
||||
process_tasks();
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
-l 'bin3' &&
|
||||
readlink('bin3') eq '../stow/pkg3a/bin3'
|
||||
=> 'fold tree after unstowing'
|
||||
);
|
||||
|
||||
#
|
||||
# existing link is owned by stow but is invalid so it gets removed anyway
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('bin4');
|
||||
make_dir('../stow/pkg4/bin4');
|
||||
make_file('../stow/pkg4/bin4/file4');
|
||||
make_link('bin4/file4', '../../stow/pkg4/bin4/does-not-exist');
|
||||
|
||||
unstow_contents_orig('../stow/pkg4', './');
|
||||
process_tasks();
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
! -e 'bin4/file4'
|
||||
=> q(remove invalid link owned by stow)
|
||||
);
|
||||
|
||||
#
|
||||
# Existing link is not owned by stow
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('../stow/pkg5/bin5');
|
||||
make_link('bin5', '../not-stow');
|
||||
|
||||
unstow_contents_orig('../stow/pkg5', './');
|
||||
#like(
|
||||
# $Conflicts[-1], qr(CONFLICT:.*can't unlink.*not owned by stow)
|
||||
# => q(existing link not owned by stow)
|
||||
#);
|
||||
ok(
|
||||
-l 'bin5' && readlink('bin5') eq '../not-stow'
|
||||
=> q(existing link not owned by stow)
|
||||
);
|
||||
#
|
||||
# Target already exists, is owned by stow, but points to a different package
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('bin6');
|
||||
make_dir('../stow/pkg6a/bin6');
|
||||
make_file('../stow/pkg6a/bin6/file6');
|
||||
make_link('bin6/file6', '../../stow/pkg6a/bin6/file6');
|
||||
|
||||
make_dir('../stow/pkg6b/bin6');
|
||||
make_file('../stow/pkg6b/bin6/file6');
|
||||
|
||||
unstow_contents_orig('../stow/pkg6b', './');
|
||||
ok(
|
||||
-l 'bin6/file6' && readlink('bin6/file6') eq '../../stow/pkg6a/bin6/file6'
|
||||
=> q(existing link owned by stow but points to a different package)
|
||||
);
|
||||
|
||||
#
|
||||
# Don't unlink anything under the stow directory
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
make_dir('stow'); # make out stow dir a subdir of target
|
||||
$Stow_Path = 'stow';
|
||||
|
||||
# emulate stowing into ourself (bizzare corner case or accident)
|
||||
make_dir('stow/pkg7a/stow/pkg7b');
|
||||
make_file('stow/pkg7a/stow/pkg7b/file7b');
|
||||
make_link('stow/pkg7b', '../stow/pkg7a/stow/pkg7b');
|
||||
|
||||
unstow_contents_orig('stow/pkg7b', './');
|
||||
process_tasks();
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
-l 'stow/pkg7b' &&
|
||||
readlink('stow/pkg7b') eq '../stow/pkg7a/stow/pkg7b'
|
||||
=> q(don't unlink any nodes under the stow directory)
|
||||
);
|
||||
|
||||
#
|
||||
# Don't unlink any nodes under another stow directory
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
|
||||
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_file('stow2/.stow');
|
||||
|
||||
# emulate stowing into ourself (bizzare corner case or accident)
|
||||
make_dir('stow/pkg8a/stow2/pkg8b');
|
||||
make_file('stow/pkg8a/stow2/pkg8b/file8b');
|
||||
make_link('stow2/pkg8b', '../stow/pkg8a/stow2/pkg8b');
|
||||
|
||||
unstow_contents_orig('stow/pkg8a', './');
|
||||
process_tasks();
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
-l 'stow2/pkg8b' &&
|
||||
readlink('stow2/pkg8b') eq '../stow/pkg8a/stow2/pkg8b'
|
||||
=> q(don't unlink any nodes under another stow directory)
|
||||
);
|
||||
|
||||
#
|
||||
# overriding already stowed documentation
|
||||
#
|
||||
reset_state();
|
||||
$Stow_Path = '../stow';
|
||||
$Option{'verbose'} = 0;
|
||||
$Option{'override'} = ['man9', 'info9'];
|
||||
|
||||
make_dir('../stow/pkg9a/man9/man1');
|
||||
make_file('../stow/pkg9a/man9/man1/file9.1');
|
||||
make_dir('man9/man1');
|
||||
make_link('man9/man1/file9.1' => '../../../stow/pkg9a/man9/man1/file9.1'); # emulate stow
|
||||
|
||||
make_dir('../stow/pkg9b/man9/man1');
|
||||
make_file('../stow/pkg9b/man9/man1/file9.1');
|
||||
unstow_contents_orig('../stow/pkg9b', './');
|
||||
process_tasks();
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
!-l 'man9/man1/file9.1'
|
||||
=> 'overriding existing documentation files'
|
||||
);
|
||||
|
||||
#
|
||||
# deferring to already stowed documentation
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
$Option{'defer'} = ['man10', 'info10'];
|
||||
|
||||
make_dir('../stow/pkg10a/man10/man1');
|
||||
make_file('../stow/pkg10a/man10/man1/file10a.1');
|
||||
make_dir('man10/man1');
|
||||
make_link('man10/man1/file10a.1' => '../../../stow/pkg10a/man10/man1/file10a.1');
|
||||
|
||||
# need this to block folding
|
||||
make_dir('../stow/pkg10b/man10/man1');
|
||||
make_file('../stow/pkg10b/man10/man1/file10b.1');
|
||||
make_link('man10/man1/file10b.1' => '../../../stow/pkg10b/man10/man1/file10b.1');
|
||||
|
||||
|
||||
make_dir('../stow/pkg10c/man10/man1');
|
||||
make_file('../stow/pkg10c/man10/man1/file10a.1');
|
||||
unstow_contents_orig('../stow/pkg10c', './');
|
||||
process_tasks();
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
readlink('man10/man1/file10a.1') eq '../../../stow/pkg10a/man10/man1/file10a.1'
|
||||
=> 'defer to existing documentation files'
|
||||
);
|
||||
|
||||
#
|
||||
# Ignore temp files
|
||||
#
|
||||
reset_state();
|
||||
$Option{'verbose'} = 0;
|
||||
$Option{'ignore'} = ['~', '\.#.*'];
|
||||
|
||||
make_dir('../stow/pkg12/man12/man1');
|
||||
make_file('../stow/pkg12/man12/man1/file12.1');
|
||||
make_file('../stow/pkg12/man12/man1/file12.1~');
|
||||
make_file('../stow/pkg12/man12/man1/.#file12.1');
|
||||
make_dir('man12/man1');
|
||||
make_link('man12/man1/file12.1' => '../../../stow/pkg12/man12/man1/file12.1');
|
||||
|
||||
unstow_contents_orig('../stow/pkg12', './');
|
||||
process_tasks();
|
||||
ok(
|
||||
scalar(@Conflicts) == 0 &&
|
||||
!-e 'man12/man1/file12.1'
|
||||
=> 'ignore temp files'
|
||||
);
|
||||
|
||||
# Todo
|
||||
#
|
||||
# Test cleaning up subdirs with --paranoid option
|
||||
|
157
t/util.pm
Normal file
157
t/util.pm
Normal file
|
@ -0,0 +1,157 @@
|
|||
#
|
||||
# Utilities shared by test scripts
|
||||
#
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
#===== SUBROUTINE ===========================================================
|
||||
# Name : make_link()
|
||||
# Purpose : safely create a link
|
||||
# Parameters: $target => path to the link
|
||||
# : $source => where the new link should point
|
||||
# Returns : n/a
|
||||
# Throws : fatal error if the link can not be safely created
|
||||
# Comments : checks for existing nodes
|
||||
#============================================================================
|
||||
sub make_link {
|
||||
my ($target, $source) = @_;
|
||||
|
||||
if (-l $target) {
|
||||
my $old_source = readlink join('/',parent($target),$source)
|
||||
or die "could not read link $target/$source";
|
||||
if ($old_source ne $source) {
|
||||
die "$target already exists but points elsewhere\n";
|
||||
}
|
||||
}
|
||||
elsif (-e $target ) {
|
||||
die "$target already exists and is not a link\n";
|
||||
}
|
||||
else {
|
||||
symlink $source, $target
|
||||
or die "could not create link $target => $source ($!)\n";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#===== SUBROUTINE ===========================================================
|
||||
# Name : make_dir()
|
||||
# Purpose : create a directory and any requiste parents
|
||||
# Parameters: $dir => path to the new directory
|
||||
# Returns : n/a
|
||||
# Throws : fatal error if the directory or any of its parents cannot be
|
||||
# : created
|
||||
# Comments : none
|
||||
#============================================================================
|
||||
sub make_dir {
|
||||
my ($dir) = @_;
|
||||
|
||||
my @parents = ();
|
||||
for my $part (split '/', $dir) {
|
||||
my $path = join '/', @parents, $part;
|
||||
if (not -d $path and not mkdir $path) {
|
||||
die "could not create directory: $path ($!)\n";
|
||||
}
|
||||
push @parents, $part;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#===== SUBROUTINE ===========================================================
|
||||
# Name : create_file()
|
||||
# Purpose : create an empty file
|
||||
# Parameters: $path => proposed path to the file
|
||||
# Returns : n/a
|
||||
# Throws : fatal error if the file could not be created
|
||||
# Comments : detects clash with an existing non-file
|
||||
#============================================================================
|
||||
sub make_file {
|
||||
my ($path) =@_;
|
||||
|
||||
if (not -e $path) {
|
||||
open my $FILE ,'>', $path
|
||||
or die "could not create file: $path ($!)\n";
|
||||
close $FILE;
|
||||
}
|
||||
elsif ( not -f $path) {
|
||||
die "a non-file already exists at $path\n";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#===== SUBROUTINE ===========================================================
|
||||
# Name : remove_link()
|
||||
# Purpose : remove an esiting symbolic link
|
||||
# Parameters: $path => path to the symbolic link
|
||||
# Returns : n/a
|
||||
# Throws : fatal error if the operation fails or if passed the path to a
|
||||
# : non-link
|
||||
# Comments : none
|
||||
#============================================================================
|
||||
sub remove_link {
|
||||
my ($path) = @_;
|
||||
if (not -l $path) {
|
||||
die qq(remove_link() called with a non-link: $path);
|
||||
}
|
||||
unlink $path or die "could not remove link: $path ($!)\n";
|
||||
return;
|
||||
}
|
||||
|
||||
#===== SUBROUTINE ===========================================================
|
||||
# Name : remove_file()
|
||||
# Purpose : remove an existing empty file
|
||||
# Parameters: $path => the path to the empty file
|
||||
# Returns : n/a
|
||||
# Throws : fatal error if given file is non-empty or the operation fails
|
||||
# Comments : none
|
||||
#============================================================================
|
||||
sub remove_file {
|
||||
my ($path) = @_;
|
||||
if (-z $path) {
|
||||
die "file at $path is non-empty\n";
|
||||
}
|
||||
unlink $path or die "could not remove empty file: $path ($!)\n";
|
||||
return;
|
||||
}
|
||||
|
||||
#===== SUBROUTINE ===========================================================
|
||||
# Name : remove_dir()
|
||||
# Purpose : safely remove a tree of test files
|
||||
# Parameters: $dir => path to the top of the tree
|
||||
# Returns : n/a
|
||||
# Throws : fatal error if the tree contains a non-link or non-empty file
|
||||
# Comments : recursively removes directories containing softlinks empty files
|
||||
#============================================================================
|
||||
sub remove_dir {
|
||||
my ($dir) = @_;
|
||||
|
||||
if (not -d $dir) {
|
||||
die "$dir is not a directory";
|
||||
}
|
||||
|
||||
opendir my $DIR, $dir or die "cannot read directory: $dir ($!)\n";
|
||||
my @listing = readdir $DIR;
|
||||
closedir $DIR;
|
||||
|
||||
NODE:
|
||||
for my $node (@listing) {
|
||||
next NODE if $node eq '.';
|
||||
next NODE if $node eq '..';
|
||||
|
||||
my $path = "$dir/$node";
|
||||
if (-l $path or -z $path) {
|
||||
unlink $path or die "cannot unlink $path ($!)\n";
|
||||
}
|
||||
elsif (-d "$path") {
|
||||
remove_dir($path);
|
||||
}
|
||||
else {
|
||||
die "$path is not a link, directory, or empty file\n";
|
||||
}
|
||||
}
|
||||
rmdir $dir or die "cannot rmdir $dir ($!)\n";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
1;
|
Loading…
Add table
Add a link
Reference in a new issue