From 58959060caa72fda1ad10a68e3cc684eaa411588 Mon Sep 17 00:00:00 2001 From: Adam Spiers Date: Sun, 8 Sep 2024 12:43:46 +0100 Subject: [PATCH 1/3] extract setup_global_ignore() into testutil.pm --- t/ignore.t | 2 +- t/testutil.pm | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/t/ignore.t b/t/ignore.t index 3da9dd4..2e0c1e8 100755 --- a/t/ignore.t +++ b/t/ignore.t @@ -112,7 +112,7 @@ sub test_user_global_list { sub setup_user_global_list { # Now test with global ignore list in home directory $ENV{HOME} = tempdir(); - make_file(join_paths($ENV{HOME}, $Stow::GLOBAL_IGNORE_FILE), < Date: Sun, 8 Sep 2024 12:47:54 +0100 Subject: [PATCH 2/3] extract setup_package_ignore() into testutil.pm --- t/ignore.t | 7 +++---- t/testutil.pm | 9 ++++++++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/t/ignore.t b/t/ignore.t index 2e0c1e8..0e8d98b 100755 --- a/t/ignore.t +++ b/t/ignore.t @@ -124,10 +124,9 @@ sub setup_package_local_list { my ($stow_path, $package, $list) = @_; my $package_path = join_paths($stow_path, $package); make_path($package_path); - my $local_ignore = join_paths($package_path, $Stow::LOCAL_IGNORE_FILE); - make_file($local_ignore, $list); - $stow->invalidate_memoized_regexp($local_ignore); - return $local_ignore; + my $package_ignore = setup_package_ignore($package_path, $list); + $stow->invalidate_memoized_regexp($package_ignore); + return $package_ignore; } sub main { diff --git a/t/testutil.pm b/t/testutil.pm index ede2f2c..c685cc4 100755 --- a/t/testutil.pm +++ b/t/testutil.pm @@ -41,7 +41,7 @@ our @EXPORT = qw( cd new_Stow new_compat_Stow make_path make_link make_invalid_link make_file - setup_global_ignore + setup_global_ignore setup_package_ignore remove_dir remove_file remove_link cat_file is_link is_dir_not_symlink is_nonexistent_path @@ -168,6 +168,13 @@ sub setup_global_ignore { return $global_ignore_file; } +sub setup_package_ignore { + my ($package_path, $contents) = @_; + my $package_ignore_file = join_paths($package_path, $Stow::LOCAL_IGNORE_FILE); + make_file($package_ignore_file, $contents); + return $package_ignore_file; +} + #===== SUBROUTINE =========================================================== # Name : remove_link() # Purpose : remove an esiting symbolic link From 37025f55dfbbf15c02dc5bca3c3c80eeb099f89c Mon Sep 17 00:00:00 2001 From: Adam Spiers Date: Sun, 8 Sep 2024 13:05:16 +0100 Subject: [PATCH 3/3] ignore based on package dirent name prior to dot- adjustment If `--dotfiles` was enabled, files in the package such as `dot-gitignore` would be translated to `.gitignore` and then ignored by the default ignore list. However any file named `dot-*` in a package is obviously intended to be stowed as a dot file, so should not be ignored. To fix this, ignore based on the name in the package, not the potentially translated name used for stowing. --- NEWS | 12 ++++++++++++ doc/stow.texi | 7 +++++++ lib/Stow.pm.in | 13 +++++++------ t/dotfiles.t | 33 ++++++++++++++++++++++++++++++++- 4 files changed, 58 insertions(+), 7 deletions(-) diff --git a/NEWS b/NEWS index 4706fe7..fda7c2a 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,18 @@ News file for Stow. which reintroduced this warning when running Stow on Perl >= 5.40.0. This has now been fixed. +*** =--dotfiles= option now works correctly with ignore lists + + If the =--dotfiles= option was enabled, files in the package such + as =dot-gitignore= would be translated to =.gitignore= prior to + stowing, and consequently ignored by the default ignore list. + However any file named =dot-*= in a package is obviously intended + to be stowed as a dot file, so should not be ignored. + + To fix this, Stow now ignores based on the name in the package, + not the potentially translated name used for stowing, and + similarly for unstowing. + *** Use shell-like parsing for =.stowrc= arguments If a file path or regex in =.stowrc= has a space, the option diff --git a/doc/stow.texi b/doc/stow.texi index 6eba53e..06f6b0d 100644 --- a/doc/stow.texi +++ b/doc/stow.texi @@ -437,6 +437,13 @@ option, Stow will create symlinks from @file{.bashrc} to @file{stow/dot-emacs.d/init.el}. Any other files, whose name does not begin with @samp{dot-}, will be processed as usual. +Note that when this option is enabled, any package file or directory +prefixed with @samp{dot-} is assumed to be named deliberately to be +stowed with a @samp{.} prefix, and therefore will only be ignored if +there is an entry in the ignore list (@xref{Ignore Lists}) which matches +this prefix. So for example, by default @file{dot-gitignore} would not +be ignored even though @samp{\.gitignore} is in the default ignore list. + @item --no-folding This disables any further tree folding (@pxref{tree folding}) or diff --git a/lib/Stow.pm.in b/lib/Stow.pm.in index b9b3b30..2bbaf46 100755 --- a/lib/Stow.pm.in +++ b/lib/Stow.pm.in @@ -431,17 +431,17 @@ sub stow_contents { my $package_node_path = join_paths($pkg_subdir, $node); my $target_node = $node; + my $target_node_path = join_paths($target_subdir, $target_node); + next NODE if $self->ignore($stow_path, $package, $target_node_path); if ($self->{dotfiles}) { my $adjusted = adjust_dotfile($node); if ($adjusted ne $node) { debug(4, 1, "Adjusting: $node => $adjusted"); $target_node = $adjusted; + $target_node_path = join_paths($target_subdir, $target_node); } } - my $target_node_path = join_paths($target_subdir, $target_node); - - next NODE if $self->ignore($stow_path, $package, $target_node_path); $self->stow_node( $stow_path, @@ -800,6 +800,9 @@ sub unstow_contents { my $package_node = $node; my $target_node = $node; + my $target_node_path = join_paths($target_subdir, $target_node); + + next NODE if $self->ignore($self->{stow_path}, $package, $target_node_path); if ($self->{dotfiles}) { if ($self->{compat}) { @@ -819,13 +822,11 @@ sub unstow_contents { if ($adjusted ne $node) { debug(4, 1, "Adjusting: $node => $adjusted"); $target_node = $adjusted; + $target_node_path = join_paths($target_subdir, $target_node); } } } my $package_node_path = join_paths($pkg_subdir, $package_node); - my $target_node_path = join_paths($target_subdir, $target_node); - - next NODE if $self->ignore($self->{stow_path}, $package, $target_node_path); $self->unstow_node( $package, diff --git a/t/dotfiles.t b/t/dotfiles.t index 643b873..4db742c 100755 --- a/t/dotfiles.t +++ b/t/dotfiles.t @@ -22,7 +22,7 @@ use strict; use warnings; -use Test::More tests => 12; +use Test::More tests => 14; use English qw(-no_match_vars); use Stow::Util qw(adjust_dotfile unadjust_dotfile); @@ -185,6 +185,21 @@ subtest("dot-. should not have that part expanded.", sub { ); }); +subtest("when stowing, dot-gitignore is not ignored by default", sub { + plan tests => 1; + $stow = new_Stow(dir => '../stow', dotfiles => 1); + + make_file('../stow/dotfiles/dot-gitignore'); + + $stow->plan_stow('dotfiles'); + $stow->process_tasks(); + is( + readlink('.gitignore'), + '../stow/dotfiles/dot-gitignore', + => "dot-gitignore shouldn't have been ignored" + ); +}); + subtest("unstow .bar from dot-bar", sub { plan tests => 3; $stow = new_Stow(dir => '../stow', dotfiles => 1); @@ -233,3 +248,19 @@ subtest("unstow dot-emacs.d/init.el in --compat mode", sub { ok(! -e '.emacs.d/init.el', '.emacs.d/init.el unstowed'); ok(-d '.emacs.d/' => '.emacs.d left behind'); }); + +subtest("when unstowing, dot-gitignore is not ignored by default", sub { + plan tests => 1; + $stow = new_Stow(dir => '../stow', dotfiles => 1); + + system('pwd'); + make_file('../stow/dotfiles/dot-gitignore'); + -e '.gitignore' or make_link('.gitignore', '../stow/dotfiles/dot-gitignore'); + + $stow->plan_unstow('dotfiles'); + $stow->process_tasks(); + ok( + ! -e ('.gitignore') + => "dot-gitignore shouldn't have been ignored" + ); +});