From 58c2ef4e37fa635945e19a1650e15206d457830b Mon Sep 17 00:00:00 2001 From: Arfrever Frehtes Taifersar Arahesis Date: Sun, 14 Oct 2012 01:57:06 +0200 Subject: [PATCH] EAPI="5-progress": Add master_repositories(), repository_path(), available_eclasses(), eclass_path() and license_path() functions. --- bin/eapi.sh | 20 +++ bin/ebuild.sh | 12 +- bin/phase-helpers.sh | 159 ++++++++++++++++++ bin/portageq | 112 +++++++++++- bin/save-ebuild-env.sh | 9 +- doc/package/ebuild/eapi/5-progress.docbook | 30 ++++ pym/_emerge/AbstractEbuildProcess.py | 13 +- pym/portage/dep/__init__.py | 1 + .../package/ebuild/_ipc/QueryCommand.py | 86 +++++++--- 9 files changed, 402 insertions(+), 40 deletions(-) diff --git a/bin/eapi.sh b/bin/eapi.sh index a561c1cf8..d21b69df7 100644 --- a/bin/eapi.sh +++ b/bin/eapi.sh @@ -64,6 +64,26 @@ ___eapi_has_usex() { [[ ! ${1-${EAPI}} =~ ^(0|1|2|3|4|4-python|4-slot-abi)$ ]] } +___eapi_has_master_repositories() { + [[ ${1-${EAPI}} =~ ^(5-progress)$ ]] +} + +___eapi_has_repository_path() { + [[ ${1-${EAPI}} =~ ^(5-progress)$ ]] +} + +___eapi_has_available_eclasses() { + [[ ${1-${EAPI}} =~ ^(5-progress)$ ]] +} + +___eapi_has_eclass_path() { + [[ ${1-${EAPI}} =~ ^(5-progress)$ ]] +} + +___eapi_has_license_path() { + [[ ${1-${EAPI}} =~ ^(5-progress)$ ]] +} + # HELPERS BEHAVIOR ___eapi_best_version_and_has_version_support_--host-root() { diff --git a/bin/ebuild.sh b/bin/ebuild.sh index de54e22eb..b04244128 100755 --- a/bin/ebuild.sh +++ b/bin/ebuild.sh @@ -34,9 +34,7 @@ else # These dummy functions return false in non-strict EAPIs, in order to ensure that # `use multislot` is false for the "depend" phase. funcs="use useq usev" - if ___eapi_has_usex; then - funcs+=" usex" - fi + ___eapi_has_usex && funcs+=" usex" for x in ${funcs} ; do eval "${x}() { if ___eapi_disallows_helpers_in_global_scope; then @@ -48,7 +46,13 @@ else done # These functions die because calls to them during the "depend" phase # are considered to be severe QA violations. - for x in best_version has_version portageq ; do + funcs="best_version has_version portageq" + ___eapi_has_master_repositories && funcs+=" master_repositories" + ___eapi_has_repository_path && funcs+=" repository_path" + ___eapi_has_available_eclasses && funcs+=" available_eclasses" + ___eapi_has_eclass_path && funcs+=" eclass_path" + ___eapi_has_license_path && funcs+=" license_path" + for x in ${funcs} ; do eval "${x}() { die \"\${FUNCNAME}() calls are not allowed in global scope\"; }" done unset funcs x diff --git a/bin/phase-helpers.sh b/bin/phase-helpers.sh index 55fe9f0f6..67d09a462 100644 --- a/bin/phase-helpers.sh +++ b/bin/phase-helpers.sh @@ -736,3 +736,162 @@ best_version() { ;; esac } + +if ___eapi_has_master_repositories; then + master_repositories() { + local output repository=$1 retval + shift + [[ $# -gt 0 ]] && die "${FUNCNAME[0]}: unused argument(s): $*" + + if [[ -n ${PORTAGE_IPC_DAEMON} ]]; then + "${PORTAGE_BIN_PATH}/ebuild-ipc" master_repositories "${EROOT}" "${repository}" + else + output=$(PYTHONPATH=${PORTAGE_PYM_PATH}${PYTHONPATH:+:}${PYTHONPATH} \ + "${PORTAGE_PYTHON:-/usr/bin/python}" "${PORTAGE_BIN_PATH}/portageq" master_repositories "${EROOT}" "${repository}") + fi + retval=$? + [[ -n ${output} ]] && echo "${output}" + case "${retval}" in + 0|1) + return ${retval} + ;; + 2) + die "${FUNCNAME[0]}: invalid repository: ${repository}" + ;; + *) + if [[ -n ${PORTAGE_IPC_DAEMON} ]]; then + die "${FUNCNAME[0]}: unexpected ebuild-ipc exit code: ${retval}" + else + die "${FUNCNAME[0]}: unexpected portageq exit code: ${retval}" + fi + ;; + esac + } +fi + +if ___eapi_has_repository_path; then + repository_path() { + local output repository=$1 retval + shift + [[ $# -gt 0 ]] && die "${FUNCNAME[0]}: unused argument(s): $*" + + if [[ -n ${PORTAGE_IPC_DAEMON} ]]; then + "${PORTAGE_BIN_PATH}/ebuild-ipc" repository_path "${EROOT}" "${repository}" + else + output=$(PYTHONPATH=${PORTAGE_PYM_PATH}${PYTHONPATH:+:}${PYTHONPATH} \ + "${PORTAGE_PYTHON:-/usr/bin/python}" "${PORTAGE_BIN_PATH}/portageq" get_repo_path "${EROOT}" "${repository}") + fi + retval=$? + [[ -n ${output} ]] && echo "${output}" + case "${retval}" in + 0|1) + return ${retval} + ;; + 2) + die "${FUNCNAME[0]}: invalid repository: ${repository}" + ;; + *) + if [[ -n ${PORTAGE_IPC_DAEMON} ]]; then + die "${FUNCNAME[0]}: unexpected ebuild-ipc exit code: ${retval}" + else + die "${FUNCNAME[0]}: unexpected portageq exit code: ${retval}" + fi + ;; + esac + } +fi + +if ___eapi_has_available_eclasses; then + available_eclasses() { + local output repository=${PORTAGE_REPO_NAME} retval + [[ $# -gt 0 ]] && die "${FUNCNAME[0]}: unused argument(s): $*" + + if [[ -n ${PORTAGE_IPC_DAEMON} ]]; then + "${PORTAGE_BIN_PATH}/ebuild-ipc" available_eclasses "${EROOT}" "${repository}" + else + output=$(PYTHONPATH=${PORTAGE_PYM_PATH}${PYTHONPATH:+:}${PYTHONPATH} \ + "${PORTAGE_PYTHON:-/usr/bin/python}" "${PORTAGE_BIN_PATH}/portageq" available_eclasses "${EROOT}" "${repository}") + fi + retval=$? + [[ -n ${output} ]] && echo "${output}" + case "${retval}" in + 0|1) + return ${retval} + ;; + 2) + die "${FUNCNAME[0]}: invalid repository: ${repository}" + ;; + *) + if [[ -n ${PORTAGE_IPC_DAEMON} ]]; then + die "${FUNCNAME[0]}: unexpected ebuild-ipc exit code: ${retval}" + else + die "${FUNCNAME[0]}: unexpected portageq exit code: ${retval}" + fi + ;; + esac + } +fi + +if ___eapi_has_eclass_path; then + eclass_path() { + local eclass=$1 output repository=${PORTAGE_REPO_NAME} retval + shift + [[ $# -gt 0 ]] && die "${FUNCNAME[0]}: unused argument(s): $*" + + if [[ -n ${PORTAGE_IPC_DAEMON} ]]; then + "${PORTAGE_BIN_PATH}/ebuild-ipc" eclass_path "${EROOT}" "${repository}" "${eclass}" + else + output=$(PYTHONPATH=${PORTAGE_PYM_PATH}${PYTHONPATH:+:}${PYTHONPATH} \ + "${PORTAGE_PYTHON:-/usr/bin/python}" "${PORTAGE_BIN_PATH}/portageq" eclass_path "${EROOT}" "${repository}" "${eclass}") + fi + retval=$? + [[ -n ${output} ]] && echo "${output}" + case "${retval}" in + 0|1) + return ${retval} + ;; + 2) + die "${FUNCNAME[0]}: invalid repository: ${repository}" + ;; + *) + if [[ -n ${PORTAGE_IPC_DAEMON} ]]; then + die "${FUNCNAME[0]}: unexpected ebuild-ipc exit code: ${retval}" + else + die "${FUNCNAME[0]}: unexpected portageq exit code: ${retval}" + fi + ;; + esac + } +fi + +if ___eapi_has_license_path; then + license_path() { + local license=$1 output repository=${PORTAGE_REPO_NAME} retval + shift + [[ $# -gt 0 ]] && die "${FUNCNAME[0]}: unused argument(s): $*" + + if [[ -n ${PORTAGE_IPC_DAEMON} ]]; then + "${PORTAGE_BIN_PATH}/ebuild-ipc" license_path "${EROOT}" "${repository}" "${license}" + else + output=$(PYTHONPATH=${PORTAGE_PYM_PATH}${PYTHONPATH:+:}${PYTHONPATH} \ + "${PORTAGE_PYTHON:-/usr/bin/python}" "${PORTAGE_BIN_PATH}/portageq" license_path "${EROOT}" "${repository}" "${license}") + fi + retval=$? + [[ -n ${output} ]] && echo "${output}" + case "${retval}" in + 0|1) + return ${retval} + ;; + 2) + die "${FUNCNAME[0]}: invalid repository: ${repository}" + ;; + *) + if [[ -n ${PORTAGE_IPC_DAEMON} ]]; then + die "${FUNCNAME[0]}: unexpected ebuild-ipc exit code: ${retval}" + else + die "${FUNCNAME[0]}: unexpected portageq exit code: ${retval}" + fi + ;; + esac + } +fi diff --git a/bin/portageq b/bin/portageq index 97b5f3f14..7b5c2cd31 100755 --- a/bin/portageq +++ b/bin/portageq @@ -730,21 +730,127 @@ def get_repos(argv): get_repos.uses_eroot = True +def master_repositories(argv): + """ + + Returns space-separated list of master repositories for specified repository. + """ + if len(argv) < 2: + print("ERROR: insufficient parameters!", file=sys.stderr) + return 3 + for arg in argv[1:]: + if portage.dep._repo_name_re.match(arg) is None: + print("ERROR: invalid repository: %s" % arg, file=sys.stderr) + return 2 + try: + repo = portage.db[argv[0]]["porttree"].dbapi.repositories[arg] + except KeyError: + print("") + return 1 + else: + print(" ".join(x.name for x in repo.masters)) + +master_repositories.uses_eroot = True + def get_repo_path(argv): """ + Returns the path to the repo named argv[1], argv[0] = $EROOT """ if len(argv) < 2: - print("ERROR: insufficient parameters!") - return 2 + print("ERROR: insufficient parameters!", file=sys.stderr) + return 3 for arg in argv[1:]: + if portage.dep._repo_name_re.match(arg) is None: + print("ERROR: invalid repository: %s" % arg, file=sys.stderr) + return 2 path = portage.db[argv[0]]["porttree"].dbapi.getRepositoryPath(arg) if path is None: - path = "" + print("") + return 1 print(path) get_repo_path.uses_eroot = True +def available_eclasses(argv): + """ + + Returns space-separated list of available eclasses for specified repository. + """ + if len(argv) < 2: + print("ERROR: insufficient parameters!", file=sys.stderr) + return 3 + for arg in argv[1:]: + if portage.dep._repo_name_re.match(arg) is None: + print("ERROR: invalid repository: %s" % arg, file=sys.stderr) + return 2 + try: + repo = portage.db[argv[0]]["porttree"].dbapi.repositories[arg] + except KeyError: + print("") + return 1 + else: + print(" ".join(sorted(repo.eclass_db.eclasses))) + +available_eclasses.uses_eroot = True + +def eclass_path(argv): + """ + + Returns the path to specified eclass for specified repository. + """ + if len(argv) < 3: + print("ERROR: insufficient parameters!", file=sys.stderr) + return 3 + if portage.dep._repo_name_re.match(argv[1]) is None: + print("ERROR: invalid repository: %s" % argv[1], file=sys.stderr) + return 2 + try: + repo = portage.db[argv[0]]["porttree"].dbapi.repositories[argv[1]] + except KeyError: + print("") + return 1 + else: + retval = 0 + for arg in argv[2:]: + try: + eclass = repo.eclass_db.eclasses[arg] + except KeyError: + print("") + retval = 1 + else: + print(eclass.location) + return retval + +eclass_path.uses_eroot = True + +def license_path(argv): + """ + + Returns the path to specified license for specified repository. + """ + if len(argv) < 3: + print("ERROR: insufficient parameters!", file=sys.stderr) + return 3 + if portage.dep._repo_name_re.match(argv[1]) is None: + print("ERROR: invalid repository: %s" % argv[1], file=sys.stderr) + return 2 + try: + repo = portage.db[argv[0]]["porttree"].dbapi.repositories[argv[1]] + except KeyError: + print("") + return 1 + else: + retval = 0 + for arg in argv[2:]: + eclass_path = "" + paths = reversed([os.path.join(x.location, 'licenses', arg) for x in list(repo.masters) + [repo]]) + for path in paths: + if os.path.exists(path): + eclass_path = path + break + if eclass_path == "": + retval = 1 + print(eclass_path) + return retval + +license_path.uses_eroot = True + def list_preserved_libs(argv): """ Print a list of libraries preserved during a package update in the form diff --git a/bin/save-ebuild-env.sh b/bin/save-ebuild-env.sh index 92cc692db..f6dc2c5e7 100644 --- a/bin/save-ebuild-env.sh +++ b/bin/save-ebuild-env.sh @@ -76,9 +76,12 @@ __save_ebuild_env() { __unpack_tar __unset_colors \ ${QA_INTERCEPTORS} - if ___eapi_has_usex; then - unset -f usex - fi + ___eapi_has_usex && unset -f usex + ___eapi_has_master_repositories && unset -f master_repositories + ___eapi_has_repository_path && unset -f repository_path + ___eapi_has_available_eclasses && unset -f available_eclasses + ___eapi_has_eclass_path && unset -f eclass_path + ___eapi_has_license_path && unset -f license_path unset -f $(compgen -A function ___eapi_) diff --git a/doc/package/ebuild/eapi/5-progress.docbook b/doc/package/ebuild/eapi/5-progress.docbook index bb0b3286a..2acda9597 100644 --- a/doc/package/ebuild/eapi/5-progress.docbook +++ b/doc/package/ebuild/eapi/5-progress.docbook @@ -5,6 +5,36 @@
Helpers +
+ master_repositories + + New master_repositories function prints space-separated list of master repositories for specified repository. + +
+
+ repository_path + + New repository_path function prints path to specified repository. + +
+
+ available_eclasses + + New available_eclasses function prints space-separated list of available eclasses for current repository. + +
+
+ eclass_path + + New eclass_path function prints path to specified eclass for current repository. + +
+
+ license_path + + New license_path function prints path to specified license for current repository. + +
Extended default list of extensions in dohtml diff --git a/pym/_emerge/AbstractEbuildProcess.py b/pym/_emerge/AbstractEbuildProcess.py index c7b8f83ca..91b962f3a 100644 --- a/pym/_emerge/AbstractEbuildProcess.py +++ b/pym/_emerge/AbstractEbuildProcess.py @@ -1,4 +1,4 @@ -# Copyright 1999-2011 Gentoo Foundation +# Copyright 1999-2012 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 import io @@ -143,9 +143,14 @@ class AbstractEbuildProcess(SpawnProcess): self._exit_command.reply_hook = self._exit_command_callback query_command = QueryCommand(self.settings, self.phase) commands = { - 'best_version' : query_command, - 'exit' : self._exit_command, - 'has_version' : query_command, + 'available_eclasses' : query_command, + 'best_version' : query_command, + 'eclass_path' : query_command, + 'exit' : self._exit_command, + 'has_version' : query_command, + 'license_path' : query_command, + 'master_repositories' : query_command, + 'repository_path' : query_command, } input_fifo, output_fifo = self._init_ipc_fifos() self._ipc_daemon = EbuildIpcDaemon(commands=commands, diff --git a/pym/portage/dep/__init__.py b/pym/portage/dep/__init__.py index b1a46b8aa..ddab4a30e 100644 --- a/pym/portage/dep/__init__.py +++ b/pym/portage/dep/__init__.py @@ -55,6 +55,7 @@ _op = r'([=~]|[><]=?)' _repo_separator = "::" _repo_name = r'[\w][\w-]*' +_repo_name_re = re.compile('^' + _repo_name + '$', re.UNICODE) _repo = r'(?:' + _repo_separator + '(' + _repo_name + ')' + ')?' _extended_cat = r'[\w+*][\w+.*-]*' diff --git a/pym/portage/package/ebuild/_ipc/QueryCommand.py b/pym/portage/package/ebuild/_ipc/QueryCommand.py index c015e3a6c..fa8b506d7 100644 --- a/pym/portage/package/ebuild/_ipc/QueryCommand.py +++ b/pym/portage/package/ebuild/_ipc/QueryCommand.py @@ -6,7 +6,7 @@ import io import portage from portage import os from portage import _unicode_decode -from portage.dep import Atom +from portage.dep import Atom, _repo_name_re from portage.eapi import eapi_has_repo_deps from portage.elog import messages as elog_messages from portage.exception import InvalidAtom @@ -36,40 +36,47 @@ class QueryCommand(IpcCommand): @return: tuple of (stdout, stderr, returncode) """ - cmd, root, atom_str = argv - - eapi = self.settings.get('EAPI') - allow_repo = eapi_has_repo_deps(eapi) - try: - atom = Atom(atom_str, allow_repo=allow_repo) - except InvalidAtom: - return ('', 'invalid atom: %s\n' % atom_str, 2) + # Python 3: + # cmd, root, *args = argv + cmd = argv[0] + root = argv[1] + args = argv[2:] warnings = [] - try: - atom = Atom(atom_str, allow_repo=allow_repo, eapi=eapi) - except InvalidAtom as e: - warnings.append(_unicode_decode("QA Notice: %s: %s") % (cmd, e)) - - use = self.settings.get('PORTAGE_BUILT_USE') - if use is None: - use = self.settings['PORTAGE_USE'] - - use = frozenset(use.split()) - atom = atom.evaluate_conditionals(use) + warnings_str = '' db = self.get_db() - - warnings_str = '' - if warnings: - warnings_str = self._elog('eqawarn', warnings) + eapi = self.settings.get('EAPI') root = normalize_path(root).rstrip(os.path.sep) + os.path.sep if root not in db: - return ('', 'invalid ROOT: %s\n' % root, 3) + return ('', '%s: Invalid ROOT: %s\n' % (cmd, root), 3) + portdb = db[root]["porttree"].dbapi vardb = db[root]["vartree"].dbapi + if cmd in ('best_version', 'has_version'): + allow_repo = eapi_has_repo_deps(eapi) + try: + atom = Atom(args[0], allow_repo=allow_repo) + except InvalidAtom: + return ('', '%s: Invalid atom: %s\n' % (cmd, args[0]), 2) + + try: + atom = Atom(args[0], allow_repo=allow_repo, eapi=eapi) + except InvalidAtom as e: + warnings.append(_unicode_decode("QA Notice: %s: %s") % (cmd, e)) + + use = self.settings.get('PORTAGE_BUILT_USE') + if use is None: + use = self.settings['PORTAGE_USE'] + + use = frozenset(use.split()) + atom = atom.evaluate_conditionals(use) + + if warnings: + warnings_str = self._elog('eqawarn', warnings) + if cmd == 'has_version': if vardb.match(atom): returncode = 0 @@ -79,8 +86,35 @@ class QueryCommand(IpcCommand): elif cmd == 'best_version': m = best(vardb.match(atom)) return ('%s\n' % m, warnings_str, 0) + elif cmd in ('master_repositories', 'repository_path', 'available_eclasses', 'eclass_path', 'license_path'): + repo = _repo_name_re.match(args[0]) + if repo is None: + return ('', '%s: Invalid repository: %s\n' % (cmd, args[0]), 2) + try: + repo = portdb.repositories[args[0]] + except KeyError: + return ('', warnings_str, 1) + + if cmd == 'master_repositories': + return ('%s\n' % ' '.join(x.name for x in repo.masters), warnings_str, 0) + elif cmd == 'repository_path': + return ('%s\n' % repo.location, warnings_str, 0) + elif cmd == 'available_eclasses': + return ('%s\n' % ' '.join(sorted(repo.eclass_db.eclasses)), warnings_str, 0) + elif cmd == 'eclass_path': + try: + eclass = repo.eclass_db.eclasses[args[1]] + except KeyError: + return ('', warnings_str, 1) + return ('%s\n' % eclass.location, warnings_str, 0) + elif cmd == 'license_path': + paths = reversed([os.path.join(x.location, 'licenses', args[1]) for x in list(repo.masters) + [repo]]) + for path in paths: + if os.path.exists(path): + return ('%s\n' % path, warnings_str, 0) + return ('', warnings_str, 1) else: - return ('', 'invalid command: %s\n' % cmd, 3) + return ('', 'Invalid command: %s\n' % cmd, 3) def _elog(self, elog_funcname, lines): """ -- 2.26.2