Gentoo Archives: gentoo-commits

From: Arfrever Frehtes Taifersar Arahesis <arfrever.fta@×××××.com>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage:master commit in: pym/portage/package/ebuild/, pym/portage/package/ebuild/_config/, pym/portage/, ...
Date: Sat, 24 Nov 2012 12:29:51
Message-Id: 1353760124.44f2b8f9603964abe230cfe8ef75831a82855da5.arfrever@gentoo
1 commit: 44f2b8f9603964abe230cfe8ef75831a82855da5
2 Author: Arfrever Frehtes Taifersar Arahesis <Arfrever <AT> Apache <DOT> Org>
3 AuthorDate: Sat Nov 24 12:28:44 2012 +0000
4 Commit: Arfrever Frehtes Taifersar Arahesis <arfrever.fta <AT> gmail <DOT> com>
5 CommitDate: Sat Nov 24 12:28:44 2012 +0000
6 URL: http://git.overlays.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=44f2b8f9
7
8 EAPI="5-progress": Add automatic unpack dependencies.
9
10 ---
11 doc/package/ebuild/eapi/5-progress.docbook | 30 +++++++++
12 pym/_emerge/EbuildMetadataPhase.py | 9 +++
13 pym/portage/__init__.py | 1 +
14 pym/portage/dep/__init__.py | 45 ++++++++++++++
15 pym/portage/eapi.py | 3 +
16 .../package/ebuild/_config/unpack_dependencies.py | 38 +++++++++++
17 pym/portage/package/ebuild/config.py | 3 +
18 pym/portage/tests/resolver/ResolverPlayground.py | 7 ++-
19 .../tests/resolver/test_unpack_dependencies.py | 65 ++++++++++++++++++++
20 9 files changed, 199 insertions(+), 2 deletions(-)
21
22 diff --git a/doc/package/ebuild/eapi/5-progress.docbook b/doc/package/ebuild/eapi/5-progress.docbook
23 index 3346464..93ce6dc 100644
24 --- a/doc/package/ebuild/eapi/5-progress.docbook
25 +++ b/doc/package/ebuild/eapi/5-progress.docbook
26 @@ -121,6 +121,36 @@
27 </tgroup>
28 </table>
29 </section>
30 + <section id='package-ebuild-eapi-5-progress-metadata-automatic-unpack-dependencies'>
31 + <title>Automatic Unpack Dependencies</title>
32 + <para>
33 + Dependencies on packages required to unpack archives specified in SRC_URI are automatically appended to DEPEND. These dependencies are calculated from filename extensions of archives specified in SRC_URI. Dependencies (for ebuilds using given EAPI) corresponding to given filename extensions are configured in ${repository_path}/profiles/unpack_dependencies/${EAPI} files.
34 + </para>
35 + <table><title>Unpack Dependencies Configuration Examples</title>
36 + <tgroup cols='1' align='left'>
37 + <tbody>
38 + <row>
39 + <entry>bz2 app-arch/bzip2</entry>
40 + </row>
41 + <row>
42 + <entry>gz app-arch/gzip</entry>
43 + </row>
44 + <row>
45 + <entry>tar app-arch/tar</entry>
46 + </row>
47 + <row>
48 + <entry>tar.bz2 app-arch/tar app-arch/bzip2</entry>
49 + </row>
50 + <row>
51 + <entry>tar.gz app-arch/tar app-arch/gzip</entry>
52 + </row>
53 + <row>
54 + <entry>zip app-arch/unzip</entry>
55 + </row>
56 + </tbody>
57 + </tgroup>
58 + </table>
59 + </section>
60 </section>
61 <section id='package-ebuild-eapi-5-progress-globstar'>
62 <title>globstar shell option enabled by default</title>
63
64 diff --git a/pym/_emerge/EbuildMetadataPhase.py b/pym/_emerge/EbuildMetadataPhase.py
65 index a6c515a..f351b16 100644
66 --- a/pym/_emerge/EbuildMetadataPhase.py
67 +++ b/pym/_emerge/EbuildMetadataPhase.py
68 @@ -12,6 +12,8 @@ from portage import os
69 from portage import _encodings
70 from portage import _unicode_decode
71 from portage import _unicode_encode
72 +from portage.dep import extract_unpack_dependencies
73 +from portage.eapi import eapi_has_automatic_unpack_dependencies
74
75 import errno
76 import fcntl
77 @@ -180,6 +182,13 @@ class EbuildMetadataPhase(SubProcess):
78 metadata["_eclasses_"] = {}
79 metadata.pop("INHERITED", None)
80
81 + if eapi_has_automatic_unpack_dependencies(metadata["EAPI"]):
82 + repo = self.portdb.repositories.get_name_for_location(self.repo_path)
83 + unpackers = self.settings.unpack_dependencies.get(repo, {}).get(metadata["EAPI"], {})
84 + unpack_dependencies = extract_unpack_dependencies(metadata["SRC_URI"], unpackers)
85 + if unpack_dependencies:
86 + metadata["DEPEND"] += (" " if metadata["DEPEND"] else "") + unpack_dependencies
87 +
88 # If called by egencache, this cache write is
89 # undesirable when metadata-transfer is disabled.
90 if self.write_auxdb is not False:
91
92 diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py
93 index 08d9e5d..3e634b5 100644
94 --- a/pym/portage/__init__.py
95 +++ b/pym/portage/__init__.py
96 @@ -427,6 +427,7 @@ _doebuild_manifest_exempt_depend = 0
97
98 _testing_eapis = frozenset(["4-python", "4-slot-abi", "5-progress", "5-hdepend"])
99 _deprecated_eapis = frozenset(["4_pre1", "3_pre2", "3_pre1", "5_pre1", "5_pre2"])
100 +_supported_eapis = frozenset([str(x) for x in range(portage.const.EAPI)] + list(_testing_eapis) + list(_deprecated_eapis))
101
102 def _eapi_is_deprecated(eapi):
103 return eapi in _deprecated_eapis
104
105 diff --git a/pym/portage/dep/__init__.py b/pym/portage/dep/__init__.py
106 index 60d1cc9..e2aa00d 100644
107 --- a/pym/portage/dep/__init__.py
108 +++ b/pym/portage/dep/__init__.py
109 @@ -2764,3 +2764,48 @@ def extract_affecting_use(mystr, atom, eapi=None):
110 _("malformed syntax: '%s'") % mystr)
111
112 return affecting_use
113 +
114 +def extract_unpack_dependencies(src_uri, unpackers):
115 + """
116 + Return unpack dependencies string for given SRC_URI string.
117 +
118 + @param src_uri: SRC_URI string
119 + @type src_uri: String
120 + @param unpackers: Dictionary mapping archive suffixes to dependency strings
121 + @type unpackers: Dictionary
122 + @rtype: String
123 + @return: Dependency string specifying packages required to unpack archives.
124 + """
125 + src_uri = src_uri.split()
126 +
127 + depend = []
128 + for i in range(len(src_uri)):
129 + if src_uri[i][-1] == "?" or src_uri[i] in ("(", ")"):
130 + depend.append(src_uri[i])
131 + elif (i+1 < len(src_uri) and src_uri[i+1] == "->") or src_uri[i] == "->":
132 + continue
133 + else:
134 + for suffix in sorted(unpackers, key=lambda x: len(x), reverse=True):
135 + suffix = suffix.lower()
136 + if src_uri[i].lower().endswith(suffix):
137 + depend.append(unpackers[suffix])
138 + break
139 +
140 + while True:
141 + cleaned_depend = depend[:]
142 + for i in range(len(cleaned_depend)):
143 + if cleaned_depend[i] is None:
144 + continue
145 + elif cleaned_depend[i] == "(" and cleaned_depend[i+1] == ")":
146 + cleaned_depend[i] = None
147 + cleaned_depend[i+1] = None
148 + elif cleaned_depend[i][-1] == "?" and cleaned_depend[i+1] == "(" and cleaned_depend[i+2] == ")":
149 + cleaned_depend[i] = None
150 + cleaned_depend[i+1] = None
151 + cleaned_depend[i+2] = None
152 + if depend == cleaned_depend:
153 + break
154 + else:
155 + depend = [x for x in cleaned_depend if x is not None]
156 +
157 + return " ".join(depend)
158
159 diff --git a/pym/portage/eapi.py b/pym/portage/eapi.py
160 index bc1240c..4f77910 100644
161 --- a/pym/portage/eapi.py
162 +++ b/pym/portage/eapi.py
163 @@ -86,6 +86,9 @@ def eapi_allows_directories_on_profile_level_and_repository_level(eapi):
164 def eapi_has_use_aliases(eapi):
165 return eapi in ("4-python", "5-progress")
166
167 +def eapi_has_automatic_unpack_dependencies(eapi):
168 + return eapi in ("5-progress",)
169 +
170 def eapi_has_hdepend(eapi):
171 return eapi in ("5-hdepend",)
172
173
174 diff --git a/pym/portage/package/ebuild/_config/unpack_dependencies.py b/pym/portage/package/ebuild/_config/unpack_dependencies.py
175 new file mode 100644
176 index 0000000..1375189
177 --- /dev/null
178 +++ b/pym/portage/package/ebuild/_config/unpack_dependencies.py
179 @@ -0,0 +1,38 @@
180 +# Copyright 2012 Gentoo Foundation
181 +# Distributed under the terms of the GNU General Public License v2
182 +
183 +from portage import os, _supported_eapis
184 +from portage.dep import use_reduce
185 +from portage.eapi import eapi_has_automatic_unpack_dependencies
186 +from portage.exception import InvalidDependString
187 +from portage.localization import _
188 +from portage.util import grabfile, writemsg
189 +
190 +def load_unpack_dependencies_configuration(repositories):
191 + repo_dict = {}
192 + for repo in repositories.repos_with_profiles():
193 + for eapi in _supported_eapis:
194 + if eapi_has_automatic_unpack_dependencies(eapi):
195 + file_name = os.path.join(repo.location, "profiles", "unpack_dependencies", eapi)
196 + lines = grabfile(file_name, recursive=True)
197 + for line in lines:
198 + elements = line.split()
199 + suffix = elements[0].lower()
200 + if len(elements) == 1:
201 + writemsg(_("--- Missing unpack dependencies for '%s' suffix in '%s'\n") % (suffix, file_name))
202 + depend = " ".join(elements[1:])
203 + try:
204 + use_reduce(depend, eapi=eapi)
205 + except InvalidDependString as e:
206 + writemsg(_("--- Invalid unpack dependencies for '%s' suffix in '%s': '%s'\n" % (suffix, file_name, e)))
207 + else:
208 + repo_dict.setdefault(repo.name, {}).setdefault(eapi, {})[suffix] = depend
209 +
210 + ret = {}
211 + for repo in repositories.repos_with_profiles():
212 + for repo_name in [x.name for x in repo.masters] + [repo.name]:
213 + for eapi in repo_dict.get(repo_name, {}):
214 + for suffix, depend in repo_dict.get(repo_name, {}).get(eapi, {}).items():
215 + ret.setdefault(repo.name, {}).setdefault(eapi, {})[suffix] = depend
216 +
217 + return ret
218
219 diff --git a/pym/portage/package/ebuild/config.py b/pym/portage/package/ebuild/config.py
220 index 45a3351..86eac8a 100644
221 --- a/pym/portage/package/ebuild/config.py
222 +++ b/pym/portage/package/ebuild/config.py
223 @@ -56,6 +56,7 @@ from portage.package.ebuild._config.LocationsManager import LocationsManager
224 from portage.package.ebuild._config.MaskManager import MaskManager
225 from portage.package.ebuild._config.VirtualsManager import VirtualsManager
226 from portage.package.ebuild._config.helper import ordered_by_atom_specificity, prune_incremental
227 +from portage.package.ebuild._config.unpack_dependencies import load_unpack_dependencies_configuration
228
229 if sys.hexversion >= 0x3000000:
230 basestring = str
231 @@ -237,6 +238,7 @@ class config(object):
232 self.profiles = clone.profiles
233 self.packages = clone.packages
234 self.repositories = clone.repositories
235 + self.unpack_dependencies = clone.unpack_dependencies
236 self._iuse_effective = clone._iuse_effective
237 self._iuse_implicit_match = clone._iuse_implicit_match
238 self._non_user_variables = clone._non_user_variables
239 @@ -489,6 +491,7 @@ class config(object):
240 x = Atom(x.lstrip('*'))
241 self.prevmaskdict.setdefault(x.cp, []).append(x)
242
243 + self.unpack_dependencies = load_unpack_dependencies_configuration(self.repositories)
244
245 mygcfg = {}
246 if self.profiles:
247
248 diff --git a/pym/portage/tests/resolver/ResolverPlayground.py b/pym/portage/tests/resolver/ResolverPlayground.py
249 index 9b30edb..f81e046 100644
250 --- a/pym/portage/tests/resolver/ResolverPlayground.py
251 +++ b/pym/portage/tests/resolver/ResolverPlayground.py
252 @@ -2,6 +2,7 @@
253 # Distributed under the terms of the GNU General Public License v2
254
255 from itertools import permutations
256 +import fnmatch
257 import sys
258 import tempfile
259 import portage
260 @@ -37,7 +38,7 @@ class ResolverPlayground(object):
261 config_files = frozenset(("eapi", "layout.conf", "make.conf", "package.accept_keywords",
262 "package.keywords", "package.license", "package.mask", "package.properties",
263 "package.unmask", "package.use", "package.use.aliases", "package.use.stable.mask",
264 - "use.aliases", "use.force", "use.mask", "layout.conf"))
265 + "unpack_dependencies", "use.aliases", "use.force", "use.mask", "layout.conf"))
266
267 metadata_xml_template = """<?xml version="1.0" encoding="UTF-8"?>
268 <!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
269 @@ -282,13 +283,15 @@ class ResolverPlayground(object):
270 repo_config = repo_configs.get(repo)
271 if repo_config:
272 for config_file, lines in repo_config.items():
273 - if config_file not in self.config_files:
274 + if config_file not in self.config_files and not any(fnmatch.fnmatch(config_file, os.path.join(x, "*")) for x in self.config_files):
275 raise ValueError("Unknown config file: '%s'" % config_file)
276
277 if config_file in ("layout.conf",):
278 file_name = os.path.join(repo_dir, "metadata", config_file)
279 else:
280 file_name = os.path.join(profile_dir, config_file)
281 + if "/" in config_file and not os.path.isdir(os.path.dirname(file_name)):
282 + os.makedirs(os.path.dirname(file_name))
283 f = open(file_name, "w")
284 for line in lines:
285 f.write("%s\n" % line)
286
287 diff --git a/pym/portage/tests/resolver/test_unpack_dependencies.py b/pym/portage/tests/resolver/test_unpack_dependencies.py
288 new file mode 100644
289 index 0000000..cfceff4
290 --- /dev/null
291 +++ b/pym/portage/tests/resolver/test_unpack_dependencies.py
292 @@ -0,0 +1,65 @@
293 +# Copyright 2012 Gentoo Foundation
294 +# Distributed under the terms of the GNU General Public License v2
295 +
296 +from portage.tests import TestCase
297 +from portage.tests.resolver.ResolverPlayground import ResolverPlayground, ResolverPlaygroundTestCase
298 +
299 +class UnpackDependenciesTestCase(TestCase):
300 + def testUnpackDependencies(self):
301 + distfiles = {
302 + "A-1.tar.gz": b"binary\0content",
303 + "B-1.TAR.XZ": b"binary\0content",
304 + "B-docs-1.tar.bz2": b"binary\0content",
305 + "C-1.TAR.XZ": b"binary\0content",
306 + "C-docs-1.tar.bz2": b"binary\0content",
307 + }
308 +
309 + ebuilds = {
310 + "dev-libs/A-1": {"SRC_URI": "A-1.tar.gz", "EAPI": "5-progress"},
311 + "dev-libs/B-1": {"IUSE": "doc", "SRC_URI": "B-1.TAR.XZ doc? ( B-docs-1.tar.bz2 )", "EAPI": "5-progress"},
312 + "dev-libs/C-1": {"IUSE": "doc", "SRC_URI": "C-1.TAR.XZ doc? ( C-docs-1.tar.bz2 )", "EAPI": "5-progress"},
313 + "app-arch/bzip2-1": {},
314 + "app-arch/gzip-1": {},
315 + "app-arch/tar-1": {},
316 + "app-arch/xz-utils-1": {},
317 + }
318 +
319 + repo_configs = {
320 + "test_repo": {
321 + "unpack_dependencies/5-progress": (
322 + "tar.bz2 app-arch/tar app-arch/bzip2",
323 + "tar.gz app-arch/tar app-arch/gzip",
324 + "tar.xz app-arch/tar app-arch/xz-utils",
325 + ),
326 + },
327 + }
328 +
329 + test_cases = (
330 + ResolverPlaygroundTestCase(
331 + ["dev-libs/A"],
332 + success = True,
333 + ignore_mergelist_order = True,
334 + mergelist = ["app-arch/tar-1", "app-arch/gzip-1", "dev-libs/A-1"]),
335 + ResolverPlaygroundTestCase(
336 + ["dev-libs/B"],
337 + success = True,
338 + ignore_mergelist_order = True,
339 + mergelist = ["app-arch/tar-1", "app-arch/xz-utils-1", "dev-libs/B-1"]),
340 + ResolverPlaygroundTestCase(
341 + ["dev-libs/C"],
342 + success = True,
343 + ignore_mergelist_order = True,
344 + mergelist = ["app-arch/tar-1", "app-arch/xz-utils-1", "app-arch/bzip2-1", "dev-libs/C-1"]),
345 + )
346 +
347 + user_config = {
348 + "package.use": ("dev-libs/C doc",)
349 + }
350 +
351 + playground = ResolverPlayground(distfiles=distfiles, ebuilds=ebuilds, repo_configs=repo_configs, user_config=user_config)
352 + try:
353 + for test_case in test_cases:
354 + playground.run_TestCase(test_case)
355 + self.assertEqual(test_case.test_success, True, test_case.fail_msg)
356 + finally:
357 + playground.cleanup()