diff --git a/Makefile.am b/Makefile.am index acb217c..d572c14 100644 --- a/Makefile.am +++ b/Makefile.am @@ -55,7 +55,10 @@ TESTS = \ test/rcup-hooks-failure.t \ test/rcup-hooks-run-in-situ.t \ test/rcup-hooks-run-in-order.t \ - test/rcup-spaces.t + test/rcup-spaces.t \ + test/rcup-target.t \ + test/rcup-target-subst.t \ + test/rcrc-target.t dist_check_SCRIPTS = $(TESTS) dist_check_DATA = test/helper.sh diff --git a/NEWS.md.in b/NEWS.md.in index a6e6e1d..6ab08c4 100644 --- a/NEWS.md.in +++ b/NEWS.md.in @@ -1,6 +1,7 @@ rcm (@PACKAGE_VERSION@) unstable; urgency=low * Feature: rcup/rcdn hooks can bail early (Patrick Brisbin) + * Feature: specify a target directory instead of $HOME (see -T or TARGET setting .rcrc(5)) * Documentation improvement (Teo Ljungberg) -- Mike Burns Fri, 30 Dec 2022 11:43:00 -0500 diff --git a/bin/lsrc.in b/bin/lsrc.in index 5ecdc09..6d4bc11 100755 --- a/bin/lsrc.in +++ b/bin/lsrc.in @@ -257,12 +257,13 @@ handle_command_line() { local undotted= local never_undotted= - while getopts :FVqvhI:x:B:S:s:U:u:t:d: opt; do + while getopts :FVqvhI:x:B:S:s:U:u:t:d:T: opt; do case "$opt" in F) show_sigils=1;; h) show_help ;; I) includes="$(append_variable "$includes" "$OPTARG")" ;; t) arg_tags="$(append_variable "$arg_tags" "$OPTARG")" ;; + T) DEST_DIR="$OPTARG" ;; v) verbosity=$(($verbosity + 1));; q) verbosity=$(($verbosity - 1));; d) dotfiles_dirs="$(append_variable "$dotfiles_dirs" "$OPTARG")" ;; diff --git a/bin/rcdn.in b/bin/rcdn.in index ed4ccfd..534affb 100755 --- a/bin/rcdn.in +++ b/bin/rcdn.in @@ -44,7 +44,7 @@ handle_command_line() { local never_undotted= local hostname= - while getopts :VqvhIKk:x:S:s:U:u:t:d:B: opt; do + while getopts :VqvhIKk:x:S:s:U:u:t:d:B:T: opt; do case "$opt" in h) show_help ;; B) hostname="$OPTARG" ;; @@ -52,6 +52,7 @@ handle_command_line() { k) run_hooks=1 ;; K) run_hooks=0 ;; t) arg_tags="$(append_variable "$arg_tags" "$OPTARG")" ;; + T) DEST_DIR="$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")" ;; diff --git a/bin/rcup.in b/bin/rcup.in index 626bfe7..284cea2 100755 --- a/bin/rcup.in +++ b/bin/rcup.in @@ -209,7 +209,7 @@ handle_command_line() { REPLACE_ALL=0 GENERATE= - while getopts :CVqvfghikKI:x:S:s:U:u:t:d:B: opt; do + while getopts :CVqvfghikKI:x:S:s:U:u:t:d:B:T: opt; do case "$opt" in B) hostname="$OPTARG" ;; C) always_copy=1 ;; @@ -223,6 +223,7 @@ handle_command_line() { K) run_hooks=0 ;; q) verbosity=$(($verbosity - 1)) ;; t) arg_tags="$(append_variable "$arg_tags" "$OPTARG")" ;; + T) DEST_DIR="$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")" ;; @@ -302,7 +303,7 @@ if [ "$pre_up_ret" -ne 0 ]; then exit "$pre_up_ret" fi -dests_and_srcs="$(eval "lsrc $LS_ARGS")" +dests_and_srcs="$(eval "lsrc -T \"$DEST_DIR\" $LS_ARGS")" saved_ifs="$IFS" IFS=' diff --git a/man/lsrc.1 b/man/lsrc.1 index 7242497..6fe6902 100644 --- a/man/lsrc.1 +++ b/man/lsrc.1 @@ -19,7 +19,8 @@ .Op files ... .Sh DESCRIPTION This program lists all configuration files, both the sources in the -dotfiles directories and the destinations in your home directory. +dotfiles directories and the destinations in the destination +directory (by default your home directory). . See .Xr rcup 1 , @@ -90,6 +91,8 @@ protect it from your shell. . .It Fl t Ar TAG list dotfiles according to TAG +.It Fl T Ar DIR +consider dotfiles having destinations within target directory DIR . .It Fl U Ar excl_pat the rc files or directories matching this pattern will not be symlinked or diff --git a/man/rcdn.1 b/man/rcdn.1 index e5d8bf4..ad1bc47 100644 --- a/man/rcdn.1 +++ b/man/rcdn.1 @@ -98,6 +98,8 @@ This can be repeated. .It Fl t Ar TAG remove dotfiles according to .Ar TAG +.It Fl T Ar DIR +remove dotfiles relative to target directory DIR .It Fl U Ar EXCL_PAT any rc file or directory that matches .Ar EXCL_PAT diff --git a/man/rcm.7.mustache b/man/rcm.7.mustache index 003ed6d..293dce0 100644 --- a/man/rcm.7.mustache +++ b/man/rcm.7.mustache @@ -139,6 +139,22 @@ option. For example: .Pp .Dl mkrc -U bin . +.Ss COMMON PROBLEM: CHANGING THE TARGET LOCATION DEPENDENT ON THE VALUE OF AN ENVIRONMENT VARIABLE +By default, the rcm suite will assume that all dotfiles are installed relative to +.Pa $HOME . +If instead, the dotfiles are to be installed to, say, +.Pa $XDG_CONFIG_HOME , +there are two options: + +The default target can be redefined by using +.Va TARGET +location in the rcrc file, or by using the +.Fl T +flag. References to environment variables can be specified in any of these, +e.g. +.Pp +.Dl rcup -T $XDG_CONFIG_HOME +. .Sh QUICK START FOR EMPTY DOTFILES DIRECTORIES This section is for those who do not have an existing dotfiles directory and whose dotfiles are standard. @@ -249,6 +265,35 @@ macOS users should see the .Sx BUGS section for more details. . +.Sh ALTERNATIVE TARGET INSTALL LOCATIONS +. +Sometimes it is useful to instruct rcm to install dotfiles to a location +other than +.Sx $HOME . + +The default target directory is taken to be the first specified by: +.Bl -enum offset indent -compact +.It +command-line flag +.Fl T , +for an invocation of rcup, rcdn, or lsrc. +.It +Variable +.Va TARGET +in the rcrc file. (see +.Xr rcrc 5 +and the +.Sx FILES +section below) +.It +$HOME +.El + +A target location can also be specified on a per dotfiles directory basis. +This is achieved by placing meta-file +.Pa target +in the root, which contains a single line denoting the desired target directory. + .Sh STANDALONE INSTALLATION SCRIPT . The diff --git a/man/rcrc.5 b/man/rcrc.5 index 6b6dda9..38d7423 100644 --- a/man/rcrc.5 +++ b/man/rcrc.5 @@ -54,6 +54,8 @@ command, but this command is non-standard and can prove unreliable. The variable forces a known hostname. .It Va TAGS the default tags. +.It Va TARGET +the new default location to manage dotfiles relative to. . .It Va SYMLINK_DIRS a space-separated list of patterns. Directories matching a pattern are diff --git a/man/rcup.1 b/man/rcup.1 index 0931877..9dc5307 100644 --- a/man/rcup.1 +++ b/man/rcup.1 @@ -93,6 +93,8 @@ This option can be repeated. .It Fl t Ar TAG install dotfiles according to .Ar TAG . +.It Fl T Ar DIR +install dotfiles relative to target directory DIR .It Fl U Ar EXCL_PAT any rc file that matches .Ar EXCL_PAT diff --git a/share/rcm.sh.in b/share/rcm.sh.in index 47312d9..3b71466 100644 --- a/share/rcm.sh.in +++ b/share/rcm.sh.in @@ -189,4 +189,5 @@ append_variable() { if [ -r "$RCRC" ]; then . "$RCRC" + DEST_DIR="${TARGET:-$DEST_DIR}" fi diff --git a/test/rcrc-target.t b/test/rcrc-target.t new file mode 100644 index 0000000..8c9cfc2 --- /dev/null +++ b/test/rcrc-target.t @@ -0,0 +1,13 @@ + $ . "$TESTDIR/helper.sh" + +The target for rcup should be specifiable in .rcrc and expand variables + + $ touch .dotfiles/example + > mkdir "$HOME/target-rcrc" + + $ echo 'TARGET=$HOME/target-rcrc' > $HOME/.rcrc + + $ rcup -v > /dev/null + + $ assert_linked "$HOME/target-rcrc/.example" "$HOME/.dotfiles/example" + diff --git a/test/rcup-target-subst.t b/test/rcup-target-subst.t new file mode 100644 index 0000000..a92b600 --- /dev/null +++ b/test/rcup-target-subst.t @@ -0,0 +1,11 @@ + $ . "$TESTDIR/helper.sh" + +Should be able to modify the global dotfiles target using a command line argument, +with environment variables within being expanded + + $ touch .dotfiles/example + > mkdir "$HOME/target" + + $ rcup -v -T '$HOME/target' > /dev/null + + $ assert_linked "$HOME/target/.example" "$HOME/.dotfiles/example" diff --git a/test/rcup-target.t b/test/rcup-target.t new file mode 100644 index 0000000..211aef2 --- /dev/null +++ b/test/rcup-target.t @@ -0,0 +1,10 @@ + $ . "$TESTDIR/helper.sh" + +Should be able to modify the global dotfiles target using a command line argument + + $ touch .dotfiles/example + > mkdir "$HOME/target" + + $ rcup -v -T "$HOME/target" > /dev/null + + $ assert_linked "$HOME/target/.example" "$HOME/.dotfiles/example"