From 2424457efbec81401acc405f3c59e9de21b1a4ef Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Tue, 5 Apr 2016 22:11:02 -0700 Subject: testing my new stow mr lib --- bin/weekly-backups | 7 ++-- home-mrconfig | 15 --------- lib/mr/stow | 99 ++++++++++++++++++++++++++++++++++++++++++------------ 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 # -# Author: Adam Spiers +# Reworked & now maintained by: Sean Whitton -# 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 -- cgit v1.2.3