Gentoo Archives: gentoo-portage-dev

From: Brian Dolbec <dolsen@g.o>
To: gentoo-portage-dev@l.g.o
Subject: Re: [gentoo-portage-dev] [PATCH] Add an emaint module that can scan for failed merges and that can fix failed merges.
Date: Wed, 19 Feb 2014 23:24:39
Message-Id: 20140219152008.78e5afa1@big_daddy.dol-sen.ca
In Reply to: Re: [gentoo-portage-dev] [PATCH] Add an emaint module that can scan for failed merges and that can fix failed merges. by Alec Warner
1 On Wed, 19 Feb 2014 14:32:02 -0800
2 Alec Warner <antarus@g.o> wrote:
3
4 > On Wed, Feb 19, 2014 at 12:31 PM, Pavel Kazakov <nullishzero@g.o>wrote:
5 >
6 > > ---
7 > > pym/portage/emaint/modules/merges/__init__.py | 20 ++++++++
8 > > pym/portage/emaint/modules/merges/merges.py | 70
9 > > +++++++++++++++++++++++++++
10 > > 2 files changed, 90 insertions(+)
11 > > create mode 100644 pym/portage/emaint/modules/merges/__init__.py
12 > > create mode 100644 pym/portage/emaint/modules/merges/merges.py
13 > >
14 > > diff --git a/pym/portage/emaint/modules/merges/__init__.py
15 > > b/pym/portage/emaint/modules/merges/__init__.py
16 > > new file mode 100644
17 > > index 0000000..2cd79af
18 > > --- /dev/null
19 > > +++ b/pym/portage/emaint/modules/merges/__init__.py
20 > > @@ -0,0 +1,20 @@
21 > > +# Copyright 2005-2014 Gentoo Foundation
22 > > +# Distributed under the terms of the GNU General Public License v2
23 > > +
24 > > +"""Scan for failed merges and fix them.
25 > > +"""
26 > >
27 >
28 Correct ^^
29
30 > """Scan for failed merges fix them."""
31
32 No, your grammar is wrong
33
34 >
35 >
36 > > +
37 > > +
38 > > +module_spec = {
39 > > + 'name': 'merges',
40 > > + 'description': __doc__,
41 > > + 'provides':{
42 > >
43 >
44 > 'module1' ?
45 >
46
47 It is just an identifier, not used other than to group together
48 everything for that module. The plugin system can handle multiple
49 sub-modules within the same general module directory. See the
50 emaint/modules/move/__init__.py. Move supplies 2 submodules.
51
52 The new websync sync module (emerge-webrsync replacement) we started
53 roughing in also has 2 sub-modules, the 1st will be the module that
54 runs the original bash script.
55 The 2nd will be the new python converted code to replace it.
56
57 >
58 > > + 'module1': {
59 > > + 'name': "merges",
60 > > + 'class': "MergesHandler",
61 > > + 'description': __doc__,
62 > > + 'functions': ['check', 'fix',],
63 > > + 'func_desc': {}
64 > > + }
65 > > + }
66 > > + }
67 > > diff --git a/pym/portage/emaint/modules/merges/merges.py
68 > > b/pym/portage/emaint/modules/merges/merges.py
69 > > new file mode 100644
70 > > index 0000000..b243082
71 > > --- /dev/null
72 > > +++ b/pym/portage/emaint/modules/merges/merges.py
73 > > @@ -0,0 +1,70 @@
74 > > +# Copyright 2005-2014 Gentoo Foundation
75 > > +# Distributed under the terms of the GNU General Public License v2
76 > > +
77 > > +import portage
78 > > +from portage import os
79 > > +from portage.const import PRIVATE_PATH, VDB_PATH
80 > > +from portage.util import writemsg
81 > > +
82 > > +import shutil
83 > > +import sys
84 > > +
85 > > +if sys.hexversion >= 0x3000000:
86 > > + # pylint: disable=W0622
87 > > + long = int
88 > >
89 >
90 > What is this little guy? Can we just do this in a library someplace?
91 >
92 >
93 > > +
94 > > +class MergesHandler(object):
95 > > +
96 > > + short_desc = "Remove failed merges"
97 > > +
98 > >
99 >
100 > @staticmethod decorator?
101
102 Yeah, that is copying legacy emaint code from the original module
103 classes.
104
105
106 >
107 > > + def name():
108 > > + return "merges"
109 > > + name = staticmethod(name)
110 > > +
111 > > + def __init__(self):
112 > >
113 >
114 > Generally you want to be able to change these later, so you might do
115 > something like:
116 >
117 > def __init__(self, eroot=None, vardb=None, vardb_path=None):
118 > self._eroot = error or portage.settings['EROOT']
119 > ... and so forth.
120 >
121
122 The emaint code was not setup to handle init variable assignments.
123 None of the original module classes used any. The plugin system
124 doesn't care. But the TaskHandler class in main.py would need to be
125 modified. Also, all modules must use the same method of initializing,
126 regardless whether they need it or not. In the new sync modules all
127 relevant data is passed in using kwargs, then it saves any info it
128 needs.
129
130 > Also..why can't self._vardb_path be queried from the vardb?
131 >
132 >
133 > > + self._eroot = portage.settings['EROOT']
134 > > + self._vardb = portage.db[self._eroot]["vartree"].dbapi
135 > > + self._vardb_path = os.path.join(self._eroot, VDB_PATH) +
136 > > os.path.sep
137 > > +
138 > > + def can_progressbar(self, func):
139 > > + return True
140 > > +
141 > > + def _failed_packages(self, onProgress):
142 > > + for cat in os.listdir(self._vardb_path):
143 > >
144 > os.listdir(os.path.join(...)) ?
145 >
146 > > + pkgs = os.listdir(self._vardb_path + cat)
147 > > + maxval = len(pkgs)
148 > > + for i, pkg in enumerate(pkgs):
149 > > + if onProgress:
150 > > + onProgress(maxval, i+1)
151 > > +
152 > > + if '-MERGING-' in pkg:
153 > > + yield cat + os.path.sep + pkg
154 > > +
155 > > + def check(self, **kwargs):
156 > > + onProgress = kwargs.get('onProgress', None)
157 > > + failed_pkgs = []
158 > > + for pkg in self._failed_packages(onProgress):
159 > > + failed_pkgs.append(pkg)
160 > > +
161 > > + errors = ["'%s' failed to merge." % x for x in failed_pkgs]
162 > > + return errors
163 > > +
164 > > + def fix(self, **kwargs):
165 > > + onProgress = kwargs.get('onProgress', None)
166 > > + tracking_path = os.path.join(self._eroot, PRIVATE_PATH,
167 > > 'failed-merges');
168 > > + try:
169 > > + with open(tracking_path, 'w') as tracking_file:
170 > >
171 >
172 > is this unicode safe?
173
174 you can turn on the unicode option.
175
176 >
177 >
178 > > + for failed_pkg in
179 > > self._failed_packages(onProgress):
180 > > +
181 > > tracking_file.write(failed_pkg + '\n')
182 > > + pkg_path =
183 > > self._vardb_path + failed_pkg
184 > >
185 >
186 > os.path.join(...)
187 >
188 >
189 > > + # Delete failed merge
190 > > directory
191 > > + # XXX: Would be a good
192 > > idea to attempt try removing
193 > > + # package contents to
194 > > prevent orphaned files
195 > >
196 >
197 > # XXX is terrible style. I realize a bunch of code does that, and it is
198 > stupid.
199 > # use
200 > # TODO: foo
201 >
202 >
203 >
204 >
205 > > + shutil.rmtree(pkg_path)
206 > > + # Re-emerge package
207 > >
208 > + pkg_name = '=' +
209 > > failed_pkg.replace('-MERGING-', '')
210 > > +
211 > > features='FEATURES="-collision-detect -protect-owned"'
212 > > + emerge_cmd="emerge
213 > > --verbose --oneshot --complete-graph=y"
214 > > + os.system('%s %s %s' %
215 > > (features, emerge_cmd, pkg_name))
216 > >
217 >
218 > This is a security vulnerability :)
219 >
220 > -A
221 >
222
223 Yeah, but it is the only way to actually fix a failed merge. You must
224 turn off collision protect so it can overwrite the stray files from
225 the previously failed merge. There often is not a valid CONTENTS file.
226 Plus it may not be accurate as to the files actually merged. This
227 module is for fixing pkgs that fail during the merge phase to the live
228 filesystem.
229
230
231
232
233 --
234 Brian Dolbec <dolsen>

Replies