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] Scheduler: increase visiblity of postinst failures (bug 547778)
Date: Sun, 03 May 2015 21:40:29
Message-Id: 1430689207-7235-1-git-send-email-zmedico@gentoo.org
1 This makes postinst failures behave more like "real" failures in
2 terms of output and the final emerge return code. However, in other
3 respects, these packages will be treated as successful installations.
4 This means that they will not cause emerge to immediately exit, and
5 they will not trigger recalculation of dependencies when --keep-going
6 is enabled.
7
8 X-Gentoo-Bug: 547778
9 X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=547778
10 ---
11 pym/_emerge/EbuildMerge.py | 3 ++-
12 pym/_emerge/PackageMerge.py | 9 +++++++--
13 pym/_emerge/Scheduler.py | 20 +++++++++++++++++---
14 pym/portage/const.py | 2 ++
15 pym/portage/dbapi/_MergeProcess.py | 9 ++++++++-
16 pym/portage/dbapi/vartree.py | 6 ++++++
17 6 files changed, 42 insertions(+), 7 deletions(-)
18
19 diff --git a/pym/_emerge/EbuildMerge.py b/pym/_emerge/EbuildMerge.py
20 index df0778c..07d9134 100644
21 --- a/pym/_emerge/EbuildMerge.py
22 +++ b/pym/_emerge/EbuildMerge.py
23 @@ -8,7 +8,7 @@ from portage.dbapi._MergeProcess import MergeProcess
24 class EbuildMerge(CompositeTask):
25
26 __slots__ = ("exit_hook", "find_blockers", "logger", "ldpath_mtimes",
27 - "pkg", "pkg_count", "pkg_path", "pretend",
28 + "pkg", "pkg_count", "pkg_path", "postinst_failure", "pretend",
29 "settings", "tree", "world_atom")
30
31 def _start(self):
32 @@ -39,6 +39,7 @@ class EbuildMerge(CompositeTask):
33 self.wait()
34 return
35
36 + self.postinst_failure = merge_task.postinst_failure
37 pkg = self.pkg
38 self.world_atom(pkg)
39 pkg_count = self.pkg_count
40 diff --git a/pym/_emerge/PackageMerge.py b/pym/_emerge/PackageMerge.py
41 index fa2102f..1e7b58b 100644
42 --- a/pym/_emerge/PackageMerge.py
43 +++ b/pym/_emerge/PackageMerge.py
44 @@ -5,7 +5,7 @@ from _emerge.CompositeTask import CompositeTask
45 from portage.dep import _repo_separator
46 from portage.output import colorize
47 class PackageMerge(CompositeTask):
48 - __slots__ = ("merge",)
49 + __slots__ = ("merge", "postinst_failure")
50
51 def _start(self):
52
53 @@ -41,4 +41,9 @@ class PackageMerge(CompositeTask):
54 self.merge.statusMessage(msg)
55
56 task = self.merge.create_install_task()
57 - self._start_task(task, self._default_final_exit)
58 + self._start_task(task, self._install_exit)
59 +
60 + def _install_exit(self, task):
61 + self.postinst_failure = getattr(task, 'postinst_failure', None)
62 + self._final_exit(task)
63 + self.wait()
64 diff --git a/pym/_emerge/Scheduler.py b/pym/_emerge/Scheduler.py
65 index 6b39e3b..13abc92 100644
66 --- a/pym/_emerge/Scheduler.py
67 +++ b/pym/_emerge/Scheduler.py
68 @@ -115,7 +115,8 @@ class Scheduler(PollScheduler):
69 emergelog(self.xterm_titles, *pargs, **kwargs)
70
71 class _failed_pkg(SlotObject):
72 - __slots__ = ("build_dir", "build_log", "pkg", "returncode")
73 + __slots__ = ("build_dir", "build_log", "pkg",
74 + "postinst_failure", "returncode")
75
76 class _ConfigPool(object):
77 """Interface for a task to temporarily allocate a config
78 @@ -1155,10 +1156,10 @@ class Scheduler(PollScheduler):
79 if len(self._failed_pkgs_all) > 1:
80 msg = "The following %d packages have " % \
81 len(self._failed_pkgs_all) + \
82 - "failed to build or install:"
83 + "failed to build, install, or execute postinst:"
84 else:
85 msg = "The following package has " + \
86 - "failed to build or install:"
87 + "failed to build, install, or execute postinst:"
88
89 printer.eerror("")
90 for line in textwrap.wrap(msg, 72):
91 @@ -1168,6 +1169,8 @@ class Scheduler(PollScheduler):
92 # Use unicode_literals to force unicode format string so
93 # that Package.__unicode__() is called in python2.
94 msg = " %s" % (failed_pkg.pkg,)
95 + if failed_pkg.postinst_failure:
96 + msg += " (postinst failed)"
97 log_path = self._locate_failure_log(failed_pkg)
98 if log_path is not None:
99 msg += ", Log file:"
100 @@ -1289,6 +1292,17 @@ class Scheduler(PollScheduler):
101 self._status_display.failed = len(self._failed_pkgs)
102 return
103
104 + if merge.postinst_failure:
105 + # Append directly to _failed_pkgs_all for non-critical errors.
106 + self._failed_pkgs_all.append(self._failed_pkg(
107 + build_dir=merge.merge.settings.get("PORTAGE_BUILDDIR"),
108 + build_log=merge.merge.settings.get("PORTAGE_LOG_FILE"),
109 + pkg=pkg,
110 + postinst_failure=True,
111 + returncode=merge.returncode))
112 + self._failed_pkg_msg(self._failed_pkgs_all[-1],
113 + "execute postinst for", "for")
114 +
115 self._task_complete(pkg)
116 pkg_to_replace = merge.merge.pkg_to_replace
117 if pkg_to_replace is not None:
118 diff --git a/pym/portage/const.py b/pym/portage/const.py
119 index c7ecda2..6c1201d 100644
120 --- a/pym/portage/const.py
121 +++ b/pym/portage/const.py
122 @@ -277,6 +277,8 @@ TIMESTAMP_FORMAT = "%a, %d %b %Y %H:%M:%S +0000" # to be used with time.gmtime()
123 # Top-level names of Python packages installed by Portage.
124 PORTAGE_PYM_PACKAGES = ("_emerge", "portage", "repoman")
125
126 +RETURNCODE_POSTINST_FAILURE = 5
127 +
128 # ===========================================================================
129 # END OF CONSTANTS -- END OF CONSTANTS -- END OF CONSTANTS -- END OF CONSTANT
130 # ===========================================================================
131 diff --git a/pym/portage/dbapi/_MergeProcess.py b/pym/portage/dbapi/_MergeProcess.py
132 index 956dbb9..35591af 100644
133 --- a/pym/portage/dbapi/_MergeProcess.py
134 +++ b/pym/portage/dbapi/_MergeProcess.py
135 @@ -23,7 +23,8 @@ class MergeProcess(ForkProcess):
136
137 __slots__ = ('mycat', 'mypkg', 'settings', 'treetype',
138 'vartree', 'blockers', 'pkgloc', 'infloc', 'myebuild',
139 - 'mydbapi', 'prev_mtimes', 'unmerge', '_elog_reader_fd', '_elog_reg_id',
140 + 'mydbapi', 'postinst_failure', 'prev_mtimes', 'unmerge',
141 + '_elog_reader_fd', '_elog_reg_id',
142 '_buf', '_elog_keys', '_locked_vdb')
143
144 def _start(self):
145 @@ -250,6 +251,12 @@ class MergeProcess(ForkProcess):
146 # in order to avoid a race condition.
147 os._exit(1)
148
149 + def _set_returncode(self, wait_retval):
150 + ForkProcess._set_returncode(self, wait_retval)
151 + if self.returncode == portage.const.RETURNCODE_POSTINST_FAILURE:
152 + self.postinst_failure = True
153 + self.returncode = os.EX_OK
154 +
155 def _unregister(self):
156 """
157 Unregister from the scheduler and close open files.
158 diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py
159 index fca84d1..a2fb325 100644
160 --- a/pym/portage/dbapi/vartree.py
161 +++ b/pym/portage/dbapi/vartree.py
162 @@ -1577,6 +1577,7 @@ class dblink(object):
163 self._hash_key = (self._eroot, self.mycpv)
164 self._protect_obj = None
165 self._pipe = pipe
166 + self._postinst_failure = False
167
168 # When necessary, this attribute is modified for
169 # compliance with RESTRICT=preserve-libs.
170 @@ -4376,6 +4377,7 @@ class dblink(object):
171 if a != os.EX_OK:
172 # It's stupid to bail out here, so keep going regardless of
173 # phase return code.
174 + self._postinst_failure = True
175 self._elog("eerror", "postinst", [
176 _("FAILED postinst: %s") % (a,),
177 ])
178 @@ -5042,6 +5044,10 @@ class dblink(object):
179 self.vartree.dbapi._bump_mtime(self.mycpv)
180 if not parallel_install:
181 self.unlockdb()
182 +
183 + if retval == os.EX_OK and self._postinst_failure:
184 + retval = portage.const.RETURNCODE_POSTINST_FAILURE
185 +
186 return retval
187
188 def getstring(self,name):
189 --
190 2.3.5

Replies