summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bin/eapi.sh20
-rwxr-xr-xbin/ebuild.sh12
-rw-r--r--bin/phase-helpers.sh159
-rwxr-xr-xbin/portageq112
-rw-r--r--bin/save-ebuild-env.sh9
-rw-r--r--doc/package/ebuild/eapi/5-progress.docbook30
-rw-r--r--pym/_emerge/AbstractEbuildProcess.py13
-rw-r--r--pym/portage/dep/__init__.py1
-rw-r--r--pym/portage/package/ebuild/_ipc/QueryCommand.py86
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):
+ """<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
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 @@
</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>
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):
"""