So my portable dotfiles are working out really well. There is only one fly in the ointment left. When a file has changed, it gets overwritten with a newer version, that's fine. But when a file has been renamed or removed, it will stick around in ~
, creating the false impression that it's supposed to be there.
This is not a huge problem, but it does get to be tiresome when you're moving around directory hierarchies. I recently started using emacs more seriously and I expect a lot of stuff will eventually pile up in .emacs.d
. Meanwhile, obsolete files and directories will clutter the hierarchy and possibly interfere with the system.
What can we do about it? The archive that holds the dotfiles is a sufficient record of what is actually in the dotfiles at any given moment. We can diff that with the files found on the system locally and pinpoint the ones that have been made obsolete.
For example, I initially had an ~/.emacs
file, but then I moved it to ~/.emacs.d/init.el
. So ~/.emacs
is obsolete. But when I sync my dotfiles on a machine with an older version of my dotfiles, it will still have ~/.emacs
around.
Not anymore. Now this happens:
Files directly in ~
have to be listed explicitly, because we don't know anything about ~
as a whole. But files in known subdirs of ~
, like ~/.emacs.d
, are detected automatically.
killobsolete() {
# files directly in ~ formerly used, now obsolete
# subdirs of ~ checked automatically
local suspected=".emacs"
# init tempfiles we need to run diff on
local found="/tmp/.myshell_found"
local pulled="/tmp/.myshell_pulled"
# detect files found locally
for i in $(gunzip -c cfg.tar.gz | tar -tf -); do
echo $(dirname "$i");
done | grep -v '^.$' | sort | uniq | xargs find | sort | uniq | \
grep -v ".myshell/.*_local*" > "$found"
# detect suspected files
for f in $(find $suspected 2>/dev/null); do
echo "$f" >> "$found";
done
# sort found list
cat "$found" | sort | uniq > "$found.x" ; mv "$found.x" "$found"
# list files pulled from upstream
for i in $(gunzip -c cfg.tar.gz | tar -tf -); do
echo "$i";
echo $(dirname "$i");
done | grep -v '^.$' | sed "s|\/$||g" | sort | uniq > "$pulled"
# list obsolete files
local num=$(diff "$pulled" "$found" | grep '>' | cut -b3- | wc -l)
if [ $num -gt 0 ]; then
echo -e "${cyellow} ++ files found to be obsolete${creset}";
diff "$pulled" "$found" | grep '>' | cut -b3-;
# prompt for deletion
echo -e "${cyellow} ++ kill obsolete? [yN]${creset}"
read ans
if [[ "$ans" == "y" ]]; then
for i in $(diff "$pulled" "$found" | grep '>' | cut -b3-); do
if [ -d "$i" ]; then
rm -rf "$i"
else
rm -f "$i"
fi
done
fi
fi
# dispose of tempfiles
rm -f "$pulled" "$found"
}