Gentoo Archives: gentoo-commits

From: Zac Medico <zmedico@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage:master commit in: man/, pym/_emerge/, pym/portage/tests/emerge/
Date: Sat, 02 Jul 2016 21:05:51
Message-Id: 1467493487.e2d88ef3ff5958571ef2da5f69e8756522390f0f.zmedico@gentoo
1 commit: e2d88ef3ff5958571ef2da5f69e8756522390f0f
2 Author: Zac Medico <zmedico <AT> gentoo <DOT> org>
3 AuthorDate: Fri Jul 1 06:48:03 2016 +0000
4 Commit: Zac Medico <zmedico <AT> gentoo <DOT> org>
5 CommitDate: Sat Jul 2 21:04:47 2016 +0000
6 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=e2d88ef3
7
8 Add emerge --autounmask-continue option (bug 582624)
9
10 This option will cause emerge to automatically apply autounmask changes
11 to configuration files, and continue to execute the specified command.
12 If the dependency calculation is not entirely successful, then emerge
13 will simply abort without modifying any configuration files.
14
15 This sort of behavior can be very useful in a continuous integration
16 setting, where the emerge invocation might be inside of a container that
17 is later discarded (so there is no threat of negative consequences).
18 It's also safe for general use, when combined with the --ask option.
19
20 X-Gentoo-Bug: 582624
21 X-Gentoo-Bug-url: https://bugs.gentoo.org/show_bug.cgi?id=582624
22 Acked-by: Brian Dolbec <dolsen <AT> gentoo.org>
23
24 man/emerge.1 | 14 +++++++++++-
25 pym/_emerge/actions.py | 36 +++++++++++++++++++++++------
26 pym/_emerge/depgraph.py | 40 +++++++++++++++++++++++++++++----
27 pym/_emerge/main.py | 9 ++++++++
28 pym/portage/tests/emerge/test_simple.py | 15 +++++++++++++
29 5 files changed, 102 insertions(+), 12 deletions(-)
30
31 diff --git a/man/emerge.1 b/man/emerge.1
32 index 75862d7..da1d852 100644
33 --- a/man/emerge.1
34 +++ b/man/emerge.1
35 @@ -1,4 +1,4 @@
36 -.TH "EMERGE" "1" "Feb 2016" "Portage VERSION" "Portage"
37 +.TH "EMERGE" "1" "Jul 2016" "Portage VERSION" "Portage"
38 .SH "NAME"
39 emerge \- Command\-line interface to the Portage system
40 .SH "SYNOPSIS"
41 @@ -361,6 +361,18 @@ the specified configuration file(s), or enable the
42 \fBEMERGE_DEFAULT_OPTS\fR variable may be used to
43 disable this option by default in \fBmake.conf\fR(5).
44 .TP
45 +.BR "\-\-autounmask\-continue [ y | n ]"
46 +Automatically apply autounmask changes to configuration
47 +files, and continue to execute the specified command. If
48 +the dependency calculation is not entirely successful, then
49 +emerge will simply abort without modifying any configuration
50 +files.
51 +\fBWARNING:\fR
52 +This option is intended to be used only with great caution,
53 +since it is possible for it to make nonsensical configuration
54 +changes which may lead to system breakage. Therefore, it is
55 +advisable to use \fB\-\-ask\fR together with this option.
56 +.TP
57 .BR "\-\-autounmask\-only [ y | n ]"
58 Instead of doing any package building, just unmask
59 packages and generate package.use settings as necessary
60
61 diff --git a/pym/_emerge/actions.py b/pym/_emerge/actions.py
62 index 2ca7902..1dc2b0d 100644
63 --- a/pym/_emerge/actions.py
64 +++ b/pym/_emerge/actions.py
65 @@ -96,8 +96,22 @@ if sys.hexversion >= 0x3000000:
66 else:
67 _unicode = unicode
68
69 -def action_build(settings, trees, mtimedb,
70 - myopts, myaction, myfiles, spinner):
71 +def action_build(emerge_config, trees=DeprecationWarning,
72 + mtimedb=DeprecationWarning, myopts=DeprecationWarning,
73 + myaction=DeprecationWarning, myfiles=DeprecationWarning, spinner=None):
74 +
75 + if not isinstance(emerge_config, _emerge_config):
76 + warnings.warn("_emerge.actions.action_build() now expects "
77 + "an _emerge_config instance as the first parameter",
78 + DeprecationWarning, stacklevel=2)
79 + emerge_config = load_emerge_config(
80 + action=myaction, args=myfiles, trees=trees, opts=myopts)
81 + adjust_configs(emerge_config.opts, emerge_config.trees)
82 +
83 + settings, trees, mtimedb = emerge_config
84 + myopts = emerge_config.opts
85 + myaction = emerge_config.action
86 + myfiles = emerge_config.args
87
88 if '--usepkgonly' not in myopts:
89 old_tree_timestamp_warn(settings['PORTDIR'], settings)
90 @@ -327,6 +341,11 @@ def action_build(settings, trees, mtimedb,
91 display_missing_pkg_set(root_config, e.value)
92 return 1
93
94 + if success and mydepgraph.need_config_reload():
95 + load_emerge_config(emerge_config=emerge_config)
96 + adjust_configs(emerge_config.opts, emerge_config.trees)
97 + settings, trees, mtimedb = emerge_config
98 +
99 if "--autounmask-only" in myopts:
100 mydepgraph.display_problems()
101 return 0
102 @@ -2384,7 +2403,13 @@ def load_emerge_config(emerge_config=None, **kargs):
103 settings = root_trees["vartree"].settings
104 settings._init_dirs()
105 setconfig = load_default_config(settings, root_trees)
106 - root_trees["root_config"] = RootConfig(settings, root_trees, setconfig)
107 + root_config = RootConfig(settings, root_trees, setconfig)
108 + if "root_config" in root_trees:
109 + # Propagate changes to the existing instance,
110 + # which may be referenced by a depgraph.
111 + root_trees["root_config"].update(root_config)
112 + else:
113 + root_trees["root_config"] = root_config
114
115 target_eroot = emerge_config.trees._target_eroot
116 emerge_config.target_config = \
117 @@ -3230,10 +3255,7 @@ def run_action(emerge_config):
118 except OSError:
119 writemsg("Please install eselect to use this feature.\n",
120 noiselevel=-1)
121 - retval = action_build(emerge_config.target_config.settings,
122 - emerge_config.trees, emerge_config.target_config.mtimedb,
123 - emerge_config.opts, emerge_config.action,
124 - emerge_config.args, spinner)
125 + retval = action_build(emerge_config, spinner=spinner)
126 post_emerge(emerge_config.action, emerge_config.opts,
127 emerge_config.args, emerge_config.target_config.root,
128 emerge_config.trees, emerge_config.target_config.mtimedb, retval)
129
130 diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py
131 index c1c37b4..fc957f5 100644
132 --- a/pym/_emerge/depgraph.py
133 +++ b/pym/_emerge/depgraph.py
134 @@ -431,6 +431,7 @@ class _dynamic_depgraph_config(object):
135 self._slot_operator_replace_installed = backtrack_parameters.slot_operator_replace_installed
136 self._prune_rebuilds = backtrack_parameters.prune_rebuilds
137 self._need_restart = False
138 + self._need_config_reload = False
139 # For conditions that always require user intervention, such as
140 # unsatisfied REQUIRED_USE (currently has no autounmask support).
141 self._skip_restart = False
142 @@ -438,6 +439,7 @@ class _dynamic_depgraph_config(object):
143
144 self._buildpkgonly_deps_unsatisfied = False
145 self._autounmask = depgraph._frozen_config.myopts.get('--autounmask') != 'n'
146 + self._displayed_autounmask = False
147 self._success_without_autounmask = False
148 self._required_use_unsatisfied = False
149 self._traverse_ignored_deps = False
150 @@ -4179,11 +4181,30 @@ class depgraph(object):
151 self._dynamic_config._needed_license_changes) :
152 #We failed if the user needs to change the configuration
153 self._dynamic_config._success_without_autounmask = True
154 + if (self._frozen_config.myopts.get("--autounmask-continue") is True and
155 + "--pretend" not in self._frozen_config.myopts):
156 + # This will return false if it fails or if the user
157 + # aborts via --ask.
158 + if self._display_autounmask(autounmask_continue=True):
159 + self._apply_autounmask_continue_state()
160 + self._dynamic_config._need_config_reload = True
161 + return True, myfavorites
162 return False, myfavorites
163
164 # We're true here unless we are missing binaries.
165 return (True, myfavorites)
166
167 + def _apply_autounmask_continue_state(self):
168 + """
169 + Apply autounmask changes to Package instances, so that their
170 + state will be consistent configuration file changes.
171 + """
172 + for node in self._dynamic_config._serialized_tasks_cache:
173 + if isinstance(node, Package):
174 + effective_use = self._pkg_use_enabled(node)
175 + if effective_use != node.use.enabled:
176 + node._metadata['USE'] = ' '.join(effective_use)
177 +
178 def _apply_parent_use_changes(self):
179 """
180 For parents with unsatisfied conditional dependencies, translate
181 @@ -7994,14 +8015,19 @@ class depgraph(object):
182
183 return display(self, mylist, favorites, verbosity)
184
185 - def _display_autounmask(self):
186 + def _display_autounmask(self, autounmask_continue=False):
187 """
188 Display --autounmask message and optionally write it to config files
189 (using CONFIG_PROTECT). The message includes the comments and the changes.
190 """
191
192 + if self._dynamic_config._displayed_autounmask:
193 + return
194 +
195 + self._dynamic_config._displayed_autounmask = True
196 +
197 ask = "--ask" in self._frozen_config.myopts
198 - autounmask_write = \
199 + autounmask_write = autounmask_continue or \
200 self._frozen_config.myopts.get("--autounmask-write",
201 ask) is True
202 autounmask_unrestricted_atoms = \
203 @@ -8286,7 +8312,7 @@ class depgraph(object):
204 writemsg(format_msg(license_msg[root]), noiselevel=-1)
205
206 protect_obj = {}
207 - if write_to_file:
208 + if write_to_file and not autounmask_continue:
209 for root in roots:
210 settings = self._frozen_config.roots[root].settings
211 protect_obj[root] = ConfigProtect(
212 @@ -8313,7 +8339,8 @@ class depgraph(object):
213 (file_to_write_to, e))
214 if file_contents is not None:
215 file_contents.extend(changes)
216 - if protect_obj[root].isprotected(file_to_write_to):
217 + if (not autounmask_continue and
218 + protect_obj[root].isprotected(file_to_write_to)):
219 # We want to force new_protect_filename to ensure
220 # that the user will see all our changes via
221 # dispatch-conf, even if file_to_write_to doesn't
222 @@ -8372,6 +8399,8 @@ class depgraph(object):
223 elif write_to_file and roots:
224 writemsg("\nAutounmask changes successfully written.\n",
225 noiselevel=-1)
226 + if autounmask_continue:
227 + return True
228 for root in roots:
229 chk_updated_cfg_files(root,
230 [os.path.join(os.sep, USER_CONFIG_PATH)])
231 @@ -8893,6 +8922,9 @@ class depgraph(object):
232 return self._dynamic_config._success_without_autounmask or \
233 self._dynamic_config._required_use_unsatisfied
234
235 + def need_config_reload(self):
236 + return self._dynamic_config._need_config_reload
237 +
238 def autounmask_breakage_detected(self):
239 try:
240 for pargs, kwargs in self._dynamic_config._unsatisfied_deps_for_display:
241
242 diff --git a/pym/_emerge/main.py b/pym/_emerge/main.py
243 index 5dbafee..0e672a2 100644
244 --- a/pym/_emerge/main.py
245 +++ b/pym/_emerge/main.py
246 @@ -127,6 +127,7 @@ def insert_optional_args(args):
247 '--alert' : y_or_n,
248 '--ask' : y_or_n,
249 '--autounmask' : y_or_n,
250 + '--autounmask-continue' : y_or_n,
251 '--autounmask-only' : y_or_n,
252 '--autounmask-keep-masks': y_or_n,
253 '--autounmask-unrestricted-atoms' : y_or_n,
254 @@ -324,6 +325,11 @@ def parse_opts(tmpcmdline, silent=False):
255 "choices" : true_y_or_n
256 },
257
258 + "--autounmask-continue": {
259 + "help" : "write autounmask changes and continue",
260 + "choices" : true_y_or_n
261 + },
262 +
263 "--autounmask-only": {
264 "help" : "only perform --autounmask",
265 "choices" : true_y_or_n
266 @@ -751,6 +757,9 @@ def parse_opts(tmpcmdline, silent=False):
267 if myoptions.autounmask in true_y:
268 myoptions.autounmask = True
269
270 + if myoptions.autounmask_continue in true_y:
271 + myoptions.autounmask_continue = True
272 +
273 if myoptions.autounmask_only in true_y:
274 myoptions.autounmask_only = True
275 else:
276
277 diff --git a/pym/portage/tests/emerge/test_simple.py b/pym/portage/tests/emerge/test_simple.py
278 index e5ecd4b..b1a2af5 100644
279 --- a/pym/portage/tests/emerge/test_simple.py
280 +++ b/pym/portage/tests/emerge/test_simple.py
281 @@ -109,6 +109,16 @@ pkg_preinst() {
282 "LICENSE": "GPL-2",
283 "MISC_CONTENT": install_something,
284 },
285 + "dev-libs/C-1": {
286 + "EAPI" : "6",
287 + "KEYWORDS": "~x86",
288 + "RDEPEND": "dev-libs/D[flag]",
289 + },
290 + "dev-libs/D-1": {
291 + "EAPI" : "6",
292 + "KEYWORDS": "~x86",
293 + "IUSE" : "flag",
294 + },
295 "virtual/foo-0": {
296 "EAPI" : "5",
297 "KEYWORDS": "x86",
298 @@ -301,6 +311,11 @@ pkg_preinst() {
299 emerge_cmd + ("--unmerge", "--quiet", "dev-libs/A"),
300 emerge_cmd + ("-C", "--quiet", "dev-libs/B"),
301
302 + emerge_cmd + ("--autounmask-continue", "dev-libs/C",),
303 + # Verify that the above --autounmask-continue command caused
304 + # USE=flag to be applied correctly to dev-libs/D.
305 + portageq_cmd + ("match", eroot, "dev-libs/D[flag]"),
306 +
307 # Test cross-prefix usage, including chpathtool for binpkgs.
308 ({"EPREFIX" : cross_prefix},) + \
309 emerge_cmd + ("--usepkgonly", "dev-libs/A"),