1 |
On Wed, 19 Feb 2014 12:31:44 -0800 |
2 |
Pavel Kazakov <nullishzero@g.o> wrote: |
3 |
|
4 |
> --- |
5 |
> pym/portage/emaint/modules/merges/__init__.py | 20 ++++++++ |
6 |
> pym/portage/emaint/modules/merges/merges.py | 70 +++++++++++++++++++++++++++ |
7 |
> 2 files changed, 90 insertions(+) |
8 |
> create mode 100644 pym/portage/emaint/modules/merges/__init__.py |
9 |
> create mode 100644 pym/portage/emaint/modules/merges/merges.py |
10 |
> |
11 |
> diff --git a/pym/portage/emaint/modules/merges/__init__.py b/pym/portage/emaint/modules/merges/__init__.py |
12 |
> new file mode 100644 |
13 |
> index 0000000..2cd79af |
14 |
> --- /dev/null |
15 |
> +++ b/pym/portage/emaint/modules/merges/__init__.py |
16 |
> @@ -0,0 +1,20 @@ |
17 |
> +# Copyright 2005-2014 Gentoo Foundation |
18 |
> +# Distributed under the terms of the GNU General Public License v2 |
19 |
> + |
20 |
> +"""Scan for failed merges and fix them. |
21 |
> +""" |
22 |
> + |
23 |
> + |
24 |
> +module_spec = { |
25 |
> + 'name': 'merges', |
26 |
> + 'description': __doc__, |
27 |
> + 'provides':{ |
28 |
> + 'module1': { |
29 |
> + 'name': "merges", |
30 |
> + 'class': "MergesHandler", |
31 |
> + 'description': __doc__, |
32 |
> + 'functions': ['check', 'fix',], |
33 |
> + 'func_desc': {} |
34 |
> + } |
35 |
> + } |
36 |
> + } |
37 |
> diff --git a/pym/portage/emaint/modules/merges/merges.py b/pym/portage/emaint/modules/merges/merges.py |
38 |
> new file mode 100644 |
39 |
> index 0000000..b243082 |
40 |
> --- /dev/null |
41 |
> +++ b/pym/portage/emaint/modules/merges/merges.py |
42 |
> @@ -0,0 +1,70 @@ |
43 |
> +# Copyright 2005-2014 Gentoo Foundation |
44 |
> +# Distributed under the terms of the GNU General Public License v2 |
45 |
> + |
46 |
> +import portage |
47 |
> +from portage import os |
48 |
> +from portage.const import PRIVATE_PATH, VDB_PATH |
49 |
> +from portage.util import writemsg |
50 |
> + |
51 |
> +import shutil |
52 |
> +import sys |
53 |
> + |
54 |
> +if sys.hexversion >= 0x3000000: |
55 |
> + # pylint: disable=W0622 |
56 |
> + long = int |
57 |
> + |
58 |
> +class MergesHandler(object): |
59 |
> + |
60 |
> + short_desc = "Remove failed merges" |
61 |
> + |
62 |
> + def name(): |
63 |
> + return "merges" |
64 |
> + name = staticmethod(name) |
65 |
> + |
66 |
> + def __init__(self): |
67 |
> + self._eroot = portage.settings['EROOT'] |
68 |
> + self._vardb = portage.db[self._eroot]["vartree"].dbapi |
69 |
> + self._vardb_path = os.path.join(self._eroot, VDB_PATH) + os.path.sep |
70 |
> + |
71 |
> + def can_progressbar(self, func): |
72 |
> + return True |
73 |
> + |
74 |
> + def _failed_packages(self, onProgress): |
75 |
> + for cat in os.listdir(self._vardb_path): |
76 |
> + pkgs = os.listdir(self._vardb_path + cat) |
77 |
> + maxval = len(pkgs) |
78 |
> + for i, pkg in enumerate(pkgs): |
79 |
> + if onProgress: |
80 |
> + onProgress(maxval, i+1) |
81 |
> + |
82 |
> + if '-MERGING-' in pkg: |
83 |
> + yield cat + os.path.sep + pkg |
84 |
> + |
85 |
> + def check(self, **kwargs): |
86 |
> + onProgress = kwargs.get('onProgress', None) |
87 |
> + failed_pkgs = [] |
88 |
> + for pkg in self._failed_packages(onProgress): |
89 |
> + failed_pkgs.append(pkg) |
90 |
> + |
91 |
> + errors = ["'%s' failed to merge." % x for x in failed_pkgs] |
92 |
> + return errors |
93 |
> + |
94 |
> + def fix(self, **kwargs): |
95 |
> + onProgress = kwargs.get('onProgress', None) |
96 |
> + tracking_path = os.path.join(self._eroot, PRIVATE_PATH, 'failed-merges'); |
97 |
> + try: |
98 |
> + with open(tracking_path, 'w') as tracking_file: |
99 |
> + for failed_pkg in self._failed_packages(onProgress): |
100 |
> + tracking_file.write(failed_pkg + '\n') |
101 |
> + pkg_path = self._vardb_path + failed_pkg |
102 |
> + # Delete failed merge directory |
103 |
> + # XXX: Would be a good idea to attempt try removing |
104 |
> + # package contents to prevent orphaned files |
105 |
> + shutil.rmtree(pkg_path) |
106 |
> + # Re-emerge package |
107 |
> + pkg_name = '=' + failed_pkg.replace('-MERGING-', '') |
108 |
> + features='FEATURES="-collision-detect -protect-owned"' |
109 |
> + emerge_cmd="emerge --verbose --oneshot --complete-graph=y" |
110 |
> + os.system('%s %s %s' % (features, emerge_cmd, pkg_name)) |
111 |
> + except Exception as ex: |
112 |
> + writemsg('Unable to fix failed package: %s' % str(ex)) |
113 |
|
114 |
|
115 |
Really |
116 |
? don't use os.system() It is nearly obsolete. use subprocess.call() |
117 |
or Popen(). call() is a direct sub. Use Popen for piping output... |
118 |
|
119 |
Also, it would be better to call emerge with all pkgs in one command. |
120 |
I know it will rarely be more than 1, maybe 2 but, emerge is slow |
121 |
enough just intitializing. |
122 |
|
123 |
You might also want to turn off the progressbar for fix unless you |
124 |
intend to pipe emerge's output and hide it. I might be inclined to |
125 |
just run emerge in minimum output mode. It will display what it is |
126 |
doing and any more failed builds/merges. I know I had the other |
127 |
modules output the data without displaying and let the cli handle any |
128 |
display. We should be able to do similar to the progressbar, and |
129 |
connect the emerge stdout pipe to a display code. That way any other |
130 |
frontend could do with the output what they like. |
131 |
|
132 |
|
133 |
-- |
134 |
Brian Dolbec <dolsen> |