From: Paul Varner Date: Wed, 29 Dec 2010 00:30:14 +0000 (-0600) Subject: Merge branch 'gentoolkit' into euse X-Git-Tag: gentoolkit-0.3.0~42^2~2 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=879cf3ce1f3041854c9dc886b59ac7e136ae9b9b;p=gentoolkit.git Merge branch 'gentoolkit' into euse Conflicts: bin/euse --- 879cf3ce1f3041854c9dc886b59ac7e136ae9b9b diff --cc bin/euse index fc9d60f,297d4f6..c54135f --- a/bin/euse +++ 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" + [ ! -r "${MAKE_GLOBALS_PATH}" ] && fatal "${MAKE_GLOBALS_PATH} is not readable" - [ ! -h "${MAKE_PROFILE_PATH}" ] && fatal "${MAKE_PROFILE_PATH} is not a symlink" + [ -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" + - [ ! -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" 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}" @@@ -254,139 -207,36 +288,146 @@@ 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 + # Bug 181309, emerge may complain if EMERGE_DEFAULT_OPTS="--ask" is set - ACTIVE_FLAGS[9]="$(emerge --ignore-default-opts --info | grep 'USE=' | cut -b 5- | sed -e 's:"::g')" #' + ACTIVE_FLAGS[9]="$(portageq envvar USE)" #' - 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) + _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.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 + } -# get all make.defaults by traversing the cascaded profile directories -get_all_make_defaults() { +# 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 @@@ -700,49 -341,37 +743,49 @@@ [ "${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 #####