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 22:54:53
Message-Id: 20140219145022.1b74722b@big_daddy.dol-sen.ca
In Reply to: [gentoo-portage-dev] [PATCH] Add an emaint module that can scan for failed merges and that can fix failed merges. by Pavel Kazakov
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>

Replies