Skip to content

Commit b879a4d

Browse files
committed
Support building with version prefix
Commonly in CI pipelines and other scripts, users may want to install the latest from a specific series, e.g. `3.4` or `jruby-10.0`. ```bash $ bin/ruby-build 3.4 /tmp/3.4 ... Downloading ruby-3.4.9.tar.gz... $ bin/ruby-build 4.0 /tmp/4.0 ... Downloading ruby-4.0.2.tar.gz... ``` Also support `--resolve`: ```bash $ bin/ruby-build --resolve 3.4 3.4.9 ```
1 parent aa270b3 commit b879a4d

3 files changed

Lines changed: 134 additions & 2 deletions

File tree

bin/ruby-build

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
#
33
# Usage: ruby-build [-dvpk] <definition> <prefix> [-- <configure-args...>]
44
# ruby-build {--list|--definitions}
5+
# ruby-build {--resolve} <version>
56
# ruby-build --version
67
#
78
# -l, --list List latest stable releases for each Ruby
9+
# -r, --resolve Find the most recent version matching a prefix.
810
# --definitions List all local definitions, including outdated ones
911
# --version Show version of ruby-build
1012
#
@@ -1401,6 +1403,52 @@ list_maintained_versions() {
14011403
} | extract_latest_versions | sort_versions | uniq
14021404
}
14031405

1406+
filter_version_prefix()
1407+
{
1408+
match=1
1409+
prefix="$1"
1410+
if [[ "${prefix}" = "ruby" ]]; then
1411+
# Filter MRI versions
1412+
grep -e '^[0-9]'
1413+
elif echo "${prefix}" | grep -e '^\([0-9]\|[a-z\+]\+-[0-9]\)' > /dev/null; then
1414+
# Filter by version prefix
1415+
while IFS= read -r version; do
1416+
if [[ "${version}" = "${prefix}" ]] || [[ "${version}" = "${prefix}."* ]]; then
1417+
match=0
1418+
echo "${version}"
1419+
fi
1420+
done
1421+
else
1422+
# Filter by implementation
1423+
while IFS= read -r version; do
1424+
if [[ "${version}" = "${prefix}-"* ]]; then
1425+
match=0
1426+
echo "${version}"
1427+
fi
1428+
done
1429+
fi
1430+
return $match
1431+
}
1432+
1433+
resolve() {
1434+
prefix="${1%.}"
1435+
prefix="${prefix#ruby-}"
1436+
1437+
list_definitions | \
1438+
grep -v -e '-rc[0-9]*$' -e '-preview[0-9]*$' -e '-dev$' | \
1439+
filter_version_prefix "${prefix}" | \
1440+
LC_ALL=C sort -t. -k 1,1 -k 2,2n -k 3,3n -k 4,4n -k 5,5n | \
1441+
tail -n 1
1442+
}
1443+
1444+
resolve_version() {
1445+
version=$(resolve "$@")
1446+
if [[ -z "${version}" ]]; then
1447+
exit 1
1448+
fi
1449+
echo "${version}"
1450+
}
1451+
14041452
extract_latest_versions() {
14051453
# sort in this function looks redundunt but it is necessary
14061454
# rbx-3.99 appears latest unless the sort
@@ -1443,6 +1491,9 @@ for option in "${OPTIONS[@]}"; do
14431491
"l" | "list")
14441492
EARLY_EXIT=list_maintained_versions
14451493
;;
1494+
"r" | "resolve")
1495+
EARLY_EXIT=resolve_version
1496+
;;
14461497
"d" | "dir")
14471498
APPEND_DEFINITION_TO_PREFIX=true
14481499
;;
@@ -1507,8 +1558,9 @@ help )
15071558
echo
15081559
usage 0
15091560
;;
1510-
version | list_definitions | list_maintained_versions )
1511-
"$EARLY_EXIT"
1561+
version | list_definitions | list_maintained_versions | resolve_version )
1562+
shift
1563+
"$EARLY_EXIT" "$@"
15121564
exit 0
15131565
;;
15141566
usage_error )
@@ -1543,6 +1595,16 @@ if [[ ! -f "$DEFINITION_PATH" && ! -p "$DEFINITION_PATH" ]]; then
15431595
done
15441596
fi
15451597

