summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Whitton <spwhitton@spwhitton.name>2016-04-05 22:11:02 -0700
committerSean Whitton <spwhitton@spwhitton.name>2016-04-05 22:11:02 -0700
commit2424457efbec81401acc405f3c59e9de21b1a4ef (patch)
treefc478acb54057bddfc4d8f38ede3b65314206621
parentb1507233c7f70f32ceff5f7b39a0d45c85821414 (diff)
downloaddotfiles-2424457efbec81401acc405f3c59e9de21b1a4ef.tar.gz
testing my new stow mr lib
-rwxr-xr-xbin/weekly-backups7
-rw-r--r--home-mrconfig15
-rw-r--r--lib/mr/stow99
3 files changed, 82 insertions, 39 deletions
diff --git a/bin/weekly-backups b/bin/weekly-backups
index 2e8c296b..c03b25fc 100755
--- a/bin/weekly-backups
+++ b/bin/weekly-backups
@@ -35,9 +35,10 @@ status "(and tracking branches set up, and new alioth repos added to coldbkup sc
status periodically remove old projects from ~/src
zero src-unregistered
-status "running restow operation: failures indicate symlinks replaced by updated files"
-status "move these into the relevant stow'd repository"
-try mr -ms restow
+# status "running restow operation: failures indicate symlinks replaced by updated files"
+# status "move these into the relevant stow'd repository"
+# try mr -ms restow
+zero mr -ms misstowed # use 'mr adopt' on the result
try mr -ms autoci
# `mr -ms isclean` checks for stuff to be checked in ...
diff --git a/home-mrconfig b/home-mrconfig
index fcfbcb8f..a8b69201 100644
--- a/home-mrconfig
+++ b/home-mrconfig
@@ -31,11 +31,6 @@ git_isclean =
# --- Adam Spiers' plugin for managing dotfile symlinks with mr
-# To make this work we must set the variable MR_NAME for each
-# repository that we want to stow. Adam Spiers' fork of mr
-# ("kitenet-mr") sets this, but we don't want to use that outdated
-# fork
-
include =
if [ -e ~/lib/mr/stow ]; then
cat ~/lib/mr/stow
@@ -49,13 +44,6 @@ include =
elif [ -e ~/local/lib/stow ]; then
cat ~/local/lib/stow
fi
-lib =
- # reimplement kitenet-mr stow library function which relies on mr
- # "-r" parameter which is only present in aspiers' outdated fork
- is_stowable () {
- [ -z "$MR_DISABLE_STOW" ] &&
- ( mr stowable >/dev/null 2>&1 )
- }
# --- joeyh's code for specifying what machine we're on for repo skip
# --- tests, plus my code for detecting Git-on-Windows
@@ -179,7 +167,6 @@ lib =
[src/dotfiles]
checkout = git clone https://git.spwhitton.name/dotfiles.git dotfiles
-lib = MR_NAME=dotfiles
stowable = true
update =
@@ -255,7 +242,6 @@ pre_update = fix_overwritten_symlink .gtk-bookmarks; fix_overwritten_symlink .co
[src/priv]
checkout = git clone gcrypt::athenap:priv priv
-lib = MR_NAME=priv
stowable = true
# this repository can't be checked out until we install
@@ -284,7 +270,6 @@ pre_update = fix_overwritten_symlink_aggressive .gnupg/pubring.gpg; fix_overwrit
[src/athpriv]
checkout = git clone athenap:athpriv athpriv
-lib = MR_NAME=athpriv
stowable = true
skip = ! mine
diff --git a/lib/mr/stow b/lib/mr/stow
index f6fca334..8e1b6c72 100644
--- a/lib/mr/stow
+++ b/lib/mr/stow
@@ -1,10 +1,11 @@
-# stow plug-in for Joey Hess' excellent mr tool.
+# Plug-in to use GNU Stow to manage symlinks whose targets lie in a
+# repository managed with myrepos
#
-# This allows using GNU Stow as a symlink manager with mr.
+# Original author: Adam Spiers <mr@adamspiers.org>
#
-# Author: Adam Spiers <mr@adamspiers.org>
+# Reworked & now maintained by: Sean Whitton <spwhitton@spwhitton.name>
-# INSTRUCTIONS
+# BASIC USAGE INSTRUCTIONS
#
# To make mr use this file, add a line like this inside the [DEFAULT]
# section of your ~/.mrconfig:
@@ -16,21 +17,10 @@
#
# stowable = true
#
-# Obviously you also need Stow installed. This plug-in assumes that
-# the stow script is somewhere on your $PATH, but you can export
-# STOW_COMMAND to override this if it's somewhere else.
+# You must have at least version 2.1.0 of stow available. [1]
#
-# At least version 2.1.0 is required[1], but you can easily build the
-# latest from git using the following recipe:
-#
-# --------- 8< --- copy into your ~/.mrconfig ---- 8< ---------
-# [stow]
-# checkout = git_clone git://git.savannah.gnu.org/stow.git
-# fixups =
-# cd "$MR_REPO"
-# ./configure --prefix=$HOME
-# make install
-# --------- 8< --------- 8< --------- 8< --------- 8< ---------
+# If stow is not in your $PATH, you can export STOW_COMMAND to tell
+# this plug-in where it is.
#
# The default behaviour is to stow on checkout, and restow on update.
# The manual actions 'stow', 'restow', and 'unstow' are also
@@ -40,7 +30,37 @@
# target directory. You can export STOW_DIR and STOW_TARGET to
# override these defaults.
#
-# stowing is automatically performed via post_checkout, and restowing
+# DEALING WITH APPLICATIONS THAT MISTREAT SYMLINKS
+#
+# Some programs will replace a symlink to a stowed file with a regular
+# copy of the file, and a subset of these will do this even if they
+# haven't edited the file. There are two actions designed to deal
+# with this:
+#
+# - 'cd ~/stowed && mr adopt ~/foo' will replace ~/stowed/foo with
+# ~/foo so that when you restow, ~/foo is once again a symlink
+# pointing to ~/stowed/foo
+#
+# - 'cd ~/stowed && mr misstowed' will output a list of all symlinks
+# that have been replaced with regular files *and modified* by you
+# or a program.
+#
+# - If you pass '--delete-unmodified' to 'mr misstowed', it will
+# additionally delete all symlink targets that have been replaced
+# with *unmodified* regular files
+#
+# The recommended workflow is:
+#
+# 1. Run 'mr misstowed', look for files whose modifications you want
+# to keep, and run 'mr adopt' on them.
+#
+# 2. Run 'mr restowover' to replace unmodified regular files, or
+# regular files whose modifications you want to discard, with
+# symlinks once again.
+#
+# FIXUPS THAT CREATE FILES TO BE STOWED
+#
+# Stowing is automatically performed via post_checkout, and restowing
# via post_update, as can be seen from below (search for 'Automatic
# actions'). Note that these run before fixups, which allows fixups
# to refer to stowed files, but isn't ideal if the fixups are
@@ -81,6 +101,7 @@
lib =
: ${STOW_DIR:=$HOME/.STOW}
: ${STOW_TARGET:=$HOME}
+ MR_NAME=$(echo "$MR_REPO" | tr / _)
#
if ! [ -d "$STOW_TARGET" ]; then mkdir -p "$STOW_TARGET"; fi
if ! [ -d "$STOW_DIR" ]; then mkdir -p "$STOW_DIR" ; fi
@@ -89,7 +110,7 @@ lib =
#MR_STOWABLE=no
is_stowable () {
[ -z "$MR_DISABLE_STOW" ] &&
- ( cd && mr -r "$MR_NAME" stowable >/dev/null 2>&1 )
+ ( cd "$MR_REPO" && mr stowable >/dev/null 2>&1 )
#[ "$MR_STOWABLE" = yes ]
}
stowable_then_continue () {
@@ -121,6 +142,9 @@ lib =
if [ -n "$MR_STOW_OVER" ]; then
stow_common_opts="$stow_common_opts --override=$MR_STOW_OVER"
fi
+ if [ -z "$MR_FOLD" ]; then
+ stow_common_opts="$stow_common_opts --no-folding"
+ fi
}
#
mr_stow () {
@@ -144,6 +168,9 @@ lib =
set_stow_common_opts
ensure_package_exists
mr_pre_unstow
+ # don't bother the user about unmodified dereferenced
+ # symlinks; just fix them:
+ mr_misstowed --delete-unmodified >/dev/null
command "$STOW" -R $stow_common_opts "$@" "$MR_NAME"
mr_post_stow
info "Restowed $MR_NAME"
@@ -195,7 +222,7 @@ lib =
ensure_symlink_exists "$STOW_PKG_PATH" "$MR_REPO"
;;
directory)
- [ -e "$STOW_PKG_PATH" ] || error "$STOW_PKG_PATH didn't exist; aborting."
+ [ -e "$STOW_PKG_PATH" ] || mkdir "$STOW_PKG_PATH"
[ -d "$STOW_PKG_PATH" ] || error "Expected $STOW_PKG_PATH to be a directory; aborting."
if [ -L "$STOW_PKG_PATH" ]; then
error "Didn't expect $STOW_PKG_PATH to be a symlink; aborting."
@@ -206,6 +233,34 @@ lib =
;;
esac
}
+ #
+ mr_adopt () {
+ stowable_then_continue || return 0
+ for wanted in "$@"; do
+ if [ -e "$wanted" -a ! -L "$wanted" ]; then
+ dest=$(printf '%s' "$wanted" | sed -e "s@$STOW_TARGET@$MR_REPO@")
+ mkdir -p "$(dirname $dest)"
+ mv "$wanted" "$dest"
+ else
+ error "$wanted is a symlink; won't adopt"
+ fi
+ done
+ }
+ #
+ mr_misstowed () {
+ stowable_then_continue || return 0
+ re="^ \* existing target is neither a link nor a directory: "
+ for file in $(mr_restow_regardless 3>&1 1>&2 2>&3 | grep "$re" \
+ | sed -e "s|$re|$STOW_TARGET/|" | sort | uniq); do
+ dest=$(printf '%s' "$file" | sed -e "s@$STOW_TARGET@$MR_REPO@")
+ # this 'if' is executed if the file IS different from the repository version
+ if ! diff -q "$dest" "$file" >/dev/null 2>&1; then
+ echo "$file"
+ elif [ "$1" = "--delete-unmodified" ]; then
+ rm "$file"
+ fi
+ done
+ }
#stowable = is_stowable
stowable = false
@@ -227,6 +282,8 @@ stowover = MR_STOW_OVER=. mr_stow "$@"
unstow = mr_unstow "$@"
restow = mr_restow_regardless "$@"
restowover = MR_STOW_OVER=. mr_restow_regardless "$@"
+adopt = mr_adopt "$@"
+misstowed = mr_misstowed "$@"
# Local variables:
# mode: sh