[PATCH] dispatch-conf: Add support for update-conf.d hook directory
Florian Schmaus <[email protected]>
| Newsgroups | gmane.linux.gentoo.portage.devel |
|---|---|
| Message-ID | <[email protected]> |
Those hooks can be used by tools that manage /etc to get notified
about updated configuration files. For example, etckeeper could hook
this mechanism like the following:
/etc/portage/conf-update.d/etckeeper
case "${1}" in
pre-update)
etckeeper pre-install
;;
post-update)
etckeeper post-install
;;
esac
Signed-off-by: Florian Schmaus <[email protected]>
Closes: https://bugs.gentoo.org/698316
---
bin/dispatch-conf | 8 +++++++-
lib/portage/dispatch_conf.py | 25 ++++++++++++++++++++++++-
2 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/bin/dispatch-conf b/bin/dispatch-conf
index 1759b89b8..ff9698f14 100755
--- a/bin/dispatch-conf
+++ b/bin/dispatch-conf
@@ -29,7 +29,7 @@ import portage
portage._internal_caller = True
from portage import os, shutil
from portage import _encodings, _unicode_decode
-from portage.dispatch_conf import diffstatusoutput, diff_mixed_wrapper
+from portage.dispatch_conf import diffstatusoutput, diff_mixed_wrapper, perform_conf_update_hooks
from portage.process import find_binary, spawn
from portage.util import writemsg, writemsg_stdout
@@ -382,11 +382,17 @@ class dispatch:
encoding=_encodings["stdio"]) as f:
f.write(output + "\n")
+ perform_conf_update_hooks("pre-update", curconf)
+
try:
os.rename(newconf, curconf)
except (IOError, os.error) as why:
writemsg('dispatch-conf: Error renaming %s to %s: %s; fatal\n' % \
(newconf, curconf, str(why)), noiselevel=-1)
+ return
+
+ perform_conf_update_hooks("post-update", curconf)
+
def post_process(self, curconf):
diff --git a/lib/portage/dispatch_conf.py b/lib/portage/dispatch_conf.py
index 71693bb36..8f40c7724 100644
--- a/lib/portage/dispatch_conf.py
+++ b/lib/portage/dispatch_conf.py
@@ -16,11 +16,13 @@ import subprocess
import sys
import tempfile
+from collections import OrderedDict
+
import portage
from portage import _encodings, os, shutil
from portage.env.loaders import KeyValuePairFileLoader
from portage.localization import _
-from portage.util import shlex_split, varexpand
+from portage.util import shlex_split, varexpand, _recursive_file_list
from portage.util.path import iter_parents
RCS_BRANCH = '1.1.1'
@@ -386,3 +388,24 @@ def file_archive_post_process(archive):
if os.path.isdir(dest) and not os.path.islink(dest):
_file_archive_rotate(dest)
os.rename(archive + '.dist.new', dest)
+
+def perform_conf_update_hooks(kind, conf):
+ conf_update_dir = os.path.join(portage.settings["PORTAGE_CONFIGROOT"],
+ portage.USER_CONFIG_PATH, "conf-update.d")
+ hooks = OrderedDict()
+ for filepath in _recursive_file_list(conf_update_dir):
+ name = filepath.split(conf_update_dir)[1].lstrip(os.sep)
+ if os.access(filepath, os.X_OK):
+ hooks[filepath] = name
+ else:
+ writemsg_level(" %s %s hook: '%s' is not executable\n"
+ % (warn("*"), _dir, _unicode_decode(name),),
+ level=logging.WARN, noiselevel=2)
+
+ for filepath in hooks:
+ retval = portage.process.spawn([filepath, kind, conf])
+
+ if retval != os.EX_OK:
+ writemsg_level(" %s Spawn failed for: %s, %s\n" % (bad("*"),
+ _unicode_decode(_hooks[filepath]), filepath),
+ level=logging.ERROR, noiselevel=-1)
--
2.26.2