summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--DEVELOPERS.md7
-rw-r--r--Makefile.am3
-rw-r--r--NEWS.md.in9
-rw-r--r--README.md14
-rwxr-xr-xbin/lsrc.in20
-rwxr-xr-xbin/mkrc.in25
-rwxr-xr-xbin/rcdn.in54
-rwxr-xr-xbin/rcup.in54
-rw-r--r--configure.ac2
-rwxr-xr-xmaint/release.in22
-rw-r--r--man/lsrc.17
-rw-r--r--share/rcm.sh.in12
-rw-r--r--test/lsrc-globs.t7
-rw-r--r--test/lsrc-sigils.t9
-rw-r--r--test/lsrc-undotted-star.t14
-rw-r--r--test/mkrc-no-symlinks.t26
16 files changed, 179 insertions, 106 deletions
diff --git a/DEVELOPERS.md b/DEVELOPERS.md
index 828a4cd..5791990 100644
--- a/DEVELOPERS.md
+++ b/DEVELOPERS.md
@@ -19,10 +19,9 @@ First build the distribution:
./configure
make distcheck
-On any system you can build the tarball, Homebrew package, and tag:
+On any system you can build the tarball and tag:
./maint/release build tarball rcm-*.tar.gz
- ./maint/release build homebrew rcm-*.tar.gz
./maint/release build tag rcm-*.tar.gz
You need mdocml to tranform the manpages into HTML:
@@ -32,14 +31,12 @@ You need mdocml to tranform the manpages into HTML:
Once built, you can push it live:
./maint/release push tarball rcm-*.tar.gz
- ./maint/release push homebrew rcm-*.tar.gz
./maint/release push tag rcm-*.tar.gz
./maint/release push man_html rcm-*.tar.gz
And once pushed, you should clean up
./maint/release clean tarball rcm-*.tar.gz
- ./maint/release clean homebrew rcm-*.tar.gz
./maint/release clean tag rcm-*.tar.gz
./maint/release clean man_html rcm-*.tar.gz
@@ -53,7 +50,7 @@ And once pushed, you should clean up
| Fedora | Carl van Tonder | <carl@supervacuo.com> | 0xa478c47bcb683786 |
| Gentoo | Florian Tham | <fgtham@gmail.com> | 0x7286dc0e62941423 |
| Korora | Carl van Tonder | <carl@supervacuo.com> | 0xb55275fbcbe8383c |
-| Homebrew | Mike Burns | <mburns@thoughtbot.com> | 0x3E6761F72846B014 |
+| Homebrew | Stephen Groat | <stephen@groat.us> | 0x3FEA0C7A20399F68 |
| MacPorts | Aljaž Srebrnič | <a2piratesoft@gmail.com> | 0xe140e1eea54ee677 |
| OpenBSD | Mike Burns | <mike+openbsd@mike-burns.com> | 0x3E6761F72846B014 |
| openSUSE | Andrei Dziahel | <develop7@develop7.info> | 0x58BA3FA4A49D76C2 |
diff --git a/Makefile.am b/Makefile.am
index 16164d9..fb68ca8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -19,11 +19,14 @@ TESTS = \
test/lsrc-tags.t \
test/lsrc-usage.t \
test/lsrc-undotted.t \
+ test/lsrc-undotted-star.t \
test/lsrc-host-tags-default.t \
+ test/lsrc-globs.t \
test/mkrc-alternate-dotfiles-dir.t \
test/mkrc-copy-file.t \
test/mkrc-host-file.t \
test/mkrc-hostname.t \
+ test/mkrc-no-symlinks.t \
test/mkrc-simple-output.t \
test/mkrc-spaces.t \
test/mkrc-symlink-dirs.t \
diff --git a/NEWS.md.in b/NEWS.md.in
index a288d5e..cbce2c4 100644
--- a/NEWS.md.in
+++ b/NEWS.md.in
@@ -1,5 +1,14 @@
rcm (@PACKAGE_VERSION@) unstable; urgency=low
+ * BUGFIX: Globs no longer expand permanently (Edd Salkield).
+ * BUGFIX: Show $ for symlinked dirs in `lsrc -F` (Mathias Michel).
+ * Feature: All symlinks in input are rejected (Mat M).
+ * Packaging improvements (Stephen Groat, Martin Frost, Link Dupont).
+
+ -- Mike Burns <mburns@thoughtbot.com> Fri, 13 Jul 2018 14:12:00 -0500
+
+rcm (1.3.3) unstable; urgency=low
+
* Feature: Expand ~ in DOTFILES_DIR hooks (Eric Collins).
-- Mike Burns <mburns@thoughtbot.com> Fri, 13 Jul 2018 14:12:00 -0500
diff --git a/README.md b/README.md
index c8c2807..6c4f720 100644
--- a/README.md
+++ b/README.md
@@ -22,16 +22,15 @@ Arch Linux:
https://aur.archlinux.org/packages/rcm/
-Debian-based:
+Debian (see further down for Ubuntu):
wget -qO - https://apt.thoughtbot.com/thoughtbot.gpg.key | sudo apt-key add -
echo "deb https://apt.thoughtbot.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/thoughtbot.list
sudo apt-get update
sudo apt-get install rcm
-Fedora 22, 23, 24, 25:
+Fedora:
- sudo dnf copr enable seeitcoming/rcm
sudo dnf install rcm
FreeBSD:
@@ -57,7 +56,6 @@ Korora:
macOS with Homebrew:
- brew tap thoughtbot/formulae
brew install rcm
macOS with MacPorts:
@@ -70,8 +68,14 @@ OpenBSD:
openSUSE/RHEL/CentOS: [instructions](http://software.opensuse.org/download.html?project=utilities&package=rcm)
-Ubuntu:
+Ubuntu (19.04 or later):
+ sudo apt update
+ sudo apt install rcm
+
+Ubuntu (12.04, 14.04, 16.04, 18.04, or 18.10):
+
+ sudo apt-get install software-properties-common
sudo add-apt-repository ppa:martin-frost/thoughtbot-rcm
sudo apt-get update
sudo apt-get install rcm
diff --git a/bin/lsrc.in b/bin/lsrc.in
index 6fb6162..7a531f0 100755
--- a/bin/lsrc.in
+++ b/bin/lsrc.in
@@ -144,7 +144,7 @@ handle_file() {
elif is_excluded "$dotfiles_subdir/$file" "$exclude_file_globs" "$include_file_globs"; then
$VERBOSE "skipping excluded file $file"
elif [ -d "$file" ] && is_excluded "$dotfiles_subdir/$file" "$symlink_dirs_file_globs" "$mk_dirs_file_globs"; then
- show_file "$file" "$dest_dir" "$dotfiles_dir" "$dotfiles_subdir" $dotted
+ show_file "$file" "$dest_dir" "$dotfiles_dir" "$dotfiles_subdir" $dotted "$symlink_dirs_file_globs"
elif [ -d "$file" ]; then
show_dir "$file" "$dest_dir" "$dotfiles_dir" "$dotfiles_subdir" $dotted "$exclude_file_globs" "$include_file_globs" "$symlink_dirs_file_globs" "$mk_dirs_file_globs"
else
@@ -166,7 +166,7 @@ dotfiles_dir_excludes() {
$DEBUG "dotfiles_dir_excludes $dotfiles_dir"
$DEBUG " with excludes: $excludes"
- for exclude in $excludes; do
+ for exclude in "$excludes"; do
if echo "$exclude" | grep ':' >/dev/null; then
dotfiles_dir_pat="$(echo "$exclude" | sed 's/:.*//')"
file_glob="$(echo "$exclude" | sed 's/.*://')"
@@ -259,17 +259,17 @@ handle_command_line() {
case "$opt" in
F) show_sigils=1;;
h) show_help ;;
- I) includes="$includes $OPTARG";;
- t) arg_tags="$arg_tags $OPTARG";;
+ I) includes="$(append_variable "$includes" "$OPTARG")" ;;
+ t) arg_tags="$(append_variable "$arg_tags" "$OPTARG")" ;;
v) verbosity=$(($verbosity + 1));;
q) verbosity=$(($verbosity - 1));;
- d) dotfiles_dirs="$dotfiles_dirs $OPTARG";;
+ d) dotfiles_dirs="$(append_variable "$dotfiles_dirs" "$OPTARG")" ;;
V) version=1;;
- x) excludes="$excludes $OPTARG";;
- S) symlink_dirs="$symlink_dirs $OPTARG";;
- s) never_symlink_dirs="$never_symlink_dirs $OPTARG";;
- U) undotted="$undotted $OPTARG";;
- u) never_undotted="$never_undotted $OPTARG";;
+ x) excludes="$(append_variable "$excludes" "$OPTARG")" ;;
+ S) symlink_dirs="$(append_variable "$symlink_dirs" "$OPTARG")" ;;
+ s) never_symlink_dirs="$(append_variable "$never_symlink_dirs" "$OPTARG")" ;;
+ U) undotted="$(append_variable "$undotted" "$OPTARG")" ;;
+ u) never_undotted="$(append_variable "$never_undotted" "$OPTARG")" ;;
B) hostname="$OPTARG";;
?) show_help 64 ;;
esac
diff --git a/bin/mkrc.in b/bin/mkrc.in
index 5d6af7e..5628f14 100755
--- a/bin/mkrc.in
+++ b/bin/mkrc.in
@@ -20,6 +20,28 @@ destination() {
fi
}
+exit_if_dangerous() {
+ local file="$1"
+
+ if [ -L "$file" ]; then
+ $ERROR 1 "'$file' is a symlink. Cannot process file."
+ elif is_nested "$file"; then
+ # Remove DEST_DIR in case $HOME is under a symlink
+ saved_ifs="$IFS"
+ IFS=/
+ set -- $(dirname "$file" | sed "s|$DEST_DIR/||")
+ IFS="$saved_ifs"
+
+ built_dir="$DEST_DIR"
+ for dir in $@; do
+ built_dir="$built_dir/$dir"
+ if [ -L "$built_dir" ]; then
+ $ERROR 1 "'$file' path contains a symlink ($dir). Cannot process file."
+ fi
+ done
+ fi
+}
+
show_help() {
local exit_code=${1:-0}
@@ -64,7 +86,7 @@ while getopts :ChSsUuVvqot:d:B: opt; do
B)
in_host=1
hostname="$OPTARG"
- install_args="-B $hostname"
+ install_args=$(append_variable "$install_args" "-B $hostname")
;;
?) show_help 64 ;;
esac
@@ -84,6 +106,7 @@ fi
files=""
for i; do
+ exit_if_dangerous "$i"
files="$(printf "$files\n$i")"
done
diff --git a/bin/rcdn.in b/bin/rcdn.in
index a2a8472..3ebbd27 100755
--- a/bin/rcdn.in
+++ b/bin/rcdn.in
@@ -48,19 +48,19 @@ handle_command_line() {
case "$opt" in
h) show_help ;;
B) hostname="$OPTARG" ;;
- I) includes="$includes $OPTARG";;
+ I) includes="$(append_variable "$includes" "$OPTARG")" ;;
k) run_hooks=1 ;;
K) run_hooks=0 ;;
- t) arg_tags="$arg_tags $OPTARG" ;;
- S) symlink_dirs="$symlink_dirs $OPTARG";;
- s) never_symlink_dirs="$never_symlink_dirs $OPTARG";;
- U) undotted="$undotted $OPTARG";;
- u) never_undotted="$never_undotted $OPTARG";;
+ t) arg_tags="$(append_variable "$arg_tags" "$OPTARG")" ;;
+ S) symlink_dirs="$(append_variable "$symlink_dirs" "$OPTARG")" ;;
+ s) never_symlink_dirs="$(append_variable "$never_symlink_dirs" "$OPTARG")" ;;
+ U) undotted="$(append_variable "$undotted" "$OPTARG")" ;;
+ u) never_undotted="$(append_variable "$never_undotted" "$OPTARG")";;
v) verbosity=$(($verbosity + 1));;
q) verbosity=$(($verbosity - 1));;
- d) dotfiles_dirs="$dotfiles_dirs $OPTARG" ;;
+ d) dotfiles_dirs="$(append_variable "$dotfiles_dirs" "$OPTARG")" ;;
V) version=1 ;;
- x) excludes="$excludes $OPTARG" ;;
+ x) excludes="$(append_variable "$excludes" "$OPTARG")" ;;
?) show_help 64 ;;
esac
done
@@ -72,34 +72,34 @@ handle_command_line() {
tags="${arg_tags:-$TAGS}"
dotfiles_dirs="${dotfiles_dirs:-$DOTFILES_DIRS}"
files="$@"
- RUN_HOOKS=$run_hooks
+ RUN_HOOKS="$run_hooks"
- for tag in $tags; do
- LS_ARGS="$LS_ARGS -t $tag"
+ for tag in "$tags"; do
+ LS_ARGS="$LS_ARGS -t \"$tag\""
done
- for dotfiles_dir in $dotfiles_dirs; do
- LS_ARGS="$LS_ARGS -d $dotfiles_dir"
+ for dotfiles_dir in "$dotfiles_dirs"; do
+ LS_ARGS="$LS_ARGS -d \"$dotfiles_dir\""
done
- for exclude in $excludes; do
- LS_ARGS="$LS_ARGS -x $exclude"
+ for exclude in "$excludes"; do
+ LS_ARGS="$LS_ARGS -x \"$exclude\""
done
- for include in $includes; do
- LS_ARGS="$LS_ARGS -I $include"
+ for include in "$includes"; do
+ LS_ARGS="$LS_ARGS -I \"$include\""
done
- for symlink_dir in $symlink_dirs; do
- LS_ARGS="$LS_ARGS -S $symlink_dir"
+ for symlink_dir in "$symlink_dirs"; do
+ LS_ARGS="$LS_ARGS -S \"$symlink_dir\""
done
- for never_symlink_dir in $symlink_dirs; do
- LS_ARGS="$LS_ARGS -s $never_symlink_dir"
+ for never_symlink_dir in "$symlink_dirs"; do
+ LS_ARGS="$LS_ARGS -s \"$never_symlink_dir\""
done
- for undot in $undotted; do
- LS_ARGS="$LS_ARGS -U $undot"
+ for undot in "$undotted"; do
+ LS_ARGS="$LS_ARGS -U \"$undot\""
done
- for never_undot in $never_undotted; do
- LS_ARGS="$LS_ARGS -u $never_undot"
+ for never_undot in "$never_undotted"; do
+ LS_ARGS="$LS_ARGS -u \"$never_undot\""
done
- LS_ARGS="$LS_ARGS -B $hostname $files"
+ LS_ARGS="$LS_ARGS -B \"$hostname\" $files"
$DEBUG "LS_ARGS: $LS_ARGS"
}
@@ -111,7 +111,7 @@ handle_command_line "$@"
run_hooks pre down
-dests_and_srcs="$(lsrc $LS_ARGS)"
+dests_and_srcs="$(eval "lsrc $LS_ARGS")"
saved_ifs="$IFS"
IFS='
diff --git a/bin/rcup.in b/bin/rcup.in
index 910e534..65f0ab8 100755
--- a/bin/rcup.in
+++ b/bin/rcup.in
@@ -121,10 +121,6 @@ replace_file() {
link_file "$src" "$dest" "$sigil"
}
-is_nested() {
- echo "$1" | sed "s:$DEST_DIR/::" | grep '/' >/dev/null
-}
-
is_identical() {
diff -c "$1" "$2" > /dev/null 2>&1
}
@@ -217,23 +213,23 @@ handle_command_line() {
case "$opt" in
B) hostname="$OPTARG" ;;
C) always_copy=1 ;;
- d) dotfiles_dirs="$dotfiles_dirs $OPTARG" ;;
+ d) dotfiles_dirs="$(append_variable "$dotfiles_dirs" "$OPTARG")" ;;
f) REPLACE_ALL=1 ;;
g) generate=1 ;;
h) show_help ;;
i) REPLACE_ALL=0 ;;
- I) includes="$includes $OPTARG" ;;
+ I) includes="$(append_variable "$includes" "$OPTARG")" ;;
k) run_hooks=1 ;;
K) run_hooks=0 ;;
q) verbosity=$(($verbosity - 1)) ;;
- t) arg_tags="$arg_tags $OPTARG" ;;
- S) symlink_dirs="$symlink_dirs $OPTARG";;
- s) never_symlink_dirs="$never_symlink_dirs $OPTARG";;
- U) undotted="$undotted $OPTARG";;
- u) never_undotted="$never_undotted $OPTARG";;
+ t) arg_tags="$(append_variable "$arg_tags" "$OPTARG")" ;;
+ S) symlink_dirs="$(append_variable "$symlink_dirs" "$OPTARG")" ;;
+ s) never_symlink_dirs="$(append_variable "$never_symlink_dirs" "$OPTARG")";;
+ U) undotted="$(append_variable "$undotted" "$OPTARG")" ;;
+ u) never_undotted="$(append_variable "$never_undotted" "$OPTARG")" ;;
v) verbosity=$(($verbosity + 1)) ;;
V) version=1 ;;
- x) excludes="$excludes $OPTARG" ;;
+ x) excludes="$(append_variable "$excludes" "$OPTARG")" ;;
?) show_help 64 ;;
esac
done
@@ -265,31 +261,31 @@ handle_command_line() {
done
for tag in $tags; do
- LS_ARGS="$LS_ARGS -t $tag"
+ LS_ARGS="$LS_ARGS -t \"$tag\""
done
- for dotfiles_dir in $DOTFILES_DIRS; do
- LS_ARGS="$LS_ARGS -d $dotfiles_dir"
+ for dotfiles_dir in "$DOTFILES_DIRS"; do
+ LS_ARGS="$LS_ARGS -d \"$dotfiles_dir\""
done
- for exclude in $excludes; do
- LS_ARGS="$LS_ARGS -x $exclude"
+ for exclude in "$excludes"; do
+ LS_ARGS="$LS_ARGS -x \"$exclude\""
done
- for include in $includes; do
- LS_ARGS="$LS_ARGS -I $include"
+ for include in "$includes"; do
+ LS_ARGS="$LS_ARGS -I \"$include\""
done
- for symlink_dir in $symlink_dirs; do
- LS_ARGS="$LS_ARGS -S $symlink_dir"
+ for symlink_dir in "$symlink_dirs"; do
+ LS_ARGS="$LS_ARGS -S \"$symlink_dir\""
done
- for never_symlink_dir in $never_symlink_dirs; do
- LS_ARGS="$LS_ARGS -s $never_symlink_dir"
+ for never_symlink_dir in "$never_symlink_dirs"; do
+ LS_ARGS="$LS_ARGS -s \"$never_symlink_dir\""
done
- for undot in $undotted; do
- LS_ARGS="$LS_ARGS -U $undot"
+ for undot in "$undotted"; do
+ LS_ARGS="$LS_ARGS -U \"$undot\""
done
- for never_undot in $never_undotted; do
- LS_ARGS="$LS_ARGS -u $never_undot"
+ for never_undot in "$never_undotted"; do
+ LS_ARGS="$LS_ARGS -u \"$never_undot\""
done
- LS_ARGS="$LS_ARGS -B $hostname $files"
+ LS_ARGS="$LS_ARGS -B \"$hostname\" $files"
$DEBUG "LS_ARGS: $LS_ARGS"
}
@@ -301,7 +297,7 @@ handle_command_line "$@"
run_hooks pre up
-dests_and_srcs="$(lsrc $LS_ARGS)"
+dests_and_srcs="$(eval "lsrc $LS_ARGS")"
saved_ifs="$IFS"
IFS='
diff --git a/configure.ac b/configure.ac
index dcdfe54..0b7202f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
AC_PREREQ([2.69])
-AC_INIT(rcm, 1.3.3, mburns@thoughtbot.com)
+AC_INIT(rcm, 1.3.4, mburns@thoughtbot.com)
AM_INIT_AUTOMAKE([subdir-objects])
# /bin/sh on Solaris is not POSIX, so try to find another one.
diff --git a/maint/release.in b/maint/release.in
index 4edf91f..133bc66 100755
--- a/maint/release.in
+++ b/maint/release.in
@@ -38,26 +38,6 @@ release_clean_tarball() {
rm -rf $DIST_ARCHIVES
}
-# Homebrew
-release_build_homebrew() {
- ([ -d homebrew-formulae ] || git clone git@github.com:thoughtbot/homebrew-formulae.git homebrew-formulae) && \
- generate_dist_sha && \
- edit_package homebrew/$PACKAGE.rb.in > homebrew-formulae/Formula/$PACKAGE.rb && \
- cd homebrew-formulae && \
- git add Formula/$PACKAGE.rb && \
- git commit -m "$PACKAGE: Release version $PACKAGE_VERSION"
-}
-
-release_push_homebrew() {
- cd homebrew-formulae && \
- git push
-}
-
-release_clean_homebrew() {
- rm -rf homebrew-formulae
- rm -rf $DIST_ARCHIVES
-}
-
# Arch
release_build_arch() {
([ -d gh-pages ] || git clone --branch gh-pages . gh-pages) && \
@@ -156,7 +136,7 @@ release_clean_man_html() {
# Main:
if [ $# -lt 3 ]; then
- echo "Usage: release (build|push|clean) (tarball|homebrew|arch|deb|tag|man_html) DIST_ARCHIVES" >&2
+ echo "Usage: release (build|push|clean) (tarball|arch|deb|tag|man_html) DIST_ARCHIVES" >&2
exit 64
fi
diff --git a/man/lsrc.1 b/man/lsrc.1
index 5abf7ee..b938fee 100644
--- a/man/lsrc.1
+++ b/man/lsrc.1
@@ -190,10 +190,3 @@ We use the
program to determine the unique identifier for the host. This program is
not specified by POSIX and can vary by system. On macOS the hostname is
unpredictable, and can even change as part of the DHCP handshake.
-.Pp
-There are a few bugs around shell globs. Anything involving an exclude
-pattern is unpredictable, so use
-.Fl v
-when dealing with patterns. Specifically, globs may expand at any
-time and remain expanded for the duration of the run, which means they
-cannot be applied more than once.
diff --git a/share/rcm.sh.in b/share/rcm.sh.in
index a2b4492..5d0a373 100644
--- a/share/rcm.sh.in
+++ b/share/rcm.sh.in
@@ -58,6 +58,10 @@ is_relative() {
echo "$1" | grep -v '^/' >/dev/null
}
+is_nested() {
+ echo "$1" | sed "s|$DEST_DIR/||" | grep '/' >/dev/null
+}
+
version() {
cat << EOV
$1 (rcm) $VERSION
@@ -167,6 +171,14 @@ decode() {
echo "$file" | tr "$DELIMITER" " "
}
+append_variable() {
+ if [ -z "$1" ]; then
+ echo "$2"
+ else
+ echo "$1 $2"
+ fi
+}
+
: ${RCRC:=$HOME/.rcrc}
if [ -r "$RCRC" ]; then
diff --git a/test/lsrc-globs.t b/test/lsrc-globs.t
new file mode 100644
index 0000000..cf04385
--- /dev/null
+++ b/test/lsrc-globs.t
@@ -0,0 +1,7 @@
+ $ . "$TESTDIR/helper.sh"
+
+Keeps globs as globs
+
+ $ mkdir vimulator
+ > lsrc -vvv -x '*vim*' 2>&1 | grep exclude_file_globs
+ exclude_file_globs: *vim*
diff --git a/test/lsrc-sigils.t b/test/lsrc-sigils.t
index 98573b2..9bdc82d 100644
--- a/test/lsrc-sigils.t
+++ b/test/lsrc-sigils.t
@@ -14,3 +14,12 @@ Should print X for files in COPY_ALWAYS
$ COPY_ALWAYS=copy lsrc -F
/*/.copy:/*/.dotfiles/copy:X (glob)
/*/.example:/*/.dotfiles/example:@ (glob)
+
+Should print $ for directory links
+
+ $ mkdir .dotfiles/folder
+
+ $ SYMLINK_DIRS=folder COPY_ALWAYS=copy lsrc -F
+ /*/.copy:/*/.dotfiles/copy:X (glob)
+ /*/.example:/*/.dotfiles/example:@ (glob)
+ /*/.folder:/*/.dotfiles/folder:$ (glob)
diff --git a/test/lsrc-undotted-star.t b/test/lsrc-undotted-star.t
new file mode 100644
index 0000000..04db053
--- /dev/null
+++ b/test/lsrc-undotted-star.t
@@ -0,0 +1,14 @@
+ $ . "$TESTDIR/helper.sh"
+
+Should undot files with -U, with wildcard * expansion
+
+ $ touch .dotfiles/example
+ > touch .dotfiles/undotted
+
+ $ lsrc -v -U '*'
+ /*/example:/*/.dotfiles/example (glob)
+ /*/undotted:/*/.dotfiles/undotted (glob)
+
+ $ lsrc -v -U '*:*'
+ /*/example:/*/.dotfiles/example (glob)
+ /*/undotted:/*/.dotfiles/undotted (glob)
diff --git a/test/mkrc-no-symlinks.t b/test/mkrc-no-symlinks.t
new file mode 100644
index 0000000..e37d56a
--- /dev/null
+++ b/test/mkrc-no-symlinks.t
@@ -0,0 +1,26 @@
+ $ . "$TESTDIR/helper.sh"
+
+Passing a linked file is rejected.
+We need a second path not under what will be $HOME
+
+ $ EXTDIR="${CRAMTMP}2"
+ > mkdir -p "$EXTDIR"
+ > echo 'Content' > "$EXTDIR/example"
+ > ln -s "$EXTDIR/example" "$HOME/.example"
+
+ $ mkrc .example
+ '.example' is a symlink. Cannot process file.
+ [1]
+
+ $ refute "is a symlink" -h $HOME/.dotfiles/.example
+
+Passing a file in one linked dir is rejected
+
+ $ mkdir "$HOME/.config"
+ > ln -s "$EXTDIR/" "$HOME/.config/tmpdir"
+
+ $ mkrc -v .config/tmpdir/example
+ '.config/tmpdir/example' path contains a symlink (tmpdir). Cannot process file.
+ [1]
+
+ $ refute "is a symlink" -h "$HOME/.dotfiles/config/tmpdir/example"