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 |
> |