1598+
if [ ! -f "$DEFINITION_PATH" ]; then
1599+
fully_qualified_version=$(resolve "$DEFINITION_PATH")
1600+
for DEFINITION_DIR in "${RUBY_BUILD_DEFINITIONS[@]}"; do
1601+
if [ -f "${DEFINITION_DIR}/${fully_qualified_version}" ]; then
1602+
DEFINITION_PATH="${DEFINITION_DIR}/${fully_qualified_version}"
1603+
break
1604+
fi
1605+
done
1606+
fi
1607+
15461608
if [ ! -f "$DEFINITION_PATH" ]; then
15471609
echo "ruby-build: definition not found: ${DEFINITION_PATH}" >&2
15481610
exit 2

test/definitions.bats

100644100755
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,76 @@ NUM_DEFINITIONS="$(ls "$BATS_TEST_DIRNAME"/../share/ruby-build | wc -l)"
6060
assert_success ""
6161
}
6262

63+
@test "installing definition by prefix" {
64+
export RUBY_BUILD_DEFINITIONS="${TMP}/definitions"
65+
mkdir -p "${TMP}/definitions"
66+
67+
echo false > "${TMP}/definitions/1.8.6"
68+
echo false > "${TMP}/definitions/1.9.3"
69+
echo true > "${TMP}/definitions/1.9.10"
70+
echo false > "${TMP}/definitions/1.90.0"
71+
echo false > "${TMP}/definitions/2.0.0"
72+
73+
run bin/ruby-build "1.9" "${TMP}/install"
74+
assert_success ""
75+
}
76+
77+
@test "resolve definition by version prefix" {
78+
export RUBY_BUILD_DEFINITIONS="${TMP}/definitions"
79+
mkdir -p "${TMP}/definitions"
80+
81+
touch "${TMP}/definitions/1.8.6"
82+
touch "${TMP}/definitions/1.9.3"
83+
touch "${TMP}/definitions/1.9.10"
84+
touch "${TMP}/definitions/1.90.0"
85+
touch "${TMP}/definitions/2.0.0"
86+
87+
run bin/ruby-build -r "1.9" "${TMP}/install"
88+
assert_success "1.9.10"
89+
}
90+
91+
@test "resolve definition with ruby prefix" {
92+
export RUBY_BUILD_DEFINITIONS="${TMP}/definitions"
93+
mkdir -p "${TMP}/definitions"
94+
95+
touch "${TMP}/definitions/1.8.6"
96+
touch "${TMP}/definitions/1.9.3"
97+
touch "${TMP}/definitions/1.9.10"
98+
touch "${TMP}/definitions/1.90.0"
99+
touch "${TMP}/definitions/2.0.0"
100+
101+
run bin/ruby-build -r "ruby-1.9" "${TMP}/install"
102+
assert_success "1.9.10"
103+
}
104+
105+
@test "resolve definition by implementation name" {
106+
export RUBY_BUILD_DEFINITIONS="${TMP}/definitions"
107+
mkdir -p "${TMP}/definitions"
108+
109+
touch "${TMP}/definitions/foo-1.8.6"
110+
touch "${TMP}/definitions/foo-1.9.3"
111+
touch "${TMP}/definitions/1.9.10"
112+
touch "${TMP}/definitions/1.90.0"
113+
touch "${TMP}/definitions/2.0.0"
114+
115+
run bin/ruby-build -r "foo" "${TMP}/install"
116+
assert_success "foo-1.9.3"
117+
}
118+
119+
@test "resolve definition by implementation name and version" {
120+
export RUBY_BUILD_DEFINITIONS="${TMP}/definitions"
121+
mkdir -p "${TMP}/definitions"
122+
123+
touch "${TMP}/definitions/foo-1.8.6"
124+
touch "${TMP}/definitions/foo-1.9.3"
125+
touch "${TMP}/definitions/1.9.10"
126+
touch "${TMP}/definitions/1.90.0"
127+
touch "${TMP}/definitions/2.0.0"
128+
129+
run bin/ruby-build -r "foo-1.8" "${TMP}/install"
130+
assert_success "foo-1.8.6"
131+
}
132+
63133
@test "installing nonexistent definition" {
64134
run ruby-build "nonexistent" "${TMP}/install"
65135
assert [ "$status" -eq 2 ]

test/installer.bats

100644100755
File mode changed.

0 commit comments

Comments
 (0)