Merge pull request #106 from aspiers/dev
This commit is contained in:
commit
fee2225dc9
29 changed files with 3148 additions and 9741 deletions
6
.dir-locals.el
Normal file
6
.dir-locals.el
Normal file
|
@ -0,0 +1,6 @@
|
|||
((cperl-mode . ((dumb-jump-force-searcher . rg)
|
||||
(cperl-indent-level . 4)
|
||||
(cperl-close-paren-offset . -4)
|
||||
(cperl-indent-subs-specially . nil)
|
||||
(indent-tabs-mode . nil)
|
||||
(eval . (auto-fill-mode -1)))))
|
2
.dumbjump
Normal file
2
.dumbjump
Normal file
|
@ -0,0 +1,2 @@
|
|||
+bin/*.in
|
||||
+lib/*.pm.in
|
4
AUTHORS
4
AUTHORS
|
@ -1,3 +1,7 @@
|
|||
This file documents the high-level history of Stow, and some of its
|
||||
major contributors. See also the THANKS file for a more complete list
|
||||
of contributors.
|
||||
|
||||
Stow was originally written by Bob Glickstein <bobg+stow@zanshin.com>,
|
||||
Zanshin Software, Inc.
|
||||
|
||||
|
|
106
CONTRIBUTING.md
Normal file
106
CONTRIBUTING.md
Normal file
|
@ -0,0 +1,106 @@
|
|||
Contributing to GNU Stow
|
||||
========================
|
||||
|
||||
Development of Stow, and GNU in general, is a volunteer effort, and
|
||||
you can contribute. If you'd like to get involved, it's a good idea to join
|
||||
the [stow-devel](https://lists.gnu.org/mailman/listinfo/stow-devel)
|
||||
mailing list.
|
||||
|
||||
Bug reporting
|
||||
-------------
|
||||
|
||||
Please follow the procedure described in [the "Reporting Bugs"
|
||||
section](https://www.gnu.org/software/stow/manual/html_node/Reporting-Bugs.html#Reporting-Bugs)
|
||||
of [the manual](README.md#documentation).
|
||||
|
||||
Development
|
||||
-----------
|
||||
|
||||
For [development sources](https://savannah.gnu.org/git/?group=stow)
|
||||
and other information, please see the [Stow project
|
||||
page](http://savannah.gnu.org/projects/stow/) at
|
||||
[savannah.gnu.org](http://savannah.gnu.org).
|
||||
|
||||
There is also a
|
||||
[stow-devel](https://lists.gnu.org/mailman/listinfo/stow-devel)
|
||||
mailing list (see [Mailing lists](README.md#mailing-lists)).
|
||||
|
||||
Please be aware that all program source files (excluding the test
|
||||
suite) end in `.in`, and are pre-processed by `Makefile` into
|
||||
corresponding files with that prefix stripped before execution. So if
|
||||
you want to test any modifications to the source, make sure that you
|
||||
change the `.in` files and then run `make` to regenerate the
|
||||
pre-processed versions before doing any testing. To avoid forgetting
|
||||
(which can potentially waste a lot of time debugging the wrong code),
|
||||
you can automatically run `make` in an infinite loop every second via:
|
||||
|
||||
make watch
|
||||
|
||||
(You could even use fancier approaches like
|
||||
[`inotifywait(1)`](https://www.man7.org/linux/man-pages/man1/inotifywait.1.html)
|
||||
or [Guard](https://guardgem.org/). But those are probably overkill in
|
||||
this case where the simple `while` loop is plenty good enough.)
|
||||
|
||||
Testing
|
||||
~~~~~~~
|
||||
|
||||
The test suite can be found in the [`t/`](t/) subdirectory. You can
|
||||
run the test suite via:
|
||||
|
||||
make check
|
||||
|
||||
Tests can be run individually as follows. First you have to ensure
|
||||
that the `t/`, `bin/`, and `lib/` directories are on Perl's search path.
|
||||
Assuming that you run all tests from the root of the repository tree,
|
||||
this will do the job:
|
||||
|
||||
export PERL5LIB=t:bin:lib
|
||||
|
||||
(Not all tests require all of these, but it's safer to include all of
|
||||
them.)
|
||||
|
||||
Secondly, be aware that if you want to test modifications to the
|
||||
source files, you will need to run `make watch`, or `make` before each
|
||||
test run as explained above.
|
||||
|
||||
Now running an individual test is as simple as:
|
||||
|
||||
perl t/chkstow.t
|
||||
|
||||
or with a given debugging verbosity corresponding to the `-v` / `--verbose`
|
||||
command-line option:
|
||||
|
||||
TEST_VERBOSE=4 perl t/chkstow.t
|
||||
|
||||
The [`prove(1)` test runner](https://perldoc.perl.org/prove) is another
|
||||
good alternative which provides several handy extra features. Invocation
|
||||
is very similar, e.g.:
|
||||
|
||||
prove t/stow.t
|
||||
|
||||
or to run the whole suite:
|
||||
|
||||
prove
|
||||
|
||||
However currently there is an issue where this interferes with
|
||||
`TEST_VERBOSE`.
|
||||
|
||||
Translating Stow
|
||||
----------------
|
||||
|
||||
Stow is not currently multi-lingual, but patches would be very
|
||||
gratefully accepted. Please e-mail
|
||||
[stow-devel](https://lists.gnu.org/mailman/listinfo/stow-devel) if you
|
||||
intend to work on this.
|
||||
|
||||
Maintainers
|
||||
-----------
|
||||
|
||||
Stow is currently being maintained by Adam Spiers. Please use [the
|
||||
mailing lists](README.md#mailing-lists).
|
||||
|
||||
Helping the GNU project
|
||||
-----------------------
|
||||
|
||||
For more general information, please read [How to help
|
||||
GNU](https://www.gnu.org/help/).
|
4
MANIFEST
4
MANIFEST
|
@ -3,6 +3,7 @@ aclocal.m4
|
|||
automake/install-sh
|
||||
automake/mdate-sh
|
||||
automake/missing
|
||||
automake/texinfo.tex
|
||||
bin/chkstow
|
||||
bin/chkstow.in
|
||||
bin/stow
|
||||
|
@ -11,6 +12,7 @@ Build.PL
|
|||
ChangeLog
|
||||
configure
|
||||
configure.ac
|
||||
CONTRIBUTING.md
|
||||
COPYING
|
||||
default-ignore-list
|
||||
doc/ChangeLog.OLD
|
||||
|
@ -19,7 +21,6 @@ doc/manual.pdf
|
|||
doc/stow.8
|
||||
doc/stow.info
|
||||
doc/stow.texi
|
||||
doc/texinfo.tex
|
||||
doc/version.texi
|
||||
INSTALL.md
|
||||
lib/Stow.pm
|
||||
|
@ -43,6 +44,7 @@ t/find_stowed_path.t
|
|||
t/foldable.t
|
||||
t/ignore.t
|
||||
t/join_paths.t
|
||||
t/link_dest_within_stow_dir.t
|
||||
t/parent.t
|
||||
t/stow.t
|
||||
t/rc_options.t
|
||||
|
|
|
@ -89,3 +89,10 @@ tmp-testing-trees
|
|||
.travis.yml
|
||||
^docker/
|
||||
^[a-zA-Z]*-docker.sh
|
||||
|
||||
# Avoid development config
|
||||
.dir-locals.el
|
||||
.dumbjump
|
||||
|
||||
# Avoid CI
|
||||
.github/
|
42
Makefile.am
42
Makefile.am
|
@ -32,24 +32,24 @@ pmstowdir = $(pmdir)/Stow
|
|||
pm_DATA = lib/Stow.pm
|
||||
pmstow_DATA = lib/Stow/Util.pm
|
||||
|
||||
TEXINFO_TEX = doc/texinfo.tex
|
||||
export TEXI2DVI_BUILD_MODE = clean
|
||||
AM_MAKEINFOFLAGS = -I $(srcdir)
|
||||
|
||||
# We require this -I parameter to ensure that the include of the
|
||||
# default ignore list in the manual works. Unfortunately this is
|
||||
# the only way to do it:
|
||||
# default ignore list in the manual works correctly, even when the
|
||||
# manual is being built via make distcheck from a different directory.
|
||||
# Unfortunately this is the only way to do it:
|
||||
#
|
||||
# http://article.gmane.org/gmane.comp.sysutils.automake.bugs/4334/match=passing+parameters
|
||||
# https://lists.gnu.org/archive/html/bug-automake/2008-09/msg00040.html
|
||||
#
|
||||
# even though it annoyingly produces a warning with the -Wall option
|
||||
# to AM_INIT_AUTOMAKE which has to be silenced via -Wno-override.
|
||||
TEXI2DVI = texi2dvi $(AM_MAKEINFOFLAGS)
|
||||
|
||||
doc_deps = $(info_TEXINFOS) doc/version.texi
|
||||
|
||||
DEFAULT_IGNORE_LIST = $(srcdir)/default-ignore-list
|
||||
|
||||
doc_deps = $(info_TEXINFOS) doc/version.texi $(DEFAULT_IGNORE_LIST)
|
||||
|
||||
TESTS_DIR = $(srcdir)/t
|
||||
TESTS_OUT = tmp-testing-trees
|
||||
TESTS_ENVIRONMENT = $(PERL) -Ibin -Ilib -I$(TESTS_DIR)
|
||||
|
@ -77,7 +77,7 @@ check_DATA = $(TESTS_OUT)
|
|||
# Note that automake's `check' rule cannot be overridden
|
||||
# for some weird reason:
|
||||
#
|
||||
# http://thread.gmane.org/gmane.comp.sysutils.automake.general/13040/focus=13041
|
||||
# https://lists.gnu.org/archive/html/automake/2011-09/msg00029.html
|
||||
#
|
||||
# so we override check-TESTS instead which is where the real work is
|
||||
# done anyway. Unfortunately this produces a warning with the -Wall
|
||||
|
@ -95,7 +95,6 @@ EXTRA_DIST = \
|
|||
bin/stow.in bin/chkstow.in lib/Stow.pm.in lib/Stow/Util.pm.in \
|
||||
doc/manual-split \
|
||||
$(TESTS) t/testutil.pm \
|
||||
$(TEXINFO_TEX) \
|
||||
$(DEFAULT_IGNORE_LIST) \
|
||||
$(CPAN_FILES)
|
||||
CLEANFILES = $(bin_SCRIPTS) $(pm_DATA) $(pmstow_DATA)
|
||||
|
@ -190,7 +189,7 @@ doc/stow.8: bin/stow.in Makefile.am
|
|||
#
|
||||
# If it were not for a troublesome dependency on doc/$(am__dirstamp):
|
||||
#
|
||||
# http://article.gmane.org/gmane.comp.sysutils.automake.general/13192
|
||||
# https://lists.gnu.org/archive/html/automake/2011-11/msg00107.html
|
||||
#
|
||||
# we could have achieved this using the built-in rules combined with
|
||||
# install-data-hook to rename from stow.pdf to manual.pdf etc. on
|
||||
|
@ -299,3 +298,28 @@ ChangeLog: doc/ChangeLog.OLD
|
|||
else \
|
||||
echo "Not in a git repository; can't update ChangeLog."; \
|
||||
fi
|
||||
|
||||
# Watch for changes, and if any rebuilds are required, also do a
|
||||
# make install.
|
||||
#
|
||||
# If we solved https://github.com/aspiers/stow/issues/84, we could
|
||||
# probably ditch this:
|
||||
watch:
|
||||
@echo "Watching for changes to program source files ..."
|
||||
@while true; do \
|
||||
if $(MAKE) 2>&1 | \
|
||||
grep -vE 'make\[[1-9]\]: (Entering|Leaving) directory ' | \
|
||||
grep -v 'Nothing to be done'; \
|
||||
then \
|
||||
echo; \
|
||||
echo "-----------------------------------------------------"; \
|
||||
echo "make found things to rebuild; doing $(MAKE) install ..."; \
|
||||
echo; \
|
||||
$(MAKE) install; \
|
||||
echo; \
|
||||
echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"; \
|
||||
echo; \
|
||||
fi; \
|
||||
sleep 1; \
|
||||
done 2>&1 | \
|
||||
grep -vE 'make\[[1-9]\]: (Entering|Leaving) directory '
|
||||
|
|
67
NEWS
67
NEWS
|
@ -1,5 +1,66 @@
|
|||
News file for Stow.
|
||||
|
||||
* Changes in version 2.3.2
|
||||
|
||||
*** Eliminated a spurious warning on unstowing
|
||||
|
||||
2.3.1 introduced a benign but annoying warning when unstowing
|
||||
in certain circumstances. It looked like:
|
||||
|
||||
BUG in find_stowed_path? Absolute/relative mismatch between Stow dir X and path Y
|
||||
|
||||
This was caused by erroneous logic, and has now been fixed.
|
||||
|
||||
*** Improved debug output
|
||||
|
||||
Extra output resulting from use of the -v / --verbose flag
|
||||
now appears in a more logical and understandable way.
|
||||
|
||||
*** Janitorial tasks
|
||||
|
||||
Users are not substantially affected by these changes.
|
||||
|
||||
***** Added some more information from the web page to the README
|
||||
|
||||
***** Made some improvements to the documentation
|
||||
|
||||
***** Improve readability of source code
|
||||
|
||||
Quite a few extra details have been added in comments to clarify
|
||||
how the code works. Many variable names have also been
|
||||
improved. The comments of many Stow class methods have been
|
||||
converted into Perl POD format.
|
||||
|
||||
***** Added a =CONTRIBUTING.md= file
|
||||
|
||||
***** Add a =watch= target to =Makefile=
|
||||
|
||||
=make watch= provides easy continual pre-processing during
|
||||
development, which reduces the risk of debugging the wrong code.
|
||||
|
||||
***** Removed texinfo.tex from the distribution
|
||||
|
||||
This eliminates existing and future bit-rot.
|
||||
|
||||
***** Updated aclocal.m4 from 1.15.1 to 1.16.5
|
||||
|
||||
This mostly just updates copyright notices to 2021, and URLs to https.
|
||||
|
||||
***** Replace broken gmane links with links to lists.gnu.org
|
||||
|
||||
[[https://lars.ingebrigtsen.no/2020/01/06/whatever-happened-to-news-gmane-org/][gmane has been dead for quite a while.]]
|
||||
|
||||
***** Improve support for navigating / editing source via emacs
|
||||
|
||||
******* Support source navigation in emacs via [[https://github.com/jacktasia/dumb-jump][dumb-jump]].
|
||||
|
||||
******* Configure cperl-mode to match existing coding style.
|
||||
|
||||
*** Various maintainer tweaks
|
||||
|
||||
Further improved the release process and its documentation in
|
||||
various minor ways.
|
||||
|
||||
* Changes in version 2.3.1
|
||||
|
||||
*** Remove dependencies on Hash::Merge and Clone::Choose
|
||||
|
@ -138,6 +199,7 @@ News file for Stow.
|
|||
consistency.
|
||||
|
||||
- INSTALL.md now also documents how to build directly from git.
|
||||
|
||||
*** Fixes for bugs, tests, and other technical debt
|
||||
|
||||
***** Add Docker files for convenient testing across multiple Perl versions
|
||||
|
@ -235,7 +297,7 @@ due to Stow::Util missing $VERSION.
|
|||
stow directory path being calculated as
|
||||
../../../usr/home/user/local/stow relative to the target.
|
||||
|
||||
See http://article.gmane.org/gmane.comp.gnu.stow.bugs/8820 for details.
|
||||
See https://lists.gnu.org/archive/html/bug-stow/2013-04/msg00000.html for details.
|
||||
|
||||
*** Fix stowing of relative links when --no-folding is used.
|
||||
|
||||
|
@ -276,7 +338,7 @@ due to Stow::Util missing $VERSION.
|
|||
|
||||
Thanks to Gabriele Balducci for reporting this problem:
|
||||
|
||||
http://thread.gmane.org/gmane.comp.gnu.stow.general/6676
|
||||
https://lists.gnu.org/archive/html/help-stow/2014-09/msg00000.html
|
||||
|
||||
*** Internal code cleanups
|
||||
|
||||
|
@ -586,4 +648,5 @@ due to Stow::Util missing $VERSION.
|
|||
org-export-with-toc: nil
|
||||
org-export-with-author: nil
|
||||
org-toc-odd-levels-only: t
|
||||
org-blank-before-new-entry: ((heading . auto) (plain-list-item . auto))
|
||||
End:
|
||||
|
|
62
README.md
62
README.md
|
@ -60,6 +60,56 @@ You can get the latest information about Stow from the home page:
|
|||
|
||||
http://www.gnu.org/software/stow/
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
See [`INSTALL.md`](INSTALL.md) for installation instructions.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
Documentation for Stow is available
|
||||
[online](https://www.gnu.org/software/stow/manual/), as is
|
||||
[documentation for most GNU
|
||||
software](https://www.gnu.org/software/manual/). Once you have Stow
|
||||
installed, you may also find more information about Stow by running
|
||||
`info stow` or `man stow`, or by looking at `/usr/share/doc/stow/`,
|
||||
`/usr/local/doc/stow/`, or similar directories on your system. A
|
||||
brief summary is available by running `stow --help`.
|
||||
|
||||
Mailing lists
|
||||
-------------
|
||||
|
||||
Stow has the following mailing lists:
|
||||
|
||||
- [help-stow](https://lists.gnu.org/mailman/listinfo/help-stow) is for
|
||||
general user help and discussion.
|
||||
- [stow-devel](https://lists.gnu.org/mailman/listinfo/stow-devel) is
|
||||
used to discuss most aspects of Stow, including development and
|
||||
enhancement requests.
|
||||
- [bug-stow](https://lists.gnu.org/mailman/listinfo/bug-stow) is for
|
||||
bug reports.
|
||||
|
||||
Announcements about Stow are posted to
|
||||
[info-stow](http://lists.gnu.org/mailman/listinfo/info-stow) and also,
|
||||
as with most other GNU software, to
|
||||
[info-gnu](http://lists.gnu.org/mailman/listinfo/info-gnu)
|
||||
([archive](http://lists.gnu.org/archive/html/info-gnu/)).
|
||||
|
||||
Security reports that should not be made immediately public can be
|
||||
sent directly to the maintainer. If there is no response to an urgent
|
||||
issue, you can escalate to the general
|
||||
[security](http://lists.gnu.org/mailman/listinfo/security) mailing
|
||||
list for advice.
|
||||
|
||||
The Savannah project also has a [mailing
|
||||
lists](https://savannah.gnu.org/mail/?group=stow) page.
|
||||
|
||||
Getting involved
|
||||
----------------
|
||||
|
||||
Please see the [`CONTRIBUTING.md` file](CONTRIBUTING.md).
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
|
@ -71,18 +121,6 @@ are permitted in any medium without royalty provided the copyright
|
|||
notice and this notice are preserved. This file is offered as-is,
|
||||
without any warranty.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
See [`INSTALL.md`](INSTALL.md) for installation instructions.
|
||||
|
||||
Feedback
|
||||
--------
|
||||
|
||||
Please do send comments, questions, and constructive criticism. The
|
||||
mailing lists and any other communication channels are detailed on the
|
||||
above home page.
|
||||
|
||||
Brief history and authorship
|
||||
----------------------------
|
||||
|
||||
|
|
2
TODO
2
TODO
|
@ -4,7 +4,7 @@
|
|||
install-info, amongst other things:
|
||||
|
||||
*** http://unix.stackexchange.com/questions/73426/dealing-with-gnu-stow-conflicts
|
||||
*** http://article.gmane.org/gmane.comp.gnu.stow.general/6661
|
||||
*** https://lists.gnu.org/archive/html/help-stow/2013-04/msg00016.html
|
||||
|
||||
* Get permission for next documentation release to be under FDL 1.3
|
||||
|
||||
|
|
71
aclocal.m4
vendored
71
aclocal.m4
vendored
|
@ -1,6 +1,6 @@
|
|||
# generated automatically by aclocal 1.15.1 -*- Autoconf -*-
|
||||
# generated automatically by aclocal 1.16.5 -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996-2017 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1996-2021 Free Software Foundation, Inc.
|
||||
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -14,13 +14,13 @@
|
|||
m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
|
||||
m4_ifndef([AC_AUTOCONF_VERSION],
|
||||
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
|
||||
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
|
||||
[m4_warning([this file was generated for autoconf 2.69.
|
||||
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.71],,
|
||||
[m4_warning([this file was generated for autoconf 2.71.
|
||||
You have another version of autoconf. It may work, but is not guaranteed to.
|
||||
If you have problems, you may need to regenerate the build system entirely.
|
||||
To do so, use the procedure documented by the package, typically 'autoreconf'.])])
|
||||
|
||||
# Copyright (C) 2002-2017 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2002-2021 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -32,10 +32,10 @@ To do so, use the procedure documented by the package, typically 'autoreconf'.])
|
|||
# generated from the m4 files accompanying Automake X.Y.
|
||||
# (This private macro should not be called outside this file.)
|
||||
AC_DEFUN([AM_AUTOMAKE_VERSION],
|
||||
[am__api_version='1.15'
|
||||
[am__api_version='1.16'
|
||||
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
|
||||
dnl require some minimum version. Point them to the right macro.
|
||||
m4_if([$1], [1.15.1], [],
|
||||
m4_if([$1], [1.16.5], [],
|
||||
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
|
||||
])
|
||||
|
||||
|
@ -51,14 +51,14 @@ m4_define([_AM_AUTOCONF_VERSION], [])
|
|||
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
|
||||
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
|
||||
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
|
||||
[AM_AUTOMAKE_VERSION([1.15.1])dnl
|
||||
[AM_AUTOMAKE_VERSION([1.16.5])dnl
|
||||
m4_ifndef([AC_AUTOCONF_VERSION],
|
||||
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
|
||||
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
|
||||
|
||||
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 2001-2017 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2001-2021 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -110,7 +110,7 @@ am_aux_dir=`cd "$ac_aux_dir" && pwd`
|
|||
|
||||
# Do all the work for Automake. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996-2017 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1996-2021 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -138,6 +138,10 @@ m4_defn([AC_PROG_CC])
|
|||
# release and drop the old call support.
|
||||
AC_DEFUN([AM_INIT_AUTOMAKE],
|
||||
[AC_PREREQ([2.65])dnl
|
||||
m4_ifdef([_$0_ALREADY_INIT],
|
||||
[m4_fatal([$0 expanded multiple times
|
||||
]m4_defn([_$0_ALREADY_INIT]))],
|
||||
[m4_define([_$0_ALREADY_INIT], m4_expansion_stack)])dnl
|
||||
dnl Autoconf wants to disallow AM_ names. We explicitly allow
|
||||
dnl the ones we care about.
|
||||
m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
|
||||
|
@ -174,7 +178,7 @@ m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
|
|||
[_AM_SET_OPTIONS([$1])dnl
|
||||
dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
|
||||
m4_if(
|
||||
m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]),
|
||||
m4_ifset([AC_PACKAGE_NAME], [ok]):m4_ifset([AC_PACKAGE_VERSION], [ok]),
|
||||
[ok:ok],,
|
||||
[m4_fatal([AC_INIT should be called with package and version arguments])])dnl
|
||||
AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
|
||||
|
@ -197,8 +201,8 @@ AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
|
|||
AC_REQUIRE([AC_PROG_MKDIR_P])dnl
|
||||
# For better backward compatibility. To be removed once Automake 1.9.x
|
||||
# dies out for good. For more background, see:
|
||||
# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
|
||||
# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
|
||||
# <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
|
||||
# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
|
||||
AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
|
||||
# We need awk for the "check" target (and possibly the TAP driver). The
|
||||
# system "awk" is bad on some platforms.
|
||||
|
@ -226,6 +230,20 @@ AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
|
|||
[m4_define([AC_PROG_OBJCXX],
|
||||
m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
|
||||
])
|
||||
# Variables for tags utilities; see am/tags.am
|
||||
if test -z "$CTAGS"; then
|
||||
CTAGS=ctags
|
||||
fi
|
||||
AC_SUBST([CTAGS])
|
||||
if test -z "$ETAGS"; then
|
||||
ETAGS=etags
|
||||
fi
|
||||
AC_SUBST([ETAGS])
|
||||
if test -z "$CSCOPE"; then
|
||||
CSCOPE=cscope
|
||||
fi
|
||||
AC_SUBST([CSCOPE])
|
||||
|
||||
AC_REQUIRE([AM_SILENT_RULES])dnl
|
||||
dnl The testsuite driver may need to know about EXEEXT, so add the
|
||||
dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This
|
||||
|
@ -265,7 +283,7 @@ END
|
|||
Aborting the configuration process, to ensure you take notice of the issue.
|
||||
|
||||
You can download and install GNU coreutils to get an 'rm' implementation
|
||||
that behaves properly: <http://www.gnu.org/software/coreutils/>.
|
||||
that behaves properly: <https://www.gnu.org/software/coreutils/>.
|
||||
|
||||
If you want to complete the configuration process using your problematic
|
||||
'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
|
||||
|
@ -307,7 +325,7 @@ for _am_header in $config_headers :; do
|
|||
done
|
||||
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
|
||||
|
||||
# Copyright (C) 2001-2017 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2001-2021 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -328,7 +346,7 @@ if test x"${install_sh+set}" != xset; then
|
|||
fi
|
||||
AC_SUBST([install_sh])])
|
||||
|
||||
# Copyright (C) 2003-2017 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2003-2021 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -349,7 +367,7 @@ AC_SUBST([am__leading_dot])])
|
|||
|
||||
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1997-2017 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1997-2021 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -370,12 +388,7 @@ AC_DEFUN([AM_MISSING_HAS_RUN],
|
|||
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
|
||||
AC_REQUIRE_AUX_FILE([missing])dnl
|
||||
if test x"${MISSING+set}" != xset; then
|
||||
case $am_aux_dir in
|
||||
*\ * | *\ *)
|
||||
MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
|
||||
*)
|
||||
MISSING="\${SHELL} $am_aux_dir/missing" ;;
|
||||
esac
|
||||
MISSING="\${SHELL} '$am_aux_dir/missing'"
|
||||
fi
|
||||
# Use eval to expand $SHELL
|
||||
if eval "$MISSING --is-lightweight"; then
|
||||
|
@ -388,7 +401,7 @@ fi
|
|||
|
||||
# Helper functions for option handling. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 2001-2017 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2001-2021 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -419,7 +432,7 @@ AC_DEFUN([_AM_IF_OPTION],
|
|||
|
||||
# Check to make sure that the build environment is sane. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996-2017 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1996-2021 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -500,7 +513,7 @@ AC_CONFIG_COMMANDS_PRE(
|
|||
rm -f conftest.file
|
||||
])
|
||||
|
||||
# Copyright (C) 2009-2017 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2009-2021 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -560,7 +573,7 @@ AC_SUBST([AM_BACKSLASH])dnl
|
|||
_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
|
||||
])
|
||||
|
||||
# Copyright (C) 2001-2017 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2001-2021 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -588,7 +601,7 @@ fi
|
|||
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
|
||||
AC_SUBST([INSTALL_STRIP_PROGRAM])])
|
||||
|
||||
# Copyright (C) 2006-2017 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2006-2021 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -607,7 +620,7 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
|
|||
|
||||
# Check how to create a tarball. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 2004-2017 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2004-2021 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
|
1
automake/.gitignore
vendored
1
automake/.gitignore
vendored
|
@ -2,3 +2,4 @@ install-sh
|
|||
missing
|
||||
mdate-sh
|
||||
test-driver
|
||||
texinfo.tex
|
||||
|
|
|
@ -123,6 +123,5 @@ sub list {
|
|||
|
||||
# Local variables:
|
||||
# mode: perl
|
||||
# cperl-indent-level: 4
|
||||
# End:
|
||||
# vim: ft=perl
|
||||
|
|
|
@ -849,6 +849,5 @@ sub version {
|
|||
|
||||
# Local variables:
|
||||
# mode: perl
|
||||
# cperl-indent-level: 4
|
||||
# end:
|
||||
# vim: ft=perl
|
||||
|
|
|
@ -19,7 +19,7 @@ AC_INIT([stow], [2.3.2], [bug-stow@gnu.org])
|
|||
AC_PREREQ([2.61])
|
||||
AC_CONFIG_AUX_DIR([automake])
|
||||
# Unfortunately we have to disable warnings for overrides, because we
|
||||
# need to override the built-in `check' rule and also the TEXI2DVI
|
||||
# need to override the built-in `check-TESTS' rule and also the TEXI2DVI
|
||||
# variable.
|
||||
AM_INIT_AUTOMAKE([-Wall -Werror -Wno-override dist-bzip2 foreign])
|
||||
AC_PROG_INSTALL
|
||||
|
|
|
@ -31,7 +31,7 @@ Release procedure
|
|||
|
||||
- Start from a clean slate:
|
||||
|
||||
make distclean
|
||||
make maintainer-clean
|
||||
autoreconf -iv
|
||||
|
||||
- Generate stow, chkstow, and lib/Stow.pm via:
|
||||
|
|
182
doc/stow.texi
182
doc/stow.texi
|
@ -19,13 +19,13 @@ This manual describes GNU Stow version @value{VERSION}
|
|||
|
||||
Software and documentation is copyrighted by the following:
|
||||
|
||||
@copyright{} 1993, 1994, 1995, 1996 Bob Glickstein <bobg+stow@@zanshin.com>
|
||||
@copyright{} 1993, 1994, 1995, 1996 Bob Glickstein @email{bobg+stow@@zanshin.com}
|
||||
@*
|
||||
@copyright{} 2000, 2001 Guillaume Morin <gmorin@@gnu.org>
|
||||
@copyright{} 2000, 2001 Guillaume Morin @email{gmorin@@gnu.org}
|
||||
@*
|
||||
@copyright{} 2007 Kahlil (Kal) Hodgson <kahlil@@internode.on.net>
|
||||
@copyright{} 2007 Kahlil (Kal) Hodgson @email{kahlil@@internode.on.net}
|
||||
@*
|
||||
@copyright{} 2011 Adam Spiers <stow@@adamspiers.org>
|
||||
@copyright{} 2011 Adam Spiers @email{stow@@adamspiers.org}
|
||||
|
||||
@quotation
|
||||
Permission is granted to make and distribute verbatim copies of this
|
||||
|
@ -99,7 +99,7 @@ appear to be installed in a single directory tree.
|
|||
* Multiple Stow Directories:: Further segregating software.
|
||||
* Target Maintenance:: Cleaning up mistakes.
|
||||
* Resource Files:: Setting default command line options.
|
||||
* Compile-time vs Install-time:: Faking out `make install'.
|
||||
* Compile-time vs. Install-time:: Faking out `make install'.
|
||||
* Bootstrapping:: When stow and perl are not yet stowed.
|
||||
* Reporting Bugs:: How, what, where, and when to report.
|
||||
* Known Bugs:: Don't report any of these.
|
||||
|
@ -220,9 +220,12 @@ to be installed in a particular directory structure --- e.g., with
|
|||
|
||||
@cindex target directory
|
||||
A @dfn{target directory} is the root of a tree in which one or more
|
||||
packages wish to @emph{appear} to be installed. A common, but by no
|
||||
means the only such location is @file{/usr/local}. The examples in this
|
||||
manual will use @file{/usr/local} as the target directory.
|
||||
packages wish to @emph{appear} to be installed. @file{/usr/local} is a
|
||||
common choice for this, but by no means the only such location. Another
|
||||
common choice is @file{~} (i.e.@: the user's @code{$HOME} directory) in
|
||||
the case where Stow is being used to manage the user's configuration
|
||||
(``dotfiles'') and other files in their @code{$HOME}. The examples in
|
||||
this manual will use @file{/usr/local} as the target directory.
|
||||
|
||||
@cindex stow directory
|
||||
A @dfn{stow directory} is the root of a tree containing separate
|
||||
|
@ -240,6 +243,11 @@ installation image for Perl includes: a @file{bin} directory containing
|
|||
containing Texinfo documentation; a @file{lib/perl} directory containing
|
||||
Perl libraries; and a @file{man/man1} directory containing man pages.
|
||||
|
||||
@quotation Note
|
||||
This is a @emph{pre-}installation image which exists even before Stow
|
||||
has installed any symlinks into the target directory which point to it.
|
||||
@end quotation
|
||||
|
||||
@cindex package directory
|
||||
@cindex package name
|
||||
A @dfn{package directory} is the root of a tree containing the
|
||||
|
@ -255,15 +263,68 @@ target directory, @file{/usr/local/stow} is the stow directory,
|
|||
@file{/usr/local/stow/perl} is the package directory, and
|
||||
@file{bin/perl} within is part of the installation image.
|
||||
|
||||
@anchor{symlink}
|
||||
@cindex symlink
|
||||
@cindex symlink source
|
||||
@cindex symlink destination
|
||||
@cindex relative symlink
|
||||
@cindex absolute symlink
|
||||
A @dfn{symlink} is a symbolic link. A symlink can be @dfn{relative} or
|
||||
@dfn{absolute}. An absolute symlink names a full path; that is, one
|
||||
starting from @file{/}. A relative symlink names a relative path; that
|
||||
is, one not starting from @file{/}. The target of a relative symlink is
|
||||
computed starting from the symlink's own directory. Stow only
|
||||
creates relative symlinks.
|
||||
A @dfn{symlink} is a symbolic link, i.e.@: an entry on the filesystem
|
||||
whose path is sometimes called the @dfn{symlink source}, which points to
|
||||
another location on the filesystem called the @dfn{symlink destination}.
|
||||
There is no guarantee that the destination actually exists.
|
||||
|
||||
In general, symlinks can be @dfn{relative} or @dfn{absolute}. A symlink
|
||||
is absolute when the destination names a full path; that is, one
|
||||
starting from @file{/}. A symlink is relative when the destination
|
||||
names a relative path; that is, one not starting from @file{/}. The
|
||||
destination of a relative symlink is computed starting from the
|
||||
symlink's own directory, i.e.@: the directory containing the symlink
|
||||
source.
|
||||
|
||||
@quotation Note
|
||||
Stow only creates symlinks within the target directory which point to
|
||||
locations @emph{outside} the target directory and inside the stow
|
||||
directory.
|
||||
|
||||
Consequently, we avoid referring to symlink destinations as symlink
|
||||
@emph{targets}, since this would result in the word ``target'' having
|
||||
two different meanings:
|
||||
|
||||
@enumerate
|
||||
|
||||
@item
|
||||
the target directory, i.e.@: the directory into which Stow targets
|
||||
installation, where symlinks are managed by Stow, and
|
||||
|
||||
@item
|
||||
the destinations of those symlinks.
|
||||
|
||||
@end enumerate
|
||||
|
||||
If we did not avoid the second meaning of ``target'', then it would lead
|
||||
to confusing language, such as describing Stow as installing symlinks
|
||||
into the target directory which point to targets @emph{outside} the
|
||||
target directory.
|
||||
|
||||
Similarly, the word ``source'' can have two different meanings in this
|
||||
context:
|
||||
|
||||
@enumerate
|
||||
|
||||
@item
|
||||
the installation image, or some of its contents, and
|
||||
|
||||
@item
|
||||
the location of symlinks (the ``source'' of the link, vs.@: its
|
||||
destination).
|
||||
|
||||
@end enumerate
|
||||
|
||||
Therefore it should also be avoided, or at least care taken to ensure
|
||||
that the meaning is not ambiguous.
|
||||
|
||||
@end quotation
|
||||
|
||||
@c ===========================================================================
|
||||
@node Invoking Stow, Ignore Lists, Terminology, Top
|
||||
|
@ -383,7 +444,7 @@ refolding (@pxref{tree refolding}). If a new subdirectory is
|
|||
encountered whilst stowing a new package, the subdirectory is created
|
||||
within the target, and its contents are symlinked, rather than just
|
||||
creating a symlink for the directory. If removal of symlinks whilst
|
||||
unstowing a package causes a subtree to be foldable (i.e. only
|
||||
unstowing a package causes a subtree to be foldable (i.e.@: only
|
||||
containing symlinks to a single package), that subtree will not be
|
||||
removed and replaced with a symlink.
|
||||
|
||||
|
@ -428,13 +489,15 @@ doing. Verbosity levels are from 0 to 5; 0 is the default. Using
|
|||
|
||||
@item -p
|
||||
@itemx --compat
|
||||
Scan the whole target tree when unstowing. By default, only
|
||||
directories specified in the @dfn{installation image} are scanned
|
||||
during an unstow operation. Scanning the whole tree can be
|
||||
prohibitive if your target tree is very large. This option restores
|
||||
the legacy behaviour; however, the @option{--badlinks} option to the
|
||||
@command{chkstow} utility may be a better way of ensuring that your
|
||||
installation does not have any dangling symlinks (@pxref{Target
|
||||
Scan the whole target tree when unstowing. By default, only directories
|
||||
specified in the @dfn{installation image} are scanned during an unstow
|
||||
operation. Previously Stow scanned the whole tree, which can be
|
||||
prohibitive if your target tree is very large, but on the other hand has
|
||||
the advantage of unstowing previously stowed links which are no longer
|
||||
present in the installation image and therefore orphaned. This option
|
||||
restores the legacy behaviour; however, the @option{--badlinks} option
|
||||
to the @command{chkstow} utility may be a better way of ensuring that
|
||||
your installation does not have any dangling symlinks (@pxref{Target
|
||||
Maintenance}).
|
||||
|
||||
@item -V
|
||||
|
@ -813,7 +876,7 @@ This is much faster and cleaner than performing two separate
|
|||
invocations of stow, because redundant folding/unfolding operations
|
||||
can be factored out. In addition, all the operations are calculated
|
||||
and merged before being executed (@pxref{Deferred Operation}), so the
|
||||
amount of of time in which GNU Emacs is unavailable is minimised.
|
||||
amount of time in which GNU Emacs is unavailable is minimised.
|
||||
|
||||
You can mix and match any number of actions, for example,
|
||||
|
||||
|
@ -893,7 +956,7 @@ directory.
|
|||
@end table
|
||||
|
||||
@c ===========================================================================
|
||||
@node Resource Files, Compile-time vs Install-time, Target Maintenance, Top
|
||||
@node Resource Files, Compile-time vs. Install-time, Target Maintenance, Top
|
||||
@chapter Resource Files
|
||||
@cindex resource files
|
||||
@cindex configuration files
|
||||
|
@ -960,8 +1023,8 @@ resource files. This is also true of any package names given in the
|
|||
resource file.
|
||||
|
||||
@c ===========================================================================
|
||||
@node Compile-time vs Install-time, Bootstrapping, Resource Files, Top
|
||||
@chapter Compile-time vs Install-time
|
||||
@node Compile-time vs. Install-time, Bootstrapping, Resource Files, Top
|
||||
@chapter Compile-time vs. Install-time
|
||||
|
||||
Software whose installation is managed with Stow needs to be installed
|
||||
in one place (the package directory, e.g. @file{/usr/local/stow/perl})
|
||||
|
@ -1043,7 +1106,7 @@ following sections.
|
|||
@end menu
|
||||
|
||||
@c ---------------------------------------------------------------------------
|
||||
@node GNU Emacs, Other FSF Software, Compile-time vs Install-time, Compile-time vs Install-time
|
||||
@node GNU Emacs, Other FSF Software, Compile-time vs. Install-time, Compile-time vs. Install-time
|
||||
@section GNU Emacs
|
||||
|
||||
Although the Free Software Foundation has many enlightened practices
|
||||
|
@ -1076,7 +1139,7 @@ make do-install prefix=/usr/local/stow/emacs
|
|||
@end example
|
||||
|
||||
@c ---------------------------------------------------------------------------
|
||||
@node Other FSF Software, Cygnus Software, GNU Emacs, Compile-time vs Install-time
|
||||
@node Other FSF Software, Cygnus Software, GNU Emacs, Compile-time vs. Install-time
|
||||
@section Other FSF Software
|
||||
|
||||
The Free Software Foundation, the organization behind the GNU project,
|
||||
|
@ -1097,7 +1160,7 @@ and @samp{make install} steps to work correctly without needing to
|
|||
``fool'' the build process.
|
||||
|
||||
@c ---------------------------------------------------------------------------
|
||||
@node Cygnus Software, Perl and Perl 5 Modules, Other FSF Software, Compile-time vs Install-time
|
||||
@node Cygnus Software, Perl and Perl 5 Modules, Other FSF Software, Compile-time vs. Install-time
|
||||
@section Cygnus Software
|
||||
|
||||
Cygnus is a commercial supplier and supporter of GNU software. It has
|
||||
|
@ -1126,7 +1189,7 @@ is recompiling files. Usually it will work just fine; otherwise,
|
|||
install manually.
|
||||
|
||||
@c ---------------------------------------------------------------------------
|
||||
@node Perl and Perl 5 Modules, , Cygnus Software, Compile-time vs Install-time
|
||||
@node Perl and Perl 5 Modules, , Cygnus Software, Compile-time vs. Install-time
|
||||
@section Perl and Perl 5 Modules
|
||||
|
||||
Perl 4.036 allows you to specify different locations for installation
|
||||
|
@ -1229,7 +1292,7 @@ find cpan.* \( -name .exists -o -name perllocal.pod \) -print | \
|
|||
|
||||
|
||||
@c ---------------------------------------------------------------------------
|
||||
@node Bootstrapping, Reporting Bugs, Compile-time vs Install-time, Top
|
||||
@node Bootstrapping, Reporting Bugs, Compile-time vs. Install-time, Top
|
||||
@chapter Bootstrapping
|
||||
|
||||
Suppose you have a stow directory all set up and ready to go:
|
||||
|
@ -1264,9 +1327,32 @@ perl/bin/perl stow/bin/stow -vv *
|
|||
@node Reporting Bugs, Known Bugs, Bootstrapping, Top
|
||||
@chapter Reporting Bugs
|
||||
|
||||
Please send bug reports to the current maintainers by electronic
|
||||
mail. The address to use is @samp{<bug-stow@@gnu.org>}. Please
|
||||
include:
|
||||
You can report bugs to the current maintainers in one of three ways:
|
||||
|
||||
@enumerate
|
||||
@item
|
||||
Send e-mail to @email{bug-stow@@gnu.org}.
|
||||
|
||||
@item
|
||||
File an issue in @uref{https://savannah.gnu.org/bugs/?group=stow,
|
||||
the Savannah bug tracker}.
|
||||
|
||||
@item
|
||||
File an issue in
|
||||
@uref{https://github.com/aspiers/stow/issues/, the GitHub project}.
|
||||
@end enumerate
|
||||
|
||||
While GitHub is arguably the most convenient of these three options, it
|
||||
@uref{https://www.gnu.org/software/repo-criteria-evaluation.html#GitHub,
|
||||
is not the most ethical or freedom-preserving way to host software
|
||||
projects}. Therefore the GitHub project may be
|
||||
@uref{https://github.com/aspiers/stow/issues/43, moved to a more ethical
|
||||
hosting service} in the future.
|
||||
|
||||
Before reporting a bug, it is recommended to check whether it is already
|
||||
known, so please first @pxref{Known Bugs}.
|
||||
|
||||
When reporting a new bug, please include:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
|
@ -1287,12 +1373,13 @@ the precise command you gave;
|
|||
|
||||
@item
|
||||
the output from the command (preferably verbose output, obtained by
|
||||
adding @samp{--verbose=3} to the Stow command line).
|
||||
adding @samp{--verbose=5} to the Stow command line).
|
||||
@end itemize
|
||||
|
||||
If you are really keen, consider developing a minimal test case and
|
||||
creating a new test. See the @file{t/} directory in the source for
|
||||
lots of examples.
|
||||
creating a new test. See the @file{t/} directory in the source for lots
|
||||
of examples, and the @file{CONTRIBUTING.md} file for a guide on how to
|
||||
contribute.
|
||||
|
||||
Before reporting a bug, please read the manual carefully, especially
|
||||
@ref{Known Bugs}, to see whether you're encountering
|
||||
|
@ -1303,13 +1390,22 @@ something that doesn't need reporting.
|
|||
@node Known Bugs, GNU General Public License, Reporting Bugs, Top
|
||||
@chapter Known Bugs
|
||||
|
||||
There are no known bugs in Stow version @value{VERSION}!
|
||||
If you think you have found one, please @pxref{Reporting Bugs}.
|
||||
Known bugs can be found in the following locations:
|
||||
|
||||
@c @itemize @bullet
|
||||
@c @item
|
||||
@c Put known bugs here
|
||||
@c @end itemize
|
||||
@itemize
|
||||
@item
|
||||
@uref{https://github.com/aspiers/stow/issues/, the GitHub issue tracker}
|
||||
|
||||
@item
|
||||
@uref{https://savannah.gnu.org/bugs/?group=stow, the Savannah bug
|
||||
tracker}
|
||||
|
||||
@item
|
||||
the @uref{https://lists.gnu.org/archive/html/bug-stow/, bug-stow list
|
||||
archives}
|
||||
@end itemize
|
||||
|
||||
If you think you have found a new bug, please @pxref{Reporting Bugs}.
|
||||
|
||||
@c ===========================================================================
|
||||
@node GNU General Public License, Index, Known Bugs, Top
|
||||
|
|
7482
doc/texinfo.tex
7482
doc/texinfo.tex
File diff suppressed because it is too large
Load diff
1896
lib/Stow.pm.in
1896
lib/Stow.pm.in
File diff suppressed because it is too large
Load diff
|
@ -32,6 +32,7 @@ Supporting utility routines for L<Stow>.
|
|||
use strict;
|
||||
use warnings;
|
||||
|
||||
use File::Spec;
|
||||
use POSIX qw(getcwd);
|
||||
|
||||
use base qw(Exporter);
|
||||
|
@ -93,7 +94,7 @@ sub set_test_mode {
|
|||
}
|
||||
}
|
||||
|
||||
=head2 debug($level, $msg)
|
||||
=head2 debug($level[, $indent_level], $msg)
|
||||
|
||||
Logs to STDERR based on C<$debug_level> setting. C<$level> is the
|
||||
minimum verbosity level required to output C<$msg>. All output is to
|
||||
|
@ -125,13 +126,18 @@ overriding, fixing invalid links
|
|||
=cut
|
||||
|
||||
sub debug {
|
||||
my ($level, $msg) = @_;
|
||||
my $level = shift;
|
||||
my $indent_level;
|
||||
# Maintain backwards-compatibility in case anyone's relying on this.
|
||||
$indent_level = $_[0] =~ /^\d+$/ ? shift : 0;
|
||||
my $msg = shift;
|
||||
if ($debug_level >= $level) {
|
||||
my $indent = ' ' x $indent_level;
|
||||
if ($test_mode) {
|
||||
print "# $msg\n";
|
||||
print "# $indent$msg\n";
|
||||
}
|
||||
else {
|
||||
warn "$msg\n";
|
||||
warn "$indent$msg\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -142,29 +148,53 @@ sub debug {
|
|||
# Parameters: path1, path2, ... => paths
|
||||
# Returns : concatenation of given paths
|
||||
# Throws : n/a
|
||||
# Comments : factors out redundant path elements:
|
||||
# : '//' => '/' and 'a/b/../c' => 'a/c'
|
||||
# Comments : Factors out some redundant path elements:
|
||||
# : '//' => '/', and 'a/b/../c' => 'a/c'. We need this function
|
||||
# : with this behaviour, even though b could be a symlink to
|
||||
# : elsewhere, as noted in the perldoc for File::Spec->canonpath().
|
||||
# : This behaviour is deliberately different to
|
||||
# : Stow::Util::canon_path(), because the way join_paths() is used
|
||||
# : relies on this. Firstly, there is no guarantee that the paths
|
||||
# : exist, so a filesystem check is inappropriate.
|
||||
# :
|
||||
# : For example, it's used to determine the path from the target
|
||||
# : directory to a symlink destination. So if a symlink
|
||||
# : path/to/target/a/b/c points to ../../../stow/pkg/a/b/c,
|
||||
# : then joining path/to/target/a/b with ../../../stow/pkg/a/b/c
|
||||
# : yields path/to/stow/pkg/a/b/c, and it's crucial that the
|
||||
# : path/to/stow prefix matches a recognisable stow directory.
|
||||
#============================================================================
|
||||
sub join_paths {
|
||||
my @paths = @_;
|
||||
|
||||
# weed out empty components and concatenate
|
||||
my $result = join '/', grep {! /\A\z/} @paths;
|
||||
debug(5, 5, "| Joining: @paths");
|
||||
my $result = '';
|
||||
for my $part (@paths) {
|
||||
next if ! length $part; # probably shouldn't happen?
|
||||
$part = File::Spec->canonpath($part);
|
||||
|
||||
# factor out back references and remove redundant /'s)
|
||||
my @result = ();
|
||||
PART:
|
||||
for my $part (split m{/+}, $result) {
|
||||
next PART if $part eq '.';
|
||||
if (@result && $part eq '..' && $result[-1] ne '..') {
|
||||
pop @result;
|
||||
if (substr($part, 0, 1) eq '/') {
|
||||
$result = $part; # absolute path, so ignore all previous parts
|
||||
}
|
||||
else {
|
||||
push @result, $part;
|
||||
$result .= '/' if length $result && $result ne '/';
|
||||
$result .= $part;
|
||||
}
|
||||
debug(7, 6, "| Join now: $result");
|
||||
}
|
||||
debug(6, 5, "| Joined: $result");
|
||||
|
||||
return join '/', @result;
|
||||
# Need this to remove any initial ./
|
||||
$result = File::Spec->canonpath($result);
|
||||
|
||||
# remove foo/..
|
||||
1 while $result =~ s,(^|/)(?!\.\.)[^/]+/\.\.(/|$),$1,;
|
||||
debug(6, 5, "| After .. removal: $result");
|
||||
|
||||
$result = File::Spec->canonpath($result);
|
||||
debug(5, 5, "| Final join: $result");
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
#===== METHOD ===============================================================
|
||||
|
@ -209,10 +239,10 @@ sub restore_cwd {
|
|||
}
|
||||
|
||||
sub adjust_dotfile {
|
||||
my ($target) = @_;
|
||||
my ($link_dest) = @_;
|
||||
|
||||
my @result = ();
|
||||
for my $part (split m{/+}, $target) {
|
||||
for my $part (split m{/+}, $link_dest) {
|
||||
if (($part ne "dot-") && ($part ne "dot-.")) {
|
||||
$part =~ s/^dot-/./;
|
||||
}
|
||||
|
@ -232,6 +262,5 @@ sub adjust_dotfile {
|
|||
|
||||
# Local variables:
|
||||
# mode: perl
|
||||
# cperl-indent-level: 4
|
||||
# end:
|
||||
# vim: ft=perl
|
||||
|
|
|
@ -22,10 +22,11 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Test::More tests => 6;
|
||||
use Test::More tests => 4;
|
||||
use English qw(-no_match_vars);
|
||||
|
||||
use testutil;
|
||||
use Stow::Util;
|
||||
|
||||
init_test_dirs();
|
||||
cd("$TEST_DIR/target");
|
||||
|
@ -34,48 +35,64 @@ my $stow;
|
|||
|
||||
# Note that each of the following tests use a distinct set of files
|
||||
|
||||
#
|
||||
# nothing to clean in a simple tree
|
||||
#
|
||||
subtest('nothing to clean in a simple tree' => sub {
|
||||
plan tests => 1;
|
||||
|
||||
make_path('../stow/pkg1/bin1');
|
||||
make_file('../stow/pkg1/bin1/file1');
|
||||
make_link('bin1', '../stow/pkg1/bin1');
|
||||
|
||||
make_path('../stow/pkg1/bin1');
|
||||
make_file('../stow/pkg1/bin1/file1');
|
||||
make_link('bin1', '../stow/pkg1/bin1');
|
||||
|
||||
$stow = new_Stow();
|
||||
$stow->cleanup_invalid_links('./');
|
||||
is(
|
||||
$stow = new_Stow();
|
||||
$stow->cleanup_invalid_links('./');
|
||||
is(
|
||||
scalar($stow->get_tasks), 0
|
||||
=> 'nothing to clean'
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# cleanup a bad link in a simple tree
|
||||
#
|
||||
make_path('bin2');
|
||||
make_path('../stow/pkg2/bin2');
|
||||
make_file('../stow/pkg2/bin2/file2a');
|
||||
make_link('bin2/file2a', '../../stow/pkg2/bin2/file2a');
|
||||
make_invalid_link('bin2/file2b', '../../stow/pkg2/bin2/file2b');
|
||||
subtest('cleanup an orphaned owned link in a simple tree' => sub {
|
||||
plan tests => 3;
|
||||
|
||||
$stow = new_Stow();
|
||||
$stow->cleanup_invalid_links('bin2');
|
||||
is($stow->get_conflict_count, 0, 'no conflicts cleaning up bad link');
|
||||
is(scalar($stow->get_tasks), 1, 'one task cleaning up bad link');
|
||||
is($stow->link_task_action('bin2/file2b'), 'remove', 'removal task for bad link');
|
||||
make_path('bin2');
|
||||
make_path('../stow/pkg2/bin2');
|
||||
make_file('../stow/pkg2/bin2/file2a');
|
||||
make_link('bin2/file2a', '../../stow/pkg2/bin2/file2a');
|
||||
make_invalid_link('bin2/file2b', '../../stow/pkg2/bin2/file2b');
|
||||
|
||||
#
|
||||
# dont cleanup a bad link not owned by stow
|
||||
#
|
||||
$stow = new_Stow();
|
||||
$stow->cleanup_invalid_links('bin2');
|
||||
is($stow->get_conflict_count, 0, 'no conflicts cleaning up bad link');
|
||||
is(scalar($stow->get_tasks), 1, 'one task cleaning up bad link');
|
||||
is($stow->link_task_action('bin2/file2b'), 'remove', 'removal task for bad link');
|
||||
});
|
||||
|
||||
make_path('bin3');
|
||||
make_path('../stow/pkg3/bin3');
|
||||
make_file('../stow/pkg3/bin3/file3a');
|
||||
make_link('bin3/file3a', '../../stow/pkg3/bin3/file3a');
|
||||
make_invalid_link('bin3/file3b', '../../empty');
|
||||
subtest("don't cleanup a bad link not owned by stow" => sub {
|
||||
plan tests => 2;
|
||||
|
||||
$stow = new_Stow();
|
||||
$stow->cleanup_invalid_links('bin3');
|
||||
is($stow->get_conflict_count, 0, 'no conflicts cleaning up bad link not owned by stow');
|
||||
is(scalar($stow->get_tasks), 0, 'no tasks cleaning up bad link not owned by stow');
|
||||
make_path('bin3');
|
||||
make_path('../stow/pkg3/bin3');
|
||||
make_file('../stow/pkg3/bin3/file3a');
|
||||
make_link('bin3/file3a', '../../stow/pkg3/bin3/file3a');
|
||||
make_invalid_link('bin3/file3b', '../../empty');
|
||||
|
||||
$stow = new_Stow();
|
||||
$stow->cleanup_invalid_links('bin3');
|
||||
is($stow->get_conflict_count, 0, 'no conflicts cleaning up bad link not owned by stow');
|
||||
is(scalar($stow->get_tasks), 0, 'no tasks cleaning up bad link not owned by stow');
|
||||
});
|
||||
|
||||
subtest("don't cleanup a valid link in the target not owned by stow" => sub {
|
||||
plan tests => 2;
|
||||
|
||||
make_path('bin4');
|
||||
make_path('../stow/pkg4/bin4');
|
||||
make_file('../stow/pkg4/bin4/file3a');
|
||||
make_link('bin4/file3a', '../../stow/pkg4/bin4/file3a');
|
||||
make_file("unowned");
|
||||
make_link('bin4/file3b', '../unowned');
|
||||
|
||||
$stow = new_Stow();
|
||||
$stow->cleanup_invalid_links('bin4');
|
||||
is($stow->get_conflict_count, 0, 'no conflicts cleaning up bad link not owned by stow');
|
||||
is(scalar($stow->get_tasks), 0, 'no tasks cleaning up bad link not owned by stow');
|
||||
});
|
||||
|
|
212
t/dotfiles.t
212
t/dotfiles.t
|
@ -22,110 +22,188 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
|
||||
use testutil;
|
||||
|
||||
use Test::More tests => 6;
|
||||
use Test::More tests => 10;
|
||||
use English qw(-no_match_vars);
|
||||
|
||||
use Stow::Util qw(adjust_dotfile);
|
||||
use testutil;
|
||||
|
||||
init_test_dirs();
|
||||
cd("$TEST_DIR/target");
|
||||
|
||||
subtest('adjust_dotfile()', sub {
|
||||
plan tests => 9;
|
||||
my @TESTS = (
|
||||
['file'],
|
||||
['dot-file', '.file'],
|
||||
['dir1/file'],
|
||||
['dir1/dir2/file'],
|
||||
['dir1/dir2/dot-file', 'dir1/dir2/.file'],
|
||||
['dir1/dot-dir2/file', 'dir1/.dir2/file'],
|
||||
['dir1/dot-dir2/dot-file', 'dir1/.dir2/.file'],
|
||||
['dot-dir1/dot-dir2/dot-file', '.dir1/.dir2/.file'],
|
||||
['dot-dir1/dot-dir2/file', '.dir1/.dir2/file'],
|
||||
);
|
||||
for my $test (@TESTS) {
|
||||
my ($input, $expected) = @$test;
|
||||
$expected ||= $input;
|
||||
is(adjust_dotfile($input), $expected);
|
||||
}
|
||||
});
|
||||
|
||||
my $stow;
|
||||
|
||||
#
|
||||
# process a dotfile marked with 'dot' prefix
|
||||
#
|
||||
subtest("stow a dotfile marked with 'dot' prefix", sub {
|
||||
plan tests => 1;
|
||||
$stow = new_Stow(dir => '../stow', dotfiles => 1);
|
||||
make_path('../stow/dotfiles');
|
||||
make_file('../stow/dotfiles/dot-foo');
|
||||
|
||||
$stow = new_Stow(dir => '../stow', dotfiles => 1);
|
||||
|
||||
make_path('../stow/dotfiles');
|
||||
make_file('../stow/dotfiles/dot-foo');
|
||||
|
||||
$stow->plan_stow('dotfiles');
|
||||
$stow->process_tasks();
|
||||
is(
|
||||
$stow->plan_stow('dotfiles');
|
||||
$stow->process_tasks();
|
||||
is(
|
||||
readlink('.foo'),
|
||||
'../stow/dotfiles/dot-foo',
|
||||
=> 'processed dotfile'
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# ensure that turning off dotfile processing links files as usual
|
||||
#
|
||||
subtest("ensure that turning off dotfile processing links files as usual", sub {
|
||||
plan tests => 1;
|
||||
$stow = new_Stow(dir => '../stow', dotfiles => 0);
|
||||
make_path('../stow/dotfiles');
|
||||
make_file('../stow/dotfiles/dot-foo');
|
||||
|
||||
$stow = new_Stow(dir => '../stow', dotfiles => 0);
|
||||
|
||||
make_path('../stow/dotfiles');
|
||||
make_file('../stow/dotfiles/dot-foo');
|
||||
|
||||
$stow->plan_stow('dotfiles');
|
||||
$stow->process_tasks();
|
||||
is(
|
||||
$stow->plan_stow('dotfiles');
|
||||
$stow->process_tasks();
|
||||
is(
|
||||
readlink('dot-foo'),
|
||||
'../stow/dotfiles/dot-foo',
|
||||
=> 'unprocessed dotfile'
|
||||
);
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
#
|
||||
# process folder marked with 'dot' prefix
|
||||
#
|
||||
subtest("stow folder marked with 'dot' prefix", sub {
|
||||
plan tests => 1;
|
||||
$stow = new_Stow(dir => '../stow', dotfiles => 1);
|
||||
|
||||
$stow = new_Stow(dir => '../stow', dotfiles => 1);
|
||||
make_path('../stow/dotfiles/dot-emacs');
|
||||
make_file('../stow/dotfiles/dot-emacs/init.el');
|
||||
|
||||
make_path('../stow/dotfiles/dot-emacs');
|
||||
make_file('../stow/dotfiles/dot-emacs/init.el');
|
||||
|
||||
$stow->plan_stow('dotfiles');
|
||||
$stow->process_tasks();
|
||||
is(
|
||||
$stow->plan_stow('dotfiles');
|
||||
$stow->process_tasks();
|
||||
is(
|
||||
readlink('.emacs'),
|
||||
'../stow/dotfiles/dot-emacs',
|
||||
=> 'processed dotfile folder'
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# corner case: paths that have a part in them that's just "$DOT_PREFIX" or
|
||||
# "$DOT_PREFIX." should not have that part expanded.
|
||||
#
|
||||
subtest("process folder marked with 'dot' prefix when directory exists is target", sub {
|
||||
plan tests => 1;
|
||||
$stow = new_Stow(dir => '../stow', dotfiles => 1);
|
||||
|
||||
$stow = new_Stow(dir => '../stow', dotfiles => 1);
|
||||
make_path('../stow/dotfiles/dot-emacs.d');
|
||||
make_file('../stow/dotfiles/dot-emacs.d/init.el');
|
||||
make_path('.emacs.d');
|
||||
|
||||
make_path('../stow/dotfiles');
|
||||
make_file('../stow/dotfiles/dot-');
|
||||
$stow->plan_stow('dotfiles');
|
||||
$stow->process_tasks();
|
||||
is(
|
||||
readlink('.emacs.d/init.el'),
|
||||
'../../stow/dotfiles/dot-emacs.d/init.el',
|
||||
=> 'processed dotfile folder when folder exists (1 level)'
|
||||
);
|
||||
});
|
||||
|
||||
make_path('../stow/dotfiles/dot-.');
|
||||
make_file('../stow/dotfiles/dot-./foo');
|
||||
subtest("process folder marked with 'dot' prefix when directory exists is target (2 levels)", sub {
|
||||
plan tests => 1;
|
||||
$stow = new_Stow(dir => '../stow', dotfiles => 1);
|
||||
|
||||
$stow->plan_stow('dotfiles');
|
||||
$stow->process_tasks();
|
||||
is(
|
||||
make_path('../stow/dotfiles/dot-emacs.d/dot-emacs.d');
|
||||
make_file('../stow/dotfiles/dot-emacs.d/dot-emacs.d/init.el');
|
||||
make_path('.emacs.d');
|
||||
|
||||
$stow->plan_stow('dotfiles');
|
||||
$stow->process_tasks();
|
||||
is(
|
||||
readlink('.emacs.d/.emacs.d'),
|
||||
'../../stow/dotfiles/dot-emacs.d/dot-emacs.d',
|
||||
=> 'processed dotfile folder exists (2 levels)'
|
||||
);
|
||||
});
|
||||
|
||||
subtest("process folder marked with 'dot' prefix when directory exists is target", sub {
|
||||
plan tests => 1;
|
||||
$stow = new_Stow(dir => '../stow', dotfiles => 1);
|
||||
|
||||
make_path('../stow/dotfiles/dot-one/dot-two');
|
||||
make_file('../stow/dotfiles/dot-one/dot-two/three');
|
||||
make_path('.one/.two');
|
||||
|
||||
$stow->plan_stow('dotfiles');
|
||||
$stow->process_tasks();
|
||||
is(
|
||||
readlink('./.one/.two/three'),
|
||||
'../../../stow/dotfiles/dot-one/dot-two/three',
|
||||
=> 'processed dotfile 2 folder exists (2 levels)'
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
subtest("dot-. should not have that part expanded.", sub {
|
||||
plan tests => 2;
|
||||
$stow = new_Stow(dir => '../stow', dotfiles => 1);
|
||||
|
||||
make_path('../stow/dotfiles');
|
||||
make_file('../stow/dotfiles/dot-');
|
||||
|
||||
make_path('../stow/dotfiles/dot-.');
|
||||
make_file('../stow/dotfiles/dot-./foo');
|
||||
|
||||
$stow->plan_stow('dotfiles');
|
||||
$stow->process_tasks();
|
||||
is(
|
||||
readlink('dot-'),
|
||||
'../stow/dotfiles/dot-',
|
||||
=> 'processed dotfile'
|
||||
);
|
||||
is(
|
||||
);
|
||||
is(
|
||||
readlink('dot-.'),
|
||||
'../stow/dotfiles/dot-.',
|
||||
=> 'unprocessed dotfile'
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# simple unstow scenario
|
||||
#
|
||||
subtest("simple unstow scenario", sub {
|
||||
plan tests => 3;
|
||||
$stow = new_Stow(dir => '../stow', dotfiles => 1);
|
||||
|
||||
$stow = new_Stow(dir => '../stow', dotfiles => 1);
|
||||
make_path('../stow/dotfiles');
|
||||
make_file('../stow/dotfiles/dot-bar');
|
||||
make_link('.bar', '../stow/dotfiles/dot-bar');
|
||||
|
||||
make_path('../stow/dotfiles');
|
||||
make_file('../stow/dotfiles/dot-bar');
|
||||
make_link('.bar', '../stow/dotfiles/dot-bar');
|
||||
$stow->plan_unstow('dotfiles');
|
||||
$stow->process_tasks();
|
||||
is($stow->get_conflict_count, 0);
|
||||
ok(-f '../stow/dotfiles/dot-bar');
|
||||
ok(! -e '.bar' => 'unstow a simple dotfile');
|
||||
});
|
||||
|
||||
$stow->plan_unstow('dotfiles');
|
||||
$stow->process_tasks();
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
-f '../stow/dotfiles/dot-bar' && ! -e '.bar'
|
||||
=> 'unstow a simple dotfile'
|
||||
);
|
||||
subtest("unstow process folder marked with 'dot' prefix when directory exists is target", sub {
|
||||
plan tests => 4;
|
||||
$stow = new_Stow(dir => '../stow', dotfiles => 1);
|
||||
|
||||
make_path('../stow/dotfiles/dot-emacs.d');
|
||||
make_file('../stow/dotfiles/dot-emacs.d/init.el');
|
||||
make_path('.emacs.d');
|
||||
make_link('.emacs.d/init.el', '../../stow/dotfiles/dot-emacs.d/init.el');
|
||||
|
||||
$stow->plan_unstow('dotfiles');
|
||||
$stow->process_tasks();
|
||||
is($stow->get_conflict_count, 0);
|
||||
ok(-f '../stow/dotfiles/dot-emacs.d/init.el');
|
||||
ok(! -e '.emacs.d/init.el');
|
||||
ok(-d '.emacs.d/' => 'unstow dotfile folder when folder already exists');
|
||||
});
|
||||
|
|
|
@ -16,65 +16,133 @@
|
|||
# along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
|
||||
#
|
||||
# Testing find_stowed_path()
|
||||
# Testing Stow:: find_stowed_path()
|
||||
#
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Test::More tests => 18;
|
||||
use Test::More tests => 10;
|
||||
|
||||
use testutil;
|
||||
use Stow::Util qw(set_debug_level);
|
||||
|
||||
init_test_dirs();
|
||||
|
||||
my $stow = new_Stow(dir => "$TEST_DIR/stow");
|
||||
#set_debug_level(4);
|
||||
subtest("find link to a stowed path with relative target" => sub {
|
||||
plan tests => 3;
|
||||
|
||||
my ($path, $stow_path, $package) =
|
||||
$stow->find_stowed_path("$TEST_DIR/target/a/b/c", "../../../stow/a/b/c");
|
||||
is($path, "$TEST_DIR/stow/a/b/c", "path");
|
||||
is($stow_path, "$TEST_DIR/stow", "stow path");
|
||||
is($package, "a", "package");
|
||||
# This is a relative path, unlike $ABS_TEST_DIR below.
|
||||
my $target = "$TEST_DIR/target";
|
||||
|
||||
cd("$TEST_DIR/target");
|
||||
$stow->set_stow_dir("../stow");
|
||||
($path, $stow_path, $package) =
|
||||
my $stow = new_Stow(dir => "$TEST_DIR/stow", target => $target);
|
||||
my ($path, $stow_path, $package) =
|
||||
$stow->find_stowed_path("a/b/c", "../../../stow/a/b/c");
|
||||
is($path, "../stow/a/b/c", "path from target directory");
|
||||
is($stow_path, "../stow", "stow path from target directory");
|
||||
is($package, "a", "from target directory");
|
||||
is($path, "../stow/a/b/c", "path");
|
||||
is($stow_path, "../stow", "stow path");
|
||||
is($package, "a", "package");
|
||||
});
|
||||
|
||||
make_path("stow");
|
||||
cd("../..");
|
||||
$stow->set_stow_dir("$TEST_DIR/target/stow");
|
||||
my $stow = new_Stow(dir => "$ABS_TEST_DIR/stow", target => "$ABS_TEST_DIR/target");
|
||||
|
||||
($path, $stow_path, $package) =
|
||||
$stow->find_stowed_path("$TEST_DIR/target/a/b/c", "../../stow/a/b/c");
|
||||
is($path, "$TEST_DIR/target/stow/a/b/c", "path");
|
||||
is($stow_path, "$TEST_DIR/target/stow", "stow path");
|
||||
is($package, "a", "stow is subdir of target directory");
|
||||
# Required by creation of stow2 and stow2/.stow below
|
||||
cd("$ABS_TEST_DIR/target");
|
||||
|
||||
($path, $stow_path, $package) =
|
||||
$stow->find_stowed_path("$TEST_DIR/target/a/b/c", "../../empty");
|
||||
is($path, "", "empty path");
|
||||
is($stow_path, "", "empty stow path");
|
||||
is($package, "", "target is not stowed");
|
||||
subtest("find link to a stowed path" => sub {
|
||||
plan tests => 3;
|
||||
my ($path, $stow_path, $package) =
|
||||
$stow->find_stowed_path("a/b/c", "../../../stow/a/b/c");
|
||||
is($path, "../stow/a/b/c", "path from target directory");
|
||||
is($stow_path, "../stow", "stow path from target directory");
|
||||
is($package, "a", "from target directory");
|
||||
});
|
||||
|
||||
make_path("$TEST_DIR/target/stow2");
|
||||
make_file("$TEST_DIR/target/stow2/.stow");
|
||||
subtest("find link to alien path not owned by Stow" => sub {
|
||||
plan tests => 3;
|
||||
my ($path, $stow_path, $package) =
|
||||
$stow->find_stowed_path("a/b/c", "../../alien");
|
||||
is($path, "", "alien is not stowed, so path is empty");
|
||||
is($stow_path, "", "alien, so stow path is empty");
|
||||
is($package, "", "alien is not stowed in any package");
|
||||
});
|
||||
|
||||
($path, $stow_path, $package) =
|
||||
$stow->find_stowed_path("$TEST_DIR/target/a/b/c","../../stow2/a/b/c");
|
||||
is($path, "$TEST_DIR/target/stow2/a/b/c", "path");
|
||||
is($stow_path, "$TEST_DIR/target/stow2", "stow path");
|
||||
is($package, "a", "detect alternate stow directory");
|
||||
# Make a second stow directory within the target directory, so that we
|
||||
# can check that links to package files within that stow directory are
|
||||
# detected correctly.
|
||||
make_path("stow2");
|
||||
|
||||
# Possible corner case with rogue symlink pointing to ancestor of
|
||||
# stow dir.
|
||||
($path, $stow_path, $package) =
|
||||
$stow->find_stowed_path("$TEST_DIR/target/a/b/c","../../..");
|
||||
is($path, "", "path");
|
||||
is($stow_path, "", "stow path");
|
||||
is($package, "", "corner case - link points to ancestor of stow dir");
|
||||
# However this second stow directory is still "alien" to stow until we
|
||||
# put a .stow file in it. So first test a symlink pointing to a path
|
||||
# within this second stow directory
|
||||
subtest("second stow dir still alien without .stow" => sub {
|
||||
plan tests => 3;
|
||||
my ($path, $stow_path, $package) =
|
||||
$stow->find_stowed_path("a/b/c", "../../stow2/a/b/c");
|
||||
is($path, "", "stow2 not a stow dir yet, so path is empty");
|
||||
is($stow_path, "", "stow2 not a stow dir yet so stow path is empty");
|
||||
is($package, "", "not stowed in any recognised package yet");
|
||||
});
|
||||
|
||||
# Now make stow2 a secondary stow directory and test that
|
||||
make_file("stow2/.stow");
|
||||
|
||||
subtest(".stow makes second stow dir owned by Stow" => sub {
|
||||
plan tests => 3;
|
||||
my ($path, $stow_path, $package) =
|
||||
$stow->find_stowed_path("a/b/c", "../../stow2/a/b/c");
|
||||
is($path, "stow2/a/b/c", "path");
|
||||
is($stow_path, "stow2", "stow path");
|
||||
is($package, "a", "detect alternate stow directory");
|
||||
});
|
||||
|
||||
subtest("relative symlink pointing to target dir" => sub {
|
||||
plan tests => 3;
|
||||
my ($path, $stow_path, $package) =
|
||||
$stow->find_stowed_path("a/b/c", "../../..");
|
||||
# Technically the target dir is not owned by Stow, since
|
||||
# Stow won't touch the target dir itself, only its contents.
|
||||
is($path, "", "path");
|
||||
is($stow_path, "", "stow path");
|
||||
is($package, "", "corner case - link points to target dir");
|
||||
});
|
||||
|
||||
subtest("relative symlink pointing to parent of target dir" => sub {
|
||||
plan tests => 3;
|
||||
my ($path, $stow_path, $package) =
|
||||
$stow->find_stowed_path("a/b/c", "../../../..");
|
||||
is($path, "", "path");
|
||||
is($stow_path, "", "stow path");
|
||||
is($package, "", "corner case - link points to parent of target dir");
|
||||
});
|
||||
|
||||
subtest("unowned symlink pointing to absolute path inside target" => sub {
|
||||
plan tests => 3;
|
||||
my ($path, $stow_path, $package) =
|
||||
$stow->find_stowed_path("a/b/c", "$ABS_TEST_DIR/target/d");
|
||||
is($path, "", "path");
|
||||
is($stow_path, "", "stow path");
|
||||
is($package, "", "symlink unowned by Stow points to absolute path outside target directory");
|
||||
});
|
||||
|
||||
subtest("unowned symlink pointing to absolute path outside target" => sub {
|
||||
plan tests => 3;
|
||||
my ($path, $stow_path, $package) =
|
||||
$stow->find_stowed_path("a/b/c", "/dev/null");
|
||||
is($path, "", "path");
|
||||
is($stow_path, "", "stow path");
|
||||
is($package, "", "symlink unowned by Stow points to absolute path outside target directory");
|
||||
});
|
||||
|
||||
# Now make stow2 the primary stow directory and test that it still
|
||||
# works when the stow directory is under the target directory
|
||||
$stow->set_stow_dir("$ABS_TEST_DIR/target/stow2");
|
||||
|
||||
subtest("stow2 becomes the primary stow directory" => sub {
|
||||
plan tests => 3;
|
||||
|
||||
my ($path, $stow_path, $package) =
|
||||
$stow->find_stowed_path("a/b/c", "../../stow2/a/b/c");
|
||||
is($path, "stow2/a/b/c", "path in stow2");
|
||||
is($stow_path, "stow2", "stow path for stow2");
|
||||
is($package, "a", "stow2 is subdir of target directory");
|
||||
});
|
||||
|
|
117
t/join_paths.t
117
t/join_paths.t
|
@ -22,91 +22,40 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Stow::Util qw(join_paths);
|
||||
use Stow::Util qw(join_paths set_debug_level);
|
||||
|
||||
use Test::More tests => 14;
|
||||
#set_debug_level(4);
|
||||
|
||||
is(
|
||||
join_paths('a/b/c', 'd/e/f'),
|
||||
'a/b/c/d/e/f'
|
||||
=> 'simple'
|
||||
use Test::More tests => 22;
|
||||
|
||||
my @TESTS = (
|
||||
[['a/b/c', 'd/e/f'], 'a/b/c/d/e/f' => 'simple'],
|
||||
[['a/b/c', '/d/e/f'], '/d/e/f' => 'relative then absolute'],
|
||||
[['/a/b/c', 'd/e/f'], '/a/b/c/d/e/f' => 'absolute then relative'],
|
||||
[['/a/b/c', '/d/e/f'], '/d/e/f' => 'two absolutes'],
|
||||
[['/a/b/c/', '/d/e/f/'], '/d/e/f' => 'two absolutes with trailing /'],
|
||||
[['///a/b///c//', '/d///////e/f'], '/d/e/f' => "multiple /'s, absolute"],
|
||||
[['///a/b///c//', 'd///////e/f'], '/a/b/c/d/e/f' => "multiple /'s, relative"],
|
||||
[['', 'a/b/c'], 'a/b/c' => 'first empty'],
|
||||
[['a/b/c', ''], 'a/b/c' => 'second empty'],
|
||||
[['/', 'a/b/c'], '/a/b/c' => 'first is /'],
|
||||
[['a/b/c', '/'], '/' => 'second is /'],
|
||||
[['../a1/b1/../c1/', 'a2/../b2/e2'], '../a1/c1/b2/e2' => 'relative with ../'],
|
||||
[['../a1/b1/../c1/', '/a2/../b2/e2'], '/b2/e2' => 'absolute with ../'],
|
||||
[['../a1/../../c1', 'a2/../../'], '../..' => 'lots of ../'],
|
||||
[['./', '../a2'], '../a2' => 'drop any "./"'],
|
||||
[['./a1', '../../a2'], '../a2' => 'drop any "./foo"'],
|
||||
[['a/b/c', '.'], 'a/b/c' => '. on RHS'],
|
||||
[['a/b/c', '.', 'd/e'], 'a/b/c/d/e' => '. in middle'],
|
||||
[['0', 'a/b'], '0/a/b' => '0 at start'],
|
||||
[['/0', 'a/b'], '/0/a/b' => '/0 at start'],
|
||||
[['a/b/c', '0', 'd/e'], 'a/b/c/0/d/e' => '0 in middle'],
|
||||
[['a/b', '0'], 'a/b/0' => '0 at end'],
|
||||
);
|
||||
|
||||
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 "./"'
|
||||
);
|
||||
|
||||
is(
|
||||
join_paths('a/b/c', '.'),
|
||||
'a/b/c'
|
||||
=> '. on RHS'
|
||||
);
|
||||
for my $test (@TESTS) {
|
||||
my ($inputs, $expected, $scenario) = @$test;
|
||||
my $got = join_paths(@$inputs);
|
||||
my $descr = "$scenario: in=[" . join(', ', map "'$_'", @$inputs) . "] exp=[$expected] got=[$got]";
|
||||
is($got, $expected, $descr);
|
||||
}
|
||||
|
|
88
t/link_dest_within_stow_dir.t
Executable file
88
t/link_dest_within_stow_dir.t
Executable file
|
@ -0,0 +1,88 @@
|
|||
#!/usr/bin/perl
|
||||
#
|
||||
# This file is part of GNU Stow.
|
||||
#
|
||||
# GNU Stow is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# GNU Stow is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
|
||||
#
|
||||
# Testing Stow::link_dest_within_stow_dir()
|
||||
#
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Test::More tests => 6;
|
||||
|
||||
use testutil;
|
||||
use Stow::Util;
|
||||
|
||||
init_test_dirs();
|
||||
|
||||
# This is a relative path, unlike $ABS_TEST_DIR below.
|
||||
my $stow = new_Stow(dir => "$TEST_DIR/stow",
|
||||
target => "$TEST_DIR/target");
|
||||
|
||||
subtest("relative stow dir, link to top-level package file" => sub {
|
||||
plan tests => 2;
|
||||
my ($package, $path) =
|
||||
$stow->link_dest_within_stow_dir("../stow/pkg/dir/file");
|
||||
is($package, "pkg", "package");
|
||||
is($path, "dir/file", "path");
|
||||
});
|
||||
|
||||
subtest("relative stow dir, link to second-level package file" => sub {
|
||||
plan tests => 2;
|
||||
my ($package, $path) =
|
||||
$stow->link_dest_within_stow_dir("../stow/pkg/dir/subdir/file");
|
||||
is($package, "pkg", "package");
|
||||
is($path, "dir/subdir/file", "path");
|
||||
});
|
||||
|
||||
# This is an absolute path, unlike $TEST_DIR above.
|
||||
$stow = new_Stow(dir => "$ABS_TEST_DIR/stow",
|
||||
target => "$ABS_TEST_DIR/target");
|
||||
|
||||
subtest("relative stow dir, link to second-level package file" => sub {
|
||||
plan tests => 2;
|
||||
my ($package, $path) =
|
||||
$stow->link_dest_within_stow_dir("../stow/pkg/dir/file");
|
||||
is($package, "pkg", "package");
|
||||
is($path, "dir/file", "path");
|
||||
});
|
||||
|
||||
subtest("absolute stow dir, link to top-level package file" => sub {
|
||||
plan tests => 2;
|
||||
my ($package, $path) =
|
||||
$stow->link_dest_within_stow_dir("../stow/pkg/dir/subdir/file");
|
||||
is($package, "pkg", "package");
|
||||
is($path, "dir/subdir/file", "path");
|
||||
});
|
||||
|
||||
# Links with destination in the target are not pointing within
|
||||
# the stow dir, so they're not owned by stow.
|
||||
subtest("link to path in target" => sub {
|
||||
plan tests => 2;
|
||||
my ($package, $path) =
|
||||
$stow->link_dest_within_stow_dir("./alien");
|
||||
is($path, "", "alien is in target, so path is empty");
|
||||
is($package, "", "alien is in target, so package is empty");
|
||||
});
|
||||
|
||||
subtest("link to path outside target and stow dir" => sub {
|
||||
plan tests => 2;
|
||||
my ($package, $path) =
|
||||
$stow->link_dest_within_stow_dir("../alien");
|
||||
is($path, "", "alien is outside, so path is empty");
|
||||
is($package, "", "alien is outside, so package is empty");
|
||||
});
|
641
t/stow.t
641
t/stow.t
|
@ -22,7 +22,7 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Test::More tests => 118;
|
||||
use Test::More tests => 21;
|
||||
use Test::Output;
|
||||
use English qw(-no_match_vars);
|
||||
|
||||
|
@ -37,148 +37,143 @@ my %conflicts;
|
|||
|
||||
# Note that each of the following tests use a distinct set of files
|
||||
|
||||
#
|
||||
# stow a simple tree minimally
|
||||
#
|
||||
$stow = new_Stow(dir => '../stow');
|
||||
subtest('stow a simple tree minimally', sub {
|
||||
plan tests => 2;
|
||||
my $stow = new_Stow(dir => '../stow');
|
||||
|
||||
make_path('../stow/pkg1/bin1');
|
||||
make_file('../stow/pkg1/bin1/file1');
|
||||
make_path('../stow/pkg1/bin1');
|
||||
make_file('../stow/pkg1/bin1/file1');
|
||||
|
||||
$stow->plan_stow('pkg1');
|
||||
$stow->process_tasks();
|
||||
is_deeply([ $stow->get_conflicts ], [], 'no conflicts with minimal stow');
|
||||
is(
|
||||
$stow->plan_stow('pkg1');
|
||||
$stow->process_tasks();
|
||||
is_deeply([ $stow->get_conflicts ], [], 'no conflicts with minimal stow');
|
||||
is(
|
||||
readlink('bin1'),
|
||||
'../stow/pkg1/bin1',
|
||||
=> 'minimal stow of a simple tree'
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# stow a simple tree into an existing directory
|
||||
#
|
||||
$stow = new_Stow();
|
||||
subtest('stow a simple tree into an existing directory', sub {
|
||||
plan tests => 1;
|
||||
my $stow = new_Stow();
|
||||
|
||||
make_path('../stow/pkg2/lib2');
|
||||
make_file('../stow/pkg2/lib2/file2');
|
||||
make_path('lib2');
|
||||
make_path('../stow/pkg2/lib2');
|
||||
make_file('../stow/pkg2/lib2/file2');
|
||||
make_path('lib2');
|
||||
|
||||
$stow->plan_stow('pkg2');
|
||||
$stow->process_tasks();
|
||||
is(
|
||||
$stow->plan_stow('pkg2');
|
||||
$stow->process_tasks();
|
||||
is(
|
||||
readlink('lib2/file2'),
|
||||
'../../stow/pkg2/lib2/file2',
|
||||
=> 'stow simple tree to existing directory'
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# unfold existing tree
|
||||
#
|
||||
$stow = new_Stow();
|
||||
subtest('unfold existing tree', sub {
|
||||
plan tests => 3;
|
||||
my $stow = new_Stow();
|
||||
|
||||
make_path('../stow/pkg3a/bin3');
|
||||
make_file('../stow/pkg3a/bin3/file3a');
|
||||
make_link('bin3' => '../stow/pkg3a/bin3'); # emulate stow
|
||||
make_path('../stow/pkg3a/bin3');
|
||||
make_file('../stow/pkg3a/bin3/file3a');
|
||||
make_link('bin3' => '../stow/pkg3a/bin3'); # emulate stow
|
||||
|
||||
make_path('../stow/pkg3b/bin3');
|
||||
make_file('../stow/pkg3b/bin3/file3b');
|
||||
make_path('../stow/pkg3b/bin3');
|
||||
make_file('../stow/pkg3b/bin3/file3b');
|
||||
|
||||
$stow->plan_stow('pkg3b');
|
||||
$stow->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'
|
||||
);
|
||||
$stow->plan_stow('pkg3b');
|
||||
$stow->process_tasks();
|
||||
ok(-d 'bin3');
|
||||
is(readlink('bin3/file3a'), '../../stow/pkg3a/bin3/file3a');
|
||||
is(readlink('bin3/file3b'), '../../stow/pkg3b/bin3/file3b'
|
||||
=> 'target already has 1 stowed package');
|
||||
});
|
||||
|
||||
#
|
||||
# Link to a new dir 'bin4' conflicts with existing non-dir so can't
|
||||
# unfold
|
||||
#
|
||||
$stow = new_Stow();
|
||||
subtest("Package dir 'bin4' conflicts with existing non-dir so can't unfold", sub {
|
||||
plan tests => 2;
|
||||
my $stow = new_Stow();
|
||||
|
||||
make_file('bin4'); # this is a file but named like a directory
|
||||
make_path('../stow/pkg4/bin4');
|
||||
make_file('../stow/pkg4/bin4/file4');
|
||||
make_file('bin4'); # this is a file but named like a directory
|
||||
make_path('../stow/pkg4/bin4');
|
||||
make_file('../stow/pkg4/bin4/file4');
|
||||
|
||||
$stow->plan_stow('pkg4');
|
||||
%conflicts = $stow->get_conflicts();
|
||||
ok(
|
||||
$stow->get_conflict_count == 1 &&
|
||||
$conflicts{stow}{pkg4}[0] =~
|
||||
$stow->plan_stow('pkg4');
|
||||
%conflicts = $stow->get_conflicts();
|
||||
is($stow->get_conflict_count, 1);
|
||||
like(
|
||||
$conflicts{stow}{pkg4}[0],
|
||||
qr/existing target is neither a link nor a directory/
|
||||
=> 'link to new dir bin4 conflicts with existing non-directory'
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# Link to a new dir 'bin4a' conflicts with existing non-dir so can't
|
||||
# unfold even with --adopt
|
||||
#
|
||||
#$stow = new_Stow(adopt => 1);
|
||||
$stow = new_Stow();
|
||||
subtest("Package dir 'bin4a' conflicts with existing non-dir " .
|
||||
"so can't unfold even with --adopt", sub {
|
||||
plan tests => 2;
|
||||
#my $stow = new_Stow(adopt => 1);
|
||||
my $stow = new_Stow();
|
||||
|
||||
make_file('bin4a'); # this is a file but named like a directory
|
||||
make_path('../stow/pkg4a/bin4a');
|
||||
make_file('../stow/pkg4a/bin4a/file4a');
|
||||
make_file('bin4a'); # this is a file but named like a directory
|
||||
make_path('../stow/pkg4a/bin4a');
|
||||
make_file('../stow/pkg4a/bin4a/file4a');
|
||||
|
||||
$stow->plan_stow('pkg4a');
|
||||
%conflicts = $stow->get_conflicts();
|
||||
ok(
|
||||
$stow->get_conflict_count == 1 &&
|
||||
$conflicts{stow}{pkg4a}[0] =~
|
||||
$stow->plan_stow('pkg4a');
|
||||
%conflicts = $stow->get_conflicts();
|
||||
is($stow->get_conflict_count, 1);
|
||||
like($conflicts{stow}{pkg4a}[0],
|
||||
qr/existing target is neither a link nor a directory/
|
||||
=> 'link to new dir bin4a conflicts with existing non-directory'
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# Link to files 'file4b' and 'bin4b' conflict with existing files
|
||||
# without --adopt
|
||||
#
|
||||
$stow = new_Stow();
|
||||
subtest("Package files 'file4b' and 'bin4b' conflict with existing files", sub {
|
||||
plan tests => 3;
|
||||
my $stow = new_Stow();
|
||||
|
||||
# Populate target
|
||||
make_file('file4b', 'file4b - version originally in target');
|
||||
make_path ('bin4b');
|
||||
make_file('bin4b/file4b', 'bin4b/file4b - version originally in target');
|
||||
# Populate target
|
||||
make_file('file4b', 'file4b - version originally in target');
|
||||
make_path('bin4b');
|
||||
make_file('bin4b/file4b', 'bin4b/file4b - version originally in target');
|
||||
|
||||
# Populate
|
||||
make_path ('../stow/pkg4b/bin4b');
|
||||
make_file('../stow/pkg4b/file4b', 'file4b - version originally in stow package');
|
||||
make_file('../stow/pkg4b/bin4b/file4b', 'bin4b/file4b - version originally in stow package');
|
||||
# Populate stow package
|
||||
make_path('../stow/pkg4b');
|
||||
make_file('../stow/pkg4b/file4b', 'file4b - version originally in stow package');
|
||||
make_path('../stow/pkg4b/bin4b');
|
||||
make_file('../stow/pkg4b/bin4b/file4b', 'bin4b/file4b - version originally in stow package');
|
||||
|
||||
$stow->plan_stow('pkg4b');
|
||||
%conflicts = $stow->get_conflicts();
|
||||
is($stow->get_conflict_count, 2 => 'conflict per file');
|
||||
for my $i (0, 1) {
|
||||
$stow->plan_stow('pkg4b');
|
||||
%conflicts = $stow->get_conflicts();
|
||||
is($stow->get_conflict_count, 2 => 'conflict per file');
|
||||
for my $i (0, 1) {
|
||||
like(
|
||||
$conflicts{stow}{pkg4b}[$i],
|
||||
qr/existing target is neither a link nor a directory/
|
||||
=> 'link to file4b conflicts with existing non-directory'
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
#
|
||||
# Link to files 'file4b' and 'bin4b' do not conflict with existing
|
||||
# files when --adopt is given
|
||||
#
|
||||
$stow = new_Stow(adopt => 1);
|
||||
subtest("Package files 'file4c' and 'bin4c' can adopt existing versions", sub {
|
||||
plan tests => 8;
|
||||
my $stow = new_Stow(adopt => 1);
|
||||
|
||||
# Populate target
|
||||
make_file('file4c', "file4c - version originally in target\n");
|
||||
make_path ('bin4c');
|
||||
make_file('bin4c/file4c', "bin4c/file4c - version originally in target\n");
|
||||
# Populate target
|
||||
make_file('file4c', "file4c - version originally in target\n");
|
||||
make_path ('bin4c');
|
||||
make_file('bin4c/file4c', "bin4c/file4c - version originally in target\n");
|
||||
|
||||
# Populate
|
||||
make_path ('../stow/pkg4c/bin4c');
|
||||
make_file('../stow/pkg4c/file4c', "file4c - version originally in stow package\n");
|
||||
make_file('../stow/pkg4c/bin4c/file4c', "bin4c/file4c - version originally in stow package\n");
|
||||
# Populate stow package
|
||||
make_path('../stow/pkg4c');
|
||||
make_file('../stow/pkg4c/file4c', "file4c - version originally in stow package\n");
|
||||
make_path ('../stow/pkg4c/bin4c');
|
||||
make_file('../stow/pkg4c/bin4c/file4c', "bin4c/file4c - version originally in stow package\n");
|
||||
|
||||
$stow->plan_stow('pkg4c');
|
||||
is($stow->get_conflict_count, 0 => 'no conflicts with --adopt');
|
||||
is($stow->get_tasks, 4 => 'two tasks per file');
|
||||
$stow->process_tasks();
|
||||
for my $file ('file4c', 'bin4c/file4c') {
|
||||
$stow->plan_stow('pkg4c');
|
||||
is($stow->get_conflict_count, 0 => 'no conflicts with --adopt');
|
||||
is($stow->get_tasks, 4 => 'two tasks per file');
|
||||
$stow->process_tasks();
|
||||
for my $file ('file4c', 'bin4c/file4c') {
|
||||
ok(-l $file, "$file turned into a symlink");
|
||||
is(
|
||||
readlink $file,
|
||||
|
@ -186,282 +181,273 @@ for my $file ('file4c', 'bin4c/file4c') {
|
|||
. "../stow/pkg4c/$file" => "$file points to right place"
|
||||
);
|
||||
is(cat_file($file), "$file - version originally in target\n" => "$file has right contents");
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
#
|
||||
# Target already exists but is not owned by stow
|
||||
#
|
||||
$stow = new_Stow();
|
||||
subtest("Target already exists but is not owned by stow", sub {
|
||||
plan tests => 1;
|
||||
my $stow = new_Stow();
|
||||
|
||||
make_path('bin5');
|
||||
make_invalid_link('bin5/file5','../../empty');
|
||||
make_path('../stow/pkg5/bin5/file5');
|
||||
make_path('bin5');
|
||||
make_invalid_link('bin5/file5','../../empty');
|
||||
make_path('../stow/pkg5/bin5/file5');
|
||||
|
||||
$stow->plan_stow('pkg5');
|
||||
%conflicts = $stow->get_conflicts();
|
||||
like(
|
||||
$stow->plan_stow('pkg5');
|
||||
%conflicts = $stow->get_conflicts();
|
||||
like(
|
||||
$conflicts{stow}{pkg5}[-1],
|
||||
qr/not owned by stow/
|
||||
=> 'target already exists but is not owned by stow'
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# Replace existing but invalid target
|
||||
#
|
||||
$stow = new_Stow();
|
||||
subtest("Replace existing but invalid target", sub {
|
||||
plan tests => 1;
|
||||
my $stow = new_Stow();
|
||||
|
||||
make_invalid_link('file6','../stow/path-does-not-exist');
|
||||
make_path('../stow/pkg6');
|
||||
make_file('../stow/pkg6/file6');
|
||||
make_invalid_link('file6','../stow/path-does-not-exist');
|
||||
make_path('../stow/pkg6');
|
||||
make_file('../stow/pkg6/file6');
|
||||
|
||||
$stow->plan_stow('pkg6');
|
||||
$stow->process_tasks();
|
||||
is(
|
||||
$stow->plan_stow('pkg6');
|
||||
$stow->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)
|
||||
#
|
||||
$stow = new_Stow();
|
||||
#set_debug_level(4);
|
||||
subtest("Target already exists, is owned by stow, but points to a non-directory", sub {
|
||||
plan tests => 1;
|
||||
my $stow = new_Stow();
|
||||
#set_debug_level(4);
|
||||
|
||||
make_path('bin7');
|
||||
make_path('../stow/pkg7a/bin7');
|
||||
make_file('../stow/pkg7a/bin7/node7');
|
||||
make_link('bin7/node7','../../stow/pkg7a/bin7/node7');
|
||||
make_path('../stow/pkg7b/bin7/node7');
|
||||
make_file('../stow/pkg7b/bin7/node7/file7');
|
||||
make_path('bin7');
|
||||
make_path('../stow/pkg7a/bin7');
|
||||
make_file('../stow/pkg7a/bin7/node7');
|
||||
make_link('bin7/node7','../../stow/pkg7a/bin7/node7');
|
||||
make_path('../stow/pkg7b/bin7/node7');
|
||||
make_file('../stow/pkg7b/bin7/node7/file7');
|
||||
|
||||
$stow->plan_stow('pkg7b');
|
||||
%conflicts = $stow->get_conflicts();
|
||||
like(
|
||||
$stow->plan_stow('pkg7b');
|
||||
%conflicts = $stow->get_conflicts();
|
||||
like(
|
||||
$conflicts{stow}{pkg7b}[-1],
|
||||
qr/existing target is stowed to a different package/
|
||||
=> 'link to new dir conflicts with existing stowed non-directory'
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# stowing directories named 0
|
||||
#
|
||||
$stow = new_Stow();
|
||||
subtest("stowing directories named 0", sub {
|
||||
plan tests => 4;
|
||||
my $stow = new_Stow();
|
||||
|
||||
make_path('../stow/pkg8a/0');
|
||||
make_file('../stow/pkg8a/0/file8a');
|
||||
make_link('0' => '../stow/pkg8a/0'); # emulate stow
|
||||
make_path('../stow/pkg8a/0');
|
||||
make_file('../stow/pkg8a/0/file8a');
|
||||
make_link('0' => '../stow/pkg8a/0'); # emulate stow
|
||||
|
||||
make_path('../stow/pkg8b/0');
|
||||
make_file('../stow/pkg8b/0/file8b');
|
||||
make_path('../stow/pkg8b/0');
|
||||
make_file('../stow/pkg8b/0/file8b');
|
||||
|
||||
$stow->plan_stow('pkg8b');
|
||||
$stow->process_tasks();
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
-d '0' &&
|
||||
readlink('0/file8a') eq '../../stow/pkg8a/0/file8a' &&
|
||||
readlink('0/file8b') eq '../../stow/pkg8b/0/file8b'
|
||||
$stow->plan_stow('pkg8b');
|
||||
$stow->process_tasks();
|
||||
is($stow->get_conflict_count, 0);
|
||||
ok(-d '0');
|
||||
is(readlink('0/file8a'), '../../stow/pkg8a/0/file8a');
|
||||
is(readlink('0/file8b'), '../../stow/pkg8b/0/file8b'
|
||||
=> 'stowing directories named 0'
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# overriding already stowed documentation
|
||||
#
|
||||
$stow = new_Stow(override => ['man9', 'info9']);
|
||||
subtest("overriding already stowed documentation", sub {
|
||||
plan tests => 2;
|
||||
my $stow = new_Stow(override => ['man9', 'info9']);
|
||||
|
||||
make_path('../stow/pkg9a/man9/man1');
|
||||
make_file('../stow/pkg9a/man9/man1/file9.1');
|
||||
make_path('man9/man1');
|
||||
make_link('man9/man1/file9.1' => '../../../stow/pkg9a/man9/man1/file9.1'); # emulate stow
|
||||
make_path('../stow/pkg9a/man9/man1');
|
||||
make_file('../stow/pkg9a/man9/man1/file9.1');
|
||||
make_path('man9/man1');
|
||||
make_link('man9/man1/file9.1' => '../../../stow/pkg9a/man9/man1/file9.1'); # emulate stow
|
||||
|
||||
make_path('../stow/pkg9b/man9/man1');
|
||||
make_file('../stow/pkg9b/man9/man1/file9.1');
|
||||
make_path('../stow/pkg9b/man9/man1');
|
||||
make_file('../stow/pkg9b/man9/man1/file9.1');
|
||||
|
||||
$stow->plan_stow('pkg9b');
|
||||
$stow->process_tasks();
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
readlink('man9/man1/file9.1') eq '../../../stow/pkg9b/man9/man1/file9.1'
|
||||
$stow->plan_stow('pkg9b');
|
||||
$stow->process_tasks();
|
||||
is($stow->get_conflict_count, 0);
|
||||
is(readlink('man9/man1/file9.1'), '../../../stow/pkg9b/man9/man1/file9.1'
|
||||
=> 'overriding existing documentation files'
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# deferring to already stowed documentation
|
||||
#
|
||||
$stow = new_Stow(defer => ['man10', 'info10']);
|
||||
subtest("deferring to already stowed documentation", sub {
|
||||
plan tests => 3;
|
||||
my $stow = new_Stow(defer => ['man10', 'info10']);
|
||||
|
||||
make_path('../stow/pkg10a/man10/man1');
|
||||
make_file('../stow/pkg10a/man10/man1/file10.1');
|
||||
make_path('man10/man1');
|
||||
make_link('man10/man1/file10.1' => '../../../stow/pkg10a/man10/man1/file10.1'); # emulate stow
|
||||
make_path('../stow/pkg10a/man10/man1');
|
||||
make_file('../stow/pkg10a/man10/man1/file10.1');
|
||||
make_path('man10/man1');
|
||||
make_link('man10/man1/file10.1' => '../../../stow/pkg10a/man10/man1/file10.1'); # emulate stow
|
||||
|
||||
make_path('../stow/pkg10b/man10/man1');
|
||||
make_file('../stow/pkg10b/man10/man1/file10.1');
|
||||
make_path('../stow/pkg10b/man10/man1');
|
||||
make_file('../stow/pkg10b/man10/man1/file10.1');
|
||||
|
||||
$stow->plan_stow('pkg10b');
|
||||
is($stow->get_tasks, 0, 'no tasks to process');
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
readlink('man10/man1/file10.1') eq '../../../stow/pkg10a/man10/man1/file10.1'
|
||||
$stow->plan_stow('pkg10b');
|
||||
is($stow->get_tasks, 0, 'no tasks to process');
|
||||
is($stow->get_conflict_count, 0);
|
||||
is(readlink('man10/man1/file10.1'), '../../../stow/pkg10a/man10/man1/file10.1'
|
||||
=> 'defer to existing documentation files'
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# Ignore temp files
|
||||
#
|
||||
$stow = new_Stow(ignore => ['~', '\.#.*']);
|
||||
subtest("Ignore temp files", sub {
|
||||
plan tests => 4;
|
||||
my $stow = new_Stow(ignore => ['~', '\.#.*']);
|
||||
|
||||
make_path('../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_path('man11/man1');
|
||||
make_path('../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_path('man11/man1');
|
||||
|
||||
$stow->plan_stow('pkg11');
|
||||
$stow->process_tasks();
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
readlink('man11/man1/file11.1') eq '../../../stow/pkg11/man11/man1/file11.1' &&
|
||||
!-e 'man11/man1/file11.1~' &&
|
||||
!-e 'man11/man1/.#file11.1'
|
||||
$stow->plan_stow('pkg11');
|
||||
$stow->process_tasks();
|
||||
is($stow->get_conflict_count, 0);
|
||||
is(readlink('man11/man1/file11.1'), '../../../stow/pkg11/man11/man1/file11.1');
|
||||
ok(!-e 'man11/man1/file11.1~');
|
||||
ok(!-e 'man11/man1/.#file11.1'
|
||||
=> 'ignore temp files'
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# stowing links library files
|
||||
#
|
||||
$stow = new_Stow();
|
||||
subtest("stowing links library files", sub {
|
||||
plan tests => 3;
|
||||
my $stow = new_Stow();
|
||||
|
||||
make_path('../stow/pkg12/lib12/');
|
||||
make_file('../stow/pkg12/lib12/lib.so.1');
|
||||
make_link('../stow/pkg12/lib12/lib.so', 'lib.so.1');
|
||||
make_path('../stow/pkg12/lib12/');
|
||||
make_file('../stow/pkg12/lib12/lib.so.1');
|
||||
make_link('../stow/pkg12/lib12/lib.so', 'lib.so.1');
|
||||
|
||||
make_path('lib12/');
|
||||
make_path('lib12/');
|
||||
|
||||
$stow->plan_stow('pkg12');
|
||||
$stow->process_tasks();
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
readlink('lib12/lib.so.1') eq '../../stow/pkg12/lib12/lib.so.1' &&
|
||||
readlink('lib12/lib.so' ) eq '../../stow/pkg12/lib12/lib.so'
|
||||
$stow->plan_stow('pkg12');
|
||||
$stow->process_tasks();
|
||||
is($stow->get_conflict_count, 0);
|
||||
is(readlink('lib12/lib.so.1'), '../../stow/pkg12/lib12/lib.so.1');
|
||||
is(readlink('lib12/lib.so'), '../../stow/pkg12/lib12/lib.so'
|
||||
=> 'stow links to libraries'
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# unfolding to stow links to library files
|
||||
#
|
||||
$stow = new_Stow();
|
||||
subtest("unfolding to stow links to library files", sub {
|
||||
plan tests => 5;
|
||||
my $stow = new_Stow();
|
||||
|
||||
make_path('../stow/pkg13a/lib13/');
|
||||
make_file('../stow/pkg13a/lib13/liba.so.1');
|
||||
make_link('../stow/pkg13a/lib13/liba.so', 'liba.so.1');
|
||||
make_link('lib13','../stow/pkg13a/lib13');
|
||||
make_path('../stow/pkg13a/lib13/');
|
||||
make_file('../stow/pkg13a/lib13/liba.so.1');
|
||||
make_link('../stow/pkg13a/lib13/liba.so', 'liba.so.1');
|
||||
make_link('lib13','../stow/pkg13a/lib13');
|
||||
|
||||
make_path('../stow/pkg13b/lib13/');
|
||||
make_file('../stow/pkg13b/lib13/libb.so.1');
|
||||
make_link('../stow/pkg13b/lib13/libb.so', 'libb.so.1');
|
||||
make_path('../stow/pkg13b/lib13/');
|
||||
make_file('../stow/pkg13b/lib13/libb.so.1');
|
||||
make_link('../stow/pkg13b/lib13/libb.so', 'libb.so.1');
|
||||
|
||||
$stow->plan_stow('pkg13b');
|
||||
$stow->process_tasks();
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
readlink('lib13/liba.so.1') eq '../../stow/pkg13a/lib13/liba.so.1' &&
|
||||
readlink('lib13/liba.so' ) eq '../../stow/pkg13a/lib13/liba.so' &&
|
||||
readlink('lib13/libb.so.1') eq '../../stow/pkg13b/lib13/libb.so.1' &&
|
||||
readlink('lib13/libb.so' ) eq '../../stow/pkg13b/lib13/libb.so'
|
||||
$stow->plan_stow('pkg13b');
|
||||
$stow->process_tasks();
|
||||
is($stow->get_conflict_count, 0);
|
||||
is(readlink('lib13/liba.so.1'), '../../stow/pkg13a/lib13/liba.so.1');
|
||||
is(readlink('lib13/liba.so' ), '../../stow/pkg13a/lib13/liba.so');
|
||||
is(readlink('lib13/libb.so.1'), '../../stow/pkg13b/lib13/libb.so.1');
|
||||
is(readlink('lib13/libb.so' ), '../../stow/pkg13b/lib13/libb.so'
|
||||
=> 'unfolding to stow links to libraries'
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# stowing to stow dir should fail
|
||||
#
|
||||
make_path('stow');
|
||||
$stow = new_Stow(dir => 'stow');
|
||||
subtest("stowing to stow dir should fail", sub {
|
||||
plan tests => 4;
|
||||
make_path('stow');
|
||||
$stow = new_Stow(dir => 'stow');
|
||||
|
||||
make_path('stow/pkg14/stow/pkg15');
|
||||
make_file('stow/pkg14/stow/pkg15/node15');
|
||||
make_path('stow/pkg14/stow/pkg15');
|
||||
make_file('stow/pkg14/stow/pkg15/node15');
|
||||
|
||||
capture_stderr();
|
||||
$stow->plan_stow('pkg14');
|
||||
is($stow->get_tasks, 0, 'no tasks to process');
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
stderr_like(
|
||||
sub { $stow->plan_stow('pkg14'); },
|
||||
qr/WARNING: skipping target which was current stow directory stow/,
|
||||
"stowing to stow dir should give warning"
|
||||
);
|
||||
|
||||
is($stow->get_tasks, 0, 'no tasks to process');
|
||||
is($stow->get_conflict_count, 0);
|
||||
ok(
|
||||
! -l 'stow/pkg15'
|
||||
=> "stowing to stow dir should fail"
|
||||
);
|
||||
like($stderr,
|
||||
qr/WARNING: skipping target which was current stow directory stow/
|
||||
=> "stowing to stow dir should give warning");
|
||||
uncapture_stderr();
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# stow a simple tree minimally when cwd isn't target
|
||||
#
|
||||
cd('../..');
|
||||
$stow = new_Stow(dir => "$TEST_DIR/stow", target => "$TEST_DIR/target");
|
||||
subtest("stow a simple tree minimally when cwd isn't target", sub {
|
||||
plan tests => 2;
|
||||
cd('../..');
|
||||
$stow = new_Stow(dir => "$TEST_DIR/stow", target => "$TEST_DIR/target");
|
||||
|
||||
make_path("$TEST_DIR/stow/pkg16/bin16");
|
||||
make_file("$TEST_DIR/stow/pkg16/bin16/file16");
|
||||
make_path("$TEST_DIR/stow/pkg16/bin16");
|
||||
make_file("$TEST_DIR/stow/pkg16/bin16/file16");
|
||||
|
||||
$stow->plan_stow('pkg16');
|
||||
$stow->process_tasks();
|
||||
is_deeply([ $stow->get_conflicts ], [], 'no conflicts with minimal stow');
|
||||
is(
|
||||
$stow->plan_stow('pkg16');
|
||||
$stow->process_tasks();
|
||||
is_deeply([ $stow->get_conflicts ], [], 'no conflicts with minimal stow');
|
||||
is(
|
||||
readlink("$TEST_DIR/target/bin16"),
|
||||
'../stow/pkg16/bin16',
|
||||
=> "minimal stow of a simple tree when cwd isn't target"
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# stow a simple tree minimally to absolute stow dir when cwd isn't
|
||||
# target
|
||||
#
|
||||
$stow = new_Stow(dir => canon_path("$TEST_DIR/stow"),
|
||||
subtest("stow a simple tree minimally to absolute stow dir when cwd isn't", sub {
|
||||
plan tests => 2;
|
||||
my $stow = new_Stow(dir => canon_path("$TEST_DIR/stow"),
|
||||
target => "$TEST_DIR/target");
|
||||
|
||||
make_path("$TEST_DIR/stow/pkg17/bin17");
|
||||
make_file("$TEST_DIR/stow/pkg17/bin17/file17");
|
||||
make_path("$TEST_DIR/stow/pkg17/bin17");
|
||||
make_file("$TEST_DIR/stow/pkg17/bin17/file17");
|
||||
|
||||
$stow->plan_stow('pkg17');
|
||||
$stow->process_tasks();
|
||||
is_deeply([ $stow->get_conflicts ], [], 'no conflicts with minimal stow');
|
||||
is(
|
||||
$stow->plan_stow('pkg17');
|
||||
$stow->process_tasks();
|
||||
is_deeply([ $stow->get_conflicts ], [], 'no conflicts with minimal stow');
|
||||
is(
|
||||
readlink("$TEST_DIR/target/bin17"),
|
||||
'../stow/pkg17/bin17',
|
||||
=> "minimal stow of a simple tree with absolute stow dir"
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# stow a simple tree minimally with absolute stow AND target dirs when
|
||||
# cwd isn't target
|
||||
#
|
||||
$stow = new_Stow(dir => canon_path("$TEST_DIR/stow"),
|
||||
subtest("stow a simple tree minimally with absolute stow AND target dirs when", sub {
|
||||
plan tests => 2;
|
||||
my $stow = new_Stow(dir => canon_path("$TEST_DIR/stow"),
|
||||
target => canon_path("$TEST_DIR/target"));
|
||||
|
||||
make_path("$TEST_DIR/stow/pkg18/bin18");
|
||||
make_file("$TEST_DIR/stow/pkg18/bin18/file18");
|
||||
make_path("$TEST_DIR/stow/pkg18/bin18");
|
||||
make_file("$TEST_DIR/stow/pkg18/bin18/file18");
|
||||
|
||||
$stow->plan_stow('pkg18');
|
||||
$stow->process_tasks();
|
||||
is_deeply([ $stow->get_conflicts ], [], 'no conflicts with minimal stow');
|
||||
is(
|
||||
$stow->plan_stow('pkg18');
|
||||
$stow->process_tasks();
|
||||
is_deeply([ $stow->get_conflicts ], [], 'no conflicts with minimal stow');
|
||||
is(
|
||||
readlink("$TEST_DIR/target/bin18"),
|
||||
'../stow/pkg18/bin18',
|
||||
=> "minimal stow of a simple tree with absolute stow and target dirs"
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# stow a tree with no-folding enabled -
|
||||
# no new folded directories should be created, and existing
|
||||
# folded directories should be split open (unfolded) where
|
||||
# (and only where) necessary
|
||||
#
|
||||
cd("$TEST_DIR/target");
|
||||
subtest("stow a tree with no-folding enabled", sub {
|
||||
plan tests => 82;
|
||||
# folded directories should be split open (unfolded) where
|
||||
# (and only where) necessary
|
||||
#
|
||||
cd("$TEST_DIR/target");
|
||||
|
||||
sub create_pkg {
|
||||
sub create_pkg {
|
||||
my ($id, $pkg) = @_;
|
||||
|
||||
my $stow_pkg = "../stow/$id-$pkg";
|
||||
|
@ -493,21 +479,21 @@ sub create_pkg {
|
|||
make_path ("$stow_pkg/$id-shared2/subdir-$pkg");
|
||||
make_file("$stow_pkg/$id-shared2/$id-file-$pkg");
|
||||
make_file("$stow_pkg/$id-shared2/subdir-$pkg/$id-file-$pkg");
|
||||
}
|
||||
}
|
||||
|
||||
foreach my $pkg (qw{a b}) {
|
||||
foreach my $pkg (qw{a b}) {
|
||||
create_pkg('no-folding', $pkg);
|
||||
}
|
||||
}
|
||||
|
||||
$stow = new_Stow('no-folding' => 1);
|
||||
$stow->plan_stow('no-folding-a');
|
||||
is_deeply([ $stow->get_conflicts ], [] => 'no conflicts with --no-folding');
|
||||
my @tasks = $stow->get_tasks;
|
||||
use Data::Dumper;
|
||||
is(scalar(@tasks), 13 => "6 dirs, 7 links") || warn Dumper(\@tasks);
|
||||
$stow->process_tasks();
|
||||
$stow = new_Stow('no-folding' => 1);
|
||||
$stow->plan_stow('no-folding-a');
|
||||
is_deeply([ $stow->get_conflicts ], [] => 'no conflicts with --no-folding');
|
||||
my @tasks = $stow->get_tasks;
|
||||
use Data::Dumper;
|
||||
is(scalar(@tasks), 13 => "6 dirs, 7 links") || warn Dumper(\@tasks);
|
||||
$stow->process_tasks();
|
||||
|
||||
sub check_no_folding {
|
||||
sub check_no_folding {
|
||||
my ($pkg) = @_;
|
||||
my $stow_pkg = "../stow/no-folding-$pkg";
|
||||
is_link("no-folding-file-$pkg", "$stow_pkg/no-folding-file-$pkg");
|
||||
|
@ -541,16 +527,17 @@ sub check_no_folding {
|
|||
"../$stow_pkg/no-folding-shared2/no-folding-file-$pkg");
|
||||
is_link("no-folding-shared2/no-folding-file-$pkg",
|
||||
"../$stow_pkg/no-folding-shared2/no-folding-file-$pkg");
|
||||
}
|
||||
}
|
||||
|
||||
check_no_folding('a');
|
||||
check_no_folding('a');
|
||||
|
||||
$stow = new_Stow('no-folding' => 1);
|
||||
$stow->plan_stow('no-folding-b');
|
||||
is_deeply([ $stow->get_conflicts ], [] => 'no conflicts with --no-folding');
|
||||
@tasks = $stow->get_tasks;
|
||||
is(scalar(@tasks), 11 => '4 dirs, 7 links') || warn Dumper(\@tasks);
|
||||
$stow->process_tasks();
|
||||
$stow = new_Stow('no-folding' => 1);
|
||||
$stow->plan_stow('no-folding-b');
|
||||
is_deeply([ $stow->get_conflicts ], [] => 'no conflicts with --no-folding');
|
||||
@tasks = $stow->get_tasks;
|
||||
is(scalar(@tasks), 11 => '4 dirs, 7 links') || warn Dumper(\@tasks);
|
||||
$stow->process_tasks();
|
||||
|
||||
check_no_folding('a');
|
||||
check_no_folding('b');
|
||||
check_no_folding('a');
|
||||
check_no_folding('b');
|
||||
});
|
||||
|
|
|
@ -28,7 +28,6 @@ use Carp qw(croak);
|
|||
use File::Basename;
|
||||
use File::Path qw(make_path remove_tree);
|
||||
use File::Spec;
|
||||
use IO::Scalar;
|
||||
use Test::More;
|
||||
|
||||
use Stow;
|
||||
|
@ -38,7 +37,6 @@ use base qw(Exporter);
|
|||
our @EXPORT = qw(
|
||||
$ABS_TEST_DIR
|
||||
$TEST_DIR
|
||||
$stderr
|
||||
init_test_dirs
|
||||
cd
|
||||
new_Stow new_compat_Stow
|
||||
|
@ -46,25 +44,11 @@ our @EXPORT = qw(
|
|||
remove_dir remove_file remove_link
|
||||
cat_file
|
||||
is_link is_dir_not_symlink is_nonexistent_path
|
||||
capture_stderr uncapture_stderr
|
||||
);
|
||||
|
||||
our $TEST_DIR = 'tmp-testing-trees';
|
||||
our $ABS_TEST_DIR = File::Spec->rel2abs('tmp-testing-trees');
|
||||
|
||||
our $stderr;
|
||||
my $tied_err;
|
||||
|
||||
sub capture_stderr {
|
||||
undef $stderr;
|
||||
$tied_err = tie *STDERR, 'IO::Scalar', \$stderr;
|
||||
}
|
||||
|
||||
sub uncapture_stderr {
|
||||
undef $tied_err;
|
||||
untie *STDERR;
|
||||
}
|
||||
|
||||
sub init_test_dirs {
|
||||
# Create a run_from/ subdirectory for tests which want to run
|
||||
# from a separate directory outside the Stow directory or
|
||||
|
@ -81,6 +65,8 @@ sub init_test_dirs {
|
|||
|
||||
sub new_Stow {
|
||||
my %opts = @_;
|
||||
# These default paths assume that execution will be triggered from
|
||||
# within the target directory.
|
||||
$opts{dir} ||= '../stow';
|
||||
$opts{target} ||= '.';
|
||||
$opts{test_mode} = 1;
|
||||
|
@ -96,28 +82,28 @@ sub new_compat_Stow {
|
|||
#===== SUBROUTINE ===========================================================
|
||||
# Name : make_link()
|
||||
# Purpose : safely create a link
|
||||
# Parameters: $target => path to the link
|
||||
# : $source => where the new link should point
|
||||
# : $invalid => true iff $source refers to non-existent file
|
||||
# Parameters: $link_src => path to the link
|
||||
# : $link_dest => where the new link should point
|
||||
# : $invalid => true iff $link_dest refers to non-existent file
|
||||
# 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, $invalid) = @_;
|
||||
my ($link_src, $link_dest, $invalid) = @_;
|
||||
|
||||
if (-l $target) {
|
||||
my $old_source = readlink join('/', parent($target), $source)
|
||||
or die "$target is already a link but could not read link $target/$source";
|
||||
if ($old_source ne $source) {
|
||||
die "$target already exists but points elsewhere\n";
|
||||
if (-l $link_src) {
|
||||
my $old_source = readlink join('/', parent($link_src), $link_dest)
|
||||
or croak "$link_src is already a link but could not read link $link_src/$link_dest";
|
||||
if ($old_source ne $link_dest) {
|
||||
croak "$link_src already exists but points elsewhere\n";
|
||||
}
|
||||
}
|
||||
die "$target already exists and is not a link\n" if -e $target;
|
||||
my $abs_target = File::Spec->rel2abs($target);
|
||||
my $target_container = dirname($abs_target);
|
||||
my $abs_source = File::Spec->rel2abs($source, $target_container);
|
||||
#warn "t $target c $target_container as $abs_source";
|
||||
croak "$link_src already exists and is not a link\n" if -e $link_src;
|
||||
my $abs_target = File::Spec->rel2abs($link_src);
|
||||
my $link_src_container = dirname($abs_target);
|
||||
my $abs_source = File::Spec->rel2abs($link_dest, $link_src_container);
|
||||
#warn "t $link_src c $link_src_container as $abs_source";
|
||||
if (-e $abs_source) {
|
||||
croak "Won't make invalid link pointing to existing $abs_target"
|
||||
if $invalid;
|
||||
|
@ -126,8 +112,8 @@ sub make_link {
|
|||
croak "Won't make link pointing to non-existent $abs_target"
|
||||
unless $invalid;
|
||||
}
|
||||
symlink $source, $target
|
||||
or die "could not create link $target => $source ($!)\n";
|
||||
symlink $link_dest, $link_src
|
||||
or croak "could not create link $link_src => $link_dest ($!)\n";
|
||||
}
|
||||
|
||||
#===== SUBROUTINE ===========================================================
|
||||
|
@ -157,11 +143,11 @@ sub make_file {
|
|||
my ($path, $contents) = @_;
|
||||
|
||||
if (-e $path and ! -f $path) {
|
||||
die "a non-file already exists at $path\n";
|
||||
croak "a non-file already exists at $path\n";
|
||||
}
|
||||
|
||||
open my $FILE ,'>', $path
|
||||
or die "could not create file: $path ($!)\n";
|
||||
or croak "could not create file: $path ($!)\n";
|
||||
print $FILE $contents if defined $contents;
|
||||
close $FILE;
|
||||
}
|
||||
|
@ -178,9 +164,9 @@ sub make_file {
|
|||
sub remove_link {
|
||||
my ($path) = @_;
|
||||
if (not -l $path) {
|
||||
die qq(remove_link() called with a non-link: $path);
|
||||
croak qq(remove_link() called with a non-link: $path);
|
||||
}
|
||||
unlink $path or die "could not remove link: $path ($!)\n";
|
||||
unlink $path or croak "could not remove link: $path ($!)\n";
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -195,9 +181,9 @@ sub remove_link {
|
|||
sub remove_file {
|
||||
my ($path) = @_;
|
||||
if (-z $path) {
|
||||
die "file at $path is non-empty\n";
|
||||
croak "file at $path is non-empty\n";
|
||||
}
|
||||
unlink $path or die "could not remove empty file: $path ($!)\n";
|
||||
unlink $path or croak "could not remove empty file: $path ($!)\n";
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -213,10 +199,10 @@ sub remove_dir {
|
|||
my ($dir) = @_;
|
||||
|
||||
if (not -d $dir) {
|
||||
die "$dir is not a directory";
|
||||
croak "$dir is not a directory";
|
||||
}
|
||||
|
||||
opendir my $DIR, $dir or die "cannot read directory: $dir ($!)\n";
|
||||
opendir my $DIR, $dir or croak "cannot read directory: $dir ($!)\n";
|
||||
my @listing = readdir $DIR;
|
||||
closedir $DIR;
|
||||
|
||||
|
@ -227,16 +213,16 @@ sub remove_dir {
|
|||
|
||||
my $path = "$dir/$node";
|
||||
if (-l $path or (-f $path and -z $path) or $node eq $Stow::LOCAL_IGNORE_FILE) {
|
||||
unlink $path or die "cannot unlink $path ($!)\n";
|
||||
unlink $path or croak "cannot unlink $path ($!)\n";
|
||||
}
|
||||
elsif (-d "$path") {
|
||||
remove_dir($path);
|
||||
}
|
||||
else {
|
||||
die "$path is not a link, directory, or empty file\n";
|
||||
croak "$path is not a link, directory, or empty file\n";
|
||||
}
|
||||
}
|
||||
rmdir $dir or die "cannot rmdir $dir ($!)\n";
|
||||
rmdir $dir or croak "cannot rmdir $dir ($!)\n";
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -251,7 +237,7 @@ sub remove_dir {
|
|||
#============================================================================
|
||||
sub cd {
|
||||
my ($dir) = @_;
|
||||
chdir $dir or die "Failed to chdir($dir): $!\n";
|
||||
chdir $dir or croak "Failed to chdir($dir): $!\n";
|
||||
}
|
||||
|
||||
#===== SUBROUTINE ===========================================================
|
||||
|
@ -264,7 +250,7 @@ sub cd {
|
|||
#============================================================================
|
||||
sub cat_file {
|
||||
my ($file) = @_;
|
||||
open F, $file or die "Failed to open($file): $!\n";
|
||||
open F, $file or croak "Failed to open($file): $!\n";
|
||||
my $contents = join '', <F>;
|
||||
close(F);
|
||||
return $contents;
|
||||
|
@ -309,6 +295,5 @@ sub is_nonexistent_path {
|
|||
|
||||
# Local variables:
|
||||
# mode: perl
|
||||
# cperl-indent-level: 4
|
||||
# end:
|
||||
# vim: ft=perl
|
||||
|
|
508
t/unstow.t
508
t/unstow.t
|
@ -22,7 +22,7 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Test::More tests => 39;
|
||||
use Test::More tests => 32;
|
||||
use Test::Output;
|
||||
use English qw(-no_match_vars);
|
||||
|
||||
|
@ -34,333 +34,321 @@ cd("$TEST_DIR/target");
|
|||
|
||||
# Note that each of the following tests use a distinct set of files
|
||||
|
||||
my $stow;
|
||||
my %conflicts;
|
||||
subtest("unstow a simple tree minimally", sub {
|
||||
plan tests => 3;
|
||||
my $stow = new_Stow();
|
||||
|
||||
#
|
||||
# unstow a simple tree minimally
|
||||
#
|
||||
$stow = new_Stow();
|
||||
make_path('../stow/pkg1/bin1');
|
||||
make_file('../stow/pkg1/bin1/file1');
|
||||
make_link('bin1', '../stow/pkg1/bin1');
|
||||
|
||||
make_path('../stow/pkg1/bin1');
|
||||
make_file('../stow/pkg1/bin1/file1');
|
||||
make_link('bin1', '../stow/pkg1/bin1');
|
||||
$stow->plan_unstow('pkg1');
|
||||
$stow->process_tasks();
|
||||
is($stow->get_conflict_count, 0);
|
||||
ok(-f '../stow/pkg1/bin1/file1');
|
||||
ok(! -e 'bin1' => 'unstow a simple tree');
|
||||
});
|
||||
|
||||
$stow->plan_unstow('pkg1');
|
||||
$stow->process_tasks();
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
-f '../stow/pkg1/bin1/file1' && ! -e 'bin1'
|
||||
=> 'unstow a simple tree'
|
||||
);
|
||||
subtest("unstow a simple tree from an existing directory", sub {
|
||||
plan tests => 3;
|
||||
my $stow = new_Stow();
|
||||
|
||||
#
|
||||
# unstow a simple tree from an existing directory
|
||||
#
|
||||
$stow = new_Stow();
|
||||
|
||||
make_path('lib2');
|
||||
make_path('../stow/pkg2/lib2');
|
||||
make_file('../stow/pkg2/lib2/file2');
|
||||
make_link('lib2/file2', '../../stow/pkg2/lib2/file2');
|
||||
$stow->plan_unstow('pkg2');
|
||||
$stow->process_tasks();
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
-f '../stow/pkg2/lib2/file2' && -d 'lib2'
|
||||
make_path('lib2');
|
||||
make_path('../stow/pkg2/lib2');
|
||||
make_file('../stow/pkg2/lib2/file2');
|
||||
make_link('lib2/file2', '../../stow/pkg2/lib2/file2');
|
||||
$stow->plan_unstow('pkg2');
|
||||
$stow->process_tasks();
|
||||
is($stow->get_conflict_count, 0);
|
||||
ok(-f '../stow/pkg2/lib2/file2');
|
||||
ok(-d 'lib2'
|
||||
=> 'unstow simple tree from a pre-existing directory'
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# fold tree after unstowing
|
||||
#
|
||||
$stow = new_Stow();
|
||||
subtest("fold tree after unstowing", sub {
|
||||
plan tests => 3;
|
||||
my $stow = new_Stow();
|
||||
|
||||
make_path('bin3');
|
||||
make_path('bin3');
|
||||
|
||||
make_path('../stow/pkg3a/bin3');
|
||||
make_file('../stow/pkg3a/bin3/file3a');
|
||||
make_link('bin3/file3a' => '../../stow/pkg3a/bin3/file3a'); # emulate stow
|
||||
make_path('../stow/pkg3a/bin3');
|
||||
make_file('../stow/pkg3a/bin3/file3a');
|
||||
make_link('bin3/file3a' => '../../stow/pkg3a/bin3/file3a'); # emulate stow
|
||||
|
||||
make_path('../stow/pkg3b/bin3');
|
||||
make_file('../stow/pkg3b/bin3/file3b');
|
||||
make_link('bin3/file3b' => '../../stow/pkg3b/bin3/file3b'); # emulate stow
|
||||
$stow->plan_unstow('pkg3b');
|
||||
$stow->process_tasks();
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
-l 'bin3' &&
|
||||
readlink('bin3') eq '../stow/pkg3a/bin3'
|
||||
make_path('../stow/pkg3b/bin3');
|
||||
make_file('../stow/pkg3b/bin3/file3b');
|
||||
make_link('bin3/file3b' => '../../stow/pkg3b/bin3/file3b'); # emulate stow
|
||||
$stow->plan_unstow('pkg3b');
|
||||
$stow->process_tasks();
|
||||
is($stow->get_conflict_count, 0);
|
||||
ok(-l 'bin3');
|
||||
is(readlink('bin3'), '../stow/pkg3a/bin3'
|
||||
=> 'fold tree after unstowing'
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# existing link is owned by stow but is invalid so it gets removed anyway
|
||||
#
|
||||
$stow = new_Stow();
|
||||
subtest("existing link is owned by stow but is invalid so it gets removed anyway", sub {
|
||||
plan tests => 2;
|
||||
my $stow = new_Stow();
|
||||
|
||||
make_path('bin4');
|
||||
make_path('../stow/pkg4/bin4');
|
||||
make_file('../stow/pkg4/bin4/file4');
|
||||
make_invalid_link('bin4/file4', '../../stow/pkg4/bin4/does-not-exist');
|
||||
make_path('bin4');
|
||||
make_path('../stow/pkg4/bin4');
|
||||
make_file('../stow/pkg4/bin4/file4');
|
||||
make_invalid_link('bin4/file4', '../../stow/pkg4/bin4/does-not-exist');
|
||||
|
||||
$stow->plan_unstow('pkg4');
|
||||
$stow->process_tasks();
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
! -e 'bin4/file4'
|
||||
$stow->plan_unstow('pkg4');
|
||||
$stow->process_tasks();
|
||||
is($stow->get_conflict_count, 0);
|
||||
ok(! -e 'bin4/file4'
|
||||
=> q(remove invalid link owned by stow)
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# Existing link is not owned by stow
|
||||
#
|
||||
$stow = new_Stow();
|
||||
subtest("Existing link is not owned by stow", sub {
|
||||
plan tests => 1;
|
||||
my $stow = new_Stow();
|
||||
|
||||
make_path('../stow/pkg5/bin5');
|
||||
make_invalid_link('bin5', '../not-stow');
|
||||
make_path('../stow/pkg5/bin5');
|
||||
make_invalid_link('bin5', '../not-stow');
|
||||
|
||||
$stow->plan_unstow('pkg5');
|
||||
%conflicts = $stow->get_conflicts;
|
||||
like(
|
||||
$stow->plan_unstow('pkg5');
|
||||
my %conflicts = $stow->get_conflicts;
|
||||
like(
|
||||
$conflicts{unstow}{pkg5}[-1],
|
||||
qr(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
|
||||
#
|
||||
$stow = new_Stow();
|
||||
subtest("Target already exists, is owned by stow, but points to a different package", sub {
|
||||
plan tests => 3;
|
||||
my $stow = new_Stow();
|
||||
|
||||
make_path('bin6');
|
||||
make_path('../stow/pkg6a/bin6');
|
||||
make_file('../stow/pkg6a/bin6/file6');
|
||||
make_link('bin6/file6', '../../stow/pkg6a/bin6/file6');
|
||||
make_path('bin6');
|
||||
make_path('../stow/pkg6a/bin6');
|
||||
make_file('../stow/pkg6a/bin6/file6');
|
||||
make_link('bin6/file6', '../../stow/pkg6a/bin6/file6');
|
||||
|
||||
make_path('../stow/pkg6b/bin6');
|
||||
make_file('../stow/pkg6b/bin6/file6');
|
||||
make_path('../stow/pkg6b/bin6');
|
||||
make_file('../stow/pkg6b/bin6/file6');
|
||||
|
||||
$stow->plan_unstow('pkg6b');
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
-l 'bin6/file6' &&
|
||||
readlink('bin6/file6') eq '../../stow/pkg6a/bin6/file6'
|
||||
$stow->plan_unstow('pkg6b');
|
||||
is($stow->get_conflict_count, 0);
|
||||
ok(-l 'bin6/file6');
|
||||
is(
|
||||
readlink('bin6/file6'),
|
||||
'../../stow/pkg6a/bin6/file6'
|
||||
=> q(ignore existing link that points to a different package)
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# Don't unlink anything under the stow directory
|
||||
#
|
||||
make_path('stow'); # make out stow dir a subdir of target
|
||||
$stow = new_Stow(dir => 'stow');
|
||||
subtest("Don't unlink anything under the stow directory", sub {
|
||||
plan tests => 4;
|
||||
make_path('stow'); # make out stow dir a subdir of target
|
||||
my $stow = new_Stow(dir => 'stow');
|
||||
|
||||
# emulate stowing into ourself (bizarre corner case or accident)
|
||||
make_path('stow/pkg7a/stow/pkg7b');
|
||||
make_file('stow/pkg7a/stow/pkg7b/file7b');
|
||||
make_link('stow/pkg7b', '../stow/pkg7a/stow/pkg7b');
|
||||
# emulate stowing into ourself (bizarre corner case or accident)
|
||||
make_path('stow/pkg7a/stow/pkg7b');
|
||||
make_file('stow/pkg7a/stow/pkg7b/file7b');
|
||||
make_link('stow/pkg7b', '../stow/pkg7a/stow/pkg7b');
|
||||
|
||||
$stow->plan_unstow('pkg7b');
|
||||
is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg7b');
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
-l 'stow/pkg7b' &&
|
||||
readlink('stow/pkg7b') eq '../stow/pkg7a/stow/pkg7b'
|
||||
$stow->plan_unstow('pkg7b');
|
||||
is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg7b');
|
||||
is($stow->get_conflict_count, 0);
|
||||
ok(-l 'stow/pkg7b');
|
||||
is(
|
||||
readlink('stow/pkg7b'),
|
||||
'../stow/pkg7a/stow/pkg7b'
|
||||
=> q(don't unlink any nodes under the stow directory)
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
subtest("Don't unlink any nodes under another stow directory", sub {
|
||||
plan tests => 5;
|
||||
my $stow = new_Stow(dir => 'stow');
|
||||
|
||||
#
|
||||
# Don't unlink any nodes under another stow directory
|
||||
#
|
||||
$stow = new_Stow(dir => 'stow');
|
||||
make_path('stow2'); # make our alternate stow dir a subdir of target
|
||||
make_file('stow2/.stow');
|
||||
|
||||
make_path('stow2'); # make our alternate stow dir a subdir of target
|
||||
make_file('stow2/.stow');
|
||||
# emulate stowing into ourself (bizarre corner case or accident)
|
||||
make_path('stow/pkg8a/stow2/pkg8b');
|
||||
make_file('stow/pkg8a/stow2/pkg8b/file8b');
|
||||
make_link('stow2/pkg8b', '../stow/pkg8a/stow2/pkg8b');
|
||||
|
||||
# emulate stowing into ourself (bizarre corner case or accident)
|
||||
make_path('stow/pkg8a/stow2/pkg8b');
|
||||
make_file('stow/pkg8a/stow2/pkg8b/file8b');
|
||||
make_link('stow2/pkg8b', '../stow/pkg8a/stow2/pkg8b');
|
||||
|
||||
capture_stderr();
|
||||
$stow->plan_unstow('pkg8a');
|
||||
is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg8a');
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
-l 'stow2/pkg8b' &&
|
||||
readlink('stow2/pkg8b') eq '../stow/pkg8a/stow2/pkg8b'
|
||||
stderr_like(
|
||||
sub { $stow->plan_unstow('pkg8a'); },
|
||||
qr/WARNING: skipping marked Stow directory stow2/
|
||||
=> "unstowing from ourself should skip stow"
|
||||
);
|
||||
is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg8a');
|
||||
is($stow->get_conflict_count, 0);
|
||||
ok(-l 'stow2/pkg8b');
|
||||
is(
|
||||
readlink('stow2/pkg8b'),
|
||||
'../stow/pkg8a/stow2/pkg8b'
|
||||
=> q(don't unlink any nodes under another stow directory)
|
||||
);
|
||||
like($stderr,
|
||||
qr/WARNING: skipping protected directory stow2/
|
||||
=> "unstowing from ourself should skip stow");
|
||||
uncapture_stderr();
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# overriding already stowed documentation
|
||||
#
|
||||
$stow = new_Stow(override => ['man9', 'info9']);
|
||||
make_file('stow/.stow');
|
||||
subtest("overriding already stowed documentation", sub {
|
||||
plan tests => 2;
|
||||
my $stow = new_Stow(override => ['man9', 'info9']);
|
||||
make_file('stow/.stow');
|
||||
|
||||
make_path('../stow/pkg9a/man9/man1');
|
||||
make_file('../stow/pkg9a/man9/man1/file9.1');
|
||||
make_path('man9/man1');
|
||||
make_link('man9/man1/file9.1' => '../../../stow/pkg9a/man9/man1/file9.1'); # emulate stow
|
||||
make_path('../stow/pkg9a/man9/man1');
|
||||
make_file('../stow/pkg9a/man9/man1/file9.1');
|
||||
make_path('man9/man1');
|
||||
make_link('man9/man1/file9.1' => '../../../stow/pkg9a/man9/man1/file9.1'); # emulate stow
|
||||
|
||||
make_path('../stow/pkg9b/man9/man1');
|
||||
make_file('../stow/pkg9b/man9/man1/file9.1');
|
||||
$stow->plan_unstow('pkg9b');
|
||||
$stow->process_tasks();
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
!-l 'man9/man1/file9.1'
|
||||
make_path('../stow/pkg9b/man9/man1');
|
||||
make_file('../stow/pkg9b/man9/man1/file9.1');
|
||||
$stow->plan_unstow('pkg9b');
|
||||
$stow->process_tasks();
|
||||
is($stow->get_conflict_count, 0);
|
||||
ok(!-l 'man9/man1/file9.1'
|
||||
=> 'overriding existing documentation files'
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# deferring to already stowed documentation
|
||||
#
|
||||
$stow = new_Stow(defer => ['man10', 'info10']);
|
||||
subtest("deferring to already stowed documentation", sub {
|
||||
plan tests => 3;
|
||||
my $stow = new_Stow(defer => ['man10', 'info10']);
|
||||
|
||||
make_path('../stow/pkg10a/man10/man1');
|
||||
make_file('../stow/pkg10a/man10/man1/file10a.1');
|
||||
make_path('man10/man1');
|
||||
make_link('man10/man1/file10a.1' => '../../../stow/pkg10a/man10/man1/file10a.1');
|
||||
make_path('../stow/pkg10a/man10/man1');
|
||||
make_file('../stow/pkg10a/man10/man1/file10a.1');
|
||||
make_path('man10/man1');
|
||||
make_link('man10/man1/file10a.1' => '../../../stow/pkg10a/man10/man1/file10a.1');
|
||||
|
||||
# need this to block folding
|
||||
make_path('../stow/pkg10b/man10/man1');
|
||||
make_file('../stow/pkg10b/man10/man1/file10b.1');
|
||||
make_link('man10/man1/file10b.1' => '../../../stow/pkg10b/man10/man1/file10b.1');
|
||||
# need this to block folding
|
||||
make_path('../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_path('../stow/pkg10c/man10/man1');
|
||||
make_file('../stow/pkg10c/man10/man1/file10a.1');
|
||||
$stow->plan_unstow('pkg10c');
|
||||
is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg10c');
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
readlink('man10/man1/file10a.1') eq '../../../stow/pkg10a/man10/man1/file10a.1'
|
||||
make_path('../stow/pkg10c/man10/man1');
|
||||
make_file('../stow/pkg10c/man10/man1/file10a.1');
|
||||
$stow->plan_unstow('pkg10c');
|
||||
is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg10c');
|
||||
is($stow->get_conflict_count, 0);
|
||||
is(
|
||||
readlink('man10/man1/file10a.1'),
|
||||
'../../../stow/pkg10a/man10/man1/file10a.1'
|
||||
=> 'defer to existing documentation files'
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# Ignore temp files
|
||||
#
|
||||
$stow = new_Stow(ignore => ['~', '\.#.*']);
|
||||
subtest("Ignore temp files", sub {
|
||||
plan tests => 2;
|
||||
my $stow = new_Stow(ignore => ['~', '\.#.*']);
|
||||
|
||||
make_path('../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_path('man12/man1');
|
||||
make_link('man12/man1/file12.1' => '../../../stow/pkg12/man12/man1/file12.1');
|
||||
make_path('../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_path('man12/man1');
|
||||
make_link('man12/man1/file12.1' => '../../../stow/pkg12/man12/man1/file12.1');
|
||||
|
||||
$stow->plan_unstow('pkg12');
|
||||
$stow->process_tasks();
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
!-e 'man12/man1/file12.1'
|
||||
=> 'ignore temp files'
|
||||
);
|
||||
$stow->plan_unstow('pkg12');
|
||||
$stow->process_tasks();
|
||||
is($stow->get_conflict_count, 0);
|
||||
ok(!-e 'man12/man1/file12.1' => 'ignore temp files');
|
||||
});
|
||||
|
||||
#
|
||||
# Unstow an already unstowed package
|
||||
#
|
||||
$stow = new_Stow();
|
||||
$stow->plan_unstow('pkg12');
|
||||
is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg12');
|
||||
ok(
|
||||
$stow->get_conflict_count == 0
|
||||
subtest("Unstow an already unstowed package", sub {
|
||||
plan tests => 2;
|
||||
my $stow = new_Stow();
|
||||
$stow->plan_unstow('pkg12');
|
||||
is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg12');
|
||||
is(
|
||||
$stow->get_conflict_count, 0
|
||||
=> 'unstow already unstowed package pkg12'
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# Unstow a never stowed package
|
||||
#
|
||||
subtest("Unstow a never stowed package", sub {
|
||||
plan tests => 2;
|
||||
|
||||
eval { remove_dir("$TEST_DIR/target"); };
|
||||
mkdir("$TEST_DIR/target");
|
||||
eval { remove_dir("$TEST_DIR/target"); };
|
||||
mkdir("$TEST_DIR/target");
|
||||
|
||||
$stow = new_Stow();
|
||||
$stow->plan_unstow('pkg12');
|
||||
is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg12 which was never stowed');
|
||||
ok(
|
||||
$stow->get_conflict_count == 0
|
||||
my $stow = new_Stow();
|
||||
$stow->plan_unstow('pkg12');
|
||||
is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg12 which was never stowed');
|
||||
is(
|
||||
$stow->get_conflict_count,
|
||||
0
|
||||
=> 'unstow never stowed package pkg12'
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# Unstowing when target contains a real file shouldn't be an issue.
|
||||
#
|
||||
make_file('man12/man1/file12.1');
|
||||
subtest("Unstowing when target contains a real file shouldn't be an issue", sub {
|
||||
plan tests => 3;
|
||||
make_file('man12/man1/file12.1');
|
||||
|
||||
$stow = new_Stow();
|
||||
$stow->plan_unstow('pkg12');
|
||||
is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg12 for third time');
|
||||
%conflicts = $stow->get_conflicts;
|
||||
ok(
|
||||
$stow->get_conflict_count == 1 &&
|
||||
$conflicts{unstow}{pkg12}[0]
|
||||
=~ m!existing target is neither a link nor a directory: man12/man1/file12\.1!
|
||||
my $stow = new_Stow();
|
||||
$stow->plan_unstow('pkg12');
|
||||
is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg12 for third time');
|
||||
my %conflicts = $stow->get_conflicts;
|
||||
is($stow->get_conflict_count, 1);
|
||||
like(
|
||||
$conflicts{unstow}{pkg12}[0],
|
||||
qr!existing target is neither a link nor a directory: man12/man1/file12\.1!
|
||||
=> 'unstow pkg12 for third time'
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# unstow a simple tree minimally when cwd isn't target
|
||||
#
|
||||
cd('../..');
|
||||
$stow = new_Stow(dir => "$TEST_DIR/stow", target => "$TEST_DIR/target");
|
||||
subtest("unstow a simple tree minimally when cwd isn't target", sub {
|
||||
plan tests => 3;
|
||||
cd('../..');
|
||||
my $stow = new_Stow(dir => "$TEST_DIR/stow", target => "$TEST_DIR/target");
|
||||
|
||||
make_path("$TEST_DIR/stow/pkg13/bin13");
|
||||
make_file("$TEST_DIR/stow/pkg13/bin13/file13");
|
||||
make_link("$TEST_DIR/target/bin13", '../stow/pkg13/bin13');
|
||||
make_path("$TEST_DIR/stow/pkg13/bin13");
|
||||
make_file("$TEST_DIR/stow/pkg13/bin13/file13");
|
||||
make_link("$TEST_DIR/target/bin13", '../stow/pkg13/bin13');
|
||||
|
||||
$stow->plan_unstow('pkg13');
|
||||
$stow->process_tasks();
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
-f "$TEST_DIR/stow/pkg13/bin13/file13" && ! -e "$TEST_DIR/target/bin13"
|
||||
=> 'unstow a simple tree'
|
||||
);
|
||||
$stow->plan_unstow('pkg13');
|
||||
$stow->process_tasks();
|
||||
is($stow->get_conflict_count, 0);
|
||||
ok(-f "$TEST_DIR/stow/pkg13/bin13/file13");
|
||||
ok(! -e "$TEST_DIR/target/bin13" => 'unstow a simple tree');
|
||||
});
|
||||
|
||||
#
|
||||
# unstow a simple tree minimally with absolute stow dir when cwd isn't
|
||||
# target
|
||||
#
|
||||
$stow = new_Stow(dir => canon_path("$TEST_DIR/stow"),
|
||||
subtest("unstow a simple tree minimally with absolute stow dir when cwd isn't target", sub {
|
||||
plan tests => 3;
|
||||
my $stow = new_Stow(dir => canon_path("$TEST_DIR/stow"),
|
||||
target => "$TEST_DIR/target");
|
||||
|
||||
make_path("$TEST_DIR/stow/pkg14/bin14");
|
||||
make_file("$TEST_DIR/stow/pkg14/bin14/file14");
|
||||
make_link("$TEST_DIR/target/bin14", '../stow/pkg14/bin14');
|
||||
make_path("$TEST_DIR/stow/pkg14/bin14");
|
||||
make_file("$TEST_DIR/stow/pkg14/bin14/file14");
|
||||
make_link("$TEST_DIR/target/bin14", '../stow/pkg14/bin14');
|
||||
|
||||
$stow->plan_unstow('pkg14');
|
||||
$stow->process_tasks();
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
-f "$TEST_DIR/stow/pkg14/bin14/file14" && ! -e "$TEST_DIR/target/bin14"
|
||||
$stow->plan_unstow('pkg14');
|
||||
$stow->process_tasks();
|
||||
is($stow->get_conflict_count, 0);
|
||||
ok(-f "$TEST_DIR/stow/pkg14/bin14/file14");
|
||||
ok(! -e "$TEST_DIR/target/bin14"
|
||||
=> 'unstow a simple tree with absolute stow dir'
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# unstow a simple tree minimally with absolute stow AND target dirs
|
||||
# when cwd isn't target
|
||||
#
|
||||
$stow = new_Stow(dir => canon_path("$TEST_DIR/stow"),
|
||||
subtest("unstow a simple tree minimally with absolute stow AND target dirs when cwd isn't target", sub {
|
||||
plan tests => 3;
|
||||
my $stow = new_Stow(dir => canon_path("$TEST_DIR/stow"),
|
||||
target => canon_path("$TEST_DIR/target"));
|
||||
|
||||
make_path("$TEST_DIR/stow/pkg15/bin15");
|
||||
make_file("$TEST_DIR/stow/pkg15/bin15/file15");
|
||||
make_link("$TEST_DIR/target/bin15", '../stow/pkg15/bin15');
|
||||
make_path("$TEST_DIR/stow/pkg15/bin15");
|
||||
make_file("$TEST_DIR/stow/pkg15/bin15/file15");
|
||||
make_link("$TEST_DIR/target/bin15", '../stow/pkg15/bin15');
|
||||
|
||||
$stow->plan_unstow('pkg15');
|
||||
$stow->process_tasks();
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
-f "$TEST_DIR/stow/pkg15/bin15/file15" && ! -e "$TEST_DIR/target/bin15"
|
||||
$stow->plan_unstow('pkg15');
|
||||
$stow->process_tasks();
|
||||
is($stow->get_conflict_count, 0);
|
||||
ok(-f "$TEST_DIR/stow/pkg15/bin15/file15");
|
||||
ok(! -e "$TEST_DIR/target/bin15"
|
||||
=> 'unstow a simple tree with absolute stow and target dirs'
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# unstow a tree with no-folding enabled -
|
||||
|
@ -428,7 +416,7 @@ foreach my $pkg (qw{a b}) {
|
|||
create_and_stow_pkg('no-folding', $pkg);
|
||||
}
|
||||
|
||||
$stow = new_Stow('no-folding' => 1);
|
||||
my $stow = new_Stow('no-folding' => 1);
|
||||
$stow->plan_unstow('no-folding-b');
|
||||
is_deeply([ $stow->get_conflicts ], [] => 'no conflicts with --no-folding');
|
||||
use Data::Dumper;
|
||||
|
|
580
t/unstow_orig.t
580
t/unstow_orig.t
|
@ -23,7 +23,7 @@ use strict;
|
|||
use warnings;
|
||||
|
||||
use File::Spec qw(make_path);
|
||||
use Test::More tests => 37;
|
||||
use Test::More tests => 17;
|
||||
use Test::Output;
|
||||
use English qw(-no_match_vars);
|
||||
|
||||
|
@ -38,366 +38,356 @@ cd("$TEST_DIR/target");
|
|||
my $stow;
|
||||
my %conflicts;
|
||||
|
||||
#
|
||||
# unstow a simple tree minimally
|
||||
#
|
||||
subtest("unstow a simple tree minimally", sub {
|
||||
plan tests => 3;
|
||||
my $stow = new_compat_Stow();
|
||||
|
||||
$stow = new_compat_Stow();
|
||||
make_path('../stow/pkg1/bin1');
|
||||
make_file('../stow/pkg1/bin1/file1');
|
||||
make_link('bin1', '../stow/pkg1/bin1');
|
||||
|
||||
make_path('../stow/pkg1/bin1');
|
||||
make_file('../stow/pkg1/bin1/file1');
|
||||
make_link('bin1', '../stow/pkg1/bin1');
|
||||
$stow->plan_unstow('pkg1');
|
||||
$stow->process_tasks();
|
||||
is($stow->get_conflict_count, 0);
|
||||
ok(-f '../stow/pkg1/bin1/file1');
|
||||
ok(! -e 'bin1' => 'unstow a simple tree');
|
||||
});
|
||||
|
||||
$stow->plan_unstow('pkg1');
|
||||
$stow->process_tasks();
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
-f '../stow/pkg1/bin1/file1' && ! -e 'bin1'
|
||||
=> 'unstow a simple tree'
|
||||
);
|
||||
subtest("unstow a simple tree from an existing directory", sub {
|
||||
plan tests => 3;
|
||||
my $stow = new_compat_Stow();
|
||||
|
||||
#
|
||||
# unstow a simple tree from an existing directory
|
||||
#
|
||||
$stow = new_compat_Stow();
|
||||
|
||||
make_path('lib2');
|
||||
make_path('../stow/pkg2/lib2');
|
||||
make_file('../stow/pkg2/lib2/file2');
|
||||
make_link('lib2/file2', '../../stow/pkg2/lib2/file2');
|
||||
$stow->plan_unstow('pkg2');
|
||||
$stow->process_tasks();
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
-f '../stow/pkg2/lib2/file2' && -d 'lib2'
|
||||
make_path('lib2');
|
||||
make_path('../stow/pkg2/lib2');
|
||||
make_file('../stow/pkg2/lib2/file2');
|
||||
make_link('lib2/file2', '../../stow/pkg2/lib2/file2');
|
||||
$stow->plan_unstow('pkg2');
|
||||
$stow->process_tasks();
|
||||
is($stow->get_conflict_count, 0);
|
||||
ok(-f '../stow/pkg2/lib2/file2');
|
||||
ok(-d 'lib2'
|
||||
=> 'unstow simple tree from a pre-existing directory'
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# fold tree after unstowing
|
||||
#
|
||||
$stow = new_compat_Stow();
|
||||
subtest("fold tree after unstowing", sub {
|
||||
plan tests => 3;
|
||||
my $stow = new_compat_Stow();
|
||||
|
||||
make_path('bin3');
|
||||
make_path('bin3');
|
||||
|
||||
make_path('../stow/pkg3a/bin3');
|
||||
make_file('../stow/pkg3a/bin3/file3a');
|
||||
make_link('bin3/file3a' => '../../stow/pkg3a/bin3/file3a'); # emulate stow
|
||||
make_path('../stow/pkg3a/bin3');
|
||||
make_file('../stow/pkg3a/bin3/file3a');
|
||||
make_link('bin3/file3a' => '../../stow/pkg3a/bin3/file3a'); # emulate stow
|
||||
|
||||
make_path('../stow/pkg3b/bin3');
|
||||
make_file('../stow/pkg3b/bin3/file3b');
|
||||
make_link('bin3/file3b' => '../../stow/pkg3b/bin3/file3b'); # emulate stow
|
||||
$stow->plan_unstow('pkg3b');
|
||||
$stow->process_tasks();
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
-l 'bin3' &&
|
||||
readlink('bin3') eq '../stow/pkg3a/bin3'
|
||||
make_path('../stow/pkg3b/bin3');
|
||||
make_file('../stow/pkg3b/bin3/file3b');
|
||||
make_link('bin3/file3b' => '../../stow/pkg3b/bin3/file3b'); # emulate stow
|
||||
$stow->plan_unstow('pkg3b');
|
||||
$stow->process_tasks();
|
||||
is($stow->get_conflict_count, 0);
|
||||
ok(-l 'bin3');
|
||||
is(readlink('bin3'), '../stow/pkg3a/bin3'
|
||||
=> 'fold tree after unstowing'
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# existing link is owned by stow but is invalid so it gets removed anyway
|
||||
#
|
||||
$stow = new_compat_Stow();
|
||||
subtest("existing link is owned by stow but is invalid so it gets removed anyway", sub {
|
||||
plan tests => 2;
|
||||
my $stow = new_compat_Stow();
|
||||
|
||||
make_path('bin4');
|
||||
make_path('../stow/pkg4/bin4');
|
||||
make_file('../stow/pkg4/bin4/file4');
|
||||
make_invalid_link('bin4/file4', '../../stow/pkg4/bin4/does-not-exist');
|
||||
make_path('bin4');
|
||||
make_path('../stow/pkg4/bin4');
|
||||
make_file('../stow/pkg4/bin4/file4');
|
||||
make_invalid_link('bin4/file4', '../../stow/pkg4/bin4/does-not-exist');
|
||||
|
||||
$stow->plan_unstow('pkg4');
|
||||
$stow->process_tasks();
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
! -e 'bin4/file4'
|
||||
$stow->plan_unstow('pkg4');
|
||||
$stow->process_tasks();
|
||||
is($stow->get_conflict_count, 0);
|
||||
ok(! -e 'bin4/file4'
|
||||
=> q(remove invalid link owned by stow)
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# Existing link is not owned by stow
|
||||
#
|
||||
$stow = new_compat_Stow();
|
||||
subtest("Existing link is not owned by stow", sub {
|
||||
plan tests => 2;
|
||||
my $stow = new_compat_Stow();
|
||||
|
||||
make_path('../stow/pkg5/bin5');
|
||||
make_invalid_link('bin5', '../not-stow');
|
||||
make_path('../stow/pkg5/bin5');
|
||||
make_invalid_link('bin5', '../not-stow');
|
||||
|
||||
$stow->plan_unstow('pkg5');
|
||||
# Unlike the corresponding stow_contents.t test, this doesn't
|
||||
# cause any conflicts.
|
||||
#
|
||||
#like(
|
||||
# $Conflicts[-1], qr(can't unlink.*not owned by stow)
|
||||
# => q(existing link not owned by stow)
|
||||
#);
|
||||
ok(
|
||||
-l 'bin5' && readlink('bin5') eq '../not-stow'
|
||||
$stow->plan_unstow('pkg5');
|
||||
# Unlike the corresponding stow_contents.t test, this doesn't
|
||||
# cause any conflicts.
|
||||
#
|
||||
#like(
|
||||
# $Conflicts[-1], qr(can't unlink.*not owned by stow)
|
||||
# => q(existing link not owned by stow)
|
||||
#);
|
||||
ok(-l 'bin5');
|
||||
is(
|
||||
readlink('bin5'),
|
||||
'../not-stow'
|
||||
=> q(existing link not owned by stow)
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# Target already exists, is owned by stow, but points to a different package
|
||||
#
|
||||
$stow = new_compat_Stow();
|
||||
subtest("Target already exists, is owned by stow, but points to a different package", sub {
|
||||
plan tests => 3;
|
||||
my $stow = new_compat_Stow();
|
||||
|
||||
make_path('bin6');
|
||||
make_path('../stow/pkg6a/bin6');
|
||||
make_file('../stow/pkg6a/bin6/file6');
|
||||
make_link('bin6/file6', '../../stow/pkg6a/bin6/file6');
|
||||
make_path('bin6');
|
||||
make_path('../stow/pkg6a/bin6');
|
||||
make_file('../stow/pkg6a/bin6/file6');
|
||||
make_link('bin6/file6', '../../stow/pkg6a/bin6/file6');
|
||||
|
||||
make_path('../stow/pkg6b/bin6');
|
||||
make_file('../stow/pkg6b/bin6/file6');
|
||||
make_path('../stow/pkg6b/bin6');
|
||||
make_file('../stow/pkg6b/bin6/file6');
|
||||
|
||||
$stow->plan_unstow('pkg6b');
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
-l 'bin6/file6' &&
|
||||
readlink('bin6/file6') eq '../../stow/pkg6a/bin6/file6'
|
||||
$stow->plan_unstow('pkg6b');
|
||||
is($stow->get_conflict_count, 0);
|
||||
ok(-l 'bin6/file6');
|
||||
is(
|
||||
readlink('bin6/file6'),
|
||||
'../../stow/pkg6a/bin6/file6'
|
||||
=> q(ignore existing link that points to a different package)
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# Don't unlink anything under the stow directory
|
||||
#
|
||||
make_path('stow'); # make out stow dir a subdir of target
|
||||
$stow = new_compat_Stow(dir => 'stow');
|
||||
subtest("Don't unlink anything under the stow directory", sub {
|
||||
plan tests => 5;
|
||||
make_path('stow'); # make stow dir a subdir of target
|
||||
my $stow = new_compat_Stow(dir => 'stow');
|
||||
|
||||
# emulate stowing into ourself (bizarre corner case or accident)
|
||||
make_path('stow/pkg7a/stow/pkg7b');
|
||||
make_file('stow/pkg7a/stow/pkg7b/file7b');
|
||||
make_link('stow/pkg7b', '../stow/pkg7a/stow/pkg7b');
|
||||
# emulate stowing into ourself (bizarre corner case or accident)
|
||||
make_path('stow/pkg7a/stow/pkg7b');
|
||||
make_file('stow/pkg7a/stow/pkg7b/file7b');
|
||||
make_link('stow/pkg7b', '../stow/pkg7a/stow/pkg7b');
|
||||
|
||||
capture_stderr();
|
||||
$stow->plan_unstow('pkg7b');
|
||||
is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg7b');
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
-l 'stow/pkg7b' &&
|
||||
readlink('stow/pkg7b') eq '../stow/pkg7a/stow/pkg7b'
|
||||
stderr_like(
|
||||
sub { $stow->plan_unstow('pkg7b'); },
|
||||
qr/WARNING: skipping target which was current stow directory stow/
|
||||
=> "warn when unstowing from ourself"
|
||||
);
|
||||
is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg7b');
|
||||
is($stow->get_conflict_count, 0);
|
||||
ok(-l 'stow/pkg7b');
|
||||
is(
|
||||
readlink('stow/pkg7b'),
|
||||
'../stow/pkg7a/stow/pkg7b'
|
||||
=> q(don't unlink any nodes under the stow directory)
|
||||
);
|
||||
like($stderr,
|
||||
);
|
||||
});
|
||||
|
||||
subtest("Don't unlink any nodes under another stow directory", sub {
|
||||
plan tests => 5;
|
||||
my $stow = new_compat_Stow(dir => 'stow');
|
||||
|
||||
make_path('stow2'); # make our alternate stow dir a subdir of target
|
||||
make_file('stow2/.stow');
|
||||
|
||||
# emulate stowing into ourself (bizarre corner case or accident)
|
||||
make_path('stow/pkg8a/stow2/pkg8b');
|
||||
make_file('stow/pkg8a/stow2/pkg8b/file8b');
|
||||
make_link('stow2/pkg8b', '../stow/pkg8a/stow2/pkg8b');
|
||||
|
||||
stderr_like(
|
||||
sub { $stow->plan_unstow('pkg8a'); },
|
||||
qr/WARNING: skipping target which was current stow directory stow/
|
||||
=> "warn when unstowing from ourself");
|
||||
uncapture_stderr();
|
||||
|
||||
#
|
||||
# Don't unlink any nodes under another stow directory
|
||||
#
|
||||
$stow = new_compat_Stow(dir => 'stow');
|
||||
|
||||
make_path('stow2'); # make our alternate stow dir a subdir of target
|
||||
make_file('stow2/.stow');
|
||||
|
||||
# emulate stowing into ourself (bizarre corner case or accident)
|
||||
make_path('stow/pkg8a/stow2/pkg8b');
|
||||
make_file('stow/pkg8a/stow2/pkg8b/file8b');
|
||||
make_link('stow2/pkg8b', '../stow/pkg8a/stow2/pkg8b');
|
||||
|
||||
capture_stderr();
|
||||
$stow->plan_unstow('pkg8a');
|
||||
is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg8a');
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
-l 'stow2/pkg8b' &&
|
||||
readlink('stow2/pkg8b') eq '../stow/pkg8a/stow2/pkg8b'
|
||||
=> "warn when skipping unstowing"
|
||||
);
|
||||
is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg8a');
|
||||
is($stow->get_conflict_count, 0);
|
||||
ok(-l 'stow2/pkg8b');
|
||||
is(
|
||||
readlink('stow2/pkg8b'),
|
||||
'../stow/pkg8a/stow2/pkg8b'
|
||||
=> q(don't unlink any nodes under another stow directory)
|
||||
);
|
||||
like($stderr,
|
||||
qr/WARNING: skipping target which was current stow directory stow/
|
||||
=> "warn when skipping unstowing");
|
||||
uncapture_stderr();
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# overriding already stowed documentation
|
||||
#
|
||||
|
||||
# This will be used by this and subsequent tests
|
||||
# This will be used by subsequent tests
|
||||
sub check_protected_dirs_skipped {
|
||||
my $coderef = shift;
|
||||
my $stderr = stderr_from { $coderef->(); };
|
||||
for my $dir (qw{stow stow2}) {
|
||||
like($stderr,
|
||||
qr/WARNING: skipping protected directory $dir/
|
||||
=> "warn when skipping protected directory $dir");
|
||||
qr/WARNING: skipping marked Stow directory $dir/
|
||||
=> "warn when skipping marked directory $dir");
|
||||
}
|
||||
uncapture_stderr();
|
||||
}
|
||||
|
||||
$stow = new_compat_Stow(override => ['man9', 'info9']);
|
||||
make_file('stow/.stow');
|
||||
subtest("overriding already stowed documentation", sub {
|
||||
plan tests => 4;
|
||||
|
||||
make_path('../stow/pkg9a/man9/man1');
|
||||
make_file('../stow/pkg9a/man9/man1/file9.1');
|
||||
make_path('man9/man1');
|
||||
make_link('man9/man1/file9.1' => '../../../stow/pkg9a/man9/man1/file9.1'); # emulate stow
|
||||
my $stow = new_compat_Stow(override => ['man9', 'info9']);
|
||||
make_file('stow/.stow');
|
||||
|
||||
make_path('../stow/pkg9b/man9/man1');
|
||||
make_file('../stow/pkg9b/man9/man1/file9.1');
|
||||
capture_stderr();
|
||||
$stow->plan_unstow('pkg9b');
|
||||
$stow->process_tasks();
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
!-l 'man9/man1/file9.1'
|
||||
make_path('../stow/pkg9a/man9/man1');
|
||||
make_file('../stow/pkg9a/man9/man1/file9.1');
|
||||
make_path('man9/man1');
|
||||
make_link('man9/man1/file9.1' => '../../../stow/pkg9a/man9/man1/file9.1'); # emulate stow
|
||||
|
||||
make_path('../stow/pkg9b/man9/man1');
|
||||
make_file('../stow/pkg9b/man9/man1/file9.1');
|
||||
check_protected_dirs_skipped(
|
||||
sub { $stow->plan_unstow('pkg9b'); }
|
||||
);
|
||||
$stow->process_tasks();
|
||||
is($stow->get_conflict_count, 0);
|
||||
ok(!-l 'man9/man1/file9.1'
|
||||
=> 'overriding existing documentation files'
|
||||
);
|
||||
check_protected_dirs_skipped();
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# deferring to already stowed documentation
|
||||
#
|
||||
$stow = new_compat_Stow(defer => ['man10', 'info10']);
|
||||
subtest("deferring to already stowed documentation", sub {
|
||||
plan tests => 5;
|
||||
my $stow = new_compat_Stow(defer => ['man10', 'info10']);
|
||||
|
||||
make_path('../stow/pkg10a/man10/man1');
|
||||
make_file('../stow/pkg10a/man10/man1/file10a.1');
|
||||
make_path('man10/man1');
|
||||
make_link('man10/man1/file10a.1' => '../../../stow/pkg10a/man10/man1/file10a.1');
|
||||
make_path('../stow/pkg10a/man10/man1');
|
||||
make_file('../stow/pkg10a/man10/man1/file10a.1');
|
||||
make_path('man10/man1');
|
||||
make_link('man10/man1/file10a.1' => '../../../stow/pkg10a/man10/man1/file10a.1');
|
||||
|
||||
# need this to block folding
|
||||
make_path('../stow/pkg10b/man10/man1');
|
||||
make_file('../stow/pkg10b/man10/man1/file10b.1');
|
||||
make_link('man10/man1/file10b.1' => '../../../stow/pkg10b/man10/man1/file10b.1');
|
||||
# need this to block folding
|
||||
make_path('../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_path('../stow/pkg10c/man10/man1');
|
||||
make_file('../stow/pkg10c/man10/man1/file10a.1');
|
||||
capture_stderr();
|
||||
$stow->plan_unstow('pkg10c');
|
||||
is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg10c');
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
readlink('man10/man1/file10a.1') eq '../../../stow/pkg10a/man10/man1/file10a.1'
|
||||
make_path('../stow/pkg10c/man10/man1');
|
||||
make_file('../stow/pkg10c/man10/man1/file10a.1');
|
||||
check_protected_dirs_skipped(
|
||||
sub { $stow->plan_unstow('pkg10c'); }
|
||||
);
|
||||
is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg10c');
|
||||
is($stow->get_conflict_count, 0);
|
||||
is(
|
||||
readlink('man10/man1/file10a.1'),
|
||||
'../../../stow/pkg10a/man10/man1/file10a.1'
|
||||
=> 'defer to existing documentation files'
|
||||
);
|
||||
check_protected_dirs_skipped();
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# Ignore temp files
|
||||
#
|
||||
$stow = new_compat_Stow(ignore => ['~', '\.#.*']);
|
||||
subtest("Ignore temp files", sub {
|
||||
plan tests => 4;
|
||||
my $stow = new_compat_Stow(ignore => ['~', '\.#.*']);
|
||||
|
||||
make_path('../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_path('man12/man1');
|
||||
make_link('man12/man1/file12.1' => '../../../stow/pkg12/man12/man1/file12.1');
|
||||
make_path('../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_path('man12/man1');
|
||||
make_link('man12/man1/file12.1' => '../../../stow/pkg12/man12/man1/file12.1');
|
||||
|
||||
capture_stderr();
|
||||
$stow->plan_unstow('pkg12');
|
||||
$stow->process_tasks();
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
!-e 'man12/man1/file12.1'
|
||||
=> 'ignore temp files'
|
||||
);
|
||||
check_protected_dirs_skipped();
|
||||
check_protected_dirs_skipped(
|
||||
sub { $stow->plan_unstow('pkg12'); }
|
||||
);
|
||||
$stow->process_tasks();
|
||||
is($stow->get_conflict_count, 0);
|
||||
ok(!-e 'man12/man1/file12.1' => 'ignore temp files');
|
||||
});
|
||||
|
||||
#
|
||||
# Unstow an already unstowed package
|
||||
#
|
||||
$stow = new_compat_Stow();
|
||||
capture_stderr();
|
||||
$stow->plan_unstow('pkg12');
|
||||
is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg12');
|
||||
ok(
|
||||
$stow->get_conflict_count == 0
|
||||
subtest("Unstow an already unstowed package", sub {
|
||||
plan tests => 4;
|
||||
my $stow = new_compat_Stow();
|
||||
check_protected_dirs_skipped(
|
||||
sub { $stow->plan_unstow('pkg12'); }
|
||||
);
|
||||
is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg12');
|
||||
is(
|
||||
$stow->get_conflict_count,
|
||||
0
|
||||
=> 'unstow already unstowed package pkg12'
|
||||
);
|
||||
check_protected_dirs_skipped();
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# Unstow a never stowed package
|
||||
#
|
||||
subtest("Unstow a never stowed package", sub {
|
||||
plan tests => 4;
|
||||
|
||||
eval { remove_dir("$TEST_DIR/target"); };
|
||||
mkdir("$TEST_DIR/target");
|
||||
eval { remove_dir("$TEST_DIR/target"); };
|
||||
mkdir("$TEST_DIR/target");
|
||||
|
||||
$stow = new_compat_Stow();
|
||||
capture_stderr();
|
||||
$stow->plan_unstow('pkg12');
|
||||
is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg12 which was never stowed');
|
||||
ok(
|
||||
$stow->get_conflict_count == 0
|
||||
my $stow = new_compat_Stow();
|
||||
check_protected_dirs_skipped(
|
||||
sub { $stow->plan_unstow('pkg12'); }
|
||||
);
|
||||
is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg12 which was never stowed');
|
||||
is(
|
||||
$stow->get_conflict_count,
|
||||
0
|
||||
=> 'unstow never stowed package pkg12'
|
||||
);
|
||||
check_protected_dirs_skipped();
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# Unstowing when target contains a real file shouldn't be an issue.
|
||||
#
|
||||
make_file('man12/man1/file12.1');
|
||||
subtest("Unstowing when target contains a real file shouldn't be an issue", sub {
|
||||
plan tests => 5;
|
||||
make_file('man12/man1/file12.1');
|
||||
|
||||
$stow = new_compat_Stow();
|
||||
capture_stderr();
|
||||
$stow->plan_unstow('pkg12');
|
||||
is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg12 for third time');
|
||||
%conflicts = $stow->get_conflicts;
|
||||
ok(
|
||||
$stow->get_conflict_count == 1 &&
|
||||
$conflicts{unstow}{pkg12}[0]
|
||||
=~ m!existing target is neither a link nor a directory: man12/man1/file12\.1!
|
||||
my $stow = new_compat_Stow();
|
||||
check_protected_dirs_skipped(
|
||||
sub { $stow->plan_unstow('pkg12'); }
|
||||
);
|
||||
is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg12 for third time');
|
||||
%conflicts = $stow->get_conflicts;
|
||||
is($stow->get_conflict_count, 1);
|
||||
like(
|
||||
$conflicts{unstow}{pkg12}[0],
|
||||
qr!existing target is neither a link nor a directory: man12/man1/file12\.1!
|
||||
=> 'unstow pkg12 for third time'
|
||||
);
|
||||
check_protected_dirs_skipped();
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# unstow a simple tree minimally when cwd isn't target
|
||||
#
|
||||
cd('../..');
|
||||
$stow = new_Stow(dir => "$TEST_DIR/stow", target => "$TEST_DIR/target");
|
||||
subtest("unstow a simple tree minimally when cwd isn't target", sub {
|
||||
plan tests => 3;
|
||||
cd('../..');
|
||||
my $stow = new_Stow(dir => "$TEST_DIR/stow", target => "$TEST_DIR/target");
|
||||
|
||||
make_path("$TEST_DIR/stow/pkg13/bin13");
|
||||
make_file("$TEST_DIR/stow/pkg13/bin13/file13");
|
||||
make_link("$TEST_DIR/target/bin13", '../stow/pkg13/bin13');
|
||||
make_path("$TEST_DIR/stow/pkg13/bin13");
|
||||
make_file("$TEST_DIR/stow/pkg13/bin13/file13");
|
||||
make_link("$TEST_DIR/target/bin13", '../stow/pkg13/bin13');
|
||||
|
||||
$stow->plan_unstow('pkg13');
|
||||
$stow->process_tasks();
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
-f "$TEST_DIR/stow/pkg13/bin13/file13" && ! -e "$TEST_DIR/target/bin13"
|
||||
=> 'unstow a simple tree'
|
||||
);
|
||||
$stow->plan_unstow('pkg13');
|
||||
$stow->process_tasks();
|
||||
is($stow->get_conflict_count, 0);
|
||||
ok(-f "$TEST_DIR/stow/pkg13/bin13/file13");
|
||||
ok(! -e "$TEST_DIR/target/bin13" => 'unstow a simple tree');
|
||||
});
|
||||
|
||||
#
|
||||
# unstow a simple tree minimally with absolute stow dir when cwd isn't
|
||||
# target
|
||||
#
|
||||
$stow = new_Stow(dir => canon_path("$TEST_DIR/stow"),
|
||||
subtest("unstow a simple tree minimally with absolute stow dir when cwd isn't target", sub {
|
||||
plan tests => 3;
|
||||
my $stow = new_Stow(dir => canon_path("$TEST_DIR/stow"),
|
||||
target => "$TEST_DIR/target");
|
||||
|
||||
make_path("$TEST_DIR/stow/pkg14/bin14");
|
||||
make_file("$TEST_DIR/stow/pkg14/bin14/file14");
|
||||
make_link("$TEST_DIR/target/bin14", '../stow/pkg14/bin14');
|
||||
make_path("$TEST_DIR/stow/pkg14/bin14");
|
||||
make_file("$TEST_DIR/stow/pkg14/bin14/file14");
|
||||
make_link("$TEST_DIR/target/bin14", '../stow/pkg14/bin14');
|
||||
|
||||
$stow->plan_unstow('pkg14');
|
||||
$stow->process_tasks();
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
-f "$TEST_DIR/stow/pkg14/bin14/file14" && ! -e "$TEST_DIR/target/bin14"
|
||||
$stow->plan_unstow('pkg14');
|
||||
$stow->process_tasks();
|
||||
is($stow->get_conflict_count, 0);
|
||||
ok(-f "$TEST_DIR/stow/pkg14/bin14/file14");
|
||||
ok(! -e "$TEST_DIR/target/bin14"
|
||||
=> 'unstow a simple tree with absolute stow dir'
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
#
|
||||
# unstow a simple tree minimally with absolute stow AND target dirs
|
||||
# when cwd isn't target
|
||||
#
|
||||
$stow = new_Stow(dir => canon_path("$TEST_DIR/stow"),
|
||||
subtest("unstow a simple tree minimally with absolute stow AND target dirs when cwd isn't target", sub {
|
||||
plan tests => 3;
|
||||
my $stow = new_Stow(dir => canon_path("$TEST_DIR/stow"),
|
||||
target => canon_path("$TEST_DIR/target"));
|
||||
make_path("$TEST_DIR/stow/pkg15/bin15");
|
||||
make_file("$TEST_DIR/stow/pkg15/bin15/file15");
|
||||
make_link("$TEST_DIR/target/bin15", '../stow/pkg15/bin15');
|
||||
|
||||
make_path("$TEST_DIR/stow/pkg15/bin15");
|
||||
make_file("$TEST_DIR/stow/pkg15/bin15/file15");
|
||||
make_link("$TEST_DIR/target/bin15", '../stow/pkg15/bin15');
|
||||
|
||||
$stow->plan_unstow('pkg15');
|
||||
$stow->process_tasks();
|
||||
ok(
|
||||
$stow->get_conflict_count == 0 &&
|
||||
-f "$TEST_DIR/stow/pkg15/bin15/file15" && ! -e "$TEST_DIR/target/bin15"
|
||||
$stow->plan_unstow('pkg15');
|
||||
$stow->process_tasks();
|
||||
is($stow->get_conflict_count, 0);
|
||||
ok(-f "$TEST_DIR/stow/pkg15/bin15/file15");
|
||||
ok(! -e "$TEST_DIR/target/bin15"
|
||||
=> 'unstow a simple tree with absolute stow and target dirs'
|
||||
);
|
||||
|
||||
|
||||
# Todo
|
||||
#
|
||||
# Test cleaning up subdirs with --paranoid option
|
||||
);
|
||||
});
|
||||
|
||||
# subtest("Test cleaning up subdirs with --paranoid option", sub {
|
||||
# TODO
|
||||
# });
|
||||
|
|
Loading…
Reference in a new issue