3 # This file is part of GNU Stow.
5 # GNU Stow is free software: you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # GNU Stow is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 # General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see https://www.gnu.org/licenses/.
22 Stow - manage farms of symbolic links
26 my $stow = new Stow(%$options);
28 $stow->plan_unstow(@pkgs_to_unstow);
29 $stow->plan_stow (@pkgs_to_stow);
31 my %conflicts = $stow->get_conflicts;
32 $stow->process_tasks() unless %conflicts;
36 This is the backend Perl module for GNU Stow, a program for managing
37 the installation of software packages, keeping them separate
38 (C</usr/local/stow/emacs> vs. C</usr/local/stow/perl>, for example)
39 while making them appear to be installed in the same place
42 Stow doesn't store an extra state between runs, so there's no danger
43 of mangling directories when file hierarchies don't match the
44 database. Also, stow will never delete any files, directories, or
45 links that appear in a stow directory, so it is always possible to
46 rebuild the target tree.
53 use Carp
qw(carp cluck croak confess longmess);
54 use File
::Copy
qw(move);
58 use Stow
::Util
qw(set_debug_level debug error set_test_mode
59 join_paths restore_cwd canon_path parent adjust_dotfile);
61 our $ProgramName = 'stow';
62 our $VERSION = '@VERSION@';
64 our $LOCAL_IGNORE_FILE = '.stow-local-ignore';
65 our $GLOBAL_IGNORE_FILE = '.stow-global-ignore';
67 our @default_global_ignore_regexps =
68 __PACKAGE__
->get_default_global_ignore_regexps();
70 # These are the default options for each Stow instance.
71 our %DEFAULT_OPTIONS = (
90 =head3 Required options
94 =item * dir - the stow directory
96 =item * target - the target directory
100 =head3 Non-mandatory options
102 See the documentation for the F<stow> CLI front-end for information on these.
130 N.B. This sets the current working directory to the target directory.
136 my $class = ref($self) || $self;
139 my $new = bless { }, $class;
141 $new->{action_count
} = 0;
143 for my $required_arg (qw(dir target)) {
144 croak
"$class->new() called without '$required_arg' parameter\n"
145 unless exists $opts{$required_arg};
146 $new->{$required_arg} = delete $opts{$required_arg};
149 for my $opt (keys %DEFAULT_OPTIONS) {
150 $new->{$opt} = exists $opts{$opt} ?
delete $opts{$opt}
151 : $DEFAULT_OPTIONS{$opt};
155 croak
"$class->new() called with unrecognised parameter(s): ",
156 join(", ", keys %opts), "\n";
159 set_debug_level
($new->get_verbosity());
160 set_test_mode
($new->{test_mode
});
161 $new->set_stow_dir();
170 return $self->{verbose
} unless $self->{test_mode
};
172 return 0 unless exists $ENV{TEST_VERBOSE
};
173 return 0 unless length $ENV{TEST_VERBOSE
};
175 # Convert TEST_VERBOSE=y into numeric value
176 $ENV{TEST_VERBOSE
} = 3 if $ENV{TEST_VERBOSE
} !~ /^\d+$/;
178 return $ENV{TEST_VERBOSE
};
181 =head2 set_stow_dir([$dir])
183 Sets a new stow directory. This allows the use of multiple stow
184 directories within one Stow instance, e.g.
186 $stow->plan_stow('foo');
187 $stow->set_stow_dir('/different/stow/dir');
188 $stow->plan_stow('bar');
189 $stow->process_tasks;
191 If C<$dir> is omitted, uses the value of the C<dir> parameter passed
192 to the L<new()> constructor.
203 my $stow_dir = canon_path
($self->{dir
});
204 my $target = canon_path
($self->{target
});
206 # Calculate relative path from target directory to stow directory.
207 # This will be commonly used as a prefix for constructing and
208 # recognising symlinks "installed" in the target directory which
209 # point to package files under the stow directory.
210 $self->{stow_path
} = File
::Spec
->abs2rel($stow_dir, $target);
212 debug
(2, 0, "stow dir is $stow_dir");
213 debug
(2, 0, "stow dir path relative to target $target is $self->{stow_path}");
219 # Store conflicts during pre-processing
220 $self->{conflicts
} = {};
221 $self->{conflict_count
} = 0;
223 # Store command line packages to stow (-S and -R)
224 $self->{pkgs_to_stow
} = [];
226 # Store command line packages to unstow (-D and -R)
227 $self->{pkgs_to_delete
} = [];
229 # The following structures are used by the abstractions that allow us to
230 # defer operating on the filesystem until after all potential conflicts have
233 # $self->{tasks}: list of operations to be performed (in order)
234 # each element is a hash ref of the form
236 # action => ... ('create' or 'remove' or 'move')
237 # type => ... ('link' or 'dir' or 'file')
238 # path => ... (unique)
239 # source => ... (only for links)
240 # dest => ... (only for moving files)
244 # $self->{dir_task_for}: map a path to the corresponding directory task reference
245 # This structure allows us to quickly determine if a path has an existing
246 # directory task associated with it.
247 $self->{dir_task_for
} = {};
249 # $self->{link_task_for}: map a path to the corresponding directory task reference
250 # This structure allows us to quickly determine if a path has an existing
251 # directory task associated with it.
252 $self->{link_task_for
} = {};
254 # N.B.: directory tasks and link tasks are NOT mutually exclusive due
255 # to tree splitting (which involves a remove link task followed by
256 # a create directory task).
261 =head2 plan_unstow(@packages)
263 Plan which symlink/directory creation/removal tasks need to be executed
264 in order to unstow the given packages. Any potential conflicts are then
265 accessible via L<get_conflicts()>.
273 return unless @packages;
275 debug
(2, 0, "Planning unstow of: @packages ...");
277 $self->within_target_do(sub {
278 for my $package (@packages) {
279 my $pkg_path = join_paths
($self->{stow_path
}, $package);
280 if (not -d
$pkg_path) {
281 error
("The stow directory $self->{stow_path} does not contain package $package");
283 debug
(2, 0, "Planning unstow of package $package...");
284 $self->unstow_contents(
289 debug
(2, 0, "Planning unstow of package $package... done");
290 $self->{action_count
}++;
295 =head2 plan_stow(@packages)
297 Plan which symlink/directory creation/removal tasks need to be executed
298 in order to stow the given packages. Any potential conflicts are then
299 accessible via L<get_conflicts()>.
307 return unless @packages;
309 debug
(2, 0, "Planning stow of: @packages ...");
311 $self->within_target_do(sub {
312 for my $package (@packages) {
313 my $pkg_path = join_paths
($self->{stow_path
}, $package);
314 if (not -d
$pkg_path) {
315 error
("The stow directory $self->{stow_path} does not contain package $package");
317 debug
(2, 0, "Planning stow of package $package...");
318 $self->stow_contents(
322 $pkg_path, # source from target
325 debug
(2, 0, "Planning stow of package $package... done");
326 $self->{action_count
}++;
331 =head2 within_target_do($code)
333 Execute code within target directory, preserving cwd.
339 Anonymous subroutine to execute within target dir.
343 This is done to ensure that the consumer of the Stow interface doesn't
344 have to worry about (a) what their cwd is, and (b) that their cwd
349 sub within_target_do
{
354 chdir($self->{target
})
355 or error
("Cannot chdir to target tree: $self->{target} ($!)");
356 debug
(3, 0, "cwd now $self->{target}");
361 debug
(3, 0, "cwd restored to $cwd");
364 =head2 stow_contents($stow_path, $package, $target_subdir, $source)
366 Stow the contents of the given directory.
372 Relative path from current (i.e. target) directory to the stow dir
373 containing the package to be stowed. This can differ from
374 C<$self->{stow_path}> when unfolding a (sub)tree which is already
375 stowed from a package in a different stow directory (see the "Multiple
376 Stow Directories" section of the manual).
380 The package whose contents are being stowed.
384 Subpath relative to package directory which needs stowing as a symlink
385 at subpath relative to target directory.
389 Relative path from the (sub)dir of target to symlink source.
393 C<stow_node()> and C<stow_contents()> are mutually recursive.
394 C<$source> and C<$target_subdir> are used for creating the symlink.
400 my ($stow_path, $package, $target_subdir, $source, $level) = @_;
402 # Calculate the path to the package directory or sub-directory
403 # whose contents need to be stowed, relative to the current
404 # (target directory). This is needed so that we can check it's a
405 # valid directory, and can read its contents to iterate over them.
407 # Note that $source refers to the same package (sub-)directory,
408 # but instead it's relative to the target directory or
409 # sub-directory where the symlink will be installed when the plans
412 # Remove leading $level times .. from $source
414 my $path = join '/', map { (++$n <= $level) ?
( ) : $_ } (split m
{/+}, $source);
416 return if $self->should_skip_target($target_subdir);
419 my $msg = "Stowing contents of $path (cwd=$cwd)";
420 $msg =~ s!$ENV{HOME}(/|$)!~$1!g;
422 debug
(4, 1, "=> $source");
424 error
("stow_contents() called with non-directory package path: $path")
426 error
("stow_contents() called with non-directory target: $target_subdir")
427 unless $self->is_a_node($target_subdir);
429 opendir my $DIR, $path
430 or error
("cannot read directory: $path ($!)");
431 my @listing = readdir $DIR;
435 for my $node (@listing) {
436 next NODE
if $node eq '.';
437 next NODE
if $node eq '..';
438 my $node_target = join_paths
($target_subdir, $node);
439 next NODE
if $self->ignore($stow_path, $package, $node_target);
441 if ($self->{dotfiles
}) {
442 my $adj_node_target = adjust_dotfile
($node_target);
443 debug
(4, 1, "Adjusting: $node_target => $adj_node_target");
444 $node_target = $adj_node_target;
450 $node_target, # target, potentially adjusted for dot- prefix
451 join_paths
($source, $node), # source
457 =head2 stow_node($stow_path, $package, $target_subpath, $source)
465 Relative path from current (i.e. target) directory to the stow dir
466 containing the node to be stowed. This can differ from
467 C<$self->{stow_path}> when unfolding a (sub)tree which is already
468 stowed from a package in a different stow directory (see the "Multiple
469 Stow Directories" section of the manual).
473 The package containing the node being stowed
475 =item $target_subpath
477 Subpath relative to package directory of node which needs stowing as a
478 symlink at subpath relative to target directory.
482 Relative path to symlink source from the dir of target.
486 C<stow_node()> and C<stow_contents()> are mutually recursive.
487 C<$source> and C<$target_subpath> are used for creating the symlink.
488 C<$target_subpath> is used for folding/unfolding trees as necessary.
494 my ($stow_path, $package, $target_subpath, $source, $level) = @_;
496 my $path = join_paths
($stow_path, $package, $target_subpath);
498 debug
(3, 0, "Stowing entry $stow_path / $package / $target_subpath");
499 debug
(4, 1, "=> $source");
501 # Don't try to stow absolute symlinks (they can't be unstowed)
503 my $second_source = $self->read_a_link($source);
504 if ($second_source =~ m{\A/}) {
508 "source is an absolute symlink $source => $second_source"
510 debug
(3, 0, "Absolute symlinks cannot be unstowed");
515 # Does the target already exist?
516 if ($self->is_a_link($target_subpath)) {
517 # Where is the link pointing?
518 my $existing_link_dest = $self->read_a_link($target_subpath);
519 if (not $existing_link_dest) {
520 error
("Could not read link: $target_subpath");
522 debug
(4, 1, "Evaluate existing link: $target_subpath => $existing_link_dest");
524 # Does it point to a node under any stow directory?
525 my ($existing_path, $existing_stow_path, $existing_package) =
526 $self->find_stowed_path($target_subpath, $existing_link_dest);
527 if (not $existing_path) {
531 "existing target is not owned by stow: $target_subpath"
536 # Does the existing $target_subpath actually point to anything?
537 if ($self->is_a_node($existing_path)) {
538 if ($existing_link_dest eq $source) {
539 debug
(2, 0, "--- Skipping $target_subpath as it already points to $source");
541 elsif ($self->defer($target_subpath)) {
542 debug
(2, 0, "--- Deferring installation of: $target_subpath");
544 elsif ($self->override($target_subpath)) {
545 debug
(2, 0, "--- Overriding installation of: $target_subpath");
546 $self->do_unlink($target_subpath);
547 $self->do_link($source, $target_subpath);
549 elsif ($self->is_a_dir(join_paths
(parent
($target_subpath), $existing_link_dest)) &&
550 $self->is_a_dir(join_paths
(parent
($target_subpath), $source)))
553 # If the existing link points to a directory,
554 # and the proposed new link points to a directory,
555 # then we can unfold (split open) the tree at that point
557 debug
(2, 0, "--- Unfolding $target_subpath which was already owned by $existing_package");
558 $self->do_unlink($target_subpath);
559 $self->do_mkdir($target_subpath);
560 $self->stow_contents(
564 join_paths
('..', $existing_link_dest),
567 $self->stow_contents(
571 join_paths
('..', $source),
579 "existing target is stowed to a different package: "
580 . "$target_subpath => $existing_link_dest"
585 # The existing link is invalid, so replace it with a good link
586 debug
(2, 0, "--- replacing invalid link: $path");
587 $self->do_unlink($target_subpath);
588 $self->do_link($source, $target_subpath);
591 elsif ($self->is_a_node($target_subpath)) {
592 debug
(4, 1, "Evaluate existing node: $target_subpath");
593 if ($self->is_a_dir($target_subpath)) {
594 $self->stow_contents(
598 join_paths
('..', $source),
603 if ($self->{adopt
}) {
604 $self->do_mv($target_subpath, $path);
605 $self->do_link($source, $target_subpath);
611 "existing target is neither a link nor a directory: $target_subpath"
616 elsif ($self->{'no-folding'} && -d
$path && ! -l
$path) {
617 $self->do_mkdir($target_subpath);
618 $self->stow_contents(
622 join_paths
('..', $source),
627 $self->do_link($source, $target_subpath);
632 =head2 should_skip_target($target_subdir)
634 Determine whether C<$target_subdir> is a stow directory which should
635 not be stowed to or unstowed from. This mechanism protects stow
636 directories from being altered by stow, and is a necessary safety
637 check because the stow directory could live beneath the target
642 =item $target_subdir => relative path to symlink target from the current directory
646 Returns true iff target is a stow directory
648 cwd must be the top-level target directory, otherwise
649 C<marked_stow_dir()> won't work.
653 sub should_skip_target
{
657 # Don't try to remove anything under a stow directory
658 if ($target eq $self->{stow_path
}) {
659 warn "WARNING: skipping target which was current stow directory $target\n";
663 if ($self->marked_stow_dir($target)) {
664 warn "WARNING: skipping marked Stow directory $target\n";
668 if (-e join_paths
($target, ".nonstow")) {
669 warn "WARNING: skipping protected directory $target\n";
673 debug
(4, 1, "$target not protected; shouldn't skip");
677 # cwd must be the top-level target directory, otherwise
678 # marked_stow_dir() won't work.
679 sub marked_stow_dir
{
682 if (-e join_paths
($dir, ".stow")) {
683 debug
(5, 5, "> $dir contained .stow");
689 =head2 unstow_contents($package, $target)
691 Unstow the contents of the given directory
697 The package whose contents are being unstowed.
701 Relative path to symlink target from the current directory.
705 C<unstow_node()> and C<unstow_contents()> are mutually recursive.
706 Here we traverse the source tree, rather than the target tree.
710 sub unstow_contents
{
712 my ($package, $target_subdir, $path) = @_;
714 return if $self->should_skip_target($target_subdir);
717 my $msg = "Unstowing from $target_subdir (cwd=$cwd, stow dir=$self->{stow_path})";
718 $msg =~ s!$ENV{HOME}/!~/!g;
720 debug
(4, 1, "source path is $path");
722 if ($self->{compat
}) {
723 # In compat mode we traverse the target tree not the source tree,
724 # so we're unstowing the contents of /target/foo, there's no
725 # guarantee that the corresponding /stow/mypkg/foo exists.
726 error
("unstow_contents() in compat mode called with non-directory target: $target_subdir")
727 unless -d
$target_subdir;
730 # We traverse the source tree not the target tree, so $path must exist.
731 error
("unstow_contents() called with non-directory path: $path")
734 # When called at the top level, $target_subdir should exist. And
735 # unstow_node() should only call this via mutual recursion if
736 # $target_subdir exists.
737 error
("unstow_contents() called with invalid target: $target_subdir")
738 unless $self->is_a_node($target_subdir);
741 my $dir = $self->{compat
} ?
$target_subdir : $path;
742 opendir my $DIR, $dir
743 or error
("cannot read directory: $dir ($!)");
744 my @listing = readdir $DIR;
748 for my $node (@listing) {
749 next NODE
if $node eq '.';
750 next NODE
if $node eq '..';
751 my $node_target = join_paths
($target_subdir, $node);
752 next NODE
if $self->ignore($self->{stow_path
}, $package, $node_target);
754 if ($self->{dotfiles
}) {
755 my $adj_node_target = adjust_dotfile
($node_target);
756 debug
(4, 1, "Adjusting: $node_target => $adj_node_target");
757 $node_target = $adj_node_target;
760 $self->unstow_node($package, $node_target, join_paths
($path, $node));
763 if (! $self->{compat
} && -d
$target_subdir) {
764 $self->cleanup_invalid_links($target_subdir);
768 =head2 unstow_node($package, $target_subpath)
770 Unstow the given node.
776 The package containing the node being unstowed.
778 =item $target_subpath
780 Relative path to symlink target from the current directory.
784 C<unstow_node()> and C<unstow_contents()> are mutually recursive.
790 my ($package, $target_subpath, $source) = @_;
792 my $pkg_path_from_cwd = join_paths
($self->{stow_path
}, $package, $target_subpath);
794 debug
(3, 1, "Unstowing $pkg_path_from_cwd");
795 debug
(4, 2, "target is $target_subpath");
797 # Does the target exist?
798 if ($self->is_a_link($target_subpath)) {
799 $self->unstow_link_node($package, $target_subpath, $pkg_path_from_cwd);
801 elsif ($self->{compat
} && -d
$target_subpath) {
802 $self->unstow_contents($package, $target_subpath, $pkg_path_from_cwd);
804 # This action may have made the parent directory foldable
805 if (my $parent = $self->foldable($target_subpath)) {
806 $self->fold_tree($target_subpath, $parent);
809 elsif (-e
$target_subpath) {
810 if ($self->{compat
}) {
814 "existing target is neither a link nor a directory: $target_subpath",
818 $self->unstow_existing_node($package, $target_subpath, $source);
822 debug
(2, 1, "$target_subpath did not exist to be unstowed");
827 sub unstow_link_node
{
829 my ($package, $target_subpath, $pkg_path_from_cwd) = @_;
830 debug
(4, 2, "Evaluate existing link: $target_subpath");
832 # Where is the link pointing?
833 my $existing_source = $self->read_a_link($target_subpath);
834 if (not $existing_source) {
835 error
("Could not read link: $target_subpath");
838 if ($existing_source =~ m{\A/}) {
839 warn "Ignoring an absolute symlink: $target_subpath => $existing_source\n";
843 # Does it point to a node under any stow directory?
844 my ($existing_path, $existing_stow_path, $existing_package) =
845 $self->find_stowed_path($target_subpath, $existing_source);
846 if (not $existing_path) {
847 if ($self->{compat
}) {
848 # We're traversing the target tree not the package tree,
849 # so we definitely expect to find stuff not owned by stow.
850 # Therefore we can't flag a conflict.
857 "existing target is not owned by stow: $target_subpath => $existing_source"
863 # Does the existing $target_subpath actually point to anything?
864 if (-e
$existing_path) {
865 $self->unstow_valid_link($pkg_path_from_cwd, $target_subpath, $existing_path);
868 debug
(2, 0, "--- removing invalid link into a stow directory: $pkg_path_from_cwd");
869 $self->do_unlink($target_subpath);
873 sub unstow_valid_link
{
875 my ($pkg_path_from_cwd, $target_subpath, $existing_path) = @_;
876 # Does link points to the right place?
878 # Adjust for dotfile if necessary.
879 if ($self->{dotfiles
}) {
880 $existing_path = adjust_dotfile
($existing_path);
883 if ($existing_path eq $pkg_path_from_cwd) {
884 $self->do_unlink($target_subpath);
887 # XXX we quietly ignore links that are stowed to a different
890 #elsif (defer($target_subpath)) {
891 # debug(2, 0, "--- deferring to installation of: $target_subpath");
893 #elsif ($self->override($target_subpath)) {
894 # debug(2, 0, "--- overriding installation of: $target_subpath");
895 # $self->do_unlink($target_subpath);
901 # "existing target is stowed to a different package: "
902 # . "$target_subpath => $existing_source"
907 sub unstow_existing_node
{
909 my ($package, $target_subpath, $source) = @_;
910 debug
(4, 2, "Evaluate existing node: $target_subpath");
911 if (-d
$target_subpath) {
912 $self->unstow_contents($package, $target_subpath, $source);
914 # This action may have made the parent directory foldable
915 if (my $parent = $self->foldable($target_subpath)) {
916 $self->fold_tree($target_subpath, $parent);
923 "existing target is neither a link nor a directory: $target_subpath",
928 =head2 link_owned_by_package($target_subpath, $source)
930 Determine whether the given link points to a member of a stowed
935 =item $target_subpath
937 Path to a symbolic link under current directory.
941 Where that link points to.
945 Lossy wrapper around find_stowed_path().
947 Returns the package iff link is owned by stow, otherwise ''.
951 sub link_owned_by_package
{
953 my ($target_subpath, $source) = @_;
955 my ($pkg_path_from_cwd, $stow_path, $package) =
956 $self->find_stowed_path($target_subpath, $source);
960 =head2 find_stowed_path($target_subpath, $link_dest)
962 Determine whether the given symlink within the target directory is a
963 stowed path pointing to a member of a package under the stow dir, and
964 if so, obtain a breakdown of information about this stowed path.
968 =item $target_subpath
970 Path to a symbolic link somewhere under the target directory, relative
971 to the top-level target directory (which is also expected to be the
976 Where that link points to (needed because link might not exist yet due
977 to two-phase approach, so we can't just call C<readlink()>). If this
978 is owned by Stow, it will be expressed relative to (the directory
979 containing) C<$target_subpath>. However if it's not, it could of course be
980 relative or absolute, point absolutely anywhere, and could even be
985 Returns C<($path, $stow_path, $package)> where C<$path> and
986 C<$stow_path> are relative from the top-level target directory.
987 C<$path> is the full relative path to the member of the package
988 pointed to by C<$link_dest>; C<$stow_path> is the relative path to the
989 stow directory; and C<$package> is the name of the package; or C<('',
990 '', '')> if link is not owned by stow.
992 cwd must be the top-level target directory, otherwise
993 C<find_containing_marked_stow_dir()> won't work. Allow for stow dir
994 not being under target dir.
998 sub find_stowed_path
{
1000 my ($target_subpath, $link_dest) = @_;
1002 if (substr($link_dest, 0, 1) eq '/') {
1003 # Symlink points to an absolute path, therefore it cannot be
1005 return ('', '', '');
1008 # Evaluate softlink relative to its target, without relying on
1009 # what's actually on the filesystem, since the link might not
1011 debug
(4, 2, "find_stowed_path(target=$target_subpath; source=$link_dest)");
1012 my $dest = join_paths
(parent
($target_subpath), $link_dest);
1013 debug
(4, 3, "is symlink destination $dest owned by stow?");
1015 # First check whether the link is owned by the current stow
1016 # directory, in which case $dest will be a prefix of
1017 # $self->{stow_path}.
1018 my ($package, $path) = $self->link_dest_within_stow_dir($dest);
1019 if (length $package) {
1020 debug
(4, 3, "yes - package $package in $self->{stow_path} may contain $path");
1021 return ($dest, $self->{stow_path
}, $package);
1024 # If no .stow file was found, we need to find out whether it's
1025 # owned by the current stow directory, in which case $path will be
1026 # a prefix of $self->{stow_path}.
1027 my ($stow_path, $ext_package) = $self->find_containing_marked_stow_dir($dest);
1028 if (length $stow_path) {
1029 debug
(5, 5, "yes - $stow_path in $dest was marked as a stow dir; package=$ext_package");
1030 return ($dest, $stow_path, $ext_package);
1033 return ('', '', '');
1036 =head2 link_dest_within_stow_dir($link_dest)
1038 Detect whether symlink destination is within current stow dir
1042 =item $link_dest - destination of the symlink relative
1046 Returns C<($package, $pkg_subpath)> - package within the current stow
1047 dir and subpath within that package which the symlink points to.
1051 sub link_dest_within_stow_dir
{
1053 my ($link_dest) = @_;
1055 debug
(4, 4, "common prefix? link_dest=$link_dest; stow_path=$self->{stow_path}");
1057 my $removed = $link_dest =~ s
,^\Q
$self->{stow_path
}/,,;
1059 debug
(4, 3, "no - $link_dest not under $self->{stow_path}");
1063 debug
(4, 4, "remaining after removing $self->{stow_path}: $link_dest");
1064 my @dirs = File
::Spec
->splitdir($link_dest);
1065 my $package = shift @dirs;
1066 my $pkg_subpath = File
::Spec
->catdir(@dirs);
1067 return ($package, $pkg_subpath);
1070 =head2 find_containing_marked_stow_dir($pkg_path_from_cwd)
1072 Detect whether path is within a marked stow directory
1076 =item $pkg_path_from_cwd => path to directory to check
1080 Returns C<($stow_path, $package)> where C<$stow_path> is the highest
1081 directory (relative from the top-level target directory) which is
1082 marked as a Stow directory, and C<$package> is the containing package;
1083 or C<('', '')> if no containing directory is marked as a stow
1086 cwd must be the top-level target directory, otherwise
1087 C<marked_stow_dir()> won't work.
1091 sub find_containing_marked_stow_dir
{
1093 my ($pkg_path_from_cwd) = @_;
1095 # Search for .stow files - this allows us to detect links
1096 # owned by stow directories other than the current one.
1097 my @segments = File
::Spec
->splitdir($pkg_path_from_cwd);
1098 for my $last_segment (0 .. $#segments) {
1099 my $pkg_path_from_cwd = join_paths
(@segments[0 .. $last_segment]);
1100 debug
(5, 5, "is $pkg_path_from_cwd marked stow dir?");
1101 if ($self->marked_stow_dir($pkg_path_from_cwd)) {
1102 if ($last_segment == $#segments) {
1103 # This should probably never happen. Even if it did,
1104 # there would be no way of calculating $package.
1105 internal_error
("find_stowed_path() called directly on stow dir");
1108 my $package = $segments[$last_segment + 1];
1109 return ($pkg_path_from_cwd, $package);
1115 =head2 cleanup_invalid_links($dir)
1117 Clean up orphaned links that may block folding
1123 Path to directory to check
1127 This is invoked by C<unstow_contents()>. We only clean up links which
1128 are both orphaned and owned by Stow, i.e. they point to a non-existent
1129 location within a Stow package. These can block tree folding, and
1130 they can easily occur when a file in Stow package is renamed or
1131 removed, so the benefit should outweigh the low risk of actually
1132 someone wanting to keep an orphaned link to within a Stow package.
1136 sub cleanup_invalid_links
{
1141 debug
(2, 0, "Cleaning up any invalid links in $dir (pwd=$cwd)");
1144 internal_error
("cleanup_invalid_links() called with a non-directory: $dir");
1147 opendir my $DIR, $dir
1148 or error
("cannot read directory: $dir ($!)");
1149 my @listing = readdir $DIR;
1153 for my $node (@listing) {
1154 next NODE
if $node eq '.';
1155 next NODE
if $node eq '..';
1157 my $node_path = join_paths
($dir, $node);
1159 next unless -l
$node_path;
1161 debug
(4, 1, "Checking validity of link $node_path");
1163 if (exists $self->{link_task_for
}{$node_path}) {
1164 my $action = $self->{link_task_for
}{$node_path}{action
};
1165 if ($action ne 'remove') {
1166 warn "Unexpected action $action scheduled for $node_path; skipping clean-up\n";
1169 debug
(4, 2, "$node_path scheduled for removal; skipping clean-up");
1174 # Where is the link pointing?
1175 # (don't use read_a_link() here)
1176 my $link_dest = readlink($node_path);
1177 if (not $link_dest) {
1178 error
("Could not read link $node_path");
1181 my $target_subpath = join_paths
($dir, $link_dest);
1182 debug
(4, 2, "join $dir $link_dest");
1183 if (-e
$target_subpath) {
1184 debug
(4, 2, "Link target $link_dest exists at $target_subpath; skipping clean up");
1188 debug
(4, 2, "Link target $link_dest doesn't exist at $target_subpath");
1192 "Checking whether valid link $node_path -> $link_dest is " .
1195 my $owner = $self->link_owned_by_package($node_path, $link_dest);
1198 debug
(2, 0, "--- removing link owned by $owner: $node_path => " .
1199 join_paths
($dir, $link_dest));
1200 $self->do_unlink($node_path);
1207 =head2 foldable($target)
1209 Determine whether a tree can be folded
1219 Returns path to the parent dir iff the tree can be safely folded. The
1220 path returned is relative to the parent of $target, i.e. it can be
1221 used as the source for a replacement symlink.
1229 debug
(3, 2, "Is $target foldable?");
1230 if ($self->{'no-folding'}) {
1231 debug
(3, 3, "no because --no-folding enabled");
1235 opendir my $DIR, $target
1236 or error
(qq{Cannot
read directory
"$target" ($!)\n});
1237 my @listing = readdir $DIR;
1242 for my $node (@listing) {
1244 next NODE
if $node eq '.';
1245 next NODE
if $node eq '..';
1247 my $path = join_paths
($target, $node);
1249 # Skip nodes scheduled for removal
1250 next NODE
if not $self->is_a_node($path);
1252 # If it's not a link then we can't fold its parent
1253 return '' if not $self->is_a_link($path);
1255 # Where is the link pointing?
1256 my $source = $self->read_a_link($path);
1258 error
("Could not read link $path");
1260 if ($parent eq '') {
1261 $parent = parent
($source)
1263 elsif ($parent ne parent
($source)) {
1267 return '' if not $parent;
1269 # If we get here then all nodes inside $target are links, and those links
1270 # point to nodes inside the same directory.
1272 # chop of leading '..' to get the path to the common parent directory
1273 # relative to the parent of our $target
1274 $parent =~ s{\A\.\./}{};
1276 # If the resulting path is owned by stow, we can fold it
1277 if ($self->link_owned_by_package($target, $parent)) {
1278 debug
(3, 3, "$target is foldable");
1286 =head2 fold_tree($target, source)
1294 directory that we will replace with a link to $source
1298 link to the folded tree source
1302 Only called iff foldable() is true so we can remove some checks.
1308 my ($target, $source) = @_;
1310 debug
(3, 0, "--- Folding tree: $target => $source");
1312 opendir my $DIR, $target
1313 or error
(qq{Cannot
read directory
"$target" ($!)\n});
1314 my @listing = readdir $DIR;
1318 for my $node (@listing) {
1319 next NODE
if $node eq '.';
1320 next NODE
if $node eq '..';
1321 next NODE
if not $self->is_a_node(join_paths
($target, $node));
1322 $self->do_unlink(join_paths
($target, $node));
1324 $self->do_rmdir($target);
1325 $self->do_link($source, $target);
1330 =head2 conflict($package, $message)
1332 Handle conflicts in stow operations
1338 the package involved with the conflicting operation
1342 a description of the conflict
1350 my ($action, $package, $message) = @_;
1352 debug
(2, 0, "CONFLICT when ${action}ing $package: $message");
1353 $self->{conflicts
}{$action}{$package} ||= [];
1354 push @
{ $self->{conflicts
}{$action}{$package} }, $message;
1355 $self->{conflict_count
}++;
1360 =head2 get_conflicts()
1362 Returns a nested hash of all potential conflicts discovered: the keys
1363 are actions ('stow' or 'unstow'), and the values are hashrefs whose
1364 keys are stow package names and whose values are conflict
1370 "existing target is not owned by stow: bin/a2p"
1371 "existing target is neither a link nor a directory: bin/perl"
1380 return %{ $self->{conflicts
} };
1383 =head2 get_conflict_count()
1385 Returns the number of conflicts found.
1389 sub get_conflict_count
{
1391 return $self->{conflict_count
};
1396 Returns a list of all symlink/directory creation/removal tasks.
1402 return @
{ $self->{tasks
} };
1405 =head2 get_action_count()
1407 Returns the number of actions planned for this Stow instance.
1411 sub get_action_count
{
1413 return $self->{action_count
};
1416 =head2 ignore($stow_path, $package, $target)
1418 Determine if the given path matches a regex in our ignore list.
1424 the stow directory containing the package
1428 the package containing the path
1432 the path to check against the ignore list relative to its package
1437 Returns true iff the path should be ignored.
1443 my ($stow_path, $package, $target) = @_;
1445 internal_error
(__PACKAGE__
. "::ignore() called with empty target")
1446 unless length $target;
1448 for my $suffix (@
{ $self->{ignore
} }) {
1449 if ($target =~ m/$suffix/) {
1450 debug
(4, 1, "Ignoring path $target due to --ignore=$suffix");
1455 my $package_dir = join_paths
($stow_path, $package);
1456 my ($path_regexp, $segment_regexp) =
1457 $self->get_ignore_regexps($package_dir);
1458 debug
(5, 2, "Ignore list regexp for paths: " .
1459 (defined $path_regexp ?
"/$path_regexp/" : "none"));
1460 debug
(5, 2, "Ignore list regexp for segments: " .
1461 (defined $segment_regexp ?
"/$segment_regexp/" : "none"));
1463 if (defined $path_regexp and "/$target" =~ $path_regexp) {
1464 debug
(4, 1, "Ignoring path /$target");
1468 (my $basename = $target) =~ s!.+/!!;
1469 if (defined $segment_regexp and $basename =~ $segment_regexp) {
1470 debug
(4, 1, "Ignoring path segment $basename");
1474 debug
(5, 1, "Not ignoring $target");
1478 sub get_ignore_regexps
{
1482 # N.B. the local and global stow ignore files have to have different
1484 # 1. the global one can be a symlink to within a stow
1485 # package, managed by stow itself, and
1486 # 2. the local ones can be ignored via hardcoded logic in
1487 # GlobsToRegexp(), so that they always stay within their stow packages.
1489 my $local_stow_ignore = join_paths
($dir, $LOCAL_IGNORE_FILE);
1490 my $global_stow_ignore = join_paths
($ENV{HOME
}, $GLOBAL_IGNORE_FILE);
1492 for my $file ($local_stow_ignore, $global_stow_ignore) {
1494 debug
(5, 1, "Using ignore file: $file");
1495 return $self->get_ignore_regexps_from_file($file);
1498 debug
(5, 1, "$file didn't exist");
1502 debug
(4, 1, "Using built-in ignore list");
1503 return @default_global_ignore_regexps;
1506 my %ignore_file_regexps;
1508 sub get_ignore_regexps_from_file
{
1512 if (exists $ignore_file_regexps{$file}) {
1513 debug
(4, 2, "Using memoized regexps from $file");
1514 return @
{ $ignore_file_regexps{$file} };
1517 if (! open(REGEXPS
, $file)) {
1518 debug
(4, 2, "Failed to open $file: $!");
1522 my @regexps = $self->get_ignore_regexps_from_fh(\
*REGEXPS
);
1525 $ignore_file_regexps{$file} = [ @regexps ];
1529 =head2 invalidate_memoized_regexp($file)
1531 For efficiency of performance, regular expressions are compiled from
1532 each ignore list file the first time it is used by the Stow process,
1533 and then memoized for future use. If you expect the contents of these
1534 files to change during a single run, you will need to invalidate the
1535 memoized value from this cache. This method allows you to do that.
1539 sub invalidate_memoized_regexp
{
1542 if (exists $ignore_file_regexps{$file}) {
1543 debug
(4, 2, "Invalidated memoized regexp for $file");
1544 delete $ignore_file_regexps{$file};
1547 debug
(2, 1, "WARNING: no memoized regexp for $file to invalidate");
1551 sub get_ignore_regexps_from_fh
{
1559 next if /^#/ or length($_) == 0;
1560 s/\s+#.+//; # strip comments to right of pattern
1565 # Local ignore lists should *always* stay within the stow directory,
1566 # because this is the only place stow looks for them.
1567 $regexps{"^/\Q$LOCAL_IGNORE_FILE\E\$"}++;
1569 return $self->compile_ignore_regexps(%regexps);
1572 sub compile_ignore_regexps
{
1576 my @segment_regexps;
1578 for my $regexp (keys %regexps) {
1579 if (index($regexp, '/') < 0) {
1580 # No / found in regexp, so use it for matching against basename
1581 push @segment_regexps, $regexp;
1584 # / found in regexp, so use it for matching against full path
1585 push @path_regexps, $regexp;
1589 my $segment_regexp = join '|', @segment_regexps;
1590 my $path_regexp = join '|', @path_regexps;
1591 $segment_regexp = @segment_regexps ?
1592 $self->compile_regexp("^($segment_regexp)\$") : undef;
1593 $path_regexp = @path_regexps ?
1594 $self->compile_regexp("(^|/)($path_regexp)(/|\$)") : undef;
1596 return ($path_regexp, $segment_regexp);
1599 sub compile_regexp
{
1602 my $compiled = eval { qr/$regexp/ };
1603 die "Failed to compile regexp: $@\n" if $@
;
1607 sub get_default_global_ignore_regexps
{
1609 # Bootstrap issue - first time we stow, we will be stowing
1610 # .cvsignore so it might not exist in ~ yet, or if it does, it could
1611 # be an old version missing the entries we need. So we make sure
1612 # they are there by hardcoding some crucial entries.
1613 return $class->get_ignore_regexps_from_fh(\
*DATA
);
1618 Determine if the given path matches a regex in our C<defer> list
1634 for my $prefix (@
{ $self->{defer
} }) {
1635 return 1 if $path =~ m/$prefix/;
1640 =head2 override($path)
1642 Determine if the given path matches a regex in our C<override> list
1658 for my $regex (@
{ $self->{override
} }) {
1659 return 1 if $path =~ m/$regex/;
1664 ##############################################################################
1666 # The following code provides the abstractions that allow us to defer operating
1667 # on the filesystem until after all potential conflcits have been assessed.
1669 ##############################################################################
1671 =head2 process_tasks()
1673 Process each task in the tasks list
1682 Throws : fatal error if tasks list is corrupted or a task fails
1689 debug
(2, 0, "Processing tasks...");
1691 # Strip out all tasks with a skip action
1692 $self->{tasks
} = [ grep { $_->{action
} ne 'skip' } @
{ $self->{tasks
} } ];
1694 if (not @
{ $self->{tasks
} }) {
1698 $self->within_target_do(sub {
1699 for my $task (@
{ $self->{tasks
} }) {
1700 $self->process_task($task);
1704 debug
(2, 0, "Processing tasks... done");
1707 =head2 process_task($task)
1709 Process a single task.
1713 =item $task => the task to process
1718 Throws : fatal error if task fails
1720 Must run from within target directory. Task involve either creating
1721 or deleting dirs and symlinks an action is set to 'skip' if it is
1722 found to be redundant
1730 if ($task->{action
} eq 'create') {
1731 if ($task->{type
} eq 'dir') {
1732 mkdir($task->{path
}, 0777)
1733 or error
("Could not create directory: $task->{path} ($!)");
1736 elsif ($task->{type
} eq 'link') {
1737 symlink $task->{source
}, $task->{path
}
1739 "Could not create symlink: %s => %s ($!)",
1746 elsif ($task->{action
} eq 'remove') {
1747 if ($task->{type
} eq 'dir') {
1749 or error
("Could not remove directory: $task->{path} ($!)");
1752 elsif ($task->{type
} eq 'link') {
1753 unlink $task->{path
}
1754 or error
("Could not remove link: $task->{path} ($!)");
1758 elsif ($task->{action
} eq 'move') {
1759 if ($task->{type
} eq 'file') {
1760 # rename() not good enough, since the stow directory
1761 # might be on a different filesystem to the target.
1762 move
$task->{path
}, $task->{dest
}
1763 or error
("Could not move $task->{path} -> $task->{dest} ($!)");
1768 # Should never happen.
1769 internal_error
("bad task action: $task->{action}");
1772 =head2 link_task_action($path)
1774 Finds the link task action for the given path, if there is one
1782 Returns C<'remove'>, C<'create'>, or C<''> if there is no action.
1783 Throws a fatal exception if an invalid action is found.
1787 sub link_task_action
{
1791 if (! exists $self->{link_task_for
}{$path}) {
1792 debug
(4, 1, "link_task_action($path): no task");
1796 my $action = $self->{link_task_for
}{$path}->{action
};
1797 internal_error
("bad task action: $action")
1798 unless $action eq 'remove' or $action eq 'create';
1800 debug
(4, 1, "link_task_action($path): link task exists with action $action");
1804 =head2 dir_task_action($path)
1806 Finds the dir task action for the given path, if there is one.
1814 Returns C<'remove'>, C<'create'>, or C<''> if there is no action.
1815 Throws a fatal exception if an invalid action is found.
1819 sub dir_task_action
{
1823 if (! exists $self->{dir_task_for
}{$path}) {
1824 debug
(4, 1, "dir_task_action($path): no task");
1828 my $action = $self->{dir_task_for
}{$path}->{action
};
1829 internal_error
("bad task action: $action")
1830 unless $action eq 'remove' or $action eq 'create';
1832 debug
(4, 1, "dir_task_action($path): dir task exists with action $action");
1836 =head2 parent_link_scheduled_for_removal($path)
1838 Determine whether the given path or any parent thereof is a link
1839 scheduled for removal
1851 sub parent_link_scheduled_for_removal
{
1856 for my $part (split m{/+}, $path) {
1857 $prefix = join_paths
($prefix, $part);
1858 debug
(4, 2, "parent_link_scheduled_for_removal($path): prefix $prefix");
1859 if (exists $self->{link_task_for
}{$prefix} and
1860 $self->{link_task_for
}{$prefix}->{action
} eq 'remove') {
1861 debug
(4, 2, "parent_link_scheduled_for_removal($path): link scheduled for removal");
1866 debug
(4, 2, "parent_link_scheduled_for_removal($path): returning false");
1870 =head2 is_a_link($path)
1872 Determine if the given path is a current or planned link.
1880 Returns false if an existing link is scheduled for removal and true if
1881 a non-existent link is scheduled for creation.
1888 debug
(4, 1, "is_a_link($path)");
1890 if (my $action = $self->link_task_action($path)) {
1891 if ($action eq 'remove') {
1892 debug
(4, 1, "is_a_link($path): returning 0 (remove action found)");
1895 elsif ($action eq 'create') {
1896 debug
(4, 1, "is_a_link($path): returning 1 (create action found)");
1902 # Check if any of its parent are links scheduled for removal
1903 # (need this for edge case during unfolding)
1904 debug
(4, 1, "is_a_link($path): is a real link");
1905 return $self->parent_link_scheduled_for_removal($path) ?
0 : 1;
1908 debug
(4, 1, "is_a_link($path): returning 0");
1912 =head2 is_a_dir($path)
1914 Determine if the given path is a current or planned directory
1922 Returns false if an existing directory is scheduled for removal and
1923 true if a non-existent directory is scheduled for creation. We also
1924 need to be sure we are not just following a link.
1931 debug
(4, 1, "is_a_dir($path)");
1933 if (my $action = $self->dir_task_action($path)) {
1934 if ($action eq 'remove') {
1937 elsif ($action eq 'create') {
1942 return 0 if $self->parent_link_scheduled_for_removal($path);
1945 debug
(4, 1, "is_a_dir($path): real dir");
1949 debug
(4, 1, "is_a_dir($path): returning false");
1953 =head2 is_a_node($path)
1955 Determine whether the given path is a current or planned node.
1963 Returns false if an existing node is scheduled for removal, or true if
1964 a non-existent node is scheduled for creation. We also need to be
1965 sure we are not just following a link.
1972 debug
(4, 1, "Checking whether $path is a current/planned node");
1974 my $laction = $self->link_task_action($path);
1975 my $daction = $self->dir_task_action($path);
1977 if ($laction eq 'remove') {
1978 if ($daction eq 'remove') {
1979 internal_error
("removing link and dir: $path");
1982 elsif ($daction eq 'create') {
1983 # Assume that we're unfolding $path, and that the link
1984 # removal action is earlier than the dir creation action
1985 # in the task queue. FIXME: is this a safe assumption?
1988 else { # no dir action
1992 elsif ($laction eq 'create') {
1993 if ($daction eq 'remove') {
1994 # Assume that we're folding $path, and that the dir
1995 # removal action is earlier than the link creation action
1996 # in the task queue. FIXME: is this a safe assumption?
1999 elsif ($daction eq 'create') {
2000 internal_error
("creating link and dir: $path");
2003 else { # no dir action
2009 if ($daction eq 'remove') {
2012 elsif ($daction eq 'create') {
2015 else { # no dir action
2016 # fall through to below
2020 return 0 if $self->parent_link_scheduled_for_removal($path);
2023 debug
(4, 1, "is_a_node($path): really exists");
2027 debug
(4, 1, "is_a_node($path): returning false");
2031 =head2 read_a_link($path)
2033 Return the source of a current or planned link
2039 path to the link target
2043 Returns a string. Throws a fatal exception if the given path is not a
2044 current or planned link.
2052 if (my $action = $self->link_task_action($path)) {
2053 debug
(4, 1, "read_a_link($path): task exists with action $action");
2055 if ($action eq 'create') {
2056 return $self->{link_task_for
}{$path}->{source
};
2058 elsif ($action eq 'remove') {
2060 "read_a_link() passed a path that is scheduled for removal: $path"
2065 debug
(4, 1, "read_a_link($path): real link");
2066 my $target = readlink $path or error
("Could not read link: $path ($!)");
2069 internal_error
("read_a_link() passed a non link path: $path\n");
2072 =head2 do_link($link_dest, $link_src)
2074 Wrap 'link' operation for later processing
2080 the existing file to link to
2088 Throws an error if this clashes with an existing planned operation.
2089 Cleans up operations that undo previous operations.
2095 my ($link_dest, $link_src) = @_;
2097 if (exists $self->{dir_task_for
}{$link_src}) {
2098 my $task_ref = $self->{dir_task_for
}{$link_src};
2100 if ($task_ref->{action
} eq 'create') {
2101 if ($task_ref->{type
} eq 'dir') {
2103 "new link (%s => %s) clashes with planned new directory",
2109 elsif ($task_ref->{action
} eq 'remove') {
2110 # We may need to remove a directory before creating a link so continue.
2113 internal_error
("bad task action: $task_ref->{action}");
2117 if (exists $self->{link_task_for
}{$link_src}) {
2118 my $task_ref = $self->{link_task_for
}{$link_src};
2120 if ($task_ref->{action
} eq 'create') {
2121 if ($task_ref->{source
} ne $link_dest) {
2123 "new link clashes with planned new link: %s => %s",
2125 $task_ref->{source
},
2129 debug
(1, 0, "LINK: $link_src => $link_dest (duplicates previous action)");
2133 elsif ($task_ref->{action
} eq 'remove') {
2134 if ($task_ref->{source
} eq $link_dest) {
2135 # No need to remove a link we are going to recreate
2136 debug
(1, 0, "LINK: $link_src => $link_dest (reverts previous action)");
2137 $self->{link_task_for
}{$link_src}->{action
} = 'skip';
2138 delete $self->{link_task_for
}{$link_src};
2141 # We may need to remove a link to replace it so continue
2144 internal_error
("bad task action: $task_ref->{action}");
2148 # Creating a new link
2149 debug
(1, 0, "LINK: $link_src => $link_dest");
2154 source
=> $link_dest,
2156 push @
{ $self->{tasks
} }, $task;
2157 $self->{link_task_for
}{$link_src} = $task;
2162 =head2 do_unlink($file)
2164 Wrap 'unlink' operation for later processing
2174 Throws an error if this clashes with an existing planned operation.
2175 Will remove an existing planned link.
2183 if (exists $self->{link_task_for
}{$file}) {
2184 my $task_ref = $self->{link_task_for
}{$file};
2185 if ($task_ref->{action
} eq 'remove') {
2186 debug
(1, 0, "UNLINK: $file (duplicates previous action)");
2189 elsif ($task_ref->{action
} eq 'create') {
2190 # Do need to create a link then remove it
2191 debug
(1, 0, "UNLINK: $file (reverts previous action)");
2192 $self->{link_task_for
}{$file}->{action
} = 'skip';
2193 delete $self->{link_task_for
}{$file};
2197 internal_error
("bad task action: $task_ref->{action}");
2201 if (exists $self->{dir_task_for
}{$file} and $self->{dir_task_for
}{$file} eq 'create') {
2203 "new unlink operation clashes with planned operation: %s dir %s",
2204 $self->{dir_task_for
}{$file}->{action
},
2210 debug
(1, 0, "UNLINK: $file");
2212 my $source = readlink $file or error
("could not readlink $file ($!)");
2220 push @
{ $self->{tasks
} }, $task;
2221 $self->{link_task_for
}{$file} = $task;
2226 =head2 do_mkdir($dir)
2228 Wrap 'mkdir' operation
2234 the directory to remove
2238 Throws a fatal exception if operation fails. Outputs a message if
2239 'verbose' option is set. Does not perform operation if 'simulate'
2240 option is set. Cleans up operations that undo previous operations.
2248 if (exists $self->{link_task_for
}{$dir}) {
2249 my $task_ref = $self->{link_task_for
}{$dir};
2251 if ($task_ref->{action
} eq 'create') {
2253 "new dir clashes with planned new link (%s => %s)",
2255 $task_ref->{source
},
2258 elsif ($task_ref->{action
} eq 'remove') {
2259 # May need to remove a link before creating a directory so continue
2262 internal_error
("bad task action: $task_ref->{action}");
2266 if (exists $self->{dir_task_for
}{$dir}) {
2267 my $task_ref = $self->{dir_task_for
}{$dir};
2269 if ($task_ref->{action
} eq 'create') {
2270 debug
(1, 0, "MKDIR: $dir (duplicates previous action)");
2273 elsif ($task_ref->{action
} eq 'remove') {
2274 debug
(1, 0, "MKDIR: $dir (reverts previous action)");
2275 $self->{dir_task_for
}{$dir}->{action
} = 'skip';
2276 delete $self->{dir_task_for
}{$dir};
2280 internal_error
("bad task action: $task_ref->{action}");
2284 debug
(1, 0, "MKDIR: $dir");
2291 push @
{ $self->{tasks
} }, $task;
2292 $self->{dir_task_for
}{$dir} = $task;
2297 =head2 do_rmdir($dir)
2299 Wrap 'rmdir' operation
2305 the directory to remove
2309 Throws a fatal exception if operation fails. Outputs a message if
2310 'verbose' option is set. Does not perform operation if 'simulate'
2319 if (exists $self->{link_task_for
}{$dir}) {
2320 my $task_ref = $self->{link_task_for
}{$dir};
2322 "rmdir clashes with planned operation: %s link %s => %s",
2323 $task_ref->{action
},
2329 if (exists $self->{dir_task_for
}{$dir}) {
2330 my $task_ref = $self->{link_task_for
}{$dir};
2332 if ($task_ref->{action
} eq 'remove') {
2333 debug
(1, 0, "RMDIR $dir (duplicates previous action)");
2336 elsif ($task_ref->{action
} eq 'create') {
2337 debug
(1, 0, "MKDIR $dir (reverts previous action)");
2338 $self->{link_task_for
}{$dir}->{action
} = 'skip';
2339 delete $self->{link_task_for
}{$dir};
2343 internal_error
("bad task action: $task_ref->{action}");
2347 debug
(1, 0, "RMDIR $dir");
2354 push @
{ $self->{tasks
} }, $task;
2355 $self->{dir_task_for
}{$dir} = $task;
2360 =head2 do_mv($src, $dst)
2362 Wrap 'move' operation for later processing.
2372 the path to move it to
2376 Throws an error if this clashes with an existing planned operation.
2377 Alters contents of package installation image in stow dir.
2383 my ($src, $dst) = @_;
2385 if (exists $self->{link_task_for
}{$src}) {
2386 # I don't *think* this should ever happen, but I'm not
2388 my $task_ref = $self->{link_task_for
}{$src};
2390 "do_mv: pre-existing link task for $src; action: %s, source: %s",
2391 $task_ref->{action
}, $task_ref->{source
}
2394 elsif (exists $self->{dir_task_for
}{$src}) {
2395 my $task_ref = $self->{dir_task_for
}{$src};
2397 "do_mv: pre-existing dir task for %s?! action: %s",
2398 $src, $task_ref->{action
}
2403 debug
(1, 0, "MV: $src -> $dst");
2411 push @
{ $self->{tasks
} }, $task;
2413 # FIXME: do we need this for anything?
2414 #$self->{mv_task_for}{$file} = $task;
2420 #############################################################################
2422 # End of methods; subroutines follow.
2423 # FIXME: Ideally these should be in a separate module.
2426 # ===== PRIVATE SUBROUTINE ===================================================
2427 # Name : internal_error()
2428 # Purpose : output internal error message in a consistent form and die
2431 =item $message => error message to output
2440 sub internal_error
{
2441 my ($format, @args) = @_;
2442 my $error = sprintf($format, @args);
2443 my $stacktrace = Carp
::longmess
();
2446 $ProgramName: INTERNAL ERROR: $error$stacktrace
2448 This _is_ a bug. Please submit a bug report so we can fix it! :-)
2449 See http://www.gnu.org/software/stow/ for how to do this.
2466 #############################################################################
2467 # Default global list of ignore regexps follows
2468 # (automatically appended by the Makefile)