From 847d7b25852aca12497472003a9470ab468b8f05 Mon Sep 17 00:00:00 2001 From: hasufell Date: Mon, 4 May 2015 19:43:05 +0200 Subject: [PATCH] saving uncommitted changes in /etc prior to emerge run --- etckeeper/._cfg0001_etckeeper.conf | 53 +++++ .../._cfg0000_50list-installed | 25 +++ .../post-install.d/._cfg0001_50vcs-commit | 28 +++ .../pre-install.d/._cfg0000_10packagelist | 5 + etckeeper/uninit.d/._cfg0001_50vcs-uninit | 54 +++++ .../update-ignore.d/._cfg0001_01update-ignore | 209 ++++++++++++++++++ 6 files changed, 374 insertions(+) create mode 100644 etckeeper/._cfg0001_etckeeper.conf create mode 100755 etckeeper/list-installed.d/._cfg0000_50list-installed create mode 100755 etckeeper/post-install.d/._cfg0001_50vcs-commit create mode 100755 etckeeper/pre-install.d/._cfg0000_10packagelist create mode 100755 etckeeper/uninit.d/._cfg0001_50vcs-uninit create mode 100755 etckeeper/update-ignore.d/._cfg0001_01update-ignore diff --git a/etckeeper/._cfg0001_etckeeper.conf b/etckeeper/._cfg0001_etckeeper.conf new file mode 100644 index 0000000..0a9c88b --- /dev/null +++ b/etckeeper/._cfg0001_etckeeper.conf @@ -0,0 +1,53 @@ +# The VCS to use. +#VCS="hg" +VCS="git" +#VCS="bzr" +#VCS="darcs" + +# Options passed to git commit when run by etckeeper. +GIT_COMMIT_OPTIONS="" + +# Options passed to hg commit when run by etckeeper. +HG_COMMIT_OPTIONS="" + +# Options passed to bzr commit when run by etckeeper. +BZR_COMMIT_OPTIONS="" + +# Options passed to darcs record when run by etckeeper. +DARCS_COMMIT_OPTIONS="-a" + +# Uncomment to avoid etckeeper committing existing changes +# to /etc automatically once per day. +#AVOID_DAILY_AUTOCOMMITS=1 + +# Uncomment the following to avoid special file warning +# (the option is enabled automatically by cronjob regardless). +#AVOID_SPECIAL_FILE_WARNING=1 + +# Uncomment to avoid etckeeper committing existing changes to +# /etc before installation. It will cancel the installation, +# so you can commit the changes by hand. +#AVOID_COMMIT_BEFORE_INSTALL=1 + +# The high-level package manager that's being used. +# (apt, pacman-g2, yum, dnf, zypper etc) +#HIGHLEVEL_PACKAGE_MANAGER=apt + +# Gentoo specific: +# For portage this is emerge +# For paludis this is cave +HIGHLEVEL_PACKAGE_MANAGER=emerge + +# The low-level package manager that's being used. +# (dpkg, rpm, pacman, pacman-g2, etc) +#LOWLEVEL_PACKAGE_MANAGER=dpkg + +# Gentoo specific: +# For portage this is qlist +# For paludis this is cave +LOWLEVEL_PACKAGE_MANAGER=qlist + +# To push each commit to a remote, put the name of the remote here. +# (eg, "origin" for git). Space-separated lists of multiple remotes +# also work (eg, "origin gitlab github" for git). +PUSH_REMOTE="" diff --git a/etckeeper/list-installed.d/._cfg0000_50list-installed b/etckeeper/list-installed.d/._cfg0000_50list-installed new file mode 100755 index 0000000..91718d4 --- /dev/null +++ b/etckeeper/list-installed.d/._cfg0000_50list-installed @@ -0,0 +1,25 @@ +#!/bin/sh +if [ "$1" = fmt ]; then + # If the list format changes, change the fmt + if [ "$LOWLEVEL_PACKAGE_MANAGER" = dpkg ]; then + echo 2 + else + echo "" + fi +else + # Output to stdout a *sorted* list of all currently installed + # (or removed but still with config-files) packages, in the + # format "package version\n" (or something similar). + if [ "$LOWLEVEL_PACKAGE_MANAGER" = dpkg ]; then + dpkg-query -W -f '${Status}\t${Package} ${Version} ${Architecture}\n' | \ + egrep '(ok installed|ok config-files)' | cut -f2,3 + elif [ "$LOWLEVEL_PACKAGE_MANAGER" = rpm ]; then + rpm -qa --qf "%|epoch?{%{epoch}}:{0}|:%{name}-%{version}-%{release}.%{arch}\n" | sort + elif [ "$LOWLEVEL_PACKAGE_MANAGER" = pacman ]; then + pacman -Q + elif [ "$LOWLEVEL_PACKAGE_MANAGER" = qlist ]; then + qlist -ICv + elif [ "$LOWLEVEL_PACKAGE_MANAGER" = cave ]; then + cave print-packages -r installed + fi +fi diff --git a/etckeeper/post-install.d/._cfg0001_50vcs-commit b/etckeeper/post-install.d/._cfg0001_50vcs-commit new file mode 100755 index 0000000..53138c8 --- /dev/null +++ b/etckeeper/post-install.d/._cfg0001_50vcs-commit @@ -0,0 +1,28 @@ +#!/bin/sh +set -e + +pl="/var/cache/etckeeper/packagelist" + +if etckeeper unclean; then + message="committing changes in /etc after $HIGHLEVEL_PACKAGE_MANAGER run" + + set +e + if [ -e $pl.pre-install ] && [ "$(cat $pl.fmt 2>/dev/null || true)" = "$(etckeeper list-installed fmt)" ]; then + ( + echo "$message" + echo + echo "Package changes:" + etckeeper list-installed | diff -U0 $pl.pre-install - | tail -n+4 | egrep '^[-+]' || true + ) | etckeeper commit --stdin + else + etckeeper commit "$(printf "$message")" + fi + status=$? + set -e + + if [ "$status" != 0 ]; then + echo "warning: etckeeper failed to commit changes in /etc using $VCS" >&2 + fi +fi + +rm -f $pl.pre-install $pl.fmt diff --git a/etckeeper/pre-install.d/._cfg0000_10packagelist b/etckeeper/pre-install.d/._cfg0000_10packagelist new file mode 100755 index 0000000..fbd4ac3 --- /dev/null +++ b/etckeeper/pre-install.d/._cfg0000_10packagelist @@ -0,0 +1,5 @@ +#!/bin/sh +# This list will be later used when committing. +mkdir -p /var/cache/etckeeper/ +etckeeper list-installed > /var/cache/etckeeper/packagelist.pre-install +etckeeper list-installed fmt > /var/cache/etckeeper/packagelist.fmt diff --git a/etckeeper/uninit.d/._cfg0001_50vcs-uninit b/etckeeper/uninit.d/._cfg0001_50vcs-uninit new file mode 100755 index 0000000..06317c5 --- /dev/null +++ b/etckeeper/uninit.d/._cfg0001_50vcs-uninit @@ -0,0 +1,54 @@ +#!/bin/sh +set -e + +if [ "$VCS" = git ]; then + rm -rf .git + file=.gitignore +elif [ "$VCS" = hg ]; then + rm -rf .hg + file=.hgignore +elif [ "$VCS" = bzr ]; then + rm -rf .bzr + file=.bzrignore +elif [ "$VCS" = darcs ]; then + rm -rf _darcs + file=.darcsignore +fi + +managed_by_etckeeper="managed by etckeeper" + +if ! grep -q "$managed_by_etckeeper" "$file"; then + exit 0 +else + realfile="$file" + if which tempfile >/dev/null 2>&1 || type tempfile >/dev/null 2>&1; then + tempfile="tempfile" + elif which mktemp >/dev/null 2>&1 || type mktemp >/dev/null 2>&1; then + tempfile="mktemp" + else + echo "etckeeper warning: can't find tempfile or mktemp" >&2 + exit 1 + fi + file=$($tempfile) + otherentries= + skipping= + while read -r line; do + if echo "$line" | grep -q "$managed_by_etckeeper"; then + if [ ! "$skipping" ]; then + skipping=1 + else + skipping= + fi + elif [ ! "$skipping" ]; then + echo "$line" >> "$file" + otherentries=1 + fi + done <"$realfile" + + if [ "$otherentries" ]; then + mv -f "$file" "$realfile" + else + rm -f "$file" + rm -f "$realfile" + fi +fi diff --git a/etckeeper/update-ignore.d/._cfg0001_01update-ignore b/etckeeper/update-ignore.d/._cfg0001_01update-ignore new file mode 100755 index 0000000..88243ea --- /dev/null +++ b/etckeeper/update-ignore.d/._cfg0001_01update-ignore @@ -0,0 +1,209 @@ +#!/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" ]; then + comment "new and old versions of conffiles, stored by pacman" + ignore "*.pacnew" + ignore "*.pacorig" + ignore "*.pacsave" + 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 /etc 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 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 "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 which tempfile >/dev/null 2>&1 || type tempfile >/dev/null 2>&1; then + tempfile="tempfile" + elif which mktemp >/dev/null 2>&1 || type mktemp >/dev/null 2>&1; then + tempfile="mktemp" + else + echo "etckeeper warning: can't find tempfile or mktemp" >&2 + fi + file=$($tempfile) + ( + 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