#!/bin/sh
#
# /usr/local/sbin/localbackupconfig
# Copyright 2001-2007 Jonas Smedegaard <dr@jones.dk>
#
# $Id: localbackupconfig,v 1.9 2007-06-10 23:14:57 jonas Exp $
#
# .dpkg-new files appear when refusing to update a conffile on package update
#
# .orig files you should save yourself before customizing a configfile
#
# .old files are for customizing when you don't have the original (anymore)
#
# .bak and ~ is in case you forgot to rename properly as .orig or .old!
#

# TODO: Check md5sum of all conffiles found like this:
#   dpkg-query -W -f '${Conffiles}\n' '*' | grep -v '^$' | awk '{print $1}'
#

set -e

PRG=$(basename "$0")

TEMP="`getopt -s sh -o t:f -l target:,force -n "$PRG" -- "$@"`"
if [ $? != 0 ] ; then echo >&2 "ERROR: Internal getopt error." ; exit 1 ; fi
eval set -- "$TEMP"

targetdir=''
force='no'
while true ; do
	case "$1" in
		-t|--target) targetdir="$2" ; shift 2 ;;
		-f|--force) force="yes" ; shift ;;
		--) shift ; break ;;
		*) echo >&2 "ERROR: Internal error resolving options." ; exit 1 ;;
	esac
done

basedir="/etc"
includefile="/etc/local/localtweaks.include"
excludefile="/etc/local/localtweaks.exclude"
extensions=".dpkg-new .orig .old .bak ~"

if [ -n "$targetdir" ]; then
	targetdirparent="$(dirname "$targetdir")"
	if ! [ -d "$targetdirparent" ]; then
		if [ "$force" = "yes" ]; then
			mkdir -p "$targetdirparent"
		else
			echo >&2 "Error: Parent directory for target directory does not exist."
			exit 1
		fi
	elif [ -e "$targetdir" ]; then
		if [ "$force" = "yes" ]; then
			rm -rf "$targetdir"
		else
			echo >&2 "Error: Target directory already exists."
			exit 1
		fi
	fi
fi

tempdir="$(mktemp -td localtweaks.XXXXXX)"

for ext in $extensions; do
	extfiles="$(find $basedir -name "*$ext")"
	for extfile in $extfiles; do
		xextfile="${extfile%$ext}"
		files="$files ${xextfile#$basedir}"
	done
done

includes=""
if [ -d "$(dirname "$includefile")" ] && [ -r "$includefile" ]; then
	includes="$(cat "$includefile")"
	for include in $includes; do
		files="$files ${include#$basedir}"
	done
fi

excludes=""
if [ -d "$(dirname "$excludefile")" ] && [ -r "$excludefile" ]; then
	xexcludes="$(cat "$excludefile")"
	for exclude in $xexcludes; do
		excludes="$excludes ${exclude#$basedir}"
	done
fi

# process all files once each
files="$(for x in $files; do echo "$x"; done | uniq | sort)"
for file in $files; do

	# file were chosen based on backups - it may not exist itelf
	[ -s "$basedir/$file" ] || continue

	for exclude in $excludes; do
		[ "$file" = "$exclude" ] && continue 2
	done

	ext=""
	for xext in $extensions; do
		if [ -e $basedir/$file$xext ]; then
			ext="$xext"
			continue
		fi
	done

	newdir="$tempdir/$basedir/$(dirname "$file")"
	mkdir -p "$newdir"
	cp -af "$basedir/$file" "$newdir"

	# Only diff against existing and non-empty files.
	if [ -n "$ext" ] && [ -s "$basedir/$file$ext" ]; then
		diff -ruN -a "$basedir/$file$ext" "$basedir/$file" > "$tempdir/$basedir/$file.diff" || [ $? -lt 2 ]
		chown --reference="$basedir/$file" "$tempdir/$basedir/$file.diff"
		chmod --reference="$basedir/$file" "$tempdir/$basedir/$file.diff"
		chmod a-x "$tempdir/$basedir/$file.diff"
	fi
done

if [ -n "$targetdir" ]; then
	mv "$tempdir" "$targetdir"
	rm -rf "$tempdir"
fi