1 |
Those hooks can be used by tools that manage /etc to get notified |
2 |
about updated configuration files. For example, etckeeper could hook |
3 |
this mechanism like the following: |
4 |
|
5 |
/etc/portage/conf-update.d/etckeeper |
6 |
case "${1}" in |
7 |
pre-update) |
8 |
etckeeper pre-install |
9 |
;; |
10 |
post-update) |
11 |
etckeeper post-install |
12 |
;; |
13 |
esac |
14 |
|
15 |
Signed-off-by: Florian Schmaus <flo@×××××××××.eu> |
16 |
Closes: https://bugs.gentoo.org/698316 |
17 |
--- |
18 |
bin/dispatch-conf | 8 +++++++- |
19 |
lib/portage/dispatch_conf.py | 25 ++++++++++++++++++++++++- |
20 |
2 files changed, 31 insertions(+), 2 deletions(-) |
21 |
|
22 |
diff --git a/bin/dispatch-conf b/bin/dispatch-conf |
23 |
index 1759b89b8..ff9698f14 100755 |
24 |
--- a/bin/dispatch-conf |
25 |
+++ b/bin/dispatch-conf |
26 |
@@ -29,7 +29,7 @@ import portage |
27 |
portage._internal_caller = True |
28 |
from portage import os, shutil |
29 |
from portage import _encodings, _unicode_decode |
30 |
-from portage.dispatch_conf import diffstatusoutput, diff_mixed_wrapper |
31 |
+from portage.dispatch_conf import diffstatusoutput, diff_mixed_wrapper, perform_conf_update_hooks |
32 |
from portage.process import find_binary, spawn |
33 |
from portage.util import writemsg, writemsg_stdout |
34 |
|
35 |
@@ -382,11 +382,17 @@ class dispatch: |
36 |
encoding=_encodings["stdio"]) as f: |
37 |
f.write(output + "\n") |
38 |
|
39 |
+ perform_conf_update_hooks("pre-update", curconf) |
40 |
+ |
41 |
try: |
42 |
os.rename(newconf, curconf) |
43 |
except (IOError, os.error) as why: |
44 |
writemsg('dispatch-conf: Error renaming %s to %s: %s; fatal\n' % \ |
45 |
(newconf, curconf, str(why)), noiselevel=-1) |
46 |
+ return |
47 |
+ |
48 |
+ perform_conf_update_hooks("post-update", curconf) |
49 |
+ |
50 |
|
51 |
|
52 |
def post_process(self, curconf): |
53 |
diff --git a/lib/portage/dispatch_conf.py b/lib/portage/dispatch_conf.py |
54 |
index 71693bb36..8f40c7724 100644 |
55 |
--- a/lib/portage/dispatch_conf.py |
56 |
+++ b/lib/portage/dispatch_conf.py |
57 |
@@ -16,11 +16,13 @@ import subprocess |
58 |
import sys |
59 |
import tempfile |
60 |
|
61 |
+from collections import OrderedDict |
62 |
+ |
63 |
import portage |
64 |
from portage import _encodings, os, shutil |
65 |
from portage.env.loaders import KeyValuePairFileLoader |
66 |
from portage.localization import _ |
67 |
-from portage.util import shlex_split, varexpand |
68 |
+from portage.util import shlex_split, varexpand, _recursive_file_list |
69 |
from portage.util.path import iter_parents |
70 |
|
71 |
RCS_BRANCH = '1.1.1' |
72 |
@@ -386,3 +388,24 @@ def file_archive_post_process(archive): |
73 |
if os.path.isdir(dest) and not os.path.islink(dest): |
74 |
_file_archive_rotate(dest) |
75 |
os.rename(archive + '.dist.new', dest) |
76 |
+ |
77 |
+def perform_conf_update_hooks(kind, conf): |
78 |
+ conf_update_dir = os.path.join(portage.settings["PORTAGE_CONFIGROOT"], |
79 |
+ portage.USER_CONFIG_PATH, "conf-update.d") |
80 |
+ hooks = OrderedDict() |
81 |
+ for filepath in _recursive_file_list(conf_update_dir): |
82 |
+ name = filepath.split(conf_update_dir)[1].lstrip(os.sep) |
83 |
+ if os.access(filepath, os.X_OK): |
84 |
+ hooks[filepath] = name |
85 |
+ else: |
86 |
+ writemsg_level(" %s %s hook: '%s' is not executable\n" |
87 |
+ % (warn("*"), _dir, _unicode_decode(name),), |
88 |
+ level=logging.WARN, noiselevel=2) |
89 |
+ |
90 |
+ for filepath in hooks: |
91 |
+ retval = portage.process.spawn([filepath, kind, conf]) |
92 |
+ |
93 |
+ if retval != os.EX_OK: |
94 |
+ writemsg_level(" %s Spawn failed for: %s, %s\n" % (bad("*"), |
95 |
+ _unicode_decode(_hooks[filepath]), filepath), |
96 |
+ level=logging.ERROR, noiselevel=-1) |
97 |
-- |
98 |
2.26.2 |