diff options
author | Ionen Wolkens <ionen@gentoo.org> | 2022-11-15 21:50:14 -0500 |
---|---|---|
committer | Ionen Wolkens <ionen@gentoo.org> | 2022-11-16 09:26:09 -0500 |
commit | cd681b82edf58452e185dba64ddab2a0870884da (patch) | |
tree | 5a0f979acaa4c38c2965b3170cd5bcd796a15794 | |
parent | v1.2.3 (diff) | |
download | eselect-wine-cd681b82edf58452e185dba64ddab2a0870884da.tar.gz eselect-wine-cd681b82edf58452e185dba64ddab2a0870884da.tar.bz2 eselect-wine-cd681b82edf58452e185dba64ddab2a0870884da.zip |
wine.eselect: rewrite initial import
Signed-off-by: Ionen Wolkens <ionen@gentoo.org>
-rw-r--r-- | wine.eselect | 1167 |
1 files changed, 323 insertions, 844 deletions
diff --git a/wine.eselect b/wine.eselect index 73300b7..68fa105 100644 --- a/wine.eselect +++ b/wine.eselect @@ -1,896 +1,375 @@ # -*-eselect-*- vim: ft=eselect -# Copyright 2005-2017 Gentoo Foundation +# Copyright 2022 Gentoo Authors # Distributed under the terms of the GNU GPL version 2 or later -inherit config multilib tests - -DESCRIPTION="Manage active wine version" +DESCRIPTION="Manage active Wine slots and variants" MAINTAINER="wine@gentoo.org" VERSION="1.2.3" -CONFIG_DIR="/etc/eselect/wine" - -VARIANTS=( - vanilla - staging - proton -) - -################################################################################ -# Eselect Wine # -################################################################################ - -# Verify that files exist for specified target -# Input: ${P} -is_valid_target(){ - if [[ $# -ne 1 ]]; then - die "Invalid number of parameters" - fi - - local tgt="$1" - - set_dir_env - - if [[ ! -d "${wine_bin}" ]] || \ - [[ ! "$(ls -A ${wine_bin})" ]] || \ - [[ ! -e "${wine_bin}/wine" ]]; then - return 1 - elif [[ ! -e "${EPREFIX}/usr/bin/${tgt}" ]]; then - return 1 - else - return 0 - fi - - unset_dir_env -} - -# Verify that symlinks are valid -are_symlinks_valid() { - if [[ $# -gt 1 ]]; then - die "Invalid number of parameters" - fi - - local v="wine" - - while [[ $# -gt 0 ]]; do - if [[ $1 == --* ]]; then - local flag="${1#--}" - if has "${flag}" ${VARIANTS[@]}; then - v=${flag} - else - die "Invalid variant" - fi - else - die "Invalid parameter" +# Setup env and run $@ in ${EROOT}${WINEETC} to simplify path +# handling (all other wine-* functions must be ran from this). +# Passing '-r' skips the write sanity check. +wine-run() { + local WINEETC=/etc/eselect/wine + local WINEREL=../../.. + + [[ -d ${EROOT}${WINEETC} ]] || mkdir -p -- "${EROOT}${WINEETC}" + pushd -- "${EROOT}${WINEETC}" >/dev/null || + die -q "could not change directory to '${EROOT}${WINEETC}'" + [[ ${1} == -r ]] && shift || [[ -w . ]] || + die -q "No write access to '${PWD}'" + + local shopt_reset + shopt_reset=$(shopt -p nullglob) + shopt -s nullglob + + local -A WINEMAP + wine-winemap + + "${@}" + + # hack wrt update given PATH is not updated in pkg_postinst (noisy) + [[ ${PATH} == @(|*:)"${EPREFIX}${WINEETC}/bin"*(/)@(|:*) || \ + ${1} == wine-update ]] || + write_warning_msg "'${EPREFIX}${WINEETC}/bin' missing from PATH, may need to run '. ${EROOT}/etc/profile'" + + ${shopt_reset} + popd >/dev/null || die +} + +# Run $@ for each valid wine slot, and set: +# dir_bin,inc,shr,win: relative path to bin, include, share and wine lib dir, +# dir_wrp: relative path to wine wrappers location (/usr/bin) +# slot: wine-<variant>-<version> +# suffix: <variant>-<version> +# variant: <variant> +# is_last: true if last slot, false otherwise +# is_last_variant: true if last of a variant, false otherwise +# Returns 1 if no valid slots were found. +wine-foreach_slot() { + # try non-POSIX -V to roughly sort by version, keep glob order if can't + local fe_sorted fe_dirs=("${WINEREL}"/usr/lib/wine-*-[0-9]*) + mapfile -t fe_sorted < <(printf "%s\n" "${fe_dirs[@]}" | sort -V 2>/dev/null) + (( ${#fe_sorted[@]} == ${#fe_dirs[@]} )) || fe_sorted=("${fe_dirs[@]}") + + local slot variant dir_bin dir_inc dir_shr dir_win + local is_last=false is_last_variant=false fe_run=false fe_valid=false + local fe_dir fe_newslot fe_newvariant fe_newsuffix + for fe_dir in "${fe_sorted[@]}"; do + [[ ${fe_dir} =~ /(wine-(([^-]+)-[0-9][^/]*))$ ]] || continue + fe_newslot=${BASH_REMATCH[1]} + fe_newsuffix=${BASH_REMATCH[2]} + fe_newvariant=${BASH_REMATCH[3]} + if ${fe_run}; then + fe_run=false + [[ ${fe_newvariant} != "${variant}" ]] && is_last_variant=true + "${@}" + is_last_variant=false fi - shift - done - local v_arg - if [[ ${v} != "wine" ]]; then - v_arg="--${v}" - fi - - local active=$(get_active ${v_arg}) - local tgt="${active}" - if [[ "${active}" == "(unset)" ]]; then - write_error_msg "Invalid active config" - return 1 - fi - - set_dir_env - - local possible_vars=( bin man include ) - local symlink_vars=$(load_config "${CONFIG_DIR}/links/${v}" symlink_dirs) - if [[ -z "${symlink_vars}" ]]; then - write_error_msg "Missing any configured symlink_dirs" - return 1 - fi - local var - - for var in ${possible_vars[@]}; do - if has ${var} ${symlink_vars[@]}; then - symlink_vars=$(list_rm_item "${var}" "${symlink_vars}") - else - write_warning_msg "Missing '${var}' in ${v} config" - write_warning_msg "Might want to re-run set or update" - fi + slot=${fe_newslot} + suffix=${fe_newsuffix} + variant=${fe_newvariant} + dir_bin=${fe_dir}/bin + dir_inc=${WINEREL}/usr/include/${slot} + dir_shr=${WINEREL}/usr/share/${slot} + dir_win=${fe_dir}/wine + dir_wrp=${WINEREL}/usr/bin + [[ -e ${dir_bin}/wine && -d ${dir_inc} && -d ${dir_shr} && \ + -d ${dir_win} && -d ${dir_wrp} ]] || continue + + wine-legacy_checks || continue + + fe_run=true + fe_valid=true done - if [[ ! -z ${symlink_vars} ]]; then - write_error_msg "Config contains unknown symlink_dirs ${symlink_vars}" - return 1 - fi - - symlink_vars=$(load_config "${CONFIG_DIR}/links/${v}" symlink_dirs) - for var in ${symlink_vars[@]}; do - local symlinks=$(load_config "${CONFIG_DIR}/links/${v}" ${var}) - local symlink - - if [[ -z "${symlinks}" ]]; then - die -q "Missing listing of ${var} symlinks" + is_last=true + is_last_variant=true + ${fe_run} && "${@}" + + ${fe_valid} +} + +# Remove all known files we can create +wine-reset() { + local p rm=() rmdir=() + for p in bin/* bin include share wine wine.conf; do + # only wildcard delete links + empty dirs + if [[ -L ${p} || ( ${p} == @(bin/wine|wine.conf) && -e ${p} ) ]]; then + rm+=("${p}") + elif [[ -d ${p} ]]; then + rmdir+=("${p}") fi - for symlink in ${symlinks[@]}; do - if [[ ! -L ${symlink} ]]; then - write_error_msg "${symlink} is not a symlink" - return 1 - else - local file=$(canonicalise ${symlink}) - if [[ ! -e "${file}" ]]; then - write_error_msg "${symlink} points to nonexistant ${file}" - return 1 - # Handle bin separately because symlinks don't go to wine_${var} - elif [[ "${var}" == "bin" ]]; then - local path="${symlink%${v_arg#-}}${tgt#wine}" - if [[ "${file}" != "${path}" ]]; then - write_error_msg "${symlink} points to ${file}" - write_error_msg "which doesn't appear to be the proper link" - return 1 - fi - else - local path=wine_${var} - path=${!path} - path=$(canonicalise "${path}") - if ! [[ "${file}" =~ "${path%/}"(/*)? ]]; then - write_error_msg "${symlink} points to ${file}" - write_error_msg "which doesn't appear to be part of wine" - return 1 - fi - fi - fi - done done - unset_dir_env -} - - -# print currently selected wine -get_active() { - if [[ $# -gt 1 ]]; then - die -q "Invalid number of parameters specified" - fi - - local v="wine" - - while [[ $# -gt 0 ]]; do - if [[ $1 == --* ]]; then - local flag="${1#--}" - if has "${flag}" ${VARIANTS[@]}; then - v=${flag} - else - die -q "Invalid variant" + (( ! ${#rm[@]} )) || rm -- "${rm[@]}" && + (( ! ${#rmdir[@]} )) || rmdir -- "${rmdir[@]}" || + die -q "failed to remove some files from '${PWD}', please cleanup" +} +wine-reset-feedback() { + wine-reset + write_warning_msg "Removed all known files from '${PWD}'" +} + +# Set WINEMAP associative array for current slot selections, +# with 'main' being what you get if call 'wine' without suffix. +# e.g. ${WINEMAP[vanilla]} == wine-vanilla-7.0 +wine-winemap() { + WINEMAP=() + if [[ -f wine.conf ]]; then + local wine + while read -r wine; do + if [[ ${wine} =~ ^wine-([^-]+)-[0-9].* ]]; then + WINEMAP[${BASH_REMATCH[1]}]=${wine} + [[ -v WINEMAP[main] ]] || WINEMAP[main]=${wine} fi - else - [[ -z $1 ]] || die -q "Invalid parameter" - fi - shift - done - - local active=$(load_config "${CONFIG_DIR}/active" ${v}) - - if [[ -z "${active}" ]]; then - echo "(unset)" + done < wine.conf || die else - echo "${active}" + wine-legacy_winemap fi } -get_installed(){ - if [[ $# -gt 1 ]]; then - die -q "Invalid number of parameters specified" - fi - - local v="wine" - - while [[ $# -gt 0 ]]; do - if [[ $1 == --* ]]; then - local flag="${1#--}" - if has "${flag}" ${VARIANTS[@]}; then - v=${flag} - else - die -q "Invalid variant" - fi - else - die -q "Invalid parameter" - fi - shift - done - - local installed=$(load_config "${CONFIG_DIR}/installed" ${v}) - - echo $(sort_list ${installed[@]}) -} - -### Registration action ## -describe_register(){ - echo "Register a new package with the eselect module (Internal use only)" -} - -describe_register_parameters() { - echo "<target>" -} - -describe_register_options() { - for v in ${VARIANTS[@]}; do - echo "--${v} : Register a new package with ${v}" - done - echo "target : A fully qualified variant e.g." - echo " : wine-1.9.23, wine-vanilla-2.0, or wine-staging-2.1.1" -} - -do_register(){ - if [[ $# -lt 1 ]] || [[ $# -gt 3 ]]; then - die -q "Invalid number of parameters specified" - fi - - local v="wine" - - while [[ $# -gt 0 ]]; do - if [[ $1 == --* ]]; then - local flag="${1#--}" - if has "${flag}" ${VARIANTS[@]}; then - v=${flag} - else - die -q "Invalid flag or variant" - fi - else - local tgt="$1" - fi +# Store WINEMAP to wine.conf +wine-winemap_save() { + ( + echo "# auto-generated by eselect-wine-${VERSION}, do not edit" + [[ -v WINEMAP[main] ]] && echo "${WINEMAP[main]}" + unset 'WINEMAP[main]' + (( ${#WINEMAP[@]} )) && printf '%s\n' "${WINEMAP[@]}" + : + ) > wine.conf || die +} + +### eselect commands + +describe_list() { echo "List available Wine slots and variants"; } +describe_list_parameters() { echo "[variant]"; } +describe_list_options() { echo "variant: Variant to list (all if ommitted)"; } +do_list() { wine-run -r wine-list "${@}"; } +wine-list() { + (( ${#} < 2 )) || die -q "Too many arguments" + + local target + local -i count=0 + write_list_start "Available Wine slots${1:+ for ${1}}:" + wine-list_foreach() { + count+=1 + [[ ${1} == all || ${1} == "${variant}" ]] || return 0 + target=${slot} + [[ -v 'WINEMAP[${variant}]' && ${WINEMAP[${variant}]} == "${slot}" ]] && + target=$(highlight_marker "${target}") + [[ -v WINEMAP[main] && ${WINEMAP[main]} == "${slot}" ]] && + ! is_output_mode brief && target+=" ($(highlight main))" + write_numbered_list_entry ${count} "${target}" + ${is_last_variant} && ! ${is_last} && [[ ${1} == all ]] && + ! is_output_mode brief && echo + } + wine-foreach_slot wine-list_foreach "${1:-all}" + [[ -v target ]] || write_numbered_list -m "(none found)" +} + +describe_update() { echo "Auto-select highest slot for each Wine variants"; } +describe_update_parameters() { echo "[--if-unset] [variant]"; } +describe_update_options() { + echo "--if-unset: Only update if selected slots are invalid" + echo "variant: Only update the given variant, unless invalid" +} +do_update() { wine-run wine-update "${@}"; } +wine-update() { + local ifunset variant_only + while (( ${#} )); do + case ${1} in + --if-unset) ifunset=1;; + --reset) wine-reset-feedback; return;; # private option + --all|--any|--d3d9|--proton|--staging|--vanilla);; # legacy + --*) die -q "Unrecognized option '${1}'";; + *) + [[ ! -v variant_only ]] || die -q "Too many arguments" + if [[ ${1} != all ]]; then + ifunset=1 + variant_only=${1} + fi + ;; + esac shift done - if [[ -z "${tgt}" ]]; then - die -q "Target not specified" - fi - - local v_arg - if [[ ${v} != "wine" ]]; then - v_arg="--${v}" - fi - - if is_number "${tgt}"; then - local tgts=($(get_installed ${v_arg})) - tgt=${tgts[${tgt}-1]} - fi - - if ! is_valid_target "${tgt}"; then - die -q "Target does not exist" - fi - - local list=$(get_installed ${v_arg}) - - if ! has ${tgt} ${list}; then - list=($(sort_list "${list} ${tgt}")) - store_config "${CONFIG_DIR}/installed" ${v} "${list[@]}" - fi -} - -describe_deregister(){ - echo "Deregister a package with the eselect module (Internal use only)" -} - -describe_deregister_parameters() { - echo "<target>" -} - -describe_deregister_options() { - for v in ${VARIANTS[@]}; do - echo "--${v} : Deregister a package with ${v}" - done - echo "--force : Forcibly remove a package" - echo "target : A fully qualified variant e.g." - echo " : wine-1.9.23, wine-vanilla-2.0, or wine-staging-2.1.1" -} - -do_deregister(){ - if [[ $# -lt 1 ]] || [[ $# -gt 3 ]]; then - die -q "Invalid number of parameters specified" - fi - - local v="wine" - local force=false - - while [[ $# -gt 0 ]]; do - if [[ $1 == --* ]]; then - local flag="${1#--}" - if has "${flag}" ${VARIANTS[@]}; then - v=${flag} - elif [[ "${flag}" == "force" ]]; then - force=true - else - die -q "Invalid variant" + wine-reset + + local bin display wrap + local -A is_done=() + wine-update_foreach() { + if ${is_last_variant} || + [[ -v ifunset && ${variant_only} != "${variant}" && \ + ${WINEMAP[${variant}]} == "${slot}" ]] && + [[ ! -v 'is_done[${variant}]' ]] + then + [[ -d bin ]] || mkdir bin || die + + # wine does not react well to renames, so use variant wrappers + for bin in "${dir_bin}"/*; do + wrap=${dir_wrp}/${bin##*/}-${suffix} + [[ ! -e ${wrap} ]] || + ln -s -- "../${wrap}" "bin/${bin##*/}-${variant}" || die + done + + display= + [[ ${WINEMAP[${variant}]} != "${slot}" ]] && + display="${slot} is set as ${variant} provider (auto)" + + if ${is_last} || + { ${is_last_variant} && + [[ ${WINEMAP[main]} == "${WINEMAP[${variant}]}" ]]; } || + [[ -v ifunset && ${variant_only} != "${variant}" && \ + ${WINEMAP[main]} == "${slot}" ]] && + [[ ! -v is_done[main] ]] + then + # could skip wrappers here, but use for consistency + for bin in "${dir_bin}"/*; do + wrap=${dir_wrp}/${bin##*/}-${suffix} + [[ ! -e ${wrap} ]] || + ln -s -- "../${wrap}" "bin/${bin##*/}" || die + done + ln -s -- "${dir_inc}" include || die + ln -s -- "${dir_shr}" share || die + ln -s -- "${dir_win}" wine || die + [[ ${WINEMAP[main]} != "${slot}" ]] && + display="${slot} is set as the main provider (auto)" + is_done[main]=1 + WINEMAP[main]=${slot} fi - else - local tgt="$1" - fi - shift - done - - if [[ -z "${tgt}" ]]; then - die -q "Target not specified" - fi - - local v_arg - if [[ ${v} != "wine" ]]; then - v_arg="--${v}" - fi - - if is_number "${tgt}"; then - local tgts=($(get_installed ${v_arg})) - tgt=${tgts[${tgt}-1]} - fi - if ! is_valid_target "${tgt}" && [[ ${force} == "false" ]]; then - die -q "Target does not exist" - fi - - local list=$(get_installed ${v_arg}) - - if ! has ${tgt} ${list}; then - die -q "${tgt} is not registered for ${v}" - fi + [[ ${display} ]] && echo "${display}" - if [[ "${tgt}" == "$(get_active ${v_arg})" ]]; then - do_unset ${v_arg} - fi - - list=$(list_rm_item ${tgt} "${list}") - store_config "${CONFIG_DIR}/installed" ${v} "${list}" -} - -### list action ### - -describe_list() { - echo "List available wine versions" -} - -describe_list_options() { - for v in ${VARIANTS[@]}; do - echo "--${v} : List the available 'wine-${v}'" - done -} - -do_list() { - if [[ $# -gt 1 ]]; then - die -q "Invalid number of parameters specified" - fi - - local v="wine" - - while [[ $# -gt 0 ]]; do - if [[ $1 == --* ]]; then - local flag="${1#--}" - if has "${flag}" ${VARIANTS[@]}; then - v=${flag} - else - die -q "Invalid variant" - fi - else - die -q "Invalid parameter" + is_done[${variant}]=1 + WINEMAP[${variant}]=${slot} fi - shift - done - - local v_arg - if [[ ${v} != "wine" ]]; then - v_arg="--${v}" - fi - - write_list_start "Available wine${v_arg#-} versions:" - local installed=($(get_installed ${v_arg})) - local active=$(get_active ${v_arg}) - - if [[ ${#installed} -eq 0 ]]; then - unset installed - else - for (( i = 0; i < ${#installed[@]}; i++ )); do - if [[ ${installed[i]} = ${active} ]]; then - installed[i]=$(highlight_marker "${installed[i]}") - fi + } + if wine-foreach_slot wine-update_foreach; then + # cleanup unused before saving + local variant + for variant in "${!WINEMAP[@]}"; do + [[ -v 'is_done[${variant}]' ]] || unset "WINEMAP[${variant}]" done - fi - - write_numbered_list -m "(none found)" "${installed[@]}" -} - -### show action ### - -describe_show() { - echo "Show the active wine version" -} - -describe_show_options() { - for v in ${VARIANTS[@]}; do - echo "--$v : Show the active 'wine-$v'" - done -} - -do_show() { - if [[ $# -gt 1 ]]; then - die -q "Invalid number of parameters specified" - fi - - local v="wine" - - while [[ $# -gt 0 ]]; do - if [[ $1 == --* ]]; then - local flag="${1#--}" - if has "${flag}" ${VARIANTS[@]}; then - v=${flag} - else - die -q "Invalid variant" - fi - else - die -q "Invalid parameter" - fi - shift - done - - local v_arg - if [[ ${v} != "wine" ]]; then - v_arg="--${v}" - fi - - write_list_start "Active wine${v_arg#-} version:" - local active=$(get_active ${v_arg}) - - write_kv_list_entry "${active}" "" - if [[ "${active}" != "(unset)" ]]; then - are_symlinks_valid ${v_arg} + wine-winemap_save + else + # no wine slots, keep placeholders to avoid broken references + mkdir -p bin include share wine + printf "#!/usr/bin/env sh\necho 'Error: Wine is not setup (eselect-wine)' >&2\nexit 1\n" \ + > bin/wine + chmod +x bin/wine fi } -### unset action ### - -describe_unset() { - echo "Remove wine symlinks" -} - -describe_unset_options() { - for v in ${VARIANTS[@]}; do - echo "--$v : Remove the 'wine-$v' symlinks" - done - echo "--all : Unset active wine and all variants" -} - -do_unset() { - if [[ $# -gt 1 ]]; then - die -q "Invalid number of parameters specified" - fi - - local v="wine" - local all=false - - while [[ $# -gt 0 ]]; do - if [[ $1 == --* ]]; then - local flag="${1#--}" - if has "${flag}" ${VARIANTS[@]}; then - v=${flag} - elif [[ "${flag}" == "all" ]]; then - all=true - else - die -q "Invalid variant" - fi - else - die -q "Invalid parameter" - fi - shift - done - - # Run do_unset for all variants - if ${all}; then - do_unset - for v in ${VARIANTS[@]}; do - do_unset "--${v}" - done +describe_show() { echo "Show the active Wine slot"; } +describe_show_parameters() { echo "[variant]"; } +describe_show_options() { echo "variant: Variant to show, e.g. vanilla (main if ommitted)"; } +do_show() { wine-run -r wine-show "${@}"; } +wine-show() { + (( ${#} < 2 )) || die -q "Too many arguments" - return 0 - fi - - local v_arg - if [[ ${v} != "wine" ]]; then - v_arg="--${v}" + if [[ -v 'WINEMAP[${1:-main}]' ]]; then + echo "${WINEMAP[${1:-main}]}" + else + write_warning_msg "no slot is selected${1:+ for ${1}}" fi - - remove_symlinks ${v_arg} || die -q "Couldn't remove wine${v_arg#-} symlinks" - - store_config "${CONFIG_DIR}/active" "${v}" "" -} - -### set action ### - -describe_set() { - echo "Set a new wine version" -} - -describe_set_parameters() { - echo "<target>" } +describe_set() { echo "Set active Wine slots and variants"; } +describe_set_parameters() { echo "[--only] <target>"; } describe_set_options() { - for v in ${VARIANTS[@]}; do - echo "--$v : Set only the 'wine-$v' symlinks" - done - echo "target : Target name or number (from 'list' action)" -} - -do_set() { - if [[ $# -lt 1 ]] || [[ $# -gt 2 ]]; then - die -q "Invalid number of parameters specified" - fi - - local v="wine" - - while [[ $# -gt 0 ]]; do - if [[ $1 == --* ]]; then - local flag="${1#--}" - if has "${flag}" ${VARIANTS[@]}; then - v=${flag} - else - die -q "Invalid flag or variant" - fi - else - local tgt="$1" - fi + echo "--only: Only set the variant's slot" + echo "target: Target name or number (from 'list' action)" +} +do_set() { wine-run wine-set "${@}"; } +wine-set() { + local chosen_slot only + while (( ${#} )); do + case ${1} in + --only) only=1;; + --*) die -q "Unrecognized option '${1}'";; + *) + [[ ! -v chosen_slot ]] || die -q "Too many arguments" + chosen_slot=${1} + ;; + esac shift done - - if [[ -z "${tgt}" ]]; then - die -q "Target not specified" - fi - - local v_arg - if [[ ${v} != "wine" ]]; then - v_arg="--${v}" - fi - - if is_number "${tgt}"; then - local tgts=($(get_installed ${v_arg})) - tgt=${tgts[${tgt}-1]} - fi - - if ! is_valid_target "${tgt}"; then - die -q "Target does not exist" - fi - - do_unset ${v_arg} || die -q "Failed to unset active target" - set_symlinks ${v_arg} "${tgt}" || die -q "Couldn't set wine-${v_arg#-} symlinks" - - store_config "${CONFIG_DIR}/active" "${v}" "${tgt}" -} - -### update action ### - -describe_update() { - echo "Set highest version installed active" -} - -describe_update_options() { - for v in ${VARIANTS[@]}; do - echo "--$v : Update the 'wine-$v' symlinks" - done - echo "--all : Update main active wine and all variants" - echo "--if-unset : Reuse currently selected version if it appears valid" -} - -do_update() { - if [[ $# -gt 3 ]]; then - die -q "Invalid number of parameters specified" - fi - - local v="wine" - local if_unset=false - local all=false - - while [[ $# -gt 0 ]]; do - if [[ $1 == --* ]]; then - local flag="${1#--}" - if has "${flag}" ${VARIANTS[@]}; then - v=${flag} - elif [[ "${flag}" == "if-unset" ]]; then - if_unset=true - elif [[ "${flag}" == "all" ]]; then - all=true - else - die -q "Invalid flag or variant" + [[ -v chosen_slot ]] || die -q "Please specify a target to activate" + + local -i chosen_num count=1 + printf -v chosen_num %u "${chosen_slot}" 2>/dev/null && + unset chosen_slot + + local display + wine-set_foreach() { + if (( chosen_num == count++ )) || [[ ${chosen_slot} == "${slot}" ]]; then + display="${slot} is set the ${variant} provider" + [[ ${WINEMAP[${variant}]} == "${slot}" ]] && + display="${slot} is already set as the ${variant} provider" + WINEMAP[${variant}]=${slot} + if [[ ! -v only ]]; then + display="${slot} is set as the main provider" + [[ ${WINEMAP[main]} == "${slot}" ]] && + display="${slot} is already set as the main provider" + WINEMAP[main]=${slot} fi - else - die -q "Invalid parameter" - fi - shift - done - - if [[ "${v}" != "wine" ]] && ${all}; then - die -q "Either specify a specific variant, or all, but not both" - fi - - # Run do_update for all variants - if ${all}; then - local unset_arg - if ${if_unset}; then - unset_arg="--if-unset" - fi - - do_update ${unset_arg} - for v in ${VARIANTS[@]}; do - do_update "--${v}" ${unset_arg} - done - - return 0 - fi - - local v_arg - if [[ ${v} != "wine" ]]; then - v_arg="--${v}" - fi - - # Determine if set and valid - # If so, return - if ${if_unset}; then - local active=$(get_active ${v_arg}) - if is_valid_target "${active}" && are_symlinks_valid ${v_arg}; then - return 0 fi - fi - - local installed=($(get_installed ${v_arg})) - if [[ ${#installed[@]} -eq 0 ]]; then - write_warning_msg "Skipping wine${v_arg#-}. No registered targets found." - return 0 - fi - local tgt=${installed[-1]} - - do_set ${v_arg} "${tgt}" || die -q "Couldn't set new wine${v_arg#-} symlinks" -} + } + wine-foreach_slot wine-set_foreach + [[ -v display ]] || + die -q "Target '${chosen_slot:-${chosen_num}}' was not found (select from 'list' action)" + wine-update --if-unset -# lifted from fdo-mime.eclass -desktop_database_update() { - if [[ -x "${EPREFIX}/usr/bin/update-desktop-database" ]]; then -# echo "Updating desktop mime database ..." - "${EPREFIX}/usr/bin/update-desktop-database" -q "${EPREFIX}/usr/share/applications" || die - fi + echo "${display}" } -# sort function for versions, to be used in a pipe -sort_versions() { - local vsort="sort --version-sort" - # Test if our sort supports the --version-sort option (posix does) - ${vsort} </dev/null &>/dev/null || vsort=sort - - # We sort versions as follows: - # 1. Run sed to prepend the version string by the numeric version - # 1.7.21 wine-1.7.21 - # 1.7.14 wine-compholio-1.7.14 - # 2. sort --version-sort - # 3. Run sed again to remove the prepended keys from step 1. - sed -e 's/^\(.\+-\)\([[:digit:].]*\)$/\2 &/' \ - | LC_ALL=C ${vsort} | sed 's/.* //' -} +### legacy junk beyond here waiting for cleanup (~2025?) -# Takes a list of items and returns a sorted version -sort_list() { - list=($@) - if [[ ! -z "${list}" ]]; then - for i in ${list[@]}; do - echo "${i}" - done | sort_versions +wine-legacy_checks() { + # need to be ran in postrm, not pre.. so we need a way to know we + # should ignore the slot that's about to be removed (not the end + # of the world if this fails so rely on dodgy methods, dead links + # will be fixed on the next `eselect wine update`) + if [[ ${EBUILD_PHASE_FUNC} == pkg_prerm && ${P} == "${slot}" ]]; then + return 1 fi -} -# Returns a list excluding the specified item -# list_rm_item [rm_this] [list] -list_rm_item() { - if [[ $# -lt 2 ]]; then - die "Not enough arguments" + if [[ -d ${WINEREL}/usr/lib64/${slot} ]]; then + write_warning_msg "ignored legacy installation at ${EROOT}/usr/lib64/${slot}" + [[ -e ${WINEREL}/usr/bin/${slot} ]] && + write_warning_msg "should still be usable by calling versioned ${EROOT}/usr/bin/${slot}" + return 1 fi - - rm_this=$1 - shift - list=($@) - - local i - for i in ${!list[@]};do - if [ "${list[$i]}" == "${rm_this}" ]; then - unset list[$i] - fi - done - - echo ${list[@]} } -remove_symlinks() { - if [[ $# -gt 1 ]]; then - die -q "Invalid number of parameters specified" - fi - - local v="wine" - - while [[ $# -gt 0 ]]; do - if [[ $1 == --* ]]; then - local flag="${1#--}" - if has "${flag}" ${VARIANTS[@]}; then - v=${flag} - else - die -q "Invalid flag or variant" - fi - else - die -q "Invalid parameter" - fi - shift - done - - local v_arg - if [[ ${v} != "wine" ]]; then - v_arg="--${v}" - fi - - local symlink_vars=$(load_config "${CONFIG_DIR}/links/${v}" symlink_dirs) - if [[ -z "${symlink_vars}" ]]; then - return 0 - fi - local var - for var in ${symlink_vars[@]}; do - local symlinks=$(load_config "${CONFIG_DIR}/links/${v}" ${var}) - local symlink - if [[ -z "${symlinks}" ]]; then - die -q "Missing listing of ${var} symlinks" - fi - for symlink in ${symlinks[@]}; do - if [[ -e "${symlink}" ]]; then - if [[ ! -L "${symlink}" ]]; then - die -q "${symlink} is not a symlink." - fi - rm "${symlink}" || die "Failed to rm ${symlink}" - else - write_warning_msg "${symlink} symlink was missing." - fi - - # remove entry from config file - symlinks=$(list_rm_item "${symlink}" "${symlinks}") +inherit config +wine-legacy_winemap() { + # this is created by the eselect-wine ebuild to keep same slots + if [[ -f eselect-wine-migration ]]; then + local active variant + for variant in proton staging vanilla wine; do + active=$(load_config eselect-wine-migration ${variant}) + [[ ${variant} == wine ]] && variant=main + [[ ${active} ]] && WINEMAP[${variant}]=${active} done - store_config "${CONFIG_DIR}/links/${v}" ${var} "${symlinks}" - - # remove set from config file - symlink_vars=$(list_rm_item "${var}" "${symlink_vars}") - - store_config "${CONFIG_DIR}/links/${v}" symlink_dirs "${symlink_vars}" - done - - # Remove active if it exists - store_config "${CONFIG_DIR}/active" "${v}" "" - - local desktop="${EPREFIX}/usr/share/applications/wine${v_arg#-}.desktop" - if [[ -e "${desktop}" ]]; then - rm "${desktop}" || die "Failed ro remove desktop file" - fi - desktop_database_update || die "Failed to update xorg desktop database" -} - -set_symlinks() { - if [[ $# -lt 1 ]] || [[ $# -gt 2 ]]; then - die -q "Invalid number of parameters specified" - fi - - local v="wine" - - while [[ $# -gt 0 ]]; do - if [[ $1 == --* ]]; then - local flag="${1#--}" - if has "${flag}" ${VARIANTS[@]}; then - v=${flag} - else - die -q "Invalid flag or variant" - fi - else - local tgt="$1" - fi - shift - done - - if [[ -z "${tgt}" ]]; then - die -q "Target not specified" fi - - local v_arg - if [[ ${v} != "wine" ]]; then - v_arg="--${v}" - fi - - if is_number "${tgt}"; then - local tgts=($(get_installed ${v_arg})) - tgt=${tgts[${tgt}-1]} - fi - - if ! is_valid_target "${tgt}"; then - die -q "Target does not exist" - fi - - set_dir_env - - local link - local links - ( - shopt -s failglob - - store_config "${CONFIG_DIR}/links/${v}" symlink_dirs "bin" - store_config "${CONFIG_DIR}/links/${v}" "bin" "" - for b in "${wine_bin}"/*; do - link="${EPREFIX}/usr/bin/${b##*/}${v_arg#-}" - local linktgt="${EPREFIX}/usr/bin/${b##*/}${tgt##wine}" - if [[ -L "${link}" ]]; then - write_warning_msg "${link} already exists, overwriting" - rm "${link}" || die -q "Failed to rm old link: ${link}" - fi - ln -s "${linktgt}" "${link}" - if [[ $? -ne 0 ]]; then - write_warning_msg "Failed to set symlink from ${linktgt} to ${link}" - write_warning_msg "Cleaning up" - remove_symlinks ${v_arg} - fi - links="${links} ${link}" - done - store_config "${CONFIG_DIR}/links/${v}" "bin" "${links}" - - shopt -s globstar - links="" - append_config "${CONFIG_DIR}/links/${v}" symlink_dirs "man" - store_config "${CONFIG_DIR}/links/${v}" "man" "" - pushd "${wine_man}" > /dev/null - for m in **/*.1; do - link="${EPREFIX}/usr/share/man/${m}${v_arg#-}" - if [[ -L "${link}" ]]; then - write_warning_msg "${link} already exists, overwriting" - rm "${link}" || die -q "Failed to rm old link: ${link}" - fi - mkdir -p "${link%/*}" || die -q "Failed to mkdir: ${link%/*}" - ln -s "${wine_man}/${m}" "${link}" - if [[ $? -ne 0 ]]; then - write_warning_msg "Failed to set symlink from ${wine_man}/${m} to ${link}" - write_warning_msg "Cleaning up" - remove_symlinks ${v_arg} - fi - links="${links} ${link}" - done - append_config "${CONFIG_DIR}/links/${v}" "man" "${links}" - popd > /dev/null - - append_config "${CONFIG_DIR}/links/${v}" symlink_dirs "include" - store_config "${CONFIG_DIR}/links/${v}" "include" "" - link="${EPREFIX}/usr/include/wine${v_arg#-}" - local linktgt="${wine_include}" - if [[ -L "${link}" ]]; then - write_warning_msg "${link} already exists, overwriting" - rm "${link}" || die -q "Failed to rm old link: ${link}" - fi - ln -s "${linktgt}" "${link}" - if [[ $? -ne 0 ]]; then - write_warning_msg "Failed to set symlink from ${linktgt} to ${link}" - write_warning_msg "Cleaning up" - remove_symlinks ${v_arg} - fi - store_config "${CONFIG_DIR}/links/${v}" "include" "${link}" - - - local desktop="${EPREFIX}/usr/share/applications/wine${v_arg#-}.desktop" - cp "${wine_app}/wine.desktop" "${desktop}" || die "Failed to copy desktop file" - sed -i "s:Exec=.*:Exec=wine${v_arg#-} start /unix %f:" ${desktop} || die "Failed to edit desktop file" - desktop_database_update || die "Failed to update xorg desktop database" - - ) - unset_dir_env -} - -# set env vars for us to work with -set_dir_env() { - wine_bin="${EPREFIX}/usr/lib/${tgt}/bin" - wine_include="${EPREFIX}/usr/include/${tgt}/wine" - wine_share="${EPREFIX}/usr/share/${tgt}" - wine_app="${wine_share}/applications" - wine_man="${wine_share}/man" } -# unset our env vars -unset_dir_env() { - unset wine_{bin,include,share,app,man} +# no eselect method to hide options, so describe as deprecated +describe_deregister() { echo "(deprecated)"; } +do_deregister() { :; } +describe_register() { echo "(deprecated)"; } +do_register() { + write_warning_msg "'eselect wine register' is deprecated, please migrate to:" + echo ' + IDEPEND=">=app-eselect/eselect-wine-2" + pkg_postinst() { + eselect wine update --if-unset || die + } + pkg_postrm() { # /not/ prerm + eselect wine update --if-unset || die + } +' >&2 } |