#!/bin/sh
set -e

if [ "$VCS" = git ]; then
	dir=.git
	file=.gitignore
elif [ "$VCS" = hg ]; then
	dir=.hg
	file=.hgignore
elif [ "$VCS" = bzr ]; then
	dir=.bzr
	file=.bzrignore
elif [ "$VCS" = darcs ]; then
	dir=_darcs
	file=.darcsignore
else
	echo "etckeeper: unsupported VCS $VCS" >&2
	exit 1
fi

if [ ! -d "$dir" ]; then
	exit 0
fi

managed_by_etckeeper="managed by etckeeper"

nl() {
	echo >>"$file"
}

comment() {
	comment="$1"
	echo "# $comment" >>"$file"
}

ignore() {
	glob="$1"
	
	case "$VCS" in
		git)
			# escape "#" in ignores, as otherwise it may
			# be considered a comment
			echo "$glob" | sed 's/#/\\#/g' >>"$file"
		;;
		bzr)
			echo "$glob" >>"$file"
		;;
		hg)
			# rather than converting the glob to a regexp, just
			# configure hg to use globs
			if [ -z "$hg_syntax_printed" ]; then
				comment "use glob syntax"
				echo "syntax: glob" >>"$file"
				nl
				hg_syntax_printed=1
			fi
			echo "$glob" | sed 's/#/\\#/g' >>"$file"
		;;
		darcs)
			# darcs doesn't understand globs, so we need to
			# translate them into regexs. Not a complete converter,
			# but suitable for given globs.
			if [ "${glob%\*}" != "$glob" ]; then
				glob="${glob%\*}"
			else
				glob="$glob"'($|/)'
			fi
			if [ "${glob#\*}" != "$glob" ]; then
				glob="${glob#\*}"
			else
				glob='(^|/)'"$glob"
			fi
			glob="$( printf %s $glob | sed -e 's/\./\\./g;s/\*/[^\/]*/g;s/\?/[^\/]/g' )"
			echo "$glob" >>"$file"
	esac
}

writefile () {
	comment "begin section $managed_by_etckeeper (do not edit this section by hand)"
	nl

	if [ "$VCS" = darcs ]; then
		darcs setpref boringfile .darcsignore
	fi

	if [ "$LOWLEVEL_PACKAGE_MANAGER" = dpkg ]; then
		comment "new and old versions of conffiles, stored by dpkg"
		ignore "*.dpkg-*"
		comment "new and old versions of conffiles, stored by ucf"
		ignore "*.ucf-*"
		nl
	elif [ "$LOWLEVEL_PACKAGE_MANAGER" = "rpm" ]; then
		comment "new and old versions of conffiles, stored by apt/rpm"
		ignore "*.rpm*"
		nl
	elif [ "$LOWLEVEL_PACKAGE_MANAGER" = "pacman-g2" -o "$LOWLEVEL_PACKAGE_MANAGER" = "pacman" -o "$LOWLEVEL_PACKAGE_MANAGER" = "pacmatic" ]; then
		comment "new and old versions of conffiles, stored by pacman"
		ignore "*.pacnew"
		ignore "*.pacorig"
		ignore "*.pacsave"
		nl
	elif [ "$LOWLEVEL_PACKAGE_MANAGER" = "apk" ]; then
		comment "new versions of conffiles, stored by apk"
		ignore "*.apk-new"
		nl
	elif [ "$LOWLEVEL_PACKAGE_MANAGER" = "xbps" ]; then
		comment "new versions of conffiles, stored by xbps"
		ignore "*.new-*_[0-9]*"
		nl
	elif [ "$LOWLEVEL_PACKAGE_MANAGER" = "qlist" -o "$LOWLEVEL_PACKAGE_MANAGER" = "cave" ]; then
		comment "new and old versions of conffiles, stored by emerge"
		ignore "._cfg*"
		nl
	fi

	comment "old versions of files"
	ignore "*.old"
	# Not currently ignored as admins tend to rely on these files.
	#ignore "passwd-"
	#ignore "group-"
	#ignore "shadow-"
	#ignore "gshadow-"
	nl

	comment "mount(8) records system state here, no need to store these"
	ignore blkid.tab
	ignore blkid.tab.old
	nl
	
	comment "some other files in ${ETCKEEPER_DIR} that typically do not need to be tracked"
	ignore nologin
	ignore ld.so.cache
	ignore prelink.cache
	ignore mtab
	ignore mtab.fuselock
	ignore .pwd.lock
	ignore "*.LOCK"
	ignore network/run
	ignore adjtime
	ignore udev/hwdb.bin
	ignore lvm/cache
	ignore lvm/archive
	ignore "X11/xdm/authdir/authfiles/*"
	ignore ntp.conf.dhcp
	ignore .initctl
	ignore "webmin/fsdump/*.status"
	ignore "webmin/webmin/oscache"
	ignore "apparmor.d/cache/*"
	ignore "service/*/supervise/*"
	ignore "service/*/log/supervise/*"
	ignore "sv/*/supervise/*"
	ignore "sv/*/log/supervise/*"
	ignore "*.elc"
	ignore "*.pyc"
	ignore "*.pyo"
	ignore "init.d/.depend.*"
	ignore "openvpn/openvpn-status.log"
	ignore "cups/subscriptions.conf"
	ignore "cups/subscriptions.conf.O"
	ignore "cups/printers.conf"
	ignore "cups/printers.conf.O"
	ignore "fake-hwclock.data"
	ignore "check_mk/logwatch.state"
	nl
	
	comment "editor temp files"
	ignore "*~"
	ignore ".*.sw?"
	ignore ".sw?"
	ignore "#*#"
	ignore DEADJOE

	nl
	comment "end section $managed_by_etckeeper"
}

if [ -e "$file" ]; then
	if ! grep -q "$managed_by_etckeeper" "$file"; then
		if [ "$1" != "-a" ]; then
			echo "etckeeper: "$file" does not contain \"$managed_by_etckeeper\" comment; not updating"
			exit 1
		else
			echo "etckeeper: "$file" exists but does not contain \"$managed_by_etckeeper\" comment; updating"
			writefile
			exit 0
		fi
	fi
	realfile="$file"
	if command -v mktemp >/dev/null; then
		tempfile="mktemp -t etckeeper-$VCS.XXXXXXXXXX"
	elif command -v tempfile >/dev/null; then
		tempfile="tempfile"
	else
		echo "etckeeper warning: can't find tempfile or mktemp" >&2
	fi
	file=$($tempfile)

	# preserve permissions and ownership
	cp -fp "$realfile" "$file"
	cat /dev/null >"$file"

	(
		skipping=
		while read -r line; do
			if echo "$line" | grep -q "$managed_by_etckeeper"; then
				if [ ! "$skipping" ]; then
					skipping=1
				else
					skipping=
					writefile
				fi
			elif [ ! "$skipping" ]; then
				echo "$line" >> "$file"
			fi
		done
		if [ "$skipping" ]; then
			# reached end of file w/o ending block
			writefile
		fi
	) <"$realfile"

	mv -f "$file" "$realfile"
else
	writefile
fi
