From 37025f55dfbbf15c02dc5bca3c3c80eeb099f89c Mon Sep 17 00:00:00 2001 From: Adam Spiers Date: Sun, 8 Sep 2024 13:05:16 +0100 Subject: [PATCH] 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" + ); +});