1 |
commit: 6e86186244d048e3edd5c11c18cfb4eee98a0d56 |
2 |
Author: Florian Schmaus <flo <AT> geekplace <DOT> eu> |
3 |
AuthorDate: Sun Mar 28 12:55:04 2021 +0000 |
4 |
Commit: Michał Górny <mgorny <AT> gentoo <DOT> org> |
5 |
CommitDate: Sun Aug 22 15:32:07 2021 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=6e861862 |
7 |
|
8 |
dispatch-conf: Add support for conf-update.d hook directory |
9 |
|
10 |
Those hooks can be used by tools that manage /etc to get notified |
11 |
about updated configuration files. For example, etckeeper could hook |
12 |
this mechanism like the following: |
13 |
|
14 |
/etc/portage/conf-update.d/etckeeper |
15 |
case "${1}" in |
16 |
pre-update) |
17 |
etckeeper pre-install |
18 |
;; |
19 |
post-update) |
20 |
etckeeper post-install |
21 |
;; |
22 |
esac |
23 |
|
24 |
Currently conf-update.d hooks are called with 4 different events: |
25 |
- pre-session |
26 |
- post-session |
27 |
- pre-update |
28 |
- post-update |
29 |
|
30 |
The *-session events are emitted prior starting a new configuration |
31 |
update sesssion, and when it is finished. That is, the pre-session |
32 |
event is emitted just before dispatch-conf displays the first |
33 |
configuration file, and right before it exists. |
34 |
|
35 |
The *-update events are emitted before and after a configuration file |
36 |
has been updated. The path of the configuration file is provided as |
37 |
second hook argument. |
38 |
|
39 |
Signed-off-by: Florian Schmaus <flo <AT> geekplace.eu> |
40 |
Closes: https://bugs.gentoo.org/698316 |
41 |
Bug: https://bugs.gentoo.org/260623 |
42 |
Closes: https://github.com/gentoo/portage/pull/689 |
43 |
Signed-off-by: Michał Górny <mgorny <AT> gentoo.org> |
44 |
|
45 |
bin/dispatch-conf | 13 ++++++++++++- |
46 |
lib/portage/dispatch_conf.py | 14 ++++++++++++++ |
47 |
lib/portage/util/hooks.py | 12 ++++++++++++ |
48 |
man/dispatch-conf.1 | 5 +++++ |
49 |
4 files changed, 43 insertions(+), 1 deletion(-) |
50 |
|
51 |
diff --git a/bin/dispatch-conf b/bin/dispatch-conf |
52 |
index 0fdfbaa81..f36815a52 100755 |
53 |
--- a/bin/dispatch-conf |
54 |
+++ b/bin/dispatch-conf |
55 |
@@ -34,7 +34,8 @@ import portage |
56 |
portage._internal_caller = True |
57 |
from portage import os, shutil |
58 |
from portage import _encodings, _unicode_decode |
59 |
-from portage.dispatch_conf import diffstatusoutput, diff_mixed_wrapper |
60 |
+from portage.dispatch_conf import (diffstatusoutput, diff_mixed_wrapper, |
61 |
+ perform_conf_update_hooks, perform_conf_update_session_hooks) |
62 |
from portage.process import find_binary, spawn |
63 |
from portage.util import writemsg, writemsg_stdout |
64 |
|
65 |
@@ -97,6 +98,8 @@ class dispatch: |
66 |
confs = [] |
67 |
count = 0 |
68 |
|
69 |
+ perform_conf_update_session_hooks("pre-session") |
70 |
+ |
71 |
config_root = portage.settings["EPREFIX"] or os.sep |
72 |
self.options = portage.dispatch_conf.read_config(MANDATORY_OPTS) |
73 |
|
74 |
@@ -317,6 +320,7 @@ class dispatch: |
75 |
break |
76 |
|
77 |
if c == 'q': |
78 |
+ perform_conf_update_session_hooks("post-session") |
79 |
sys.exit (0) |
80 |
if c == 'h': |
81 |
self.do_help () |
82 |
@@ -378,6 +382,8 @@ class dispatch: |
83 |
writemsg_stdout(" * '%s'\n" % frozen, noiselevel=-1) |
84 |
print() |
85 |
|
86 |
+ perform_conf_update_session_hooks("post-session") |
87 |
+ |
88 |
def replace (self, newconf, curconf): |
89 |
"""Replace current config with the new/merged version. Also logs |
90 |
the diff of what changed into the configured log file.""" |
91 |
@@ -387,11 +393,16 @@ class dispatch: |
92 |
encoding=_encodings["stdio"]) as f: |
93 |
f.write(output + "\n") |
94 |
|
95 |
+ perform_conf_update_hooks("pre-update", curconf) |
96 |
+ |
97 |
try: |
98 |
os.rename(newconf, curconf) |
99 |
except (IOError, os.error) as why: |
100 |
writemsg('dispatch-conf: Error renaming %s to %s: %s; fatal\n' % \ |
101 |
(newconf, curconf, str(why)), noiselevel=-1) |
102 |
+ return |
103 |
+ |
104 |
+ perform_conf_update_hooks("post-update", curconf) |
105 |
|
106 |
|
107 |
def post_process(self, curconf): |
108 |
|
109 |
diff --git a/lib/portage/dispatch_conf.py b/lib/portage/dispatch_conf.py |
110 |
index 3ef659852..851e6c747 100644 |
111 |
--- a/lib/portage/dispatch_conf.py |
112 |
+++ b/lib/portage/dispatch_conf.py |
113 |
@@ -384,3 +384,17 @@ def file_archive_post_process(archive): |
114 |
if os.path.isdir(dest) and not os.path.islink(dest): |
115 |
_file_archive_rotate(dest) |
116 |
os.rename(archive + '.dist.new', dest) |
117 |
+ |
118 |
+ |
119 |
+def perform_conf_update_hooks(kind, conf): |
120 |
+ """Invoke the hooks in the conf-update.d directory. The notification |
121 |
+ 'kind' must either be 'pre-update' or 'post-update'. And 'conf' is the |
122 |
+ absolute path to the configuration file that is going to be or was |
123 |
+ updated.""" |
124 |
+ perform_hooks("conf-update.d", kind, conf) |
125 |
+ |
126 |
+ |
127 |
+def perform_conf_update_session_hooks(kind): |
128 |
+ """Invoke the hooks in the conf-update-session.d directory. The |
129 |
+ notification 'kind' must either be 'pre-session' or 'post-session'.""" |
130 |
+ perform_hooks("conf-update.d", kind) |
131 |
|
132 |
diff --git a/lib/portage/util/hooks.py b/lib/portage/util/hooks.py |
133 |
index d10ec7a59..942b15543 100644 |
134 |
--- a/lib/portage/util/hooks.py |
135 |
+++ b/lib/portage/util/hooks.py |
136 |
@@ -12,6 +12,7 @@ from portage.output import create_color_func |
137 |
from portage.util import writemsg_level, _recursive_file_list |
138 |
from warnings import warn |
139 |
|
140 |
+bad = create_color_func("BAD") |
141 |
warn = create_color_func("WARN") |
142 |
|
143 |
|
144 |
@@ -29,3 +30,14 @@ def get_hooks_from_dir(rel_directory, prefix="/"): |
145 |
level=logging.WARN, noiselevel=2) |
146 |
|
147 |
return hooks |
148 |
+ |
149 |
+ |
150 |
+def perform_hooks(rel_directory, *argv, prefix="/"): |
151 |
+ for filepath, name in get_hooks_from_dir(rel_directory, prefix).items(): |
152 |
+ hook_command = filepath + " " + " ".join(map(str, argv)) |
153 |
+ retval = portage.process.spawn(hook_command) |
154 |
+ |
155 |
+ if retval != portage.os.EX_OK: |
156 |
+ writemsg_level(" %s Spawn failed for: %s, %s\n" % \ |
157 |
+ (bad("*"), name, filepath), |
158 |
+ level=logging.ERROR, noiselevel=-1) |
159 |
|
160 |
diff --git a/man/dispatch-conf.1 b/man/dispatch-conf.1 |
161 |
index a3d233bc0..b877b6942 100644 |
162 |
--- a/man/dispatch-conf.1 |
163 |
+++ b/man/dispatch-conf.1 |
164 |
@@ -70,6 +70,11 @@ older permissions of the first check in may be inherited. As |
165 |
mentioned in the \fBci\fR(1) man page, users can control access |
166 |
to RCS files by setting the permissions of the directory |
167 |
containing the files. |
168 |
+.SH "CONF-UPDATE HOOKS" |
169 |
+\fIdispatch\-conf\fR will run hooks in \fB/etc/portage/conf-update.d\fR. |
170 |
+The first argument of the hook is either \fIpre-session\fR, \fIpost-ression\fR, |
171 |
+\fIpre-update\fR, or, \fIpost-update\fR. In case of *-update events, a second |
172 |
+argument containing the path of the configuration file is also provided. |
173 |
.SH "REPORTING BUGS" |
174 |
Please report bugs via https://bugs.gentoo.org/ |
175 |
.SH "AUTHORS" |