# Copyright 2013 Gentoo Foundation # Distributed under the terms of the GNU GPL version 2 or later inherit config multilib DESCRIPTION="Manage active Clang version" MAINTAINER="eselect@gentoo.org" VERSION="20130521" B_PATH="${EROOT%/}/usr" S_PATH="${EROOT%/}/usr/share/eselect-clang" # Global Data active_slot() { local link="${B_PATH}/bin/clang" if [[ -e "${link}" ]] ; then echo $(readlink -sf "${link}") | \ sed -re 's#.*clang-([0-9]+(\.[0-9]+)?)$#\1#' fi } # Utility Functions add_slot_suffix() { local file="$1" local slot="$2" local ext="" if [[ "${file}" =~ \. ]] ; then ext=".${file#*.}" fi local base="${file%%.*}" echo "${base}-${slot}${ext}" } ### Linker Function ### # Takes two arguments: # - Full path to versioned file (e.g. /usr/share/eselect-clang/slots/3.2/versioned) # - Slot to link (e.g. 3.2) linker() { local versioned_file=$1 local slot=$2 if [[ -r ${versioned_file} ]] ; then local versioned=($(<"${versioned_file}")) local link_path for link_path in "${versioned[@]}" ; do link_path="${ROOT%/}/${link_path#/}" local link_dir=$(dirname "${link_path}") local link_name=$(basename "${link_path}") local rel_target=$(add_slot_suffix "${link_name}" "${slot}") local target="${link_dir}/${rel_target}" # For good measure, remove target before creating the symlink [[ -h ${link_path} ]] && rm -f "${link_path}" [[ -e ${link_path} ]] && \ die -q "The target '${link_path}' still exists and could not be removed!" if [[ ! -e "${target}" ]] && [[ "${link_path}" == *man* ]] ; then local suffix=$(echo "${target}"* | sed 's/.*\.1//') if [[ "${suffix}" != "*" ]] ; then rel_target="${rel_target}${suffix}" link_path="${link_path}${suffix}" fi fi # Create relative links so that they work both here and inside the new # root if $ROOT is not "/". ln -s "${rel_target}" "${link_path}" || die -q "Unable to create link!" done fi } ### Unlinker Function ### # Takes one argument: # - Full path to versioned file (e.g. /usr/share/eselect-clang/slots/3.2/versioned) unlinker() { local versioned_file=$1 if [[ -r ${versioned_file} ]] ; then local versioned=($(<"${versioned_file}")) local link_path for link_path in "${versioned[@]}" ; do if [[ ! -e "${link_path}" ]] && [[ "${link_path}" == *man* ]] ; then local suffix=$(echo "${link_path}"* | sed 's/.*\.1//') if [[ "${suffix}" != "*" ]] ; then link_path="${link_path}${suffix}" fi fi [[ -h "${ROOT%/}/${link_path}" ]] && \ rm -f "${ROOT%/}/${link_path}" [[ -e "${ROOT%/}/${link_path}" ]] && \ die -q "The target '${link_path}' still exists and could not be removed!" done fi } ### Get Slots Function ### # Find all available slots and return them. get_slots() { echo $(find "${B_PATH}/bin/" -maxdepth 1 -type f \ -regex '.*clang-[0-9][0-9]*\(\.[0-9][0-9]*\)?' | \ sed -re 's#.*clang-([0-9]+(\.[0-9]+)?)$#\1#' | sort -n) } ### List Action ### describe_list() { echo "List available Clang slots." } do_list() { write_list_start "Available Clang slots" if $(is_output_mode brief) ; then echo $(get_slots) else local slot for slot in $(get_slots) ; do local ebuild=($(<"${S_PATH}/slots/${slot}/ebuild")) case "${slot}" in "$(active_slot)" ) write_kv_list_entry \ "$(highlight_marker ${slot})" "${ebuild}";; * ) write_kv_list_entry \ "${slot}" "${ebuild}";; esac done [[ -z "${slot}" ]] && write_warning_msg "No slots available." fi } ### Show Action ### describe_show() { echo "Show which slot is currently active." } do_show() { local slot=$(active_slot) if [[ -n "${slot}" ]] ; then echo "${slot}" else echo "(none)" fi } ### Set Action ### describe_set() { echo "Create symbolic links for Clang libraries and applications." } do_set() { local slot=$1 if [[ ! -e ${B_PATH}/bin/clang-${slot} ]] ; then die -q "Not a valid slot." fi echo -ne "Switching to Clang-${slot}... " # Remove the active links to start a fresh list local active=$(active_slot) if [[ -n "${active}" ]] ; then unlinker "${S_PATH}/slots/${active}/versioned" fi linker "${S_PATH}/slots/${slot}/versioned" ${slot} echo "done." } ### Unset Action ### describe_unset() { echo "Deselect the current or given slot." } do_unset() { local slot=${1:-$(active_slot)} if [[ -n ${slot} ]] && [[ ${slot} = $(active_slot) ]] ; then echo -n "Removing symlinks... " unlinker "${S_PATH}/slots/${slot}/versioned" echo "done." do_update else echo "Inactive slot selected. Nothing to do." fi } ### Clear Action ### describe_clear() { echo "Remove all active symlinks." } do_clear() { local slot=$(active_slot) if [[ -n ${slot} ]] ; then echo -n "Removing symlinks... " unlinker "${S_PATH}/slots/${slot}/versioned" echo "done." else echo "No slot selected. Nothing to do." fi } ### Reset Action ### describe_reset() { echo "Recreate symbolic links for currently active slot." } do_reset() { local slot=$(active_slot) [[ -z ${slot} ]] && die -q "No active slot to reset." do_clear do_set ${slot} } ### Update Action ### describe_update() { echo "Refreshes all symbolic links managed by this module" } do_update() { local slot=$(active_slot) local slots=($(get_slots)) local index=${#slots[@]} # In case all slots have been unmerged if [[ ${index} -eq 0 ]] ; then if [[ -n ${slot} ]] ; then do_clear else write_warning_msg "No slots found! Nothing to do." fi return 0 fi # Reset, otherwise set the highest slot available. if [[ -n ${slot} ]] && [[ ${slots[@]} =~ ${slot} ]] ; then do_set ${slot} else # best_version doesn't work here as pkg_postrm runs before the world # file is updated, thereby returning a false positive. do_set ${slots[$index-1]} fi do_action env update &> /dev/null }