# Copyright 2025 konsolebox # Distributed under the terms of the GNU General Public License v2 # @ECLASS: rubyexec-r1.eclass # @MAINTAINER: # konsolebox # @AUTHOR: # konsolebox # @SUPPORTED_EAPIS: 5 6 7 8 # @BLURB: Rubyexec-based installation helper # @DESCRIPTION: # This eclass provides helper functions for installing gem binaries # with rubyexec as their ruby implementation selector. [[ ${EAPI} == [5678] ]] || die "EAPI needs to be 5, 6, 7 or 8." inherit get-opt-and-optarg is-var-true # @ECLASS_VARIABLE: RUBYEXEC_SHEBANG_MAX_LENGTH # @DESCRIPTION: # Implied max length of a #! header : ${RUBYEXEC_SHEBANG_MAX_LENGTH=127} # @FUNCTION: _rubyexec_all_files_the_same_or_one_file_only # @USAGE: ... # @DESCRIPTION: # Checks if all specified files are the same. # @RETURN: OK status (0) if all files match or only one file was specified; FAIL status (1) otherwise # @INTERNAL _rubyexec_all_files_the_same_or_one_file_only() { local first=$1 x shift for x; do cmp -s -- "${first}" "${x}" || return 1 done return 0 } # @FUNCTION: _rubyexec_priority_sort_impls # @USAGE: ... # @DESCRIPTION: # Produces a list of ruby implementations sorted by priority # @INTERNAL _rubyexec_priority_sort_impls() { local impl i _sorted_impls=("$1") shift for impl; do if [[ ${impl} == ruby[0-9][0-9] ]]; then for i in "${!_sorted_impls[@]}"; do if [[ ${_sorted_impls[i]} != ruby[0-9][0-9] || ${impl} > "${_sorted_impls[i]}" ]]; then _sorted_impls=("${_sorted_impls[@]:0:i}" "${impl}" "${_sorted_impls[@]:i}") continue 2 fi done fi _sorted_impls+=("${impl}") done } # @FUNCTION: _rubyexec_parse_common_options # @USAGE: [] # @DESCRIPTION: # Parses commoon options passed to rubyexec_install_fakegem_binwrapper[s] # @RETURN: Parsed values to autopick, autoversion, gem_bindir, gem_name or gem_version # @INTERNAL _rubyexec_parse_common_options() { OPTSHIFT=0 case $1 in --autopick) autopick=true ;; --autoversion) autoversion=true ;; --gem-bindir|--gem-bindir=*) get_opt_and_optarg "$@" gem_bindir=${OPTARG} ;; --gem-name|--gem-name=*) get_opt_and_optarg "$@" gem_name=${OPTARG} ;; --gem-version|--gem-version=*) get_opt_and_optarg "$@" gem_version=${OPTARG} ;; *) return 1 ;; esac return 0 } # @FUNCTION: _rubyexec_create_fakegem_binwrapper # @USAGE:
[] [] # @DESCRIPTION: # Creates a wrapper binary that's to be installed in /usr/bin. # Autoversion mode is implied if gem_version and gem_bindir aren't specified. # @INTERNAL _rubyexec_create_fakegem_binwrapper() { local path=$1 header=$2 binary_name=$3 gem_name=$4 local lines=("${new_header}" "# Generated by rubyexec-r1.eclass") if [[ ${5+.} ]]; then local gem_version=$5 gem_bindir=$6 lines+=("load RbConfig::CONFIG['sitelibdir'].gsub('site_ruby', 'gems') + '/gems/${gem_name}-${gem_version}/${gem_bindir}/${binary_name}'") else lines+=("require 'rubygems'" "load Gem.activate_bin_path('${gem_name}', '${binary_name}')") fi printf '%s\n' > "${path}" "${lines[@]}" || die "Failed to write binwrapper code to '${path}'." } # @FUNCTION: _rubyexec_get_implementations # @DESCRIPTION: # Gets implementations # @RETURN: List of implementations to use to the impls variable # @INTERNAL _rubyexec_get_implementations() { if declare -f ruby_get_use_implementations >/dev/null; then impls=($(ruby_get_use_implementations)) && [[ ${impls+.} ]] || \ die "Failed to get implementations." else die "No implementations specified." fi } # @FUNCTION: _rubyexec_get_rubyexec_arg # @USAGE: ... # @DESCRIPTION: # Gets shebang argument # Autopick mode allows other non-selected version which are still in the list to be used. # @RETURN: Shebang argument to the rubyexec_arg variable # @INTERNAL _rubyexec_get_rubyexec_arg() { local autopick=$1 impls=("${@:2}") if [[ ${autopick} == true ]]; then _rubyexec_priority_sort_impls "${impls[@]}" printf -v rubyexec_arg '%s,' "${_sorted_impls[@]}" rubyexec_arg+=--autopick else printf -v rubyexec_arg '%s,' "${impls[@]}" rubyexec_arg=${rubyexec_arg%,} fi } # @FUNCTION: _rubyexec_validate_header # @USAGE:
# @DESCRIPTION: # Validates header # @INTERNAL _rubyexec_validate_header() { local header_size=${#1} [[ ${RUBYEXEC_SHEBANG_MAX_LENGTH} && RUBYEXEC_SHEBANG_MAX_LENGTH -gt 0 ]] || \ die "Invalid value for RUBYEXEC_SHEBANG_MAX_LENGTH: ${RUBYEXEC_SHEBANG_MAX_LENGTH}" [[ header_size -le RUBYEXEC_SHEBANG_MAX_LENGTH ]] || \ die "Header size exceeds maximum length: ${header_size}" } # @FUNCTION: rubyexec_install_fakegem_binwrapper # @USAGE: ... [