Merge branch 'gentoolkit' into euse
authorPaul Varner <fuzzyray@gentoo.org>
Wed, 29 Dec 2010 00:30:14 +0000 (18:30 -0600)
committerPaul Varner <fuzzyray@gentoo.org>
Wed, 29 Dec 2010 00:30:14 +0000 (18:30 -0600)
Conflicts:
bin/euse

1  2 
bin/euse

diff --cc bin/euse
index fc9d60f047b28dc864b2bd0e9cf232d3709faa89,297d4f6b1b310e55c8e9f31cca6eb4cbbbae059d..c54135fe4cba9f0878d5b78475f14cc6246a88ad
+++ b/bin/euse
@@@ -7,13 -7,44 +7,53 @@@
  # Licensed under the GPL v2
  
  PROGRAM_NAME=euse
- PROGRAM_VERSION=$(cat /usr/share/gentoolkit/VERSION)
+ VERSION="svn"
  
- MAKE_CONF_PATH=/etc/make.conf
- MAKE_GLOBALS_PATH=/etc/make.globals
- MAKE_PROFILE_PATH=/etc/make.profile
- MAKE_CONF_BACKUP_PATH=/etc/make.conf.euse_backup
- PACKAGE_USE_PATH=/etc/portage/package.use
+ EPREFIX=${EPREFIX:-$(portageq envvar EPREFIX)}
+ ETC="${EPREFIX}/etc"
+ USR_SHARE_PORTAGE="${EPREFIX}/usr/share/portage"
 -# define error function so it can be used immediately
 -error() {
 -      echo "ERROR: ${1}"
++# define error functions so they can be used immediately
++fatal() {
++      echo -e "ERROR: ${*}"
+       set +f
+       exit 1
+ }
++error() {
++      echo -e "ERROR: ${*}"
++}
++
++warn() {
++      echo -e "WARNING: ${*}"
++}
++
+ # /etc/make.conf can now exist in /etc/portage/make.conf, prefer it over /etc/make.conf for changes
+ if [ -e "${ETC}/portage/make.conf" ]; then
+       MAKE_CONF_PATH="${ETC}/portage/make.conf"
+ elif [ -e "${ETC}/make.conf" ]; then
+       MAKE_CONF_PATH="${ETC}/make.conf"
+ else
 -      error "make.conf does not exist"
++      fatal "make.conf does not exist"
+ fi
+ MAKE_CONF_BACKUP_PATH="${MAKE_CONF_PATH}.euse_backup"
+ # /etc/make.globals has been moved to /usr/share/portage/config/make.globals
+ if [ -e "${USR_SHARE_PORTAGE}/config/make.globals" ]; then
+       MAKE_GLOBALS_PATH="${USR_SHARE_PORTAGE}/config/make.globals"
+ else
+       MAKE_GLOBALS_PATH="${ETC}/make.globals"
+ fi
+ # /etc/make.profile or /etc/portage/make.profile, if /etc/make.profile exists, it will be used
+ if [ -e "${ETC}/make.profile" ]; then
+       MAKE_PROFILE_PATH="${ETC}/make.profile"
+ elif [ -e "${ETC}/portage/make.profile" ]; then
+       MAKE_PROFILE_PATH="${ETC}/portage/make.profile"
+ else
 -      error "make.profile does not exist"
++      fatal "make.profile does not exist"
+ fi
++PACKAGE_USE_PATH=${ETC}/portage/package.use
  
  [ -z "${MODE}" ] && MODE="showhelp"           # available operation modes: showhelp, showversion, showdesc, showflags, modify
  
@@@ -79,22 -93,27 +105,28 @@@ check_sanity() 
        # file permission tests
        local descdir
        local make_defaults
-       
+       local make_conf
+       [[ ! -d "${MAKE_PROFILE_PATH}" || ! -r "${MAKE_PROFILE_PATH}" ]] && error "${MAKE_PROFILE_PATH} is not readable"
+       # 
+       for make_conf in $(get_all_make_conf); do
 -              [ ! -r "${make_conf}" ] && error "${make_conf} is not readable"
++              [ ! -r "${make_conf}" ] && fatal "${make_conf} is not readable"
+       done
        descdir="$(get_portdir)/profiles"
-       [ ! -r "${MAKE_CONF_PATH}" ] && fatal "${MAKE_CONF_PATH} is not readable"
 +      
-       [ ! -h "${MAKE_PROFILE_PATH}" ] && fatal "${MAKE_PROFILE_PATH} is not a symlink"
 +      [ ! -r "${MAKE_GLOBALS_PATH}" ] && fatal "${MAKE_GLOBALS_PATH} is not readable"
 -      [ ! -r "${MAKE_GLOBALS_PATH}" ] && error "${MAKE_GLOBALS_PATH} is not readable"
 -      [ -z "$(get_portdir)" ] && error "\$PORTDIR couldn't be determined"
 -      [ ! -d "${descdir}" ] && error "${descdir} does not exist or is not a directory"
 -      [ ! -r "${descdir}/use.desc" ] && error "${descdir}/use.desc is not readable"
 -      [ ! -r "${descdir}/use.local.desc" ] && error "${descdir}/use.local.desc is not readable"
 +      [ -z "$(get_portdir)" ] && fatal "\$PORTDIR couldn't be determined"
 +      [ ! -d "${descdir}" ] && fatal "${descdir} does not exist or is not a directory"
 +      [ ! -r "${descdir}/use.desc" ] && fatal "${descdir}/use.desc is not readable"
 +      [ ! -r "${descdir}/use.local.desc" ] && fatal "${descdir}/use.local.desc is not readable"
        for make_defaults in $(get_all_make_defaults); do
 -              [ ! -r "$make_defaults" ]  && error "$_make_defaults is not readable"
 +              [ ! -r "$make_defaults" ]  && fatal "$_make_defaults is not readable"
        done
 -#     [ ! -r "$(get_make_defaults)" ] && error "$(get_make_defaults) is not readable"
 -      [ "${MODE}" == "modify" -a ! -w "${MAKE_CONF_PATH}" ] && error ""${MAKE_CONF_PATH}" is not writable"
 -}
 +      [ "${MODE}" == "modify" -a ! -w "${MAKE_CONF_PATH}" ] && fatal ""${MAKE_CONF_PATH}" is not writable"
 +      [ "${MODE}" == "modify" -a -s "${PACKAGE_USE_PATH}" -a ! -w "${PACKAGE_USE_PATH}" ] && fatal ""${PACKAGE_USE_PATH}" is not writable"
 +} # }}}
  
  showhelp() {
  cat << HELP
@@@ -235,11 -187,13 +267,13 @@@ get_useflags() 
  
        # backup portdir so get_portdir() doesn't give false results later
        portdir_backup="${PORTDIR}"
 -
 +      
        ACTIVE_FLAGS[0]="$(reduce_incrementals ${USE})"
        USE=""
-       source "${MAKE_CONF_PATH}"
-       ACTIVE_FLAGS[1]="$(reduce_incrementals ${USE})"
+       for x in $(get_all_make_conf); do
+               source "${x}"
+               ACTIVE_FLAGS[1]="$(reduce_incrementals ${ACTIVE_FLAGS[1]} ${USE})"
+       done
        USE=""
        for x in $(get_all_make_defaults); do
                source "${x}"
        USE="${ACTIVE_FLAGS[0]}"
        PORTDIR="${portdir_backup}"
  
 +      #
 +      # Traverse through use.mask and use.force (0.5s)
 +      # Flip signs of use.mask (it's interpreted oppositely), 
 +      ACTIVE_FLAGS[6]=$(reduce_incrementals_trump \
 +              $(cat $(traverse_profile "use.mask") | sed -re "/^#.*$/{d}") \
 +                      | sed -re "s/(^| )-[^ ]*//g" -e "s/(^| )([a-z0-9])/ -\2/g")
 +      ACTIVE_FLAGS[7]=$(reduce_incrementals \
 +              $(cat $(traverse_profile "use.force") \
 +                      | sed -re "/^#.*$/ {d}"))
 +
 +      USE_FLAGS_CALCULATED=1
 +} # }}}
 +
 +# Function: get_portageuseflags # {{{
 +# Fetch USE flags reported active by Portage
 +get_portageuseflags() {
 +      # only calculate once as calling emerge is painfully slow
 +      [ -n "${_PORTAGE_USE_FLAGS_CALCULATED}" ] && return
        # get the currently active USE flags as seen by portage, this has to be after
        # restoring USE or portage won't see the original environment
-       ACTIVE_FLAGS[9]="$(emerge --ignore-default-opts --info | grep 'USE=' | cut -b 5- | sed -e 's:"::g')" #'
 +      # Bug 181309, emerge may complain if EMERGE_DEFAULT_OPTS="--ask" is set
 -      USE_FLAGS_CALCULATED=1
 -}
 -
 -# get the list of all known USE flags by reading use.desc and/or use.local.desc
 -# (depending on the value of $SCOPE)
