From eb2056631021a04b62c228206e44376f5c7a81ba Mon Sep 17 00:00:00 2001 From: Arfrever Frehtes Taifersar Arahesis Date: Sat, 12 May 2012 05:58:38 +0200 Subject: [PATCH] Allow dots in package names in EAPI="4-python". --- bin/ebuild | 10 +++- doc/package/ebuild/eapi/4-python.docbook | 6 ++ pym/portage/dep/__init__.py | 71 +++++++++++++++-------- pym/portage/eapi.py | 3 + pym/portage/package/ebuild/doebuild.py | 2 +- pym/portage/versions.py | 72 ++++++++++++++++-------- 6 files changed, 113 insertions(+), 51 deletions(-) diff --git a/bin/ebuild b/bin/ebuild index 82f0ff990..35cdc1453 100755 --- a/bin/ebuild +++ b/bin/ebuild @@ -1,5 +1,5 @@ #!/usr/bin/python -O -# Copyright 1999-2011 Gentoo Foundation +# Copyright 1999-2012 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 from __future__ import print_function @@ -29,6 +29,7 @@ def debug_signal(signum, frame): signal.signal(signal.SIGUSR1, debug_signal) import imp +import io import optparse import os @@ -165,7 +166,12 @@ if not os.path.exists(ebuild): ebuild_split = ebuild.split("/") cpv = "%s/%s" % (ebuild_split[-3], pf) -if not portage.catpkgsplit(cpv): +with io.open(_unicode_encode(ebuild, encoding=_encodings['fs'], errors='strict'), + mode='r', encoding=_encodings['repo.content'], errors='replace') as f: + eapi = portage._parse_eapi_ebuild_head(f)[0] +if eapi is None: + eapi = "0" +if not portage.catpkgsplit(cpv, eapi=eapi): print("!!! %s does not follow correct package syntax." % (cpv)) sys.exit(1) diff --git a/doc/package/ebuild/eapi/4-python.docbook b/doc/package/ebuild/eapi/4-python.docbook index 99ad197ac..04457f203 100644 --- a/doc/package/ebuild/eapi/4-python.docbook +++ b/doc/package/ebuild/eapi/4-python.docbook @@ -25,6 +25,12 @@ official EAPI 4-python Specification. +
+Support for Period Characters in Package Names + +The "." character is allowed in package names. + +
Support for Period Characters in USE Flags diff --git a/pym/portage/dep/__init__.py b/pym/portage/dep/__init__.py index 0a7fc5764..6770140e2 100644 --- a/pym/portage/dep/__init__.py +++ b/pym/portage/dep/__init__.py @@ -39,7 +39,7 @@ portage.proxy.lazyimport.lazyimport(globals(), from portage import _unicode_decode from portage.eapi import eapi_has_slot_deps, eapi_has_src_uri_arrows, \ eapi_has_use_deps, eapi_has_strong_blocks, eapi_has_use_dep_defaults, \ - eapi_has_repo_deps + eapi_has_repo_deps, eapi_allows_dots_in_PN from portage.exception import InvalidAtom, InvalidData, InvalidDependString from portage.localization import _ from portage.versions import catpkgsplit, catsplit, \ @@ -1087,11 +1087,11 @@ class Atom(_atom_base): else: blocker = False self.__dict__['blocker'] = blocker - m = _atom_re.match(s) + m = _get_atom_re(eapi).match(s) extended_syntax = False if m is None: if allow_wildcard: - m = _atom_wildcard_re.match(s) + m = _get_atom_wildcard_re(eapi).match(s) if m is None: raise InvalidAtom(self) op = None @@ -1106,32 +1106,32 @@ class Atom(_atom_base): else: raise InvalidAtom(self) elif m.group('op') is not None: - base = _atom_re.groupindex['op'] + base = _get_atom_re(eapi).groupindex['op'] op = m.group(base + 1) cpv = m.group(base + 2) cp = m.group(base + 3) - slot = m.group(_atom_re.groups - 2) - repo = m.group(_atom_re.groups - 1) - use_str = m.group(_atom_re.groups) + slot = m.group(_get_atom_re(eapi).groups - 2) + repo = m.group(_get_atom_re(eapi).groups - 1) + use_str = m.group(_get_atom_re(eapi).groups) if m.group(base + 4) is not None: raise InvalidAtom(self) elif m.group('star') is not None: - base = _atom_re.groupindex['star'] + base = _get_atom_re(eapi).groupindex['star'] op = '=*' cpv = m.group(base + 1) cp = m.group(base + 2) - slot = m.group(_atom_re.groups - 2) - repo = m.group(_atom_re.groups - 1) - use_str = m.group(_atom_re.groups) + slot = m.group(_get_atom_re(eapi).groups - 2) + repo = m.group(_get_atom_re(eapi).groups - 1) + use_str = m.group(_get_atom_re(eapi).groups) if m.group(base + 3) is not None: raise InvalidAtom(self) elif m.group('simple') is not None: op = None - cpv = cp = m.group(_atom_re.groupindex['simple'] + 1) - slot = m.group(_atom_re.groups - 2) - repo = m.group(_atom_re.groups - 1) - use_str = m.group(_atom_re.groups) - if m.group(_atom_re.groupindex['simple'] + 2) is not None: + cpv = cp = m.group(_get_atom_re(eapi).groupindex['simple'] + 1) + slot = m.group(_get_atom_re(eapi).groups - 2) + repo = m.group(_get_atom_re(eapi).groups - 1) + use_str = m.group(_get_atom_re(eapi).groups) + if m.group(_get_atom_re(eapi).groupindex['simple'] + 2) is not None: raise InvalidAtom(self) else: @@ -1640,16 +1640,41 @@ _repo_separator = "::" _repo_name = r'[\w][\w-]*' _repo = r'(?:' + _repo_separator + '(' + _repo_name + ')' + ')?' -_atom_re = re.compile('^(?P(?:' + - '(?P' + _op + _cpv + ')|' + - '(?P=' + _cpv + r'\*)|' + - '(?P' + _cp + '))' + - '(' + _slot_separator + _slot + ')?' + _repo + ')(' + _use + ')?$', re.VERBOSE) +_atom_re = { + "dots_disallowed_in_PN": re.compile('^(?P(?:' + + '(?P' + _op + _cpv['dots_disallowed_in_PN'] + ')|' + + '(?P=' + _cpv['dots_disallowed_in_PN'] + r'\*)|' + + '(?P' + _cp['dots_disallowed_in_PN'] + '))' + + '(' + _slot_separator + _slot + ')?' + _repo + ')(' + _use + ')?$', re.VERBOSE), + "dots_allowed_in_PN": re.compile('^(?P(?:' + + '(?P' + _op + _cpv['dots_allowed_in_PN'] + ')|' + + '(?P=' + _cpv['dots_allowed_in_PN'] + r'\*)|' + + '(?P' + _cp['dots_allowed_in_PN'] + '))' + + '(' + _slot_separator + _slot + ')?' + _repo + ')(' + _use + ')?$', re.VERBOSE), +} + +def _get_atom_re(eapi): + if eapi is None or eapi_allows_dots_in_PN(eapi): + return _atom_re["dots_allowed_in_PN"] + else: + return _atom_re["dots_disallowed_in_PN"] _extended_cat = r'[\w+*][\w+.*-]*' -_extended_pkg = r'[\w+*][\w+*-]*?' +_extended_pkg = { + "dots_disallowed_in_PN": r'[\w+*][\w+*-]*?', + "dots_allowed_in_PN": r'[\w+*][\w+.*-]*?', +} -_atom_wildcard_re = re.compile('(?P(' + _extended_cat + ')/(' + _extended_pkg + '))(:(?P' + _slot + '))?(' + _repo_separator + '(?P' + _repo_name + '))?$') +_atom_wildcard_re = { + "dots_disallowed_in_PN": re.compile('(?P(' + _extended_cat + ')/(' + _extended_pkg['dots_disallowed_in_PN'] + '))(:(?P' + _slot + '))?(' + _repo_separator + '(?P' + _repo_name + '))?$'), + "dots_allowed_in_PN": re.compile('(?P(' + _extended_cat + ')/(' + _extended_pkg['dots_allowed_in_PN'] + '))(:(?P' + _slot + '))?(' + _repo_separator + '(?P' + _repo_name + '))?$'), +} + +def _get_atom_wildcard_re(eapi): + if eapi is None or eapi_allows_dots_in_PN(eapi): + return _atom_wildcard_re["dots_allowed_in_PN"] + else: + return _atom_wildcard_re["dots_disallowed_in_PN"] _useflag_re = { "0": re.compile(r'^[A-Za-z0-9][A-Za-z0-9+_@-]*$'), diff --git a/pym/portage/eapi.py b/pym/portage/eapi.py index c3c4f2d22..f09052dab 100644 --- a/pym/portage/eapi.py +++ b/pym/portage/eapi.py @@ -54,3 +54,6 @@ def eapi_has_use_dep_defaults(eapi): def eapi_has_repo_deps(eapi): return eapi in ("4-python",) + +def eapi_allows_dots_in_PN(eapi): + return eapi in ("4-python",) diff --git a/pym/portage/package/ebuild/doebuild.py b/pym/portage/package/ebuild/doebuild.py index faba9b696..bb2c2e02b 100644 --- a/pym/portage/package/ebuild/doebuild.py +++ b/pym/portage/package/ebuild/doebuild.py @@ -175,7 +175,7 @@ def doebuild_environment(myebuild, mydo, myroot=None, settings=None, pkg_dir = os.path.dirname(ebuild_path) mytree = os.path.dirname(os.path.dirname(pkg_dir)) mypv = os.path.basename(ebuild_path)[:-7] - mysplit = _pkgsplit(mypv) + mysplit = _pkgsplit(mypv, eapi=mysettings.configdict["pkg"].get("EAPI")) if mysplit is None: raise IncorrectParameter( _("Invalid ebuild path: '%s'") % myebuild) diff --git a/pym/portage/versions.py b/pym/portage/versions.py index f8691d1ce..6cb15667e 100644 --- a/pym/portage/versions.py +++ b/pym/portage/versions.py @@ -1,5 +1,5 @@ # versions.py -- core Portage functionality -# Copyright 1998-2010 Gentoo Foundation +# Copyright 1998-2012 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 __all__ = [ @@ -15,6 +15,7 @@ import portage portage.proxy.lazyimport.lazyimport(globals(), 'portage.util:cmp_sort_key' ) +from portage.eapi import eapi_allows_dots_in_PN from portage.localization import _ # \w is [a-zA-Z0-9_] @@ -26,15 +27,27 @@ _cat = r'[\w+][\w+.-]*' # 2.1.2 A package name may contain any of the characters [A-Za-z0-9+_-]. # It must not begin with a hyphen, # and must not end in a hyphen followed by one or more digits. -_pkg = r'[\w+][\w+-]*?' +_pkg = { + "dots_disallowed_in_PN": r'[\w+][\w+-]*?', + "dots_allowed_in_PN": r'[\w+][\w+.-]*?', +} _v = r'(cvs\.)?(\d+)((\.\d+)*)([a-z]?)((_(pre|p|beta|alpha|rc)\d*)*)' _rev = r'\d+' _vr = _v + '(-r(' + _rev + '))?' -_cp = '(' + _cat + '/' + _pkg + '(-' + _vr + ')?)' -_cpv = '(' + _cp + '-' + _vr + ')' -_pv = '(?P' + _pkg + '(?P-' + _vr + ')?)' + '-(?P' + _v + ')(-r(?P' + _rev + '))?' +_cp = { + "dots_disallowed_in_PN": '(' + _cat + '/' + _pkg['dots_disallowed_in_PN'] + '(-' + _vr + ')?)', + "dots_allowed_in_PN": '(' + _cat + '/' + _pkg['dots_allowed_in_PN'] + '(-' + _vr + ')?)', +} +_cpv = { + "dots_disallowed_in_PN": '(' + _cp['dots_disallowed_in_PN'] + '-' + _vr + ')', + "dots_allowed_in_PN": '(' + _cp['dots_allowed_in_PN'] + '-' + _vr + ')', +} +_pv = { + "dots_disallowed_in_PN": '(?P' + _pkg['dots_disallowed_in_PN'] + '(?P-' + _vr + ')?)' + '-(?P' + _v + ')(-r(?P' + _rev + '))?', + "dots_allowed_in_PN": '(?P' + _pkg['dots_allowed_in_PN'] + '(?P-' + _vr + ')?)' + '-(?P' + _v + ')(-r(?P' + _rev + '))?', +} ver_regexp = re.compile("^" + _vr + "$") suffix_regexp = re.compile("^(alpha|beta|rc|pre|p)(\\d*)$") @@ -240,16 +253,25 @@ def pkgcmp(pkg1, pkg2): return None return vercmp("-".join(pkg1[1:]), "-".join(pkg2[1:])) -_pv_re = re.compile('^' + _pv + '$', re.VERBOSE) +_pv_re = { + "dots_disallowed_in_PN": re.compile('^' + _pv['dots_disallowed_in_PN'] + '$', re.VERBOSE), + "dots_allowed_in_PN": re.compile('^' + _pv['dots_allowed_in_PN'] + '$', re.VERBOSE), +} -def _pkgsplit(mypkg): +def _get_pv_re(eapi): + if eapi is None or eapi_allows_dots_in_PN(eapi): + return _pv_re["dots_allowed_in_PN"] + else: + return _pv_re["dots_disallowed_in_PN"] + +def _pkgsplit(mypkg, eapi=None): """ @param mypkg: pv @return: 1. None if input is invalid. 2. (pn, ver, rev) if input is pv """ - m = _pv_re.match(mypkg) + m = _get_pv_re(eapi).match(mypkg) if m is None: return None @@ -267,7 +289,7 @@ def _pkgsplit(mypkg): _cat_re = re.compile('^%s$' % _cat) _missing_cat = 'null' catcache={} -def catpkgsplit(mydata,silent=1): +def catpkgsplit(mydata, silent=1, eapi=None): """ Takes a Category/Package-Version-Rev and returns a list of each. @@ -290,11 +312,11 @@ def catpkgsplit(mydata,silent=1): p_split=None if len(mysplit)==1: cat = _missing_cat - p_split = _pkgsplit(mydata) + p_split = _pkgsplit(mydata, eapi=eapi) elif len(mysplit)==2: cat = mysplit[0] if _cat_re.match(cat) is not None: - p_split = _pkgsplit(mysplit[1]) + p_split = _pkgsplit(mysplit[1], eapi=eapi) if not p_split: catcache[mydata]=None return None @@ -302,7 +324,7 @@ def catpkgsplit(mydata,silent=1): catcache[mydata]=retval return retval -def pkgsplit(mypkg, silent=1): +def pkgsplit(mypkg, silent=1, eapi=None): """ @param mypkg: either a pv or cpv @return: @@ -310,7 +332,7 @@ def pkgsplit(mypkg, silent=1): 2. (pn, ver, rev) if input is pv 3. (cp, ver, rev) if input is a cpv """ - catpsplit = catpkgsplit(mypkg) + catpsplit = catpkgsplit(mypkg, eapi=eapi) if catpsplit is None: return None cat, pn, ver, rev = catpsplit @@ -319,9 +341,9 @@ def pkgsplit(mypkg, silent=1): else: return (cat + '/' + pn, ver, rev) -def cpv_getkey(mycpv): +def cpv_getkey(mycpv, eapi=None): """Calls catpkgsplit on a cpv and returns only the cp.""" - mysplit = catpkgsplit(mycpv) + mysplit = catpkgsplit(mycpv, eapi=eapi) if mysplit is not None: return mysplit[0] + '/' + mysplit[1] @@ -330,7 +352,7 @@ def cpv_getkey(mycpv): DeprecationWarning, stacklevel=2) myslash = mycpv.split("/", 1) - mysplit = _pkgsplit(myslash[-1]) + mysplit = _pkgsplit(myslash[-1], eapi=eapi) if mysplit is None: return None mylen = len(myslash) @@ -339,14 +361,14 @@ def cpv_getkey(mycpv): else: return mysplit[0] -def cpv_getversion(mycpv): +def cpv_getversion(mycpv, eapi=None): """Returns the v (including revision) from an cpv.""" - cp = cpv_getkey(mycpv) + cp = cpv_getkey(mycpv, eapi=eapi) if cp is None: return None return mycpv[len(cp+"-"):] -def cpv_sort_key(): +def cpv_sort_key(eapi=None): """ Create an object for sorting cpvs, to be used as the 'key' parameter in places like list.sort() or sorted(). This calls catpkgsplit() once for @@ -365,14 +387,14 @@ def cpv_sort_key(): split1 = split_cache.get(cpv1, False) if split1 is False: - split1 = catpkgsplit(cpv1) + split1 = catpkgsplit(cpv1, eapi=eapi) if split1 is not None: split1 = (split1[:2], '-'.join(split1[2:])) split_cache[cpv1] = split1 split2 = split_cache.get(cpv2, False) if split2 is False: - split2 = catpkgsplit(cpv2) + split2 = catpkgsplit(cpv2, eapi=eapi) if split2 is not None: split2 = (split2[:2], '-'.join(split2[2:])) split_cache[cpv2] = split2 @@ -387,17 +409,17 @@ def cpv_sort_key(): def catsplit(mydep): return mydep.split("/", 1) -def best(mymatches): +def best(mymatches, eapi=None): """Accepts None arguments; assumes matches are valid.""" if not mymatches: return "" if len(mymatches) == 1: return mymatches[0] bestmatch = mymatches[0] - p2 = catpkgsplit(bestmatch)[1:] + p2 = catpkgsplit(bestmatch, eapi=eapi)[1:] for x in mymatches[1:]: - p1 = catpkgsplit(x)[1:] + p1 = catpkgsplit(x, eapi=eapi)[1:] if pkgcmp(p1, p2) > 0: bestmatch = x - p2 = catpkgsplit(bestmatch)[1:] + p2 = catpkgsplit(bestmatch, eapi=eapi)[1:] return bestmatch -- 2.26.2