# -*-eselect-*- vim: ft=eselect # Copyright 1999-2011 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 or later # $Id: profile.eselect 810 2011-03-13 12:22:08Z ulm $ # This is a portage-only module. inherit package-manager DESCRIPTION="Manage the make.profile symlink" MAINTAINER="eselect@gentoo.org" SVN_DATE='$Date: 2011-07-07 20:03:44 +0200 (Thu, 07 Jul 2011) $' VERSION=$(svn_date_to_version "${SVN_DATE}") DEFAULT_REPO="gentoo" # get location of make.profile symlink get_symlink_location() { local oldloc=${EROOT%/}/etc/make.profile local newloc=${EROOT%/}/etc/portage/make.profile if [[ -e ${oldloc} ]]; then MAKE_PROFILE=${oldloc} if [[ -e ${newloc} ]]; then write_warning_msg "Both ${oldloc} and ${newloc} exist." write_warning_msg "Using ${MAKE_PROFILE} for now." fi else MAKE_PROFILE=${newloc} fi } # get list of repositories get_repos() { # sort: DEFAULT_REPO first, then alphabetical order portageq get_repos "${ROOT:-/}" \ | sed "s/[[:space:]]\+/\n/g;s/\b${DEFAULT_REPO}\b/ &/" \ | LC_ALL=C sort [[ -z ${PIPESTATUS[@]#0} ]] } # get paths for a given list of repositories get_repo_path() { portageq get_repo_path "${ROOT:-/}" "$@" } # get a list of valid profiles # returns a line :::: for every profile find_targets() { local arch desc repos repo_paths i p arch=$(arch) [[ -z ${arch} ]] && die -q "Cannot determine architecture" repos=( $(get_repos) ) || die -q "get_repos failed" repo_paths=( $(get_repo_path "${repos[@]}") ) \ || die -q "get_repo_path failed" [[ ${#repos[@]} -eq 0 || ${#repos[@]} -ne ${#repo_paths[@]} ]] \ && die -q "Cannot get list of repositories" for (( i = 0; i < ${#repos[@]}; i++ )); do desc=${repo_paths[i]}/profiles/profiles.desc [[ -r ${desc} ]] || continue # parse profiles.desc and find profiles suitable for arch for p in $(sed -n -e \ "s|^${arch}[[:space:]]\+\([^[:space:]]\+\).*$|\1|p" "${desc}") do echo "${repos[i]}::${repo_paths[i]}::${p}" done done } # remove make.profile symlink remove_symlink() { rm "${MAKE_PROFILE}" } # set the make.profile symlink set_symlink() { local target=$1 force=$2 targets arch parch repo repopath if is_number "${target}"; then targets=( $(find_targets) ) [[ ${#targets[@]} -eq 0 ]] \ && die -q "Failed to get a list of valid profiles" target=${targets[target-1]} repo=${target%%::*}; target=${target#*::} repopath=${target%%::*}; target=${target#*::} elif [[ -n ${target} ]]; then # if the profile was explicitly specified (rather than a number) # double check and make sure it's valid arch=$(arch) [[ -z ${arch} && -z ${force} ]] \ && die -q "Cannot determine architecture" repo=${target%%:*} # assume default repo if not explicitly specified [[ ${repo} == "${target}" || -z ${repo} ]] && repo=${DEFAULT_REPO} target=${target#*:} repopath=$(get_repo_path "${repo}") || die -q "get_repo_path failed" # do a reverse lookup and find the arch associated with ${target} parch=$(sed -n -e \ "s|^\([[:alnum:]]\+\)[[:space:]].*${target}[[:space:]].*$|\1|p" \ "${repopath}/profiles/profiles.desc") [[ ${arch} != "${parch}" && -z ${force} ]] \ && die -q "${target} is not a valid profile for ${arch}" fi [[ -z ${target} || -z ${repopath} ]] \ && die -q "Target \"$1\" doesn't appear to be valid!" [[ ! -d ${repopath}/profiles/${target} ]] \ && die -q "No profile directory for target \"${target}\"" # we must call remove_symlink() here instead of calling it from # do_set(), since if the link is removed, we cannot reliably # determine ${arch} in find_targets() if [[ -L ${MAKE_PROFILE} ]]; then remove_symlink \ || die -q "Couldn't remove current ${MAKE_PROFILE} symlink" fi # set relative symlink ln -s "$(relative_name \ "${repopath}" "${MAKE_PROFILE%/*}")/profiles/${target}" \ "${MAKE_PROFILE}" \ || die -q "Couldn't set new ${MAKE_PROFILE} symlink" # check if the resulting symlink is sane [[ $(canonicalise "${MAKE_PROFILE}") != "$(canonicalise "${EROOT}")"/* ]] \ && write_warning_msg "Strange path. Check ${MAKE_PROFILE} symlink" return 0 } ### show action ### describe_show() { echo "Show the current make.profile symlink" } do_show() { local link repos repo_paths dir i get_symlink_location write_list_start "Current ${MAKE_PROFILE} symlink:" if [[ -L ${MAKE_PROFILE} ]]; then link=$(canonicalise "${MAKE_PROFILE}") repos=( $(get_repos) ) || die -q "get_repos failed" repo_paths=( $(get_repo_path "${repos[@]}") ) \ || die -q "get_repo_path failed" [[ ${#repos[@]} -eq 0 || ${#repos[@]} -ne ${#repo_paths[@]} ]] \ && die -q "Cannot get list of repositories" # Unfortunately, it's not obvious where to split a given path # in repository directory and profile. So loop over all # repositories and compare the canonicalised paths. for (( i = 0; i < ${#repos[@]}; i++ )); do dir=$(canonicalise "${repo_paths[i]}/profiles") if [[ ${link} == "${dir}"/* ]]; then link=${link##"${dir}/"} [[ ${repos[i]} != "${DEFAULT_REPO}" ]] \ && link=${repos[i]}:${link} break fi done write_kv_list_entry "${link}" "" else write_kv_list_entry "(unset)" "" fi } ### list action ### describe_list() { echo "List available profile symlink targets" } do_list() { local targets active i target repo repopath targets=( $(find_targets) ) [[ ${#targets[@]} -eq 0 ]] \ && die -q "Failed to get a list of valid profiles" get_symlink_location active=$(canonicalise "${MAKE_PROFILE}") for (( i = 0; i < ${#targets[@]}; i++ )); do target=${targets[i]} repo=${target%%::*}; target=${target#*::} repopath=${target%%::*}; target=${target#*::} if [[ ${repo} == "${DEFAULT_REPO}" ]]; then targets[i]=${target} else targets[i]=${repo}:${target} fi [[ $(canonicalise "${repopath}/profiles/${target}") == "${active}" ]] \ && targets[i]=$(highlight_marker "${targets[i]}") done write_list_start "Available profile symlink targets:" write_numbered_list "${targets[@]}" } ### set action ### describe_set() { echo "Set a new profile symlink target" } describe_set_parameters() { echo "" } describe_set_options() { echo "target : Target name or number (from 'list' action)" echo "--force : Forcibly set the symlink" } do_set() { local force if [[ $1 == "--force" ]]; then force=1 shift fi [[ -z $1 ]] && die -q "You didn't tell me what to set the symlink to" [[ $# -gt 1 ]] && die -q "Too many parameters" get_symlink_location if [[ -e ${MAKE_PROFILE} ]] && [[ ! -L ${MAKE_PROFILE} ]]; then die -q "${MAKE_PROFILE} exists but is not a symlink" else set_symlink "$1" ${force} || die -q "Couldn't set a new symlink" fi }