summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbin/mkrc.in4
-rwxr-xr-xbin/rcup.in119
-rw-r--r--man/rcm.7.mustache27
-rw-r--r--man/rcup.115
-rw-r--r--test/Makefile.am1
-rw-r--r--test/rcup-standalone.t75
6 files changed, 227 insertions, 14 deletions
diff --git a/bin/mkrc.in b/bin/mkrc.in
index 55a7cd8..8932926 100755
--- a/bin/mkrc.in
+++ b/bin/mkrc.in
@@ -101,8 +101,8 @@ for file in $files; do
dotless="$(de_dot "$file")"
dest="$(destination "$DOTFILES_DIR" "$dotless" $in_host "$tag")"
mkdir -p "$dest/$(dirname "$dotless")"
- $PRINT "Moving..."
+ $VERBOSE "Moving..."
mv_v "$file" "$dest/$dotless"
- $PRINT "Linking..."
+ $VERBOSE "Linking..."
$INSTALL -d "$DOTFILES_DIR" -t "${tag:--}" $install_args "$dotless"
done
diff --git a/bin/rcup.in b/bin/rcup.in
index 1823099..80e55f3 100755
--- a/bin/rcup.in
+++ b/bin/rcup.in
@@ -3,24 +3,107 @@
: ${RCM_LIB:=$(dirname "$0")/../share/rcm}
. "$RCM_LIB/rcm.sh"
+print_ln_v() {
+ $PRINT "handle_file_ln \"$1\" \"$2\""
+}
+
+print_cp_v() {
+ $PRINT "handle_file_cp \"$1\" \"$2\""
+}
+
+print_rm_v() {
+ :
+}
+
link_or_copy() {
$DEBUG "link_or_copy $1"
local sigil="$1"
if [ "x$sigil" = "xX" ]; then
- echo "cp_v"
+ echo "$CP"
else
echo "$LN"
fi
}
+print_generated_preface() {
+ cat <<PREFACE
+#!/bin/sh
+#
+# Usage:
+#
+# sh install.sh
+#
+# Environment variables: VERBOSE, CP, LN, MKDIR, RM, DIRNAME, XARGS.
+#
+# env VERBOSE=1 sh install.sh
+#
+# DO NOT EDIT THIS FILE
+#
+# This file is generated by rcm(7) as:
+#
+# rcup $@
+#
+# To update it, re-run the above command.
+#
+: \${VERBOSE:=0}
+: \${CP:=/bin/cp}
+: \${LN:=/bin/ln}
+: \${MKDIR:=/bin/mkdir}
+: \${RM:=/bin/rm}
+: \${DIRNAME:=/usr/bin/dirname}
+: \${XARGS:=/usr/bin/xargs}
+verbose() {
+ if [ "\$VERBOSE" -gt 0 ]; then
+ echo "\$@"
+ fi
+}
+handle_file_cp() {
+ if [ -e "\$2" ]; then
+ printf "%s " "overwrite \$2? [yN]"
+ read overwrite
+ case "\$overwrite" in
+ y)
+ \$RM -rf "\$2"
+ ;;
+ *)
+ echo "skipping \$2"
+ return
+ ;;
+ esac
+ fi
+ verbose "'\$1' -> '\$2'"
+ \$DIRNAME "\$2" | \$XARGS \$MKDIR -p
+ \$CP -R "\$1" "\$2"
+}
+handle_file_ln() {
+ if [ -e "\$2" ]; then
+ printf "%s " "overwrite \$2? [yN]"
+ read overwrite
+ case "\$overwrite" in
+ y)
+ \$RM -rf "\$2"
+ ;;
+ *)
+ echo "skipping \$2"
+ return
+ ;;
+ esac
+ fi
+ verbose "'\$1' -> '\$2'"
+ \$DIRNAME "\$2" | \$XARGS \$MKDIR -p
+ \$LN -sf "\$1" "\$2"
+}
+PREFACE
+}
+
link_file() {
local src="$1"
local dest="$2"
local sigil="$3"
if [ -h "$dest" ]; then
- rm_v -f "$dest"
+ $RM -f "$dest"
fi
action="$(link_or_copy "$sigil")"
@@ -35,7 +118,7 @@ replace_file() {
$DEBUG replace_file "$1" "$2" $3
- rm_v -rf "$dest"
+ $RM -rf "$dest"
link_file "$src" "$dest" "$sigil"
}
@@ -56,13 +139,14 @@ handle_dir() {
}
handle_file() {
- local src="$1"
- local dest="$2"
- local sigil="$3"
+ local generate="$1"
+ local src="$2"
+ local dest="$3"
+ local sigil="$4"
- $DEBUG "handle_file $1 $2 $3"
+ $DEBUG "handle_file $1 $2 $3 $4"
- if [ -e "$dest" ]; then
+ if [ "$generate" -ne 1 -a -e "$dest" ]; then
if is_identical "$src" "$dest"; then
$VERBOSE "identical $dest"
elif [ $REPLACE_ALL -eq 1 ]; then
@@ -106,14 +190,18 @@ handle_command_line() {
local symlink_dirs=
local never_symlink_dirs=
local hostname=
+ local generate=0
+ local args=$*
REPLACE_ALL=0
+ GENERATE=
- while getopts :CVqvfhikKI:x:S:s:t:d:B: opt; do
+ while getopts :CVqvfghikKI:x:S:s:t:d:B: opt; do
case "$opt" in
B) hostname="$OPTARG" ;;
C) always_copy=1 ;;
d) dotfiles_dirs="$dotfiles_dirs $OPTARG" ;;
f) REPLACE_ALL=1 ;;
+ g) generate=1 ;;
h) show_help ;;
i) REPLACE_ALL=0 ;;
I) includes="$includes $OPTARG" ;;
@@ -132,9 +220,18 @@ handle_command_line() {
shift $(($OPTIND-1))
LN="ln_v"
+ CP="cp_v"
+ RM="rm_v"
if [ $always_copy -eq 1 ]; then
- LN="cp_v"
+ LN="$CP"
+ fi
+ if [ "$generate" -eq 1 ]; then
+ LN="print_ln_v"
+ CP="print_cp_v"
+ RM="print_rm_v"
+ print_generated_preface $args
fi
+ GENERATE="$generate"
handle_common_flags rcup $version $verbosity
hostname="$(determine_hostname "$hostname")"
@@ -191,7 +288,7 @@ for dest_and_src in $dests_and_srcs; do
handle_dir "$dest"
fi
- handle_file "$src" "$dest" "$sigil"
+ handle_file "$GENERATE" "$src" "$dest" "$sigil"
done
run_hooks post up
diff --git a/man/rcm.7.mustache b/man/rcm.7.mustache
index c9da706..8c8abd4 100644
--- a/man/rcm.7.mustache
+++ b/man/rcm.7.mustache
@@ -225,6 +225,33 @@ OS X users should see the
.Sx BUGS
section for more details.
.
+.Sh STANDALONE INSTALLATION SCRIPT
+.
+The
+.Xr rcup 1
+tool can be used to generate a portable shell script.
+Instead of running a command such as
+.Xr ln 1
+or
+.Xr rm 1 ,
+it will print the command to
+.Li stdout .
+This is controlled with the
+.Fl g
+flag.
+Note that this will generate a script to create an exact replica of the
+synchronization, including tags, host-specific files, and dotfiles directories.
+.Pp
+.Dl env RCRC=/dev/null rcup -B 0 -g > install.sh
+.Pp
+Using the above command, you can now run
+.Li install.sh
+to install (or re-install) your rc files.
+The
+.Li install.sh
+script can be stored in your dotfiles directory, copied between computers, and
+so on.
+.
.Sh RATIONALE
The rcm suite was built as an abstraction over the shell, Ruby, Python,
and make scripts people were writing and sharing. It is intended to run
diff --git a/man/rcup.1 b/man/rcup.1
index 9d4ee55..130ae4a 100644
--- a/man/rcup.1
+++ b/man/rcup.1
@@ -9,6 +9,7 @@
.Op Fl CfhiKkqVv
.Op Fl B Ar hostname
.Op Fl d Ar dir
+.Op Fl g
.Op Fl I Ar excl_pat
.Op Fl S Ar excl_pat
.Op Fl s Ar excl_pat
@@ -42,6 +43,15 @@ This can be specified multiple times.
if the rc file already exists in your home directory but does not match
the file in your dotfiles directory, remove the rc file then create the
symlink
+.It Fl g
+print to
+.Li stdout
+a standalone shell script that will run the
+.Nm
+command as specified.
+Nothing on your filesystem will be modified by
+.Nm
+when this flag is passed.
.It Fl h
show usage instructions.
.It Fl I Ar EXCL_PAT
@@ -86,7 +96,10 @@ decrease verbosity
.It Fl V
show the version number.
.It Fl v
-increase verbosity. This can be repeated for extra verbosity.
+increase verbosity.
+This can be repeated for extra verbosity.
+Verbose messages are printed to
+.Li stderr .
.It Fl x Ar EXCL_PAT
do not install rc files that match
.Ar EXCL_PAT .
diff --git a/test/Makefile.am b/test/Makefile.am
index afa2631..aafa5ca 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -20,6 +20,7 @@ TESTS = \
rcrc.t \
rcup-link-files.t \
rcup-hostname.t \
+ rcup-standalone.t \
rcup-symlink-dirs.t \
rcup-usage.t
diff --git a/test/rcup-standalone.t b/test/rcup-standalone.t
new file mode 100644
index 0000000..7dd3b58
--- /dev/null
+++ b/test/rcup-standalone.t
@@ -0,0 +1,75 @@
+ $ . "$TESTDIR/helper.sh"
+
+-g generates a script
+
+ $ mkdir -p .dotfiles/eggplant_firetruck/lampshade
+ > touch .dotfiles/eggplant_firetruck/lampshade/bottle
+
+ $ rcup -g
+ #!/bin/sh
+ #
+ # Usage:
+ #
+ # sh install.sh
+ #
+ # Environment variables: VERBOSE, CP, LN, MKDIR, RM, DIRNAME, XARGS.
+ #
+ # env VERBOSE=1 sh install.sh
+ #
+ # DO NOT EDIT THIS FILE
+ #
+ # This file is generated by rcm(7) as:
+ #
+ # rcup -g
+ #
+ # To update it, re-run the above command.
+ #
+ : ${VERBOSE:=0}
+ : ${CP:=/bin/cp}
+ : ${LN:=/bin/ln}
+ : ${MKDIR:=/bin/mkdir}
+ : ${RM:=/bin/rm}
+ : ${DIRNAME:=/usr/bin/dirname}
+ : ${XARGS:=/usr/bin/xargs}
+ verbose() {
+ if [ "$VERBOSE" -gt 0 ]; then
+ echo "$@"
+ fi
+ }
+ handle_file_cp() {
+ if [ -e "$2" ]; then
+ printf "%s " "overwrite $2? [yN]"
+ read overwrite
+ case "$overwrite" in
+ y)
+ $RM -rf "$2"
+ ;;
+ *)
+ echo "skipping $2"
+ return
+ ;;
+ esac
+ fi
+ verbose "'$1' -> '$2'"
+ $DIRNAME "$2" | $XARGS $MKDIR -p
+ $CP -R "$1" "$2"
+ }
+ handle_file_ln() {
+ if [ -e "$2" ]; then
+ printf "%s " "overwrite $2? [yN]"
+ read overwrite
+ case "$overwrite" in
+ y)
+ $RM -rf "$2"
+ ;;
+ *)
+ echo "skipping $2"
+ return
+ ;;
+ esac
+ fi
+ verbose "'$1' -> '$2'"
+ $DIRNAME "$2" | $XARGS $MKDIR -p
+ $LN -sf "$1" "$2"
+ }
+ handle_file_ln "*eggplant_firetruck/lampshade/bottle" "*.eggplant_firetruck/lampshade/bottle" (glob)