From: Fabian Groffen Date: Sat, 14 Feb 2009 10:57:35 +0000 (-0000) Subject: Merged from trunk -r12583:12593 X-Git-Url: http://git.tremily.us/gitweb.cgi?a=commitdiff_plain;h=5fb92c60ee1e691397309ea98b4ab738f7103015;p=portage.git Merged from trunk -r12583:12593 | 12584 | For python-3.0 compatibility, make dict-like classes modify | | zmedico | their keys(), items(), and values() methods appropriatly | | | for the current python version. | | 12585 | Inside depgraph._serialize_tasks(), simplify the logic | | zmedico | which delays selection of root nodes. | | 12586 | Make DepPriority.__str__() indicate optional deps. | | zmedico | | | 12587 | Fix digraph.clone() to properly clone priority lists. | | zmedico | | | 12588 | fix --libdir detection when econf is passed | | SpankMan | whitespace/empty arguments ... those break the plain string | | | expansion comparison | | 12589 | fix previous commit -- hasq isnt as cool as i thought and | | SpankMan | doesnt accept globs, so define a new hasg() func that does | | | and use that | | 12590 | cleanup econf() code -- use hasg* funcs in multilib code to | | SpankMan | avoid wrong/duplicate parsing methods, move all handling to | | | "$@" to avoid duplication, and make sure we prepend | | | arguments coming from the ebuild rather than append -- only | | | EXTRA_ECONF from user should override things | | 12591 | Escape globs in hasgq arguments in order to prevent bash | | zmedico | from trying to perform filename expansion. | | 12592 | Filter the new hasg and hasgq functions inside | | zmedico | save_ebuild_env(). | | 12593 | add support for .xz compressed files like .lzma | | SpankMan | | svn path=/main/branches/prefix/; revision=12607 --- diff --git a/bin/ebuild.sh b/bin/ebuild.sh index 0ce6f896e..e5df919bc 100755 --- a/bin/ebuild.sh +++ b/bin/ebuild.sh @@ -434,6 +434,14 @@ unpack() { lzma -dc "${srcdir}${x}" > ${x%.*} || die "$myfail" fi ;; + xz) + if [ "${y}" == "tar" ]; then + xz -dc "${srcdir}${x}" | tar xof - ${tar_opts} + assert "$myfail" + else + xz -dc "${srcdir}${x}" > ${x%.*} || die "$myfail" + fi + ;; *) vecho "unpack ${x}: file format not recognized. Ignoring." ;; @@ -455,17 +463,21 @@ strip_duplicate_slashes() { fi } +hasg() { + local x s=$1 + shift + for x ; do [[ ${x} == ${s} ]] && echo "${x}" && return 0 ; done + return 1 +} +hasgq() { hasg "$@" >/dev/null ; } econf() { local x - local LOCAL_EXTRA_ECONF="${EXTRA_ECONF}" ! hasq "$EAPI" 0 1 && [[ $EBUILD_PHASE = compile && \ $(type -t src_configure) = function ]] && \ eqawarn "econf called in src_compile instead of src_configure" - if [ -z "${ECONF_SOURCE}" ]; then - ECONF_SOURCE="." - fi + : ${ECONF_SOURCE:=.} if [ -x "${ECONF_SOURCE}/configure" ]; then if [ -e "${EPREFIX}"/usr/share/gnuconfig/ ]; then find "${WORKDIR}" -type f '(' \ @@ -476,64 +488,37 @@ econf() { done fi - if [ ! -z "${CBUILD}" ]; then - LOCAL_EXTRA_ECONF="--build=${CBUILD} ${LOCAL_EXTRA_ECONF}" - fi - - if [ ! -z "${CTARGET}" ]; then - LOCAL_EXTRA_ECONF="--target=${CTARGET} ${LOCAL_EXTRA_ECONF}" - fi - # if the profile defines a location to install libs to aside from default, pass it on. # if the ebuild passes in --libdir, they're responsible for the conf_libdir fun. - LIBDIR_VAR="LIBDIR_${ABI}" - if [ -n "${ABI}" -a -n "${!LIBDIR_VAR}" ]; then - CONF_LIBDIR="${!LIBDIR_VAR}" + local CONF_LIBDIR LIBDIR_VAR="LIBDIR_${ABI}" + if [[ -n ${ABI} && -n ${!LIBDIR_VAR} ]] ; then + CONF_LIBDIR=${!LIBDIR_VAR} fi - unset LIBDIR_VAR - if [ -n "${CONF_LIBDIR}" ] && [ "${*/--libdir}" == "$*" ]; then - if [ "${*/--exec-prefix}" != "$*" ]; then - local args="$(echo $*)" - local -a pref=($(echo ${args/*--exec-prefix[= ]})) - CONF_PREFIX=${pref} - [ "${CONF_PREFIX:0:1}" != "/" ] && CONF_PREFIX="/${CONF_PREFIX}" - elif [ "${*/--prefix}" != "$*" ]; then - local args="$(echo $*)" - local -a pref=($(echo ${args/*--prefix[= ]})) - CONF_PREFIX=${pref} - [ "${CONF_PREFIX:0:1}" != "/" ] && CONF_PREFIX="/${CONF_PREFIX}" - else - CONF_PREFIX="${EPREFIX}/usr" - fi - export CONF_PREFIX - [ "${CONF_LIBDIR:0:1}" != "/" ] && CONF_LIBDIR="/${CONF_LIBDIR}" - - CONF_LIBDIR_RESULT="$(strip_duplicate_slashes ${CONF_PREFIX}${CONF_LIBDIR})" - - LOCAL_EXTRA_ECONF="--libdir=${CONF_LIBDIR_RESULT} ${LOCAL_EXTRA_ECONF}" + if [[ -n ${CONF_LIBDIR} ]] && ! hasgq --libdir=\* "$@" ; then + export CONF_PREFIX=$(hasg --exec-prefix=\* "$@") + [[ -z ${CONF_PREFIX} ]] && CONF_PREFIX=$(hasg --prefix=\* "$@") + : ${CONF_PREFIX:=${EPREFIX}/usr} + CONF_PREFIX=${CONF_PREFIX#*=} + [[ ${CONF_PREFIX} != /* ]] && CONF_PREFIX="/${CONF_PREFIX}" + [[ ${CONF_LIBDIR} != /* ]] && CONF_LIBDIR="/${CONF_LIBDIR}" + set -- --libdir="$(strip_duplicate_slashes ${CONF_PREFIX}${CONF_LIBDIR})" "$@" fi - vecho "${ECONF_SOURCE}/configure" \ + set -- \ --prefix="${EPREFIX}"/usr \ + ${CBUILD:+--build=${CBUILD}} \ --host=${CHOST} \ + ${CTARGET:+--target=${CTARGET}} \ --mandir="${EPREFIX}"/usr/share/man \ --infodir="${EPREFIX}"/usr/share/info \ --datadir="${EPREFIX}"/usr/share \ --sysconfdir="${EPREFIX}"/etc \ --localstatedir="${EPREFIX}"/var/lib \ "$@" \ - ${LOCAL_EXTRA_ECONF} + ${EXTRA_ECONF} + vecho "${ECONF_SOURCE}/configure" "$@" - if ! "${ECONF_SOURCE}/configure" \ - --prefix="${EPREFIX}"/usr \ - --host=${CHOST} \ - --mandir="${EPREFIX}"/usr/share/man \ - --infodir="${EPREFIX}"/usr/share/info \ - --datadir="${EPREFIX}"/usr/share \ - --sysconfdir="${EPREFIX}"/etc \ - --localstatedir="${EPREFIX}"/var/lib \ - "$@" \ - ${LOCAL_EXTRA_ECONF}; then + if ! "${ECONF_SOURCE}/configure" "$@" ; then if [ -s config.log ]; then echo @@ -542,7 +527,7 @@ econf() { fi die "econf failed" fi - elif [ -f "${ECONF_SOURCE:-.}/configure" ]; then + elif [ -f "${ECONF_SOURCE}/configure" ]; then die "configure is not executable" else die "no configure script found" diff --git a/bin/isolated-functions.sh b/bin/isolated-functions.sh index e85e094dc..1eead1a2c 100755 --- a/bin/isolated-functions.sh +++ b/bin/isolated-functions.sh @@ -502,7 +502,8 @@ save_ebuild_env() { unset -f dump_trace die diefunc quiet_mode vecho elog_base eqawarn elog \ esyslog einfo einfon ewarn eerror ebegin _eend eend KV_major \ KV_minor KV_micro KV_to_int get_KV unset_colors set_colors has \ - hasv hasq qa_source qa_call addread addwrite adddeny addpredict \ + hasg hasgq hasv hasq qa_source qa_call \ + addread addwrite adddeny addpredict \ lchown lchgrp esyslog use usev useq has_version portageq \ best_version use_with use_enable register_die_hook check_KV \ keepdir unpack strip_duplicate_slashes econf einstall \ diff --git a/pym/_emerge/__init__.py b/pym/_emerge/__init__.py index cf34dcb00..6526194b9 100644 --- a/pym/_emerge/__init__.py +++ b/pym/_emerge/__init__.py @@ -1000,6 +1000,8 @@ class DepPriority(AbstractDepPriority): return -7 def __str__(self): + if self.optional: + return "optional" myvalue = self.__int__() if myvalue > self.MEDIUM: return "hard" @@ -6895,23 +6897,14 @@ class depgraph(object): # successfully selected. prefer_asap = True - # By default, try to avoid selecting root nodes whenever possible. This - # helps ensure that the maximimum possible number of soft dependencies - # have been removed from the graph before their parent nodes have - # selected. This is especially important when those dependencies are - # going to be rebuilt by revdep-rebuild or `emerge -e system` after the - # CHOST has been changed (like when building a stage3 from a stage2). - accept_root_node = False - - # State of prefer_asap and accept_root_node flags for successive - # iterations that loosen the criteria for node selection. + # State of variables for successive iterations that loosen the + # criteria for node selection. # - # iteration prefer_asap accept_root_node - # 1 True False - # 2 False False - # 3 False True + # iteration prefer_asap + # 1 True + # 2 False # - # If no nodes are selected on the 3rd iteration, it is due to + # If no nodes are selected on the last iteration, it is due to # unresolved blockers or circular dependencies. while not mygraph.empty(): @@ -6919,7 +6912,9 @@ class depgraph(object): selected_nodes = None ignore_priority = None if prefer_asap and asap_nodes: - """ASAP nodes are merged before their soft deps.""" + # ASAP nodes are merged before their soft deps. Go ahead and + # select root nodes here if necessary, since it's typical for + # the parent to have been removed from the graph already. asap_nodes = [node for node in asap_nodes \ if mygraph.contains(node)] for node in asap_nodes: @@ -6963,10 +6958,7 @@ class depgraph(object): # found a non-root node selected_nodes = [node] break - if not selected_nodes and \ - (accept_root_node or ignore_priority is None): - # settle for a root node - selected_nodes = [nodes[0]] + if selected_nodes: break @@ -7001,9 +6993,7 @@ class depgraph(object): for ignore_priority in xrange(DepPriority.SOFT, DepPriority.MEDIUM_SOFT + 1): for node in nodes: - if nodes is not asap_nodes and \ - not accept_root_node and \ - not mygraph.parent_nodes(node): + if not mygraph.parent_nodes(node): continue selected_nodes = set() if gather_deps(ignore_priority, @@ -7028,12 +7018,6 @@ class depgraph(object): prefer_asap = False continue - if not selected_nodes and not accept_root_node: - # Maybe there are only root nodes left, so accept them - # for the next iteration. - accept_root_node = True - continue - if selected_nodes and ignore_priority > DepPriority.SOFT: # Try to merge ignored medium deps as soon as possible. for node in selected_nodes: @@ -7214,29 +7198,37 @@ class depgraph(object): scheduler_graph.add(blocked_pkg, uninst_task, priority=BlockerDepPriority.instance) - else: - # None of the Uninstall tasks are acceptable, so - # the corresponding blockers are unresolvable. - # We need to drop an Uninstall task here in order - # to avoid the circular deps code path, but the - # blocker will still be counted as an unresolved - # conflict. - for node in myblocker_uninstalls.leaf_nodes(): - try: - mygraph.remove(node) - except KeyError: - pass - else: - uninst_task = node - ignored_uninstall_tasks.add(node) - break + # Reset the state variables for leaf node selection and + # continue trying to select leaf nodes. + prefer_asap = True + continue + + if not selected_nodes: + # Only select root nodes as a last resort. This case should + # only trigger when the graph is nearly empty and the only + # remaining nodes are isolated (no parents or children). Since + # the nodes must be isolated, ignore_priority is not needed. + selected_nodes = get_nodes() + + if not selected_nodes and not myblocker_uninstalls.is_empty(): + # If possible, drop an uninstall task here in order to avoid + # the circular deps code path. The corresponding blocker will + # still be counted as an unresolved conflict. + uninst_task = None + for node in myblocker_uninstalls.leaf_nodes(): + try: + mygraph.remove(node) + except KeyError: + pass + else: + uninst_task = node + ignored_uninstall_tasks.add(node) + break if uninst_task is not None: - # After dropping an Uninstall task, reset - # the state variables for leaf node selection and + # Reset the state variables for leaf node selection and # continue trying to select leaf nodes. prefer_asap = True - accept_root_node = False continue if not selected_nodes: @@ -7244,10 +7236,8 @@ class depgraph(object): raise self._unknown_internal_error() # At this point, we've succeeded in selecting one or more nodes, so - # it's now safe to reset the prefer_asap and accept_root_node flags - # to their default states. + # reset state variables for leaf node selection. prefer_asap = True - accept_root_node = False mygraph.difference_update(selected_nodes) diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py index 4ea435171..60fe960d5 100644 --- a/pym/portage/__init__.py +++ b/pym/portage/__init__.py @@ -562,8 +562,14 @@ class digraph(object): def clone(self): clone = digraph() clone.nodes = {} - for k, v in self.nodes.iteritems(): - clone.nodes[k] = (v[0].copy(), v[1].copy(), v[2]) + for children, parents, node in self.nodes.itervalues(): + children_clone = {} + for child, priorities in children.iteritems(): + children_clone[child] = priorities[:] + parents_clone = {} + for parent, priorities in parents.iteritems(): + parents_clone[parent] = priorities[:] + clone.nodes[node] = (children_clone, parents_clone, node) clone.order = self.order[:] return clone @@ -3002,6 +3008,10 @@ class config(object): pass return self._selinux_enabled + if sys.hexversion >= 0x3000000: + keys = __iter__ + items = iteritems + def _shell_quote(s): """ Quote a string in double-quotes and use backslashes to diff --git a/pym/portage/cache/anydbm.py b/pym/portage/cache/anydbm.py index 47b8ac1bd..9007a1a56 100644 --- a/pym/portage/cache/anydbm.py +++ b/pym/portage/cache/anydbm.py @@ -9,6 +9,7 @@ try: except ImportError: import pickle import os +import sys from portage.cache import fs_template from portage.cache import cache_errors @@ -70,3 +71,6 @@ class database(fs_template.FsBased): if "__db" in self.__dict__ and self.__db != None: self.__db.sync() self.__db.close() + + if sys.hexversion >= 0x3000000: + items = iteritems diff --git a/pym/portage/cache/mappings.py b/pym/portage/cache/mappings.py index 112301476..010eb7f8e 100644 --- a/pym/portage/cache/mappings.py +++ b/pym/portage/cache/mappings.py @@ -3,6 +3,7 @@ # License: GPL2 # $Id$ +import sys import UserDict import warnings import weakref @@ -65,6 +66,10 @@ class ProtectedDict(UserDict.DictMixin): DeprecationWarning) return key in self + if sys.hexversion >= 0x3000000: + keys = __iter__ + items = iteritems + class LazyLoad(UserDict.DictMixin): """ Lazy loading of values for a dict @@ -111,6 +116,10 @@ class LazyLoad(UserDict.DictMixin): self.pull = None return key in self.d + if sys.hexversion >= 0x3000000: + keys = __iter__ + items = iteritems + _slot_dict_classes = weakref.WeakValueDictionary() def slot_dict_class(keys, prefix="_val_"): @@ -265,6 +274,11 @@ def slot_dict_class(keys, prefix="_val_"): def __str__(self): return str(dict(self.iteritems())) + if sys.hexversion >= 0x3000000: + items = iteritems + keys = __iter__ + values = itervalues + v = SlotDict _slot_dict_classes[v.allowed_keys] = v return v diff --git a/pym/portage/cache/sql_template.py b/pym/portage/cache/sql_template.py index fe873c3ea..e5903cd67 100644 --- a/pym/portage/cache/sql_template.py +++ b/pym/portage/cache/sql_template.py @@ -3,6 +3,7 @@ # License: GPL2 # $Id$ +import sys from portage.cache import template, cache_errors from portage.cache.template import reconstruct_eclasses @@ -277,3 +278,5 @@ class SQLDatabase(template.database): return [ row[0] for row in self.con.fetchall() ] + if sys.hexversion >= 0x3000000: + items = iteritems diff --git a/pym/portage/cache/template.py b/pym/portage/cache/template.py index 238f9dc40..35b9efeff 100644 --- a/pym/portage/cache/template.py +++ b/pym/portage/cache/template.py @@ -6,6 +6,7 @@ from portage.cache import cache_errors from portage.cache.cache_errors import InvalidRestriction from portage.cache.mappings import ProtectedDict +import sys import warnings class database(object): @@ -177,6 +178,9 @@ class database(object): if cont: yield cpv + if sys.hexversion >= 0x3000000: + keys = __iter__ + items = iteritems def serialize_eclasses(eclass_dict): """takes a dict, returns a string representing said dict"""