mirror of
https://github.com/gentoo-mirror/guru.git
synced 2025-04-18 23:39:00 -04:00
Adds support for 'show --latest' to get the latest available version of Swift on the system. Signed-off-by: Itai Ferber <itai@itaiferber.net>
290 lines
7.5 KiB
Plaintext
290 lines
7.5 KiB
Plaintext
# -*-eselect-*- vim: ft=eselect
|
|
# Copyright 2005-2025 Gentoo Authors
|
|
# Distributed under the terms of the GNU GPL version 2 or later
|
|
|
|
DESCRIPTION="Manage the Swift symlink"
|
|
MAINTAINER="itai@itaiferber.net"
|
|
VERSION="1.0"
|
|
|
|
inherit path-manipulation
|
|
|
|
BIN_DIR="${EROOT%/}/usr/bin"
|
|
|
|
### Utility Functions ###
|
|
|
|
# @FUNCTION: get_index
|
|
# @USAGE: <element> <elements>...
|
|
# @DESCRIPTION:
|
|
# Returns the index of an element in an array, or the empty string if the
|
|
# element was not found.
|
|
get_index() {
|
|
local element="$1"
|
|
shift
|
|
local i elements=( "$@" )
|
|
for i in "${!elements[@]}"; do
|
|
if [[ "${elements[i]}" = "${element}" ]]; then
|
|
echo "${i}"
|
|
return 0
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
# @FUNCTION: sort_swift_targets
|
|
# @USAGE: <target identifier>...
|
|
# @DESCRIPTION:
|
|
# Lexicographically sorts an array of Swift target identifiers.
|
|
sort_swift_targets() {
|
|
# `sort` may not support '--version-sort', so fall back on error
|
|
local vsort="sort --version-sort"
|
|
${vsort} </dev/null &>/dev/null || vsort="sort"
|
|
|
|
# Stolen from `app-eselect/eselect-luajit`: to handle potential `_beta`
|
|
# version suffixes, we:
|
|
# 1. Turn `swift-x.y.z` into `x.y.z 1 swift-x.y.z`
|
|
# 2. Turn `swift-x.y.z_beta...` into `x.y.z 0 swift-x.y.z_beta...`
|
|
# 3. Sort, which moves `_beta` versions before corresponding non-beta
|
|
# versions
|
|
# 4. Remove leading trivia
|
|
printf "%s\n" "$@" \
|
|
| sed -e 's/^\(swift-\)\?\([[:digit:].]\+\)[-_]beta/\2 0 &/' \
|
|
-e 't;s/^\(swift-\)\?\([[:digit:].]\+\)/\2 1 &/' \
|
|
| LC_ALL=C ${vsort} \
|
|
| sed 's/.* //'
|
|
}
|
|
|
|
# @FUNCTION: list_targets
|
|
# @DESCRIPTION:
|
|
# Returns a lexicographically-sorted list of Swift targets found in `BIN_DIR`.
|
|
list_targets() {
|
|
local identifiers
|
|
mapfile -t identifiers < <(find "${BIN_DIR}" -maxdepth 1 -type l -iname 'swift-[[:digit:]]*' -exec basename '{}' ';')
|
|
sort_swift_targets "${identifiers[@]}"
|
|
}
|
|
|
|
# @FUNCTION: list_target_links
|
|
# @USAGE: <target identifier>
|
|
# @DESCRIPTION:
|
|
# Given a Swift target identifier, lists all of the symlinks found in `BIN_DIR`
|
|
# that correspond to that Swift target.
|
|
list_target_links() {
|
|
local target="$1"
|
|
local version_number="${target#swift-}"
|
|
local swift_dir="$(dirname "$(canonicalise "${BIN_DIR}/${target}")")"
|
|
|
|
local files
|
|
mapfile -t files < <(find "${BIN_DIR}" -maxdepth 1 -type l -iname "*-${version_number}")
|
|
for f in "${files[@]}"; do
|
|
local d="$(dirname "$(canonicalise "${f}")")"
|
|
if [[ "${d}" == "${swift_dir}"* ]]; then
|
|
echo "${f}"
|
|
fi
|
|
done
|
|
}
|
|
|
|
# @FUNCTION: current_target_index
|
|
# @USAGE: <target identifier>...
|
|
# @DESCRIPTION:
|
|
# Returns the index of the currently-set target from the given list of available
|
|
# Swift targets. If `/usr/bin/swift` does not point to any of the given Swift
|
|
# targets, returns an empty string.
|
|
current_target_index() {
|
|
local t canonical_targets=()
|
|
for t in "$@"; do
|
|
canonical_targets+=("$(canonicalise "${BIN_DIR}/${t}")")
|
|
done
|
|
|
|
local canonical_swift_path="$(canonicalise "${BIN_DIR}/swift")"
|
|
get_index "${canonical_swift_path}" "${canonical_targets[@]}"
|
|
}
|
|
|
|
# @FUNCTION: current_target
|
|
# @USAGE: <target identifier>...
|
|
# @DESCRIPTION:
|
|
# Returns the target identifier of the currently-set target from the given list
|
|
# of available Swift targets. If `/usr/bin/swift` does not point to any of the
|
|
# given Swift targets, returns an empty string.
|
|
current_target() {
|
|
local targets=( "$@" )
|
|
local target="$(current_target_index "${targets[@]}")"
|
|
if is_number "${target}"; then
|
|
echo "${targets[target]}"
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# @FUNCTION: unset_target
|
|
# @USAGE: <target identifier>
|
|
# @DESCRIPTION:
|
|
# Unsets any unversioned links in `BIN_DIR` if they point to the given Swift
|
|
# target identifier.
|
|
unset_target() {
|
|
local target="$1"
|
|
local version_number="${target#swift-}"
|
|
|
|
local links
|
|
mapfile -t links < <(list_target_links "${target}")
|
|
|
|
local link
|
|
for link in "${links[@]}"; do
|
|
local unversioned_link="${link%-"${version_number}"}"
|
|
if [[ "$(canonicalise "${link}")" = "$(canonicalise "${unversioned_link}")" ]]; then
|
|
rm "${unversioned_link}" || die -q "Couldn't remove symlink '${unversioned_link}'"
|
|
fi
|
|
done
|
|
}
|
|
|
|
# @FUNCTION: set_target
|
|
# @USAGE: <target identifier> <target identifiers>...
|
|
# @DESCRIPTION:
|
|
# Unsets the current Swift target and sets unversioned symlinks in `BIN_DIR` for
|
|
# the given Swift target identifier. Does nothing if the given target identifier
|
|
# is the same as the current target identifier.
|
|
set_target() {
|
|
local target="$1"
|
|
shift
|
|
local current_target="$(current_target "$@")"
|
|
if [[ "${target}" = "${current_target}" ]]; then
|
|
return
|
|
fi
|
|
|
|
unset_target "${current_target}"
|
|
|
|
local version_number="${target#swift-}"
|
|
local links
|
|
mapfile -t links < <(list_target_links "${target}")
|
|
|
|
local link
|
|
for link in "${links[@]}"; do
|
|
local unversioned_link="${link%-"${version_number}"}"
|
|
ln -fs "${link}" "${unversioned_link}" || die -q "Couldn't create symlink '${unversioned_link}'"
|
|
done
|
|
}
|
|
|
|
### List Action ###
|
|
|
|
describe_list() {
|
|
echo "Lists available Swift versions"
|
|
}
|
|
|
|
do_list() {
|
|
local targets
|
|
mapfile -t targets < <(list_targets)
|
|
if [[ -n "${targets}" ]]; then
|
|
local current_target="$(current_target_index "${targets[@]}")"
|
|
|
|
if is_number "${current_target}"; then
|
|
targets[current_target]="$(highlight_marker "${targets[current_target]}")"
|
|
fi
|
|
|
|
write_list_start "Available Swift versions:"
|
|
write_numbered_list "${targets[@]}"
|
|
else
|
|
write_list_start "No available Swift versions"
|
|
fi
|
|
}
|
|
|
|
### Show Action ###
|
|
|
|
describe_show() {
|
|
echo "Show the current Swift implementation"
|
|
}
|
|
|
|
describe_show_options() {
|
|
echo "--latest : Show the latest available Swift implementation"
|
|
}
|
|
|
|
do_show() {
|
|
local show_latest=false
|
|
if [[ $# -gt 0 && "$1" = "--latest" ]]; then
|
|
show_latest=true
|
|
shift
|
|
fi
|
|
|
|
[[ $# -eq 0 ]] || die "'show' takes only '--latest' as a parameter"
|
|
|
|
local targets
|
|
mapfile -t targets < <(list_targets)
|
|
|
|
if [[ -z "${targets[@]}" ]]; then
|
|
write_list_start "No available Swift versions"
|
|
elif [[ "${show_latest}" = 'true' ]]; then
|
|
write_list_start "Latest Swift implementation:"
|
|
write_kv_list_entry "${targets[-1]}"
|
|
else
|
|
write_list_start "Current Swift implementation:"
|
|
local target="$(current_target "${targets[@]}")"
|
|
write_kv_list_entry "${target:-(unset)}"
|
|
fi
|
|
}
|
|
|
|
### Set Action ###
|
|
|
|
describe_set() {
|
|
echo "Set active Swift version"
|
|
}
|
|
|
|
describe_set_parameters() {
|
|
echo "<target>"
|
|
}
|
|
|
|
describe_set_options() {
|
|
echo "target : Target number or name (from 'list')"
|
|
}
|
|
|
|
do_set() {
|
|
[[ $# -eq 0 || -z "$1" ]] && die -q "No Swift version specified"
|
|
[[ $# -gt 1 ]] && die -q "'set' takes only one parameter"
|
|
|
|
local targets
|
|
mapfile -t targets < <(list_targets)
|
|
|
|
local target="$1"
|
|
if is_number "${target}"; then
|
|
[[ "$target" -gt 0 && "$1" -le "${#targets[@]}" ]] || die -q "'$1' is not a valid target"
|
|
target="${targets[target-1]}"
|
|
else
|
|
target_index="$(get_index "$1" "${targets[@]}")"
|
|
is_number "${target_index}" || die -q "'$1' is not a valid target"
|
|
fi
|
|
|
|
set_target "${target}" "${targets[@]}"
|
|
}
|
|
|
|
### Unset Action ###
|
|
|
|
describe_unset() {
|
|
echo "Unsets any active Swift version"
|
|
}
|
|
|
|
do_unset() {
|
|
[[ $# -eq 0 ]] || die -q "'unset' does not take any parameters"
|
|
local targets
|
|
mapfile -t targets < <(list_targets)
|
|
local target="$(current_target "${targets[@]}")"
|
|
unset_target "${target}"
|
|
}
|
|
|
|
### Update Action ###
|
|
|
|
describe_update() {
|
|
echo "Switch to the most recent Swift version"
|
|
}
|
|
|
|
do_update() {
|
|
[[ $# -eq 0 ]] || die -q "'update' does not take any parameters"
|
|
|
|
local targets
|
|
mapfile -t targets < <(list_targets)
|
|
[[ "${#targets[@]}" -gt 0 ]] || die -q "No Swift versions found"
|
|
|
|
local target="$(current_target "${targets[@]}")"
|
|
if [[ -n "${target}" ]]; then
|
|
unset_target "${target}"
|
|
fi
|
|
|
|
local new_target="${targets[-1]}"
|
|
set_target "${new_target}" "${targets[@]}"
|
|
}
|