Gentoo Archives: gentoo-portage-dev

From: Pavel Kazakov <nullishzero@g.o>
To: gentoo-portage-dev@l.g.o
Subject: Re: [gentoo-portage-dev] [PATCH 3/3] Add an emaint module that can scan for failed merges and that can fix failed merges.
Date: Sat, 15 Mar 2014 05:35:06
Message-Id: 5323E685.5040301@gentoo.org
In Reply to: Re: [gentoo-portage-dev] [PATCH 3/3] Add an emaint module that can scan for failed merges and that can fix failed merges. by Alec Warner
1 On 03/13/14 15:09, Alec Warner wrote:
2 >
3 >
4 >
5 > On Wed, Mar 12, 2014 at 11:10 PM, Pavel Kazakov
6 > <nullishzero@g.o <mailto:nullishzero@g.o>> wrote:
7 >
8 > ---
9 > pym/portage/emaint/main.py | 6 +-
10 >
11
12 ...
13
14 > Perhaps add an __iter__ function to TrackingFile, that implicitly
15 > calls load?
16 >
17 > Then this can be:
18 > for pkg, mtime in self._tracking_file:
19 >
20 > ?
21 >
22 > Just a thought.
23
24 That's actually a neat idea. Going to do it.
25
26 >
27 >
28 > + for pkg, mtime in self._tracking_file.load().items():
29 > + if pkg not in failed_pkgs:
30 > + failed_pkgs[pkg] = mtime
31 > + return failed_pkgs
32 > +
33 > +
34 > + def _remove_failed_dirs(self, failed_pkgs):
35 > + """
36 > + Remove the directories of packages that failed to
37 > merge.
38 > +
39 > + @param failed_pkgs: failed packages whose
40 > directories to remove
41 > + @type failed_pkg: dict
42 > + """
43 > + for failed_pkg in failed_pkgs:
44 > + pkg_path = os.path.join(self._vardb_path,
45 > failed_pkg)
46 > + # delete failed merge directory if it
47 > exists (it might not exist
48 > + # if loaded from tracking file)
49 > + if os.path.exists(pkg_path):
50 > + shutil.rmtree(pkg_path)
51 > + # TODO: try removing package contents to
52 > prevent orphaned
53 > + # files
54 >
55 >
56 > I don't get this TODO, can you elaborate?
57
58 Right now the current code deletes only the failed merge directory (e.g.
59 /var/db/pkg/app-misc/-MERGING-lsx-0.1/).
60
61 In /var/db/pkg/app-misc/-MERGING-lsx-0.1/, there should be a file called
62 CONTENTS that records the package contents (e.g. obj
63 /usr/bin/lsx-suckless 478333aa1cb7761bc8e3a400cbd976ab 1394688298).
64 However, during a failed merge, the CONTENTS file may not be there or
65 may be corrupt, so my code doesn't handle removing the contents right
66 now, only the failed merge directory.
67
68 Any suggestions for better wording?
69
70 >
71 >
72 > +
73 > +
74 > + def _get_pkg_atoms(self, failed_pkgs, pkg_atoms, pkg_dne):
75 > + """
76 > + Get the package atoms for the specified failed
77 > packages.
78 > +
79 > + @param failed_pkgs: failed packages to iterate
80 > + @type failed_pkgs: dict
81 > + @param pkg_atoms: append package atoms to this set
82 > + @type pkg_atoms: set
83 > + @param pkg_dne: append any packages atoms that are
84 > invalid to this set
85 > + @type pkg_dne: set
86 >
87 >
88 > Not following what dne means.
89
90 How about pkg_invalid_entries? And I can change the comment to '@param
91 pkg_invalid_entries: append any packages that are invalid to this set'
92
93 After looking at the function more, I think it might make sense to
94 instead return pkg_atoms and pkg_invalid_entries as a tuple, instead of
95 having the calling code pass them in.
96
97 >
98 >
99 > + """
100 > +
101 > + emerge_config = load_emerge_config()
102 > + portdb =
103 > emerge_config.target_config.trees['porttree'].dbapi
104 > + for failed_pkg in failed_pkgs:
105 > + # validate pkg name
106 > + pkg_name = '%s' %
107 > failed_pkg.replace(MERGING_IDENTIFIER, '')
108 > + pkg_atom = '=%s' % pkg_name
109 > +
110 > + if not isvalidatom(pkg_atom):
111 > + pkg_dne.append( "'%s' is an
112 > invalid package atom." % pkg_atom)
113 > + if not portdb.cpv_exists(pkg_name):
114 > + pkg_dne.append( "'%s' does not
115 > exist in the portage tree."
116 > + % pkg_name)
117 > + pkg_atoms.add(pkg_atom)
118 > +
119 > +
120 > + def _emerge_pkg_atoms(self, module_output, pkg_atoms):
121 > + """
122 > + Emerge the specified packages atoms.
123 > +
124 > + @param module_output: output will be written to
125 > + @type module_output: Class
126 > + @param pkg_atoms: packages atoms to emerge
127 > + @type pkg_atoms: set
128 > + @rtype: list
129 > + @return: List of results
130 > + """
131 > + # TODO: rewrite code to use portage's APIs instead
132 > of a subprocess
133 > + env = {
134 > + "FEATURES" : "-collision-detect
135 > -protect-owned",
136 > + "PATH" : os.environ["PATH"]
137 > + }
138 > + emerge_cmd = (
139 > + portage._python_interpreter,
140 > + '-b',
141 > + os.path.join(PORTAGE_BIN_PATH, 'emerge'),
142 > + '--quiet',
143 > + '--oneshot',
144 > + '--complete-graph=y'
145 > + )
146 > + results = []
147 > + msg = 'Re-Emerging packages that failed to merge...\n'
148 > + if module_output:
149 > + module_output.write(msg)
150 > + else:
151 > + module_output = subprocess.PIPE
152 > + results.append(msg)
153 > + proc = subprocess.Popen(emerge_cmd +
154 > tuple(pkg_atoms), env=env,
155 > + stdout=module_output, stderr=sys.stderr)
156 > + output = proc.communicate()[0]
157 >
158 >
159 > This seems sort of weird, perhaps:
160 >
161 > output, _ = proc.communicate()
162
163 I'll change it, but in fairness 'proc.communicate()[0]' is how both the
164 official python documentation and other areas of portage do it ;)
165
166 >
167 >
168 > + if output:
169 > + results.append(output)
170 > + if proc.returncode != os.EX_OK:
171 > + emerge_status = "Failed to emerge '%s'" %
172 > (' '.join(pkg_atoms))
173 > + else:
174 >
175 ...
176
177 I'll incorporate your other changes.
178
179 Regards,
180 Pavel

Replies