summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Mike Burns <mike@mike-burns.com>2013-08-04 10:35:14 -0400
committerGravatar Mike Burns <mike@mike-burns.com>2013-08-05 04:21:21 +0200
commit63b50643b0ffd287d0070e494625056a05081ce8 (patch)
tree0ee843065deed78edf646f11f8d46ff28c6964ba
parent17c803d03d20f84cb37873e05d1539dbe7d43a77 (diff)
Introduce exclusion patterns
The lsrc(1), rcup(1), and rcdn(1) commands now take any number of `-e` flags, used to specify an exclusion pattern. This can also be controlled via rcrc(5), the `EXCLUDES` variable. An exclusion pattern specifies a file glob to skip. In the case of lsrc(1), any file matching the glob is not listed; in rcup(1) it is not symlinked; and in rcdn(1) it is not removed. The file glob can be preceded by the name of a dotfiles directory (separated from the file glob by a colon) to increase the specificity. Useful for: rcdn -e rcrc rcup -d work-dotfiles -e bashrc rcup -d ~/.dotfiles -d wife-dotfiles -d sys-dotfiles -e wife-dotfiles:tigrc
-rw-r--r--bin/Makefile.in4
-rwxr-xr-xbin/lsrc86
-rwxr-xr-xbin/rcdn7
-rwxr-xr-xbin/rcup7
-rw-r--r--man/Makefile.in4
-rw-r--r--man/lsrc.144
-rw-r--r--man/rcdn.121
-rw-r--r--man/rcm.78
-rw-r--r--man/rcrc.518
-rw-r--r--man/rcup.127
-rw-r--r--share/Makefile.in4
-rw-r--r--share/rcm.sh.in10
12 files changed, 184 insertions, 56 deletions
diff --git a/bin/Makefile.in b/bin/Makefile.in
index cdf3377..42d9875 100644
--- a/bin/Makefile.in
+++ b/bin/Makefile.in
@@ -180,9 +180,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu bin/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --foreign bin/Makefile
+ $(AUTOMAKE) --gnu bin/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
diff --git a/bin/lsrc b/bin/lsrc
index a7eca40..6267f03 100755
--- a/bin/lsrc
+++ b/bin/lsrc
@@ -34,13 +34,16 @@ link_dir() {
local dest_dir=$2
local dotfiles_dir=$3
local dotted=$4
+ local exclude_file_globs="$5"
local dest_path=`build_path $dest_dir $dir $dotted`
+ $DEBUG "link_dir $1 $2 $3 $4 $5"
+
$VERBOSE "recurring on $dest_path"
pushdir $dir
for f in *; do
$DEBUG "handling the file $f"
- handle_file $f $dest_path $dotfiles_dir/$dir 1
+ handle_file $f $dest_path $dotfiles_dir/$dir 1 "$exclude_file_globs"
done
popdir
}
@@ -64,21 +67,68 @@ handle_file() {
local dest_dir=$2
local dotfiles_dir=$3
local dotted=$4
+ local exclude_file_globs="$5"
- $DEBUG handle_file $1 $2 $3 $4
+ $DEBUG "handle_file $1 $2 $3 $4 $5"
if [ ! -e $file ]; then
$VERBOSE "skipping non-existent file $file"
+ elif is_excluded $file "$exclude_file_globs"; then
+ $VERBOSE "skipping excluded file $file"
elif [ -d $file ]; then
- link_dir $file $dest_dir $dotfiles_dir $dotted
+ link_dir $file $dest_dir $dotfiles_dir $dotted "$exclude_file_globs"
else
- dest_file=`build_path $dest_dir $file $dotted`
link_file $file $dest_dir $dotfiles_dir $dotted
fi
}
-metafile() {
- [ x$2 = 'xhost-' -o x$3 = 'xtag-' ]
+is_metafile() {
+ host_portion=`echo $1 | sed -e 's/host-.*/host-/'`
+ tag_portion=`echo $1 | sed -e 's/tag-.*/tag-/'`
+
+ [ x$host_portion = 'xhost-' -o x$tag_portion = 'xtag-' ]
+}
+
+dotfiles_dir_excludes() {
+ local dotfiles_dir=$1
+
+ $DEBUG "dotfiles_dir_excludes $dotfiles_dir"
+ $DEBUG " with EXCLUDES: $EXCLUDES"
+
+ for exclude in $EXCLUDES; do
+ if echo $exclude | grep -q :; then
+ dotfiles_dir_pat=`echo $exclude | sed 's/:.*//'`
+ file_glob=`echo $exclude | sed 's/.*://'`
+
+ if [ "x$dotfiles_dir_pat" != "x*" ] && is_relative $dotfiles_dir_pat; then
+ dotfiles_dir_pat=$PWD/$dotfiles_dir_pat
+ fi
+
+ if [ "x$dotfiles_dir_pat" = "x*" -o "x$dotfiles_dir_pat" = "x$dotfiles_dir" ]; then
+ echo $file_glob
+ fi
+ else
+ echo $exclude
+ fi
+ done
+}
+
+is_excluded() {
+ local file=$1
+ local exclude_file_globs="$2"
+
+ $DEBUG "is_excluded $file $exclude_file_globs"
+
+ for file_glob in $exclude_file_globs; do
+ $DEBUG "file_glob: $file_glob"
+ $DEBUG "file: $file"
+
+ case $file in
+ $file_glob) return 0;;
+ esac
+ done
+
+ return 1
}
handle_command_line() {
@@ -86,9 +136,11 @@ handle_command_line() {
local verbosity=0
local version=0
local dotfiles_dirs=
+ local excludes=
- while getopts Vqvt:d: opt; do
+ while getopts Vqve:t:d: opt; do
case "$opt" in
+ e) excludes="$excludes $OPTARG";;
t) arg_tags="$arg_tags $OPTARG";;
v) verbosity=$(($verbosity + 1));;
q) verbosity=$(($verbosity - 1));;
@@ -101,6 +153,7 @@ handle_command_line() {
handle_common_flags lsrc $version $verbosity
TAGS=${arg_tags:-$TAGS}
DOTFILES_DIRS=${dotfiles_dirs:-$DOTFILES_DIRS}
+ EXCLUDES=${excludes:-$EXCLUDES}
FILES=$@
$DEBUG "TAGS: $TAGS"
@@ -119,8 +172,7 @@ handle_command_line $*
$DEBUG "DOTFILES_DIRS: $DOTFILES_DIRS"
for DOTFILES_DIR in $DOTFILES_DIRS; do
-
- if echo $DOTFILES_DIR | grep -vq '^/'; then
+ if is_relative $DOTFILES_DIR; then
DOTFILES_DIR=$PWD/$DOTFILES_DIR
fi
@@ -129,15 +181,18 @@ for DOTFILES_DIR in $DOTFILES_DIRS; do
continue
fi
+ exclude_file_globs=`dotfiles_dir_excludes $DOTFILES_DIR`
+ $DEBUG "exclude_file_globs: $exclude_file_globs"
+
cd $DOTFILES_DIR
DIR_STACK=":$DOTFILES_DIR"
for file in ${FILES:-*}; do
- host_portion=`echo $file | sed -e 's/host-.*/host-/'`
- tag_portion=`echo $file | sed -e 's/tag-.*/tag-/'`
- if ! metafile $file $host_portion $tag_portion; then
- handle_file $file $DEST_DIR $DOTFILES_DIR 0
+ if is_metafile $file; then
+ continue
fi
+
+ handle_file $file $DEST_DIR $DOTFILES_DIR 0 "$exclude_file_globs"
done
cd $DOTFILES_DIR
@@ -146,7 +201,7 @@ for DOTFILES_DIR in $DOTFILES_DIRS; do
if [ -d $host_files ]; then
pushdir `basename $host_files`
for file in ${FILES:-*}; do
- handle_file $file $DEST_DIR $host_files 0
+ handle_file $file $DEST_DIR $host_files 0 "$exclude_file_globs"
done
popdir
fi
@@ -157,7 +212,8 @@ for DOTFILES_DIR in $DOTFILES_DIRS; do
if [ -d tag-$tag ]; then
pushdir `basename tag-$tag`
for file in ${FILES:-*}; do
- handle_file $file $DEST_DIR $DOTFILES_DIR/tag-$tag 0
+ $DEBUG "TAG: $tag, exclude_file_globs: $exclude_file_globs"
+ handle_file $file $DEST_DIR $DOTFILES_DIR/tag-$tag 0 "$exclude_file_globs"
done
popdir
fi
diff --git a/bin/rcdn b/bin/rcdn
index 8695c63..66e064f 100755
--- a/bin/rcdn
+++ b/bin/rcdn
@@ -9,9 +9,11 @@ handle_command_line() {
local version=0
local dotfiles_dirs=
local files=
+ local excludes=
- while getopts Vqvt:d: opt; do
+ while getopts Vqve:t:d: opt; do
case "$opt" in
+ e) excludes="$excludes $OPTARG";;
t) arg_tags="$arg_tags $OPTARG" ;;
v) verbosity=$(($verbosity + 1));;
q) verbosity=$(($verbosity - 1));;
@@ -33,6 +35,9 @@ handle_command_line() {
for dotfiles_dir in $dotfiles_dirs; do
LS_ARGS="$LS_ARGS -d $dotfiles_dir"
done
+ for exclude in $excludes; do
+ LS_ARGS="$LS_ARGS -e $exclude"
+ done
LS_ARGS="$LS_ARGS $files"
$DEBUG "LS_ARGS: $LS_ARGS"
diff --git a/bin/rcup b/bin/rcup
index 3aa5fa6..7c1cf16 100755
--- a/bin/rcup
+++ b/bin/rcup
@@ -76,11 +76,13 @@ handle_command_line() {
local version=0
local dotfiles_dirs=
local files=
+ local excludes=
REPLACE_ALL=0
- while getopts Vqvfit:d: opt; do
+ while getopts Vqvfie:t:d: opt; do
case "$opt" in
+ e) excludes="$excludes $OPTARG";;
f) REPLACE_ALL=1 ;;
i) REPLACE_ALL=0 ;;
t) arg_tags="$arg_tags $OPTARG" ;;
@@ -104,6 +106,9 @@ handle_command_line() {
for dotfiles_dir in $dotfiles_dirs; do
LS_ARGS="$LS_ARGS -d $dotfiles_dir"
done
+ for exclude in $excludes; do
+ LS_ARGS="$LS_ARGS -e $exclude"
+ done
LS_ARGS="$LS_ARGS $files"
$DEBUG "LS_ARGS: $LS_ARGS"
diff --git a/man/Makefile.in b/man/Makefile.in
index ed1e0db..51cc9de 100644
--- a/man/Makefile.in
+++ b/man/Makefile.in
@@ -184,9 +184,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign man/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu man/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --foreign man/Makefile
+ $(AUTOMAKE) --gnu man/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
diff --git a/man/lsrc.1 b/man/lsrc.1
index ff67a1f..863ceb8 100644
--- a/man/lsrc.1
+++ b/man/lsrc.1
@@ -9,6 +9,7 @@
.Op Fl vq
.Op Fl t Ar tag
.Op Fl d Ar dir
+.Op Fl e Ar excl_pat
.Op files ...
.Sh DESCRIPTION
This program lists all configuration files, both the sources in the
@@ -23,21 +24,52 @@ section, for details on the directory layout.
It supports these options:
.
.Bl -tag
-.It Fl v
-increase verbosity. This can be repeated for extra verbosity.
-.
-.It Fl q
-decrease verbosity
-.
.It Fl t Ar TAG
list dotfiles according to TAG
.
.It Fl d Ar DIR
list dotfiles from the DIR. This can be specified multiple times.
.
+.It Fl e Ar excl_pat
+Exclude the files that matches the given pattern. See
+.Sx EXCLUDE PATTERN
+for more details. This option can be repeated.
+.
+.It Fl v
+increase verbosity. This can be repeated for extra verbosity.
+.
+.It Fl q
+decrease verbosity
+.
.It Ar files ...
only list the specified file(s)
.El
+.Sh EXCLUDE PATTERN
+The exclude pattern specifies a colon-separated pair of dotfiles
+directory and file glob. The dotfiles directory is optional and, if
+omitted, defaults to
+.Li * ,
+which is a special token that matches any dotfiles directory. The file
+glob is relative to the dotfiles directory, ignoring meta directories. A
+colon combines them.
+.
+.Pp
+For example, to ignore all emacs-related items from the
+.Pa thoughtbot-dotfiles
+directory, use the exclude pattern:
+.Pp
+.Dl thoughtbot-dotfiles:*emacs*
+.Pp
+To ignore any
+.Pa bash_profile
+file, use the pattern:
+.Pp
+.Dl *:bash_profile
+.Pp
+Or more simply:
+.Pp
+.Dl bash_profile
+.Pp
.Sh FILES
.Pa ~/.dotfiles
.Pa ~/.rcrc
diff --git a/man/rcdn.1 b/man/rcdn.1
index 65c9bf0..c6f8e9f 100644
--- a/man/rcdn.1
+++ b/man/rcdn.1
@@ -19,17 +19,24 @@ and
.Fl d
flags.
.Bl -tag
-.It Fl v
-increase verbosity. This can be repeated for extra verbosity.
+.It Fl d Ar DIR
+remove rc files from the
+.Ar DIR .
+This can be specified multiple times.
+.It Fl e Ar EXCL_PAT
+do not remove rc files that match
+.Ar EXCL_PAT .
+This can be repeated with additional patterns. See
+.Xr lsrc 1 ,
+.Sx EXCLUDE PATTERN ,
+for more details.
.It Fl q
decrease verbosity
.It Fl t Ar TAG
remove dotfiles according to
.Ar TAG
-.It Fl d Ar DIR
-remove dotfiles from the
-.Ar DIR .
-This can be specified multiple times.
+.It Fl v
+increase verbosity. This can be repeated for extra verbosity.
.It Ar files
only remove the specified file(s)
.El
@@ -39,8 +46,8 @@ only remove the specified file(s)
.Dl rcdn zshrc
.Dl rcdn -t python
.Dl rcdn -d ~/corporate-dotfiles
+.Dl rcdn -e '*:.zshrc'
.Sh FILES
-.Pa ~/.dotfiles
.Pa ~/.rcrc
.Sh SEE ALSO
.Xr lsrc 1 ,
diff --git a/man/rcm.7 b/man/rcm.7
index 69ea809..3a9f659 100644
--- a/man/rcm.7
+++ b/man/rcm.7
@@ -83,10 +83,9 @@ in the directory directory. This will cause a
or
.Pa ~/.Makefile
symlink to be created in your home
-directory. The best option here is to move that file outside of your
-dotfiles directory or remove it entirely.
+directory. Use an exclusion pattern to ignore these.
.Pp
-.Dl rm -f install Rakefile Makefile install.sh
+.Dl rcup -e install -e Rakefile -e Makefile -e install.sh
.Ss COMMON PROBLEM: DOTTED FILENAMES IN DOTFILES DIRECTORY
A less common situation is for all the filenames in your dotfiles
directory to be prefixed with a period. These files are skipped by the
@@ -201,6 +200,9 @@ will take precedence over
.Pp
.Dl rcup -d .dotfiles -d marriage-dotfiles -d thoughtbot-dotfiles
.Pp
+An exclusion pattern can be tied to a specific dotfiles directory.
+.Pp
+.Dl rcup -d .dotfiles -d work-dotfiles -e 'work-dotfiles:powrc'
.
.Sh HOST-SPECIFIC DOTFILES
You can also mark host-specific files. This will go by the hostname. The
diff --git a/man/rcrc.5 b/man/rcrc.5
index c66e718..f14eecf 100644
--- a/man/rcrc.5
+++ b/man/rcrc.5
@@ -17,30 +17,36 @@
.Sh DESCRIPTION
The rcm dotfile manager can be configured using a
.Pa .rcrc
-file in your home directory. The format is POSIX shell, and it is
+file in your home directory. The format is POSIX shell. It is
sourced in by the
.Xr lsrc 1 ,
.Xr mkrc 1 ,
+.Xr rcdn 1 ,
and
.Xr rcup 1
programs.
.Pp
It supports these variables:
.Bl -tag
-.It Va TAGS
-the default tags used by
-.Nm rcup
.It Va DOTFILES_DIRS
the source directories for dotfiles. The first in the list is the
canonical source. The default value is
.Li ~/.dotfiles
+.It Va EXCLUDES
+a space-separated list of exclude patterns. Exclude patterns are
+explained in detail in
+.Xr lsrc 1
+under the section
+.Sx EXCLUDE PATTERN .
+.It Va TAGS
+the default tags.
.El
.Sh FILES
-.Pa ~/.dotfiles
.Pa ~/.rcrc
.Sh EXAMPLES
-.Dl TAGS="freebsd development email git laptop gmail notmuch"
.Dl DOTFILES_DIRS="/home/mike/.dotfiles /usr/share/dotfiles"
+.Dl EXCLUDES="irbrc *:*emacs* dotfiles:python*"
+.Dl TAGS="freebsd development email git laptop gmail notmuch"
.Sh SEE ALSO
.Xr lsrc 1 ,
.Xr mkrc 1 ,
diff --git a/man/rcup.1 b/man/rcup.1
index a0921b2..16c818c 100644
--- a/man/rcup.1
+++ b/man/rcup.1
@@ -6,9 +6,9 @@
.Nd update and install dotfiles
.Sh SYNOPSIS
.Nm rcup
-.Op Fl vqfi
-.Op Fl t Ar tag
+.Op Fl fiqv
.Op Fl d Ar dir
+.Op Fl t Ar tag
.Op Ar files ...
.Sh DESCRIPTION
This is a program to update and install personal dotfiles. These
@@ -23,25 +23,32 @@ for details on the directory layout.
.Pp
It supports these options:
.Bl -tag
-.It f
+.It Fl d Ar DIR
+install dotfiles from the
+.Ar DIR
+\&. This can be specified multiple times.
+.It Fl e Ar EXCL_PAT
+do not install rc files that match
+.Ar EXCL_PAT .
+This can be repeated with additional patterns. See
+.Xr lsrc 1 ,
+.Sx EXCLUDE PATTERN ,
+for more details.
+.It Fl f
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 i
+.It Fl i
If the rc file already exists in your home directory but does not match
the file in your dotfiles directory, prompt for how to handle it. This
is the default
.It Fl t Ar TAG
install dotfiles according to
.Ar TAG
-.It Fl d Ar DIR
-install dotfiles from the
-.Ar DIR
-\&. This can be specified multiple times.
-.It Fl v
-increase verbosity. This can be repeated for extra verbosity.
.It Fl q
decrease verbosity
+.It Fl v
+increase verbosity. This can be repeated for extra verbosity.
.It Ar files
only install the specified file(s)
.El
diff --git a/share/Makefile.in b/share/Makefile.in
index 8b2661d..448b28c 100644
--- a/share/Makefile.in
+++ b/share/Makefile.in
@@ -181,9 +181,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign share/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu share/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --foreign share/Makefile
+ $(AUTOMAKE) --gnu share/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
diff --git a/share/rcm.sh.in b/share/rcm.sh.in
index f25665b..6dae15b 100644
--- a/share/rcm.sh.in
+++ b/share/rcm.sh.in
@@ -28,6 +28,14 @@ echo_error() {
exit $exit_status
}
+echo_stderr() {
+ echo $* >&2
+}
+
+is_relative() {
+ echo $1 | grep -vq '^/'
+}
+
version() {
cat << EOV
$1 (rcm) $VERSION
@@ -47,7 +55,7 @@ handle_common_flags() {
version $prog_name
exit 0
elif [ $verbosity -ge 2 ]; then
- DEBUG=echo
+ DEBUG=echo_stderr
VERBOSE=echo
PRINT=echo
MV="$MV -v"