EAPI="5-progress": Add master_repositories(), repository_path(),
authorArfrever Frehtes Taifersar Arahesis <Arfrever@Apache.Org>
Sat, 13 Oct 2012 23:57:06 +0000 (01:57 +0200)
committerArfrever Frehtes Taifersar Arahesis <Arfrever@Apache.Org>
Sat, 13 Oct 2012 23:57:06 +0000 (01:57 +0200)
available_eclasses(), eclass_path() and license_path() functions.

bin/eapi.sh
bin/ebuild.sh
bin/phase-helpers.sh
bin/portageq
bin/save-ebuild-env.sh
doc/package/ebuild/eapi/5-progress.docbook
pym/_emerge/AbstractEbuildProcess.py
pym/portage/dep/__init__.py
pym/portage/package/ebuild/_ipc/QueryCommand.py

index a561c1cf88877aca0bcda1e7c6cfcb5e32092aff..d21b69df7a212b32ad18fd5038a235d56a1a8a73 100644 (file)
@@ -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() {
index de54e22eb87ee2e64bca8eb2d70765ea55da7e32..b04244128e51c32ccf9d4be6b28fb61865502992 100755 (executable)
@@ -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
index 55fe9f0f6cdc25af8b3ef2cda133ece007a9ab7b..67d09a462a73980eb60b0bf22d7e4e8729d7658d 100644 (file)
@@ -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
index 97b5f3f149be2261c1c85d414f63e1c43340eea8..7b5c2cd3135fa171d213c30343afe59e88b1c7e4 100755 (executable)
@@ -730,21 +730,127 @@ def get_repos(argv):
 
 get_repos.uses_eroot = True
 
+def master_repositories(argv):
+       """<eroot> <repo_id>+
+       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):
        """<eroot> <repo_id>+
        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):
+       """<eroot> <repo_id>+
+       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):
+       """<eroot> <repo_id> <eclass>+
+       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):
+       """<eroot> <repo_id> <license>+
+       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):
        """<eroot>
        Print a list of libraries preserved during a package update in the form
index 92cc692dbc558b436e222742e6d5113681f04898..f6dc2c5e71bac33d1135c5cdb5fee5f455766c9b 100644 (file)
@@ -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_)
 
index bb0b3286a5e4940abd5fc7b2fc1b0a6408af98ac..2acda95974c0e4a9e44da138d98b8c9b9ea95972 100644 (file)
@@ -5,6 +5,36 @@
        </para>
        <section id='package-ebuild-eapi-5-progress-helpers'>
                <title>Helpers</title>
+               <section id='package-ebuild-eapi-5-progress-helpers-master-repositories'>
+                       <title>master_repositories</title>
+                       <para>
+                               New master_repositories function prints space-separated list of master repositories for specified repository.
+                       </para>
+               </section>
+               <section id='package-ebuild-eapi-5-progress-helpers-repository-path'>
+                       <title>repository_path</title>
+                       <para>
+                               New repository_path function prints path to specified repository.
+                       </para>
+               </section>
+               <section id='package-ebuild-eapi-5-progress-helpers-available-eclasses'>
+                       <title>available_eclasses</title>
+                       <para>
+                               New available_eclasses function prints space-separated list of available eclasses for current repository.
+                       </para>
+               </section>
+               <section id='package-ebuild-eapi-5-progress-helpers-eclass-path'>
+                       <title>eclass_path</title>
+                       <para>
+                               New eclass_path function prints path to specified eclass for current repository.
+                       </para>
+               </section>
+               <section id='package-ebuild-eapi-5-progress-helpers-license-path'>
+                       <title>license_path</title>
+                       <para>
+                               New license_path function prints path to specified license for current repository.
+                       </para>
+               </section>
                <section id='package-ebuild-eapi-5-progress-helpers-dohtml-extended-default-list-of-extensions'>
                        <title>Extended default list of extensions in dohtml</title>
                        <para>
index c7b8f83cab444775899d167db787ff9ecf639781..91b962f3a94b22350559e379cf4ac7417382d245 100644 (file)
@@ -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,
index b1a46b8aaf5af01c4156a2390f62a969fc649622..ddab4a30eebccf98f104eafe9e844ef2d61f840e 100644 (file)
@@ -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+.*-]*'
index c015e3a6c33911adc8a6b2ffaf1f111df8177a6e..fa8b506d79482e005949a85368f3e5b599f214f5 100644 (file)
@@ -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):
                """