Gentoo Archives: gentoo-portage-dev

From: Alec Warner <antarus@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:37:42
Message-Id: CAAr7Pr9EV+cPs5A5zj+SX3gW5CwTOVXh9sszD-86njMKTFairg@mail.gmail.com
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 Brian Dolbec
1 On Wed, Feb 19, 2014 at 2:50 PM, Brian Dolbec <dolsen@g.o> wrote:
2
3 > On Wed, 19 Feb 2014 12:31:44 -0800
4 > 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 > > +module_spec = {
29 > > + 'name': 'merges',
30 > > + 'description': __doc__,
31 > > + 'provides':{
32 > > + 'module1': {
33 > > + 'name': "merges",
34 > > + 'class': "MergesHandler",
35 > > + 'description': __doc__,
36 > > + 'functions': ['check', 'fix',],
37 > > + 'func_desc': {}
38 > > + }
39 > > + }
40 > > + }
41 > > diff --git a/pym/portage/emaint/modules/merges/merges.py
42 > b/pym/portage/emaint/modules/merges/merges.py
43 > > new file mode 100644
44 > > index 0000000..b243082
45 > > --- /dev/null
46 > > +++ b/pym/portage/emaint/modules/merges/merges.py
47 > > @@ -0,0 +1,70 @@
48 > > +# Copyright 2005-2014 Gentoo Foundation
49 > > +# Distributed under the terms of the GNU General Public License v2
50 > > +
51 > > +import portage
52 > > +from portage import os
53 > > +from portage.const import PRIVATE_PATH, VDB_PATH
54 > > +from portage.util import writemsg
55 > > +
56 > > +import shutil
57 > > +import sys
58 > > +
59 > > +if sys.hexversion >= 0x3000000:
60 > > + # pylint: disable=W0622
61 > > + long = int
62 > > +
63 > > +class MergesHandler(object):
64 > > +
65 > > + short_desc = "Remove failed merges"
66 > > +
67 > > + def name():
68 > > + return "merges"
69 > > + name = staticmethod(name)
70 > > +
71 > > + def __init__(self):
72 > > + self._eroot = portage.settings['EROOT']
73 > > + self._vardb = portage.db[self._eroot]["vartree"].dbapi
74 > > + self._vardb_path = os.path.join(self._eroot, VDB_PATH) +
75 > os.path.sep
76 > > +
77 > > + def can_progressbar(self, func):
78 > > + return True
79 > > +
80 > > + def _failed_packages(self, onProgress):
81 > > + for cat in os.listdir(self._vardb_path):
82 > > + pkgs = os.listdir(self._vardb_path + cat)
83 > > + maxval = len(pkgs)
84 > > + for i, pkg in enumerate(pkgs):
85 > > + if onProgress:
86 > > + onProgress(maxval, i+1)
87 > > +
88 > > + if '-MERGING-' in pkg:
89 > > + yield cat + os.path.sep + pkg
90 > > +
91 > > + def check(self, **kwargs):
92 > > + onProgress = kwargs.get('onProgress', None)
93 > > + failed_pkgs = []
94 > > + for pkg in self._failed_packages(onProgress):
95 > > + failed_pkgs.append(pkg)
96 > > +
97 > > + errors = ["'%s' failed to merge." % x for x in failed_pkgs]
98 > > + return errors
99 > > +
100 > > + def fix(self, **kwargs):
101 > > + onProgress = kwargs.get('onProgress', None)
102 > > + tracking_path = os.path.join(self._eroot, PRIVATE_PATH,
103 > 'failed-merges');
104 > > + try:
105 > > + with open(tracking_path, 'w') as tracking_file:
106 > > + for failed_pkg in
107 > self._failed_packages(onProgress):
108 > > +
109 > tracking_file.write(failed_pkg + '\n')
110 > > + pkg_path =
111 > self._vardb_path + failed_pkg
112 > > + # Delete failed merge
113 > directory
114 > > + # XXX: Would be a good
115 > idea to attempt try removing
116 > > + # package contents to
117 > prevent orphaned files
118 > > + shutil.rmtree(pkg_path)
119 > > + # Re-emerge package
120 > > + pkg_name = '=' +
121 > failed_pkg.replace('-MERGING-', '')
122 > > +
123 > features='FEATURES="-collision-detect -protect-owned"'
124 > > + emerge_cmd="emerge
125 > --verbose --oneshot --complete-graph=y"
126 > > + os.system('%s %s %s' %
127 > (features, emerge_cmd, pkg_name))
128 > > + except Exception as ex:
129 > > + writemsg('Unable to fix failed package: %s' %
130 > str(ex))
131 >
132 >
133 > Really
134 > ? don't use os.system() It is nearly obsolete. use subprocess.call()
135 > or Popen(). call() is a direct sub. Use Popen for piping output...
136 >
137
138 os.system() invokes /bin/sh, so the first problem is you have a quoting
139 problem.
140 The second problem is that you are root, and you just told it to execute
141 'emerge' and not '/usr/bin/emerge' and so it might execute some other
142 emerge.
143
144 The third problem is that the input is not sanitized, and badly named files
145 can cause code execution.
146
147 /var/db/pkg/app-shells/hahaha;rm -rf;-MERGING-
148
149 might call
150 os.system('FEATURES="-collision-detect -protect-owned" emerge --verbose
151 --oneshot --complete-graph=y =app-shells/hahaha-1.0-r1;rm -rf')
152
153 And so forth.
154
155
156 >
157 > Also, it would be better to call emerge with all pkgs in one command.
158 > I know it will rarely be more than 1, maybe 2 but, emerge is slow
159 > enough just intitializing.
160 >
161 > You might also want to turn off the progressbar for fix unless you
162 > intend to pipe emerge's output and hide it. I might be inclined to
163 > just run emerge in minimum output mode. It will display what it is
164 > doing and any more failed builds/merges. I know I had the other
165 > modules output the data without displaying and let the cli handle any
166 > display. We should be able to do similar to the progressbar, and
167 > connect the emerge stdout pipe to a display code. That way any other
168 > frontend could do with the output what they like.
169 >
170 >
171 > --
172 > Brian Dolbec <dolsen>
173 >
174 >
175 >