+       ACTIVE_FLAGS[9]="$(portageq envvar USE)" #'
 +      _PORTAGE_USE_FLAGS_CALCULATED=1
 +} # }}}
 +
 +# Function: get_useflaglist {{{
 +# Get the list of all known USE flags by reading use.desc and/or 
 +# use.local.desc (depending on the value of $SCOPE). Also searches any 
 +# registered overlays after searching the main portage tree first.
 +# Use flags visible in both the main tree and overlays are trumped by
 +# the main tree. Overlays are indicated by brackets [xxx] at the 
 +# beginning of the description. 
 +#
 +# Returns:
 +# (written to stdout) Sorted, unique list of system-wide USE flags and
 +# descriptions. Flags defined in overlays have the overlay in brackets
 +# prepended to the descriptions.
 +#
 +# Environment:
 +# SCOPE - [local|global] constrain search to local (use.local.desc) or
 +#               global (use.desc)
  get_useflaglist() {
        local descdir
 -
 -      descdir="$(get_portdir)/profiles"
 -
 -      if [ -z "${SCOPE}" -o "${SCOPE}" == "global" ]; then
 -              egrep "^[^# ]+ +-" "${descdir}/use.desc" | cut -d\  -f 1
 -      fi
 -      if [ -z "${SCOPE}" -o "${SCOPE}" == "local" ]; then
 -              egrep "^[^# :]+:[^ ]+ +-" "${descdir}/use.local.desc" | cut -d: -f 2 | cut -d\  -f 1
 +      local overlay
 +      for profiledir in ${ALL_PORTDIRS[@]}; do
 +              descdir="${profiledir}/profiles"
 +              if [[ -z ${SCOPE} || ${SCOPE} == "global" ]]; then
 +                      [[ ! -s "${descdir}/use.desc" ]] && continue
 +                      egrep "^[^# ]+ +-" "${descdir}/use.desc" 
 +              fi
 +              if [[ -z ${SCOPE} || ${SCOPE} == "local" ]]; then
 +                      [[ ! -s "${descdir}/use.local.desc" ]] && continue
 +                      egrep "^[^# :]+:[^ ]+ +-" "${descdir}/use.local.desc" \
 +                              | cut -d: -f 2 
 +              fi
 +      done | cut -d " "  -f1 | sort --field=":" --key=1,1 --unique
 +} # }}}
 +
 +# Function: get_useflaglist_ebuild {{{
 +# Builds USE flag information for specified package atom into 
 +# ACTIVE_FLAGS[5]. For the atom, the versions available are found, and 
 +# for each, the corresponding SLOT, IUSE are stored along with which 
 +# overlay the ebuild lives in. Considering that the pieces of information 
 +# may be required in any order or any subsets, it is intended for the 
 +# function to cache the information and it be retrieved from 
 +# ACTIVE_FLAGS[5]. So the format of ACTIVE_FLAGS[5] is newline-separated 
 +# list of:
 +#
 +# category/packge;version;SLOT;IUSE;overlay
 +#
 +# Arguments:
 +# $1 - Package atom to lookup (app-editor/vim)
 +#
 +# Returns:
 +# Nothing significant
 +#
 +# Environment:
 +# PORTDIR - Root of portage tree
 +# ACTIVE_FLAGS - Array of current use flag info
 +#
 +get_useflaglist_ebuild() {
 +      local known=$(echo "${ACTIVE_FLAGS[5]}" | egrep "^${1}")
 +      if [[ -n $known ]]; then
 +              # No need to recache
 +              return
        fi
 -}
 +      local pkg=$(echo ${1} | cut -d/ -f2)
 +      declare append
 +      for portdir in ${ALL_PORTDIRS[@]}; do
 +              # Open the ebuild file and retrieve defined USE flags
 +              [[ ! -d "$portdir/${1}" ]] && continue
 +              append=$(echo -n $portdir/${1}/*.ebuild "" \
 +                      | perl -pne "s:$portdir/${1}/${pkg}-(([^.]|\.(?!e))+)\.ebuild:\1:g" \
 +                      | while read -d " " version; do
 +                              IFS=$'\n'
 +                              if [[ $portdir == $PORTDIR ]]; then 
 +                                      overlay=""
 +                              else
 +                                      if [[ -s $(dirname ${portdir}/repo_name) ]]; then
 +                                              overlay="$(cat "${portdir}/profiles/repo_name")"
 +                                      else
 +                                              # XXX: May be better to use full path
 +                                              overlay="$(basename "${portdir}")"
 +                                      fi
 +                              fi
 +                              if [[ ! -d "$portdir/metadata/cache" ]]; then
 +                                      echo "!!! Metadata cache not found. You need to run " >&2
 +                                      echo "!!! 'egencache --repo=$overlay --update'" >&2
 +                                      echo "!!! to generate metadata for your overlays" >&2
 +                                      return 1
 +                              elif [[ ! -e "$portdir/metadata/cache/${1}-$version" ]]; then
 +                                      # Repo does not have this particular package
 +                                      continue
 +                              fi
 +                              iuse=$(head -11 "$portdir/metadata/cache/${1}-$version"|tail -1)
 +                              slot=$(head -3 "$portdir/metadata/cache/${1}-$version"|tail -1)
 +                              echo "${1};${version};${slot};${iuse};${overlay}"
 +                      done
 +              )
 +              if [[ -z ${ACTIVE_FLAGS[5]} ]]; then ACTIVE_FLAGS[5]="$append"
 +              else ACTIVE_FLAGS[5]="${ACTIVE_FLAGS[5]}"$'\n'"$append"
 +              fi
 +      done
 +} # }}}
  
 -# get all make.defaults by traversing the cascaded profile directories
 -get_all_make_defaults() {
+ # get all make.conf files that exist on the system
+ get_all_make_conf() {
+       # At least one of the files exists or we would not have made it this far
+       for x in ${ETC}/make.conf ${ETC}/portage/make.conf; do
+               [ -e "${x}" ] && echo "${x}"
+       done
+ }
 +# Function: traverse_profile {{{
 +# General method of collecting the contents of a profile
 +# component by traversing through the cascading profile
 +#
 +# Arguments:
 +# $1 - Filename (make.profile)
 +# [$2] - Current directory (unspecified means to start at the top)
 +traverse_profile() {
        local curdir
        local parent
        local rvalue
@@@ -684,10 -326,9 +727,10 @@@ showdesc() 
        local current_desc
        local found_one
        local args
 -
 +      
 +      set -f
        args="${*:-*}"
-       
        if [ -z "${SCOPE}" ]; then
                SCOPE="global" showdesc ${args}
                echo
        [ "${SCOPE}" == "global" ] && echo "global use flags (searching: ${args})"
        [ "${SCOPE}" == "local" ] && echo "local use flags (searching: ${args})"
        echo "************************************************************"
 -
 +      set +f
        if [ "${args}" == "*" ]; then
 -              args="$(get_useflaglist | sort -u)"
 +              args="${useflags[*]}"
        fi
-       
        set ${args}
  
        foundone=0
 -      while [ -n "${1}" ]; do
 -              if [ "${SCOPE}" == "global" ]; then
 -                      if grep "^${1}  *-" "${descdir}/use.desc" > /dev/null; then
 +      while [[ -n "${1}" ]]; do
 +              if [[ "${SCOPE}" == "global" ]]; then
 +                      if array_contains "${useflags[*]}" "$1"; then
                                get_flagstatus "${1}"
 +                              # XXX: Handle overlay
 +                              grep "^${1}  *-" ${ALL_PORTDIRS[@]/%//profiles/use.desc} 2> /dev/null \
 +                                      | sed -re "s/^([^:]+)://"
                                foundone=1
                        fi
 -                      grep "^${1}  *-" "${descdir}/use.desc"
                fi
-               # local flags are a bit more complicated as there can be multiple 
+               # local flags are a bit more complicated as there can be multiple
                # entries per flag and we can't pipe into printf
 -              if [ "${SCOPE}" == "local" ]; then
 -                      if grep ":${1}  *-" "${descdir}/use.local.desc" > /dev/null; then
 +              if [[ "${SCOPE}" == "local" ]]; then
 +                      if array_contains "${useflags[*]}" "$1"; then
                                foundone=1
                        fi
 -                      grep ":${1}  *-" "${descdir}/use.local.desc" \
 -                              | sed -e "s/^\([^:]\+\):\(${1}\) *- *\(.\+\)/\1|\2|\3/g" \
 -                              | while read line; do
 -                                      pkg="$(echo $line | cut -d\| -f 1)"
 -                                      flag="$(echo $line | cut -d\| -f 2)"
 -                                      desc="$(echo $line | cut -d\| -f 3)"
 -                                      get_flagstatus "${flag}"
 -                                      printf "%s (%s):\n%s\n\n" "${flag}" "${pkg}" "${desc}"
 -                              done
 +                      # Fetch all the packages data using this flag
 +                      infos=$( grep ":${1}  *-" ${ALL_PORTDIRS[@]/%//profiles/use.local.desc} 2> /dev/null \
 +                              | sed -re "s/^([^:]+):([^:]+):(${1}) *- *(.+)/\1|\2|\3|\4/g")
 +                      OIFS=$IFS; IFS=$'\n'; infos=($infos); IFS=$OIFS;
 +                      for line in "${infos[@]}"; do
 +                              OIFS=$IFS; IFS="|"; line=($line); IFS=$OIFS
 +                              pkg=${line[1]} 
 +                              flag=${line[2]}
 +                              desc=${line[3]}
 +                              if get_flagstatus "${flag}"; then
 +                                      ACTIVE="+"
 +                              else
 +                                      ACTIVE="-"
 +                              fi
 +                              printf "%s\n" "${flag}"
 +                              printf "%s: %s\n" "${pkg}" "${desc}" \
 +                                      | fold --width=$((${COLUMNS:-80}-10)) -s | sed -e "s/^/    /g"
 +                              get_flagstatus_pkg "${flag}" "${pkg}" "${ACTIVE}"
 +                      done
                fi
                shift
        done
@@@ -853,10 -466,9 +896,10 @@@ showflags() 
        if [ "${args}" == "*" ]; then
                args="$(get_useflaglist | sort -u)"
        fi
-       
        set ${args}
 -
 +      get_portageuseflags
 +      
        while [ -n "${1}" ]; do
                if echo " ${ACTIVE_FLAGS[9]} " | grep " ${1} " > /dev/null; then
                        printf "%-20s" ${1}
@@@ -1226,9 -578,9 +1269,9 @@@ modify() 
                echo -ne "${NEW_MAKE_CONF_USE_2%% }"
                echo '"'
        fi ) < "${MAKE_CONF_BACKUP_PATH}" | sed -e 's:\\ $:\\:' > "${MAKE_CONF_PATH}"
-       
        echo "${MAKE_CONF_PATH} was modified, a backup copy has been placed at ${MAKE_CONF_BACKUP_PATH}"
 -}
 +} # }}}
  
  ##### main program comes now #####