1 |
This option will cause emerge to automatically apply autounmask changes |
2 |
to configuration files, and continue to execute the specified command. |
3 |
If the dependency calculation is not entirely successful, then emerge |
4 |
will simply abort without modifying any configuration files. |
5 |
|
6 |
This sort of behavior can be very useful in a continuous integration |
7 |
setting, where the emerge invocation might be inside of a container that |
8 |
is later discarded (so there is no threat of negative consequences). |
9 |
It's also safe for general use, when combined with the --ask option. |
10 |
|
11 |
X-Gentoo-Bug: 582624 |
12 |
X-Gentoo-Bug-url: https://bugs.gentoo.org/show_bug.cgi?id=582624 |
13 |
--- |
14 |
man/emerge.1 | 14 +++++++++++++- |
15 |
pym/_emerge/actions.py | 28 ++++++++++++++++++++++------ |
16 |
pym/_emerge/depgraph.py | 28 ++++++++++++++++++++++++---- |
17 |
pym/_emerge/main.py | 9 +++++++++ |
18 |
pym/portage/tests/emerge/test_simple.py | 5 +++++ |
19 |
5 files changed, 73 insertions(+), 11 deletions(-) |
20 |
|
21 |
diff --git a/man/emerge.1 b/man/emerge.1 |
22 |
index bfa2f73..40be14f 100644 |
23 |
--- a/man/emerge.1 |
24 |
+++ b/man/emerge.1 |
25 |
@@ -1,4 +1,4 @@ |
26 |
-.TH "EMERGE" "1" "Feb 2016" "Portage VERSION" "Portage" |
27 |
+.TH "EMERGE" "1" "Jul 2016" "Portage VERSION" "Portage" |
28 |
.SH "NAME" |
29 |
emerge \- Command\-line interface to the Portage system |
30 |
.SH "SYNOPSIS" |
31 |
@@ -361,6 +361,18 @@ the specified configuration file(s), or enable the |
32 |
\fBEMERGE_DEFAULT_OPTS\fR variable may be used to |
33 |
disable this option by default in \fBmake.conf\fR(5). |
34 |
.TP |
35 |
+.BR "\-\-autounmask\-continue [ y | n ]" |
36 |
+Automatically apply autounmask changes to configuration |
37 |
+files, and continue to execute the specified command. If |
38 |
+the dependency calculation is not entirely successful, then |
39 |
+emerge will simply abort without modifying any configuration |
40 |
+files. |
41 |
+\fBWARNING:\fR |
42 |
+This option is intended to be used only with great caution, |
43 |
+since it is possible for it to make nonsensical configuration |
44 |
+changes which may lead to system breakage. Therefore, it is |
45 |
+advisable to use \fB\-\-ask\fR together with this option. |
46 |
+.TP |
47 |
.BR "\-\-autounmask\-only [ y | n ]" |
48 |
Instead of doing any package building, just unmask |
49 |
packages and generate package.use settings as necessary |
50 |
diff --git a/pym/_emerge/actions.py b/pym/_emerge/actions.py |
51 |
index 2ca7902..ff22687 100644 |
52 |
--- a/pym/_emerge/actions.py |
53 |
+++ b/pym/_emerge/actions.py |
54 |
@@ -96,8 +96,22 @@ if sys.hexversion >= 0x3000000: |
55 |
else: |
56 |
_unicode = unicode |
57 |
|
58 |
-def action_build(settings, trees, mtimedb, |
59 |
- myopts, myaction, myfiles, spinner): |
60 |
+def action_build(emerge_config, trees=DeprecationWarning, |
61 |
+ mtimedb=DeprecationWarning, myopts=DeprecationWarning, |
62 |
+ myaction=DeprecationWarning, myfiles=DeprecationWarning, spinner=None): |
63 |
+ |
64 |
+ if not isinstance(emerge_config, _emerge_config): |
65 |
+ warnings.warn("_emerge.actions.action_build() now expects " |
66 |
+ "an _emerge_config instance as the first parameter", |
67 |
+ DeprecationWarning, stacklevel=2) |
68 |
+ emerge_config = load_emerge_config( |
69 |
+ action=myaction, args=myfiles, trees=trees, opts=myopts) |
70 |
+ adjust_configs(emerge_config.opts, emerge_config.trees) |
71 |
+ |
72 |
+ settings, trees, mtimedb = emerge_config |
73 |
+ myopts = emerge_config.opts |
74 |
+ myaction = emerge_config.action |
75 |
+ myfiles = emerge_config.args |
76 |
|
77 |
if '--usepkgonly' not in myopts: |
78 |
old_tree_timestamp_warn(settings['PORTDIR'], settings) |
79 |
@@ -327,6 +341,11 @@ def action_build(settings, trees, mtimedb, |
80 |
display_missing_pkg_set(root_config, e.value) |
81 |
return 1 |
82 |
|
83 |
+ if success and mydepgraph.need_config_reload(): |
84 |
+ load_emerge_config(emerge_config=emerge_config) |
85 |
+ adjust_configs(emerge_config.opts, emerge_config.trees) |
86 |
+ settings, trees, mtimedb = emerge_config |
87 |
+ |
88 |
if "--autounmask-only" in myopts: |
89 |
mydepgraph.display_problems() |
90 |
return 0 |
91 |
@@ -3230,10 +3249,7 @@ def run_action(emerge_config): |
92 |
except OSError: |
93 |
writemsg("Please install eselect to use this feature.\n", |
94 |
noiselevel=-1) |
95 |
- retval = action_build(emerge_config.target_config.settings, |
96 |
- emerge_config.trees, emerge_config.target_config.mtimedb, |
97 |
- emerge_config.opts, emerge_config.action, |
98 |
- emerge_config.args, spinner) |
99 |
+ retval = action_build(emerge_config, spinner=spinner) |
100 |
post_emerge(emerge_config.action, emerge_config.opts, |
101 |
emerge_config.args, emerge_config.target_config.root, |
102 |
emerge_config.trees, emerge_config.target_config.mtimedb, retval) |
103 |
diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py |
104 |
index f78f08d..090d7c8 100644 |
105 |
--- a/pym/_emerge/depgraph.py |
106 |
+++ b/pym/_emerge/depgraph.py |
107 |
@@ -431,6 +431,7 @@ class _dynamic_depgraph_config(object): |
108 |
self._slot_operator_replace_installed = backtrack_parameters.slot_operator_replace_installed |
109 |
self._prune_rebuilds = backtrack_parameters.prune_rebuilds |
110 |
self._need_restart = False |
111 |
+ self._need_config_reload = False |
112 |
# For conditions that always require user intervention, such as |
113 |
# unsatisfied REQUIRED_USE (currently has no autounmask support). |
114 |
self._skip_restart = False |
115 |
@@ -438,6 +439,7 @@ class _dynamic_depgraph_config(object): |
116 |
|
117 |
self._buildpkgonly_deps_unsatisfied = False |
118 |
self._autounmask = depgraph._frozen_config.myopts.get('--autounmask') != 'n' |
119 |
+ self._displayed_autounmask = False |
120 |
self._success_without_autounmask = False |
121 |
self._required_use_unsatisfied = False |
122 |
self._traverse_ignored_deps = False |
123 |
@@ -4158,6 +4160,13 @@ class depgraph(object): |
124 |
self._dynamic_config._needed_license_changes) : |
125 |
#We failed if the user needs to change the configuration |
126 |
self._dynamic_config._success_without_autounmask = True |
127 |
+ if (self._frozen_config.myopts.get("--autounmask-continue") is True and |
128 |
+ "--pretend" not in self._frozen_config.myopts): |
129 |
+ # This will return false if it fails or if the user |
130 |
+ # aborts via --ask. |
131 |
+ if self._display_autounmask(autounmask_continue=True): |
132 |
+ self._dynamic_config._need_config_reload = True |
133 |
+ return True, myfavorites |
134 |
return False, myfavorites |
135 |
|
136 |
# We're true here unless we are missing binaries. |
137 |
@@ -7973,14 +7982,19 @@ class depgraph(object): |
138 |
|
139 |
return display(self, mylist, favorites, verbosity) |
140 |
|
141 |
- def _display_autounmask(self): |
142 |
+ def _display_autounmask(self, autounmask_continue=False): |
143 |
""" |
144 |
Display --autounmask message and optionally write it to config files |
145 |
(using CONFIG_PROTECT). The message includes the comments and the changes. |
146 |
""" |
147 |
|
148 |
+ if self._dynamic_config._displayed_autounmask: |
149 |
+ return |
150 |
+ |
151 |
+ self._dynamic_config._displayed_autounmask = True |
152 |
+ |
153 |
ask = "--ask" in self._frozen_config.myopts |
154 |
- autounmask_write = \ |
155 |
+ autounmask_write = autounmask_continue or \ |
156 |
self._frozen_config.myopts.get("--autounmask-write", |
157 |
ask) is True |
158 |
autounmask_unrestricted_atoms = \ |
159 |
@@ -8265,7 +8279,7 @@ class depgraph(object): |
160 |
writemsg(format_msg(license_msg[root]), noiselevel=-1) |
161 |
|
162 |
protect_obj = {} |
163 |
- if write_to_file: |
164 |
+ if write_to_file and not autounmask_continue: |
165 |
for root in roots: |
166 |
settings = self._frozen_config.roots[root].settings |
167 |
protect_obj[root] = ConfigProtect( |
168 |
@@ -8292,7 +8306,8 @@ class depgraph(object): |
169 |
(file_to_write_to, e)) |
170 |
if file_contents is not None: |
171 |
file_contents.extend(changes) |
172 |
- if protect_obj[root].isprotected(file_to_write_to): |
173 |
+ if (not autounmask_continue and |
174 |
+ protect_obj[root].isprotected(file_to_write_to)): |
175 |
# We want to force new_protect_filename to ensure |
176 |
# that the user will see all our changes via |
177 |
# dispatch-conf, even if file_to_write_to doesn't |
178 |
@@ -8351,6 +8366,8 @@ class depgraph(object): |
179 |
elif write_to_file and roots: |
180 |
writemsg("\nAutounmask changes successfully written.\n", |
181 |
noiselevel=-1) |
182 |
+ if autounmask_continue: |
183 |
+ return True |
184 |
for root in roots: |
185 |
chk_updated_cfg_files(root, |
186 |
[os.path.join(os.sep, USER_CONFIG_PATH)]) |
187 |
@@ -8872,6 +8889,9 @@ class depgraph(object): |
188 |
return self._dynamic_config._success_without_autounmask or \ |
189 |
self._dynamic_config._required_use_unsatisfied |
190 |
|
191 |
+ def need_config_reload(self): |
192 |
+ return self._dynamic_config._need_config_reload |
193 |
+ |
194 |
def autounmask_breakage_detected(self): |
195 |
try: |
196 |
for pargs, kwargs in self._dynamic_config._unsatisfied_deps_for_display: |
197 |
diff --git a/pym/_emerge/main.py b/pym/_emerge/main.py |
198 |
index 5dbafee..0e672a2 100644 |
199 |
--- a/pym/_emerge/main.py |
200 |
+++ b/pym/_emerge/main.py |
201 |
@@ -127,6 +127,7 @@ def insert_optional_args(args): |
202 |
'--alert' : y_or_n, |
203 |
'--ask' : y_or_n, |
204 |
'--autounmask' : y_or_n, |
205 |
+ '--autounmask-continue' : y_or_n, |
206 |
'--autounmask-only' : y_or_n, |
207 |
'--autounmask-keep-masks': y_or_n, |
208 |
'--autounmask-unrestricted-atoms' : y_or_n, |
209 |
@@ -324,6 +325,11 @@ def parse_opts(tmpcmdline, silent=False): |
210 |
"choices" : true_y_or_n |
211 |
}, |
212 |
|
213 |
+ "--autounmask-continue": { |
214 |
+ "help" : "write autounmask changes and continue", |
215 |
+ "choices" : true_y_or_n |
216 |
+ }, |
217 |
+ |
218 |
"--autounmask-only": { |
219 |
"help" : "only perform --autounmask", |
220 |
"choices" : true_y_or_n |
221 |
@@ -751,6 +757,9 @@ def parse_opts(tmpcmdline, silent=False): |
222 |
if myoptions.autounmask in true_y: |
223 |
myoptions.autounmask = True |
224 |
|
225 |
+ if myoptions.autounmask_continue in true_y: |
226 |
+ myoptions.autounmask_continue = True |
227 |
+ |
228 |
if myoptions.autounmask_only in true_y: |
229 |
myoptions.autounmask_only = True |
230 |
else: |
231 |
diff --git a/pym/portage/tests/emerge/test_simple.py b/pym/portage/tests/emerge/test_simple.py |
232 |
index e5ecd4b..22f8aef 100644 |
233 |
--- a/pym/portage/tests/emerge/test_simple.py |
234 |
+++ b/pym/portage/tests/emerge/test_simple.py |
235 |
@@ -109,6 +109,10 @@ pkg_preinst() { |
236 |
"LICENSE": "GPL-2", |
237 |
"MISC_CONTENT": install_something, |
238 |
}, |
239 |
+ "dev-libs/C-1": { |
240 |
+ "EAPI" : "6", |
241 |
+ "KEYWORDS": "~x86", |
242 |
+ }, |
243 |
"virtual/foo-0": { |
244 |
"EAPI" : "5", |
245 |
"KEYWORDS": "x86", |
246 |
@@ -300,6 +304,7 @@ pkg_preinst() { |
247 |
emerge_cmd + ("-p", "--unmerge", "-q", eroot + "usr"), |
248 |
emerge_cmd + ("--unmerge", "--quiet", "dev-libs/A"), |
249 |
emerge_cmd + ("-C", "--quiet", "dev-libs/B"), |
250 |
+ emerge_cmd + ("--autounmask-continue", "dev-libs/C",), |
251 |
|
252 |
# Test cross-prefix usage, including chpathtool for binpkgs. |
253 |
({"EPREFIX" : cross_prefix},) + \ |
254 |
-- |
255 |
2.7.4 |