diff --git a/t/cli_options.t b/t/cli_options.t index 7c8a253..975e6cb 100755 --- a/t/cli_options.t +++ b/t/cli_options.t @@ -22,7 +22,7 @@ use strict; use warnings; -use Test::More tests => 10; +use Test::More tests => 6; use testutil; @@ -30,83 +30,92 @@ require 'stow'; init_test_dirs(); -local @ARGV = ( - '-v', - '-d', "$TEST_DIR/stow", - '-t', "$TEST_DIR/target", - 'dummy' -); - -my ($options, $pkgs_to_delete, $pkgs_to_stow) = process_options(); - -is($options->{verbose}, 1, 'verbose option'); -is($options->{dir}, "$TEST_DIR/stow", 'stow dir option'); - -my $stow = new_Stow(%$options); - -is($stow->{stow_path}, "../stow" => 'stow dir'); -is_deeply($pkgs_to_stow, [ 'dummy' ] => 'default to stow'); - -# -# Check mixed up package options -# -local @ARGV = ( - '-v', - '-D', 'd1', 'd2', - '-S', 's1', - '-R', 'r1', - '-D', 'd3', - '-S', 's2', 's3', - '-R', 'r2', -); - -($options, $pkgs_to_delete, $pkgs_to_stow) = 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 deferred paths -# -local @ARGV = ( - '--defer=man', - '--defer=info', - 'dummy' -); -($options, $pkgs_to_delete, $pkgs_to_stow) = process_options(); -is_deeply($options->{defer}, [ qr{\A(man)}, qr{\A(info)} ] => 'defer man and info'); - -# -# Check setting override paths -# -local @ARGV = ( - '--override=man', - '--override=info', - 'dummy' -); -($options, $pkgs_to_delete, $pkgs_to_stow) = process_options(); -is_deeply($options->{override}, [qr{\A(man)}, qr{\A(info)}] => 'override man and info'); - -# -# Check setting ignored paths -# -local @ARGV = ( - '--ignore=~', - '--ignore=\.#.*', - 'dummy' -); -($options, $pkgs_to_delete, $pkgs_to_stow) = process_options(); -is_deeply($options->{ignore}, [ qr{(~)\z}, qr{(\.#.*)\z} ] => 'ignore temp files'); - -# -# Check that expansion not applied. -# -local @ARGV = ( - "--target=$TEST_DIR/".'$HOME', - 'dummy' -); -make_path("$TEST_DIR/".'$HOME'); -($options, $pkgs_to_delete, $pkgs_to_stow) = process_options(); -is($options->{target}, "$TEST_DIR/".'$HOME', 'no expansion'); -remove_dir("$TEST_DIR/".'$HOME'); +subtest('basic CLI options', sub { + plan tests => 4; + + local @ARGV = ( + '-v', + '-d', "$TEST_DIR/stow", + '-t', "$TEST_DIR/target", + 'dummy' + ); + + my ($options, $pkgs_to_delete, $pkgs_to_stow) = process_options(); + + is($options->{verbose}, 1, 'verbose option'); + is($options->{dir}, "$TEST_DIR/stow", 'stow dir option'); + + my $stow = new_Stow(%$options); + + is($stow->{stow_path}, "../stow" => 'stow dir'); + is_deeply($pkgs_to_stow, [ 'dummy' ] => 'default to stow'); +}); + +subtest('mixed up package options', sub { + plan tests => 2; + + local @ARGV = ( + '-v', + '-D', 'd1', 'd2', + '-S', 's1', + '-R', 'r1', + '-D', 'd3', + '-S', 's2', 's3', + '-R', 'r2', + ); + + my ($options, $pkgs_to_delete, $pkgs_to_stow) = 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'); +}); + +subtest('setting deferred paths', sub { + plan tests => 1; + + local @ARGV = ( + '--defer=man', + '--defer=info', + 'dummy' + ); + my ($options, $pkgs_to_delete, $pkgs_to_stow) = process_options(); + is_deeply($options->{defer}, [ qr{\A(man)}, qr{\A(info)} ] => 'defer man and info'); +}); + +subtest('setting override paths', sub { + plan tests => 1; + + local @ARGV = ( + '--override=man', + '--override=info', + 'dummy' + ); + my ($options, $pkgs_to_delete, $pkgs_to_stow) = process_options(); + is_deeply($options->{override}, [qr{\A(man)}, qr{\A(info)}] => 'override man and info'); +}); + +subtest('setting ignored paths', sub { + plan tests => 1; + + local @ARGV = ( + '--ignore=~', + '--ignore=\.#.*', + 'dummy' + ); + my ($options, $pkgs_to_delete, $pkgs_to_stow) = process_options(); + is_deeply($options->{ignore}, [ qr{(~)\z}, qr{(\.#.*)\z} ] => 'ignore temp files'); +}); + +subtest('no expansion of environment variables', sub { + plan tests => 1; + + local @ARGV = ( + "--target=$TEST_DIR/".'$HOME', + 'dummy' + ); + make_path("$TEST_DIR/".'$HOME'); + my ($options, $pkgs_to_delete, $pkgs_to_stow) = process_options(); + is($options->{target}, "$TEST_DIR/".'$HOME', 'no expansion'); + remove_dir("$TEST_DIR/".'$HOME'); +}); # vim:ft=perl diff --git a/t/examples.t b/t/examples.t index 376de39..239ff99 100755 --- a/t/examples.t +++ b/t/examples.t @@ -24,7 +24,7 @@ use warnings; use testutil; -use Test::More tests => 10; +use Test::More tests => 5; use English qw(-no_match_vars); init_test_dirs(); @@ -32,162 +32,163 @@ cd("$TEST_DIR/target"); my $stow; -## set up some fake packages to stow - -# perl -make_path('stow/perl/bin'); -make_file('stow/perl/bin/perl'); -make_file('stow/perl/bin/a2p'); -make_path('stow/perl/info'); -make_file('stow/perl/info/perl'); -make_path('stow/perl/lib/perl'); -make_path('stow/perl/man/man1'); -make_file('stow/perl/man/man1/perl.1'); - -# emacs -make_path('stow/emacs/bin'); -make_file('stow/emacs/bin/emacs'); -make_file('stow/emacs/bin/etags'); -make_path('stow/emacs/info'); -make_file('stow/emacs/info/emacs'); -make_path('stow/emacs/libexec/emacs'); -make_path('stow/emacs/man/man1'); -make_file('stow/emacs/man/man1/emacs.1'); - -# -# stow perl into an empty target -# - -$stow = new_Stow(dir => 'stow'); -$stow->plan_stow('perl'); -$stow->process_tasks(); -ok( - $stow->get_conflict_count == 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 -# - -# clean up previous stow -remove_link('bin'); -remove_link('info'); -remove_link('lib'); -remove_link('man'); - -make_path('bin'); -make_path('lib'); -make_path('man/man1'); - -$stow = new_Stow(dir => 'stow'); -$stow->plan_stow('perl'); -$stow->process_tasks(); -ok( - $stow->get_conflict_count == 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 -# - -# clean up previous stow -remove_link('info'); -remove_dir('bin'); -remove_dir('lib'); -remove_dir('man'); - -$stow = new_Stow(dir => 'stow'); -$stow->plan_stow('perl', 'emacs'); -$stow->process_tasks(); -is($stow->get_conflict_count, 0, 'no conflicts'); -ok( - -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 -# - -make_path('stow/pkg1a/bin1'); -make_path('stow/pkg1b/bin1'); -make_file('stow/pkg1b/bin1/file1b'); - -$stow = new_Stow(dir => 'stow'); -$stow->plan_stow('pkg1a', 'pkg1b'); -$stow->plan_unstow('pkg1b'); -$stow->process_tasks(); -is($stow->get_conflict_count, 0, 'no conflicts stowing empty dirs'); -ok(-d 'bin1' => 'bug 1: stowing empty dirs'); - -# -# BUG 2: split open tree-folding symlinks pointing inside different stow -# directories -# -make_path('stow2a/pkg2a/bin2'); -make_file('stow2a/pkg2a/bin2/file2a'); -make_file('stow2a/.stow'); -make_path('stow2b/pkg2b/bin2'); -make_file('stow2b/pkg2b/bin2/file2b'); -make_file('stow2b/.stow'); - -$stow = new_Stow(dir => 'stow2a'); -$stow->plan_stow('pkg2a'); -$stow->set_stow_dir('stow2b'); -$stow->plan_stow('pkg2b'); -$stow->process_tasks(); - -is($stow->get_conflict_count, 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 +subtest('setup fake packages', sub { + plan tests => 1; + + # perl + make_path('stow/perl/bin'); + make_file('stow/perl/bin/perl'); + make_file('stow/perl/bin/a2p'); + make_path('stow/perl/info'); + make_file('stow/perl/info/perl'); + make_path('stow/perl/lib/perl'); + make_path('stow/perl/man/man1'); + make_file('stow/perl/man/man1/perl.1'); + + # emacs + make_path('stow/emacs/bin'); + make_file('stow/emacs/bin/emacs'); + make_file('stow/emacs/bin/etags'); + make_path('stow/emacs/info'); + make_file('stow/emacs/info/emacs'); + make_path('stow/emacs/libexec/emacs'); + make_path('stow/emacs/man/man1'); + make_file('stow/emacs/man/man1/emacs.1'); + + ok(1, 'created fake packages'); +}); + +subtest('stow perl into an empty target', sub { + plan tests => 9; + + $stow = new_Stow(dir => 'stow'); + $stow->plan_stow('perl'); + $stow->process_tasks(); + is($stow->get_conflict_count, 0, 'no conflicts'); + ok(-l 'bin', 'bin is a symlink'); + ok(-l 'info', 'info is a symlink'); + ok(-l 'lib', 'lib is a symlink'); + ok(-l 'man', 'man is a symlink'); + is(readlink('bin'), 'stow/perl/bin', 'bin points to stow/perl/bin'); + is(readlink('info'), 'stow/perl/info', 'info points to stow/perl/info'); + is(readlink('lib'), 'stow/perl/lib', 'lib points to stow/perl/lib'); + is(readlink('man'), 'stow/perl/man', 'man points to stow/perl/man'); +}); + +subtest('stow perl into a non-empty target', sub { + plan tests => 15; + + # clean up previous stow + remove_link('bin'); + remove_link('info'); + remove_link('lib'); + remove_link('man'); + + make_path('bin'); + make_path('lib'); + make_path('man/man1'); + + $stow = new_Stow(dir => 'stow'); + $stow->plan_stow('perl'); + $stow->process_tasks(); + is($stow->get_conflict_count, 0, 'no conflicts'); + ok(-d 'bin', 'bin is a directory'); + ok(-d 'lib', 'lib is a directory'); + ok(-d 'man', 'man is a directory'); + ok(-d 'man/man1', 'man/man1 is a directory'); + ok(-l 'info', 'info is a symlink'); + ok(-l 'bin/perl', 'bin/perl is a symlink'); + ok(-l 'bin/a2p', 'bin/a2p is a symlink'); + ok(-l 'lib/perl', 'lib/perl is a symlink'); + ok(-l 'man/man1/perl.1', 'man/man1/perl.1 is a symlink'); + is(readlink('info'), 'stow/perl/info', 'info points to stow/perl/info'); + is(readlink('bin/perl'), '../stow/perl/bin/perl', 'bin/perl points correctly'); + is(readlink('bin/a2p'), '../stow/perl/bin/a2p', 'bin/a2p points correctly'); + is(readlink('lib/perl'), '../stow/perl/lib/perl', 'lib/perl points correctly'); + is(readlink('man/man1/perl.1'), '../../stow/perl/man/man1/perl.1', 'man/man1/perl.1 points correctly'); +}); + +subtest('install perl into empty target and then install emacs', sub { + plan tests => 25; + + # clean up previous stow + remove_link('info'); + remove_dir('bin'); + remove_dir('lib'); + remove_dir('man'); + + $stow = new_Stow(dir => 'stow'); + $stow->plan_stow('perl', 'emacs'); + $stow->process_tasks(); + is($stow->get_conflict_count, 0, 'no conflicts'); + ok(-d 'bin', 'bin is a directory'); + ok(-l 'bin/perl', 'bin/perl is a symlink'); + ok(-l 'bin/emacs', 'bin/emacs is a symlink'); + ok(-l 'bin/a2p', 'bin/a2p is a symlink'); + ok(-l 'bin/etags', 'bin/etags is a symlink'); + is(readlink('bin/perl'), '../stow/perl/bin/perl', 'bin/perl points correctly'); + is(readlink('bin/a2p'), '../stow/perl/bin/a2p', 'bin/a2p points correctly'); + is(readlink('bin/emacs'), '../stow/emacs/bin/emacs', 'bin/emacs points correctly'); + is(readlink('bin/etags'), '../stow/emacs/bin/etags', 'bin/etags points correctly'); + ok(-d 'info', 'info is a directory'); + ok(-l 'info/perl', 'info/perl is a symlink'); + ok(-l 'info/emacs', 'info/emacs is a symlink'); + is(readlink('info/perl'), '../stow/perl/info/perl', 'info/perl points correctly'); + is(readlink('info/emacs'), '../stow/emacs/info/emacs', 'info/emacs points correctly'); + ok(-d 'man', 'man is a directory'); + ok(-d 'man/man1', 'man/man1 is a directory'); + ok(-l 'man/man1/perl.1', 'man/man1/perl.1 is a symlink'); + ok(-l 'man/man1/emacs.1', 'man/man1/emacs.1 is a symlink'); + is(readlink('man/man1/perl.1'), '../../stow/perl/man/man1/perl.1', 'man/man1/perl.1 points correctly'); + is(readlink('man/man1/emacs.1'), '../../stow/emacs/man/man1/emacs.1', 'man/man1/emacs.1 points correctly'); + ok(-l 'lib', 'lib is a symlink'); + ok(-l 'libexec', 'libexec is a symlink'); + is(readlink('lib'), 'stow/perl/lib', 'lib points correctly'); + is(readlink('libexec'), 'stow/emacs/libexec', 'libexec points correctly'); +}); + +subtest('bug fixes', sub { + plan tests => 6; + + # + # 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 + # + + make_path('stow/pkg1a/bin1'); + make_path('stow/pkg1b/bin1'); + make_file('stow/pkg1b/bin1/file1b'); + + $stow = new_Stow(dir => 'stow'); + $stow->plan_stow('pkg1a', 'pkg1b'); + $stow->plan_unstow('pkg1b'); + $stow->process_tasks(); + is($stow->get_conflict_count, 0, 'no conflicts stowing empty dirs'); + ok(-d 'bin1' => 'bug 1: stowing empty dirs'); + + # + # BUG 2: split open tree-folding symlinks pointing inside different stow + # directories + # + make_path('stow2a/pkg2a/bin2'); + make_file('stow2a/pkg2a/bin2/file2a'); + make_file('stow2a/.stow'); + make_path('stow2b/pkg2b/bin2'); + make_file('stow2b/pkg2b/bin2/file2b'); + make_file('stow2b/.stow'); + + $stow = new_Stow(dir => 'stow2a'); + $stow->plan_stow('pkg2a'); + $stow->set_stow_dir('stow2b'); + $stow->plan_stow('pkg2b'); + $stow->process_tasks(); + + is($stow->get_conflict_count, 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'); +}); diff --git a/t/foldable.t b/t/foldable.t index e528723..249bcf9 100755 --- a/t/foldable.t +++ b/t/foldable.t @@ -32,51 +32,49 @@ cd("$TEST_DIR/target"); my $stow = new_Stow(dir => '../stow'); -# Note that each of the following tests use a distinct set of files +subtest('can fold a simple tree', sub { + plan tests => 1; -# -# can fold a simple tree -# + make_path('../stow/pkg1/bin1'); + make_file('../stow/pkg1/bin1/file1'); + make_path('bin1'); + make_link('bin1/file1','../../stow/pkg1/bin1/file1'); -make_path('../stow/pkg1/bin1'); -make_file('../stow/pkg1/bin1/file1'); -make_path('bin1'); -make_link('bin1/file1','../../stow/pkg1/bin1/file1'); + is( $stow->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 -# +subtest("can't fold an empty directory", sub { + plan tests => 1; -make_path('../stow/pkg2/bin2'); -make_file('../stow/pkg2/bin2/file2'); -make_path('bin2'); + make_path('../stow/pkg2/bin2'); + make_file('../stow/pkg2/bin2/file2'); + make_path('bin2'); -is( $stow->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 -# +subtest("can't fold if dir contains a non-link", sub { + plan tests => 1; -make_path('../stow/pkg3/bin3'); -make_file('../stow/pkg3/bin3/file3'); -make_path('bin3'); -make_link('bin3/file3','../../stow/pkg3/bin3/file3'); -make_file('bin3/non-link'); + make_path('../stow/pkg3/bin3'); + make_file('../stow/pkg3/bin3/file3'); + make_path('bin3'); + make_link('bin3/file3','../../stow/pkg3/bin3/file3'); + make_file('bin3/non-link'); -is( $stow->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 -# +subtest("can't fold if links point to different directories", sub { + plan tests => 1; -make_path('bin4'); -make_path('../stow/pkg4a/bin4'); -make_file('../stow/pkg4a/bin4/file4a'); -make_link('bin4/file4a','../../stow/pkg4a/bin4/file4a'); -make_path('../stow/pkg4b/bin4'); -make_file('../stow/pkg4b/bin4/file4b'); -make_link('bin4/file4b','../../stow/pkg4b/bin4/file4b'); + make_path('bin4'); + make_path('../stow/pkg4a/bin4'); + make_file('../stow/pkg4a/bin4/file4a'); + make_link('bin4/file4a','../../stow/pkg4a/bin4/file4a'); + make_path('../stow/pkg4b/bin4'); + make_file('../stow/pkg4b/bin4/file4b'); + make_link('bin4/file4b','../../stow/pkg4b/bin4/file4b'); -is( $stow->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) ); +}); diff --git a/t/unstow.t b/t/unstow.t index 4252694..6f39746 100755 --- a/t/unstow.t +++ b/t/unstow.t @@ -22,7 +22,6 @@ use strict; use warnings; -use File::Spec qw(make_path); use POSIX qw(getcwd); use Test::More tests => 35; use Test::Output;