Gentoo Archives: gentoo-portage-dev

From: Zac Medico <zmedico@g.o>
To: gentoo-portage-dev@l.g.o
Cc: Zac Medico <zmedico@g.o>
Subject: [gentoo-portage-dev] [PATCH] Add emerge --autounmask-continue option (bug 582624)
Date: Fri, 01 Jul 2016 07:38:16
Message-Id: 1467358673-1484-1-git-send-email-zmedico@gentoo.org
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

Replies