Skip to content

Commit a415bfc

Browse files
committed
fix(upgrade): support multi-version tool pinning and improve prompts
- pin_version.sh: Handle multi-version tools (e.g., go@1.24) using pinned_versions object in catalog instead of looking for go@1.24.json - unpin_version.sh: Mirror support for multi-version tools - catalog.sh: Add catalog_get_pinned_version() function for version-cycle specific pin lookups - guide.sh: Check pinned_versions for multi-version tools before prompting - guide.sh: Change default prompt to Y for updates, N for installs Multi-version pins are stored as: "pinned_versions": {"1.24": "never", "1.25": "1.25.3"}
1 parent 8218265 commit a415bfc

4 files changed

Lines changed: 174 additions & 50 deletions

File tree

scripts/guide.sh

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -245,19 +245,29 @@ process_tool() {
245245
printf " will run: scripts/%s\n" "$install_cmd"
246246

247247
# Prompt with options explained
248+
# Default: Y for updates (tool installed), N for installs (new tool)
248249
printf " Options:\n"
249-
printf " y = Install/upgrade now\n"
250-
printf " a = Always update (install now + auto-update in future)\n"
251-
printf " N = Skip (ask again next time)\n"
252250
if [ -n "$installed" ]; then
251+
printf " Y = Upgrade now (default)\n"
252+
printf " a = Always update (upgrade now + auto-update in future)\n"
253+
printf " n = Skip (ask again next time)\n"
253254
printf " s = Skip version %s (ask again if newer available)\n" "$latest"
254255
printf " p = Pin to %s (don't ask for upgrades)\n" "$installed"
255256
else
257+
printf " y = Install now\n"
258+
printf " a = Always update (install now + auto-update in future)\n"
259+
printf " N = Skip (default, ask again next time)\n"
256260
printf " s = Skip version %s (ask again if newer available)\n" "$latest"
257261
printf " p = Never install (permanently skip this tool)\n"
258262
fi
259263

260-
local prompt_text="Install/update? [y/a/N/s/p] "
264+
# Different defaults: Y for update, N for install
265+
local prompt_text
266+
if [ -n "$installed" ]; then
267+
prompt_text="Upgrade? [Y/a/n/s/p] "
268+
else
269+
prompt_text="Install? [y/a/N/s/p] "
270+
fi
261271

262272
local ans=""
263273
if [ -t 0 ]; then
@@ -266,6 +276,16 @@ process_tool() {
266276
read -r -p "$prompt_text" ans </dev/tty || true
267277
fi
268278

279+
# Handle default based on install vs update
280+
# Empty answer = default (Y for update, N for install)
281+
if [ -z "$ans" ]; then
282+
if [ -n "$installed" ]; then
283+
ans="y" # Default to yes for updates
284+
else
285+
ans="n" # Default to no for installs
286+
fi
287+
fi
288+
269289
case "$ans" in
270290
[Yy])
271291
# Handle tool-specific version environment variables
@@ -425,15 +445,27 @@ while read -r line; do
425445
# Check if tool is pinned (use catalog name for pin check)
426446
pinned_version="$(catalog_get_property "$catalog_name" pinned_version)"
427447

428-
# Skip if pinned to "never" (permanently skip installation)
429-
if [ "$pinned_version" = "never" ]; then
430-
continue
431-
fi
448+
# For multi-version tools, check pinned_versions object
449+
if [ -n "$is_multi_version" ]; then
450+
version_cycle="${tool_name##*@}"
451+
multi_pin="$(catalog_get_pinned_version "$catalog_name" "$version_cycle")"
452+
if [ "$multi_pin" = "never" ]; then
453+
continue
454+
fi
455+
# Skip if this specific version cycle is pinned
456+
if [ -n "$multi_pin" ]; then
457+
continue
458+
fi
459+
else
460+
# Skip if pinned to "never" (permanently skip installation)
461+
if [ "$pinned_version" = "never" ]; then
462+
continue
463+
fi
432464

433-
# Skip if pinned to any specific version (don't prompt for upgrades)
434-
# But allow multi-version tools to be processed individually
435-
if [ -n "$pinned_version" ] && [ -z "$is_multi_version" ]; then
436-
continue
465+
# Skip if pinned to any specific version (don't prompt for upgrades)
466+
if [ -n "$pinned_version" ]; then
467+
continue
468+
fi
437469
fi
438470

439471
# Skip installed tools with upstream_method="skip" (package-manager-only tools)

scripts/lib/catalog.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,22 @@ catalog_get_property() {
5656
fi
5757
}
5858

59+
# Get pinned version for a specific version cycle (multi-version tools)
60+
catalog_get_pinned_version() {
61+
local tool="$1"
62+
local version_cycle="$2"
63+
local catalog_dir="$ROOT/catalog"
64+
65+
if ! command -v jq >/dev/null 2>&1; then
66+
return
67+
fi
68+
69+
local json="$catalog_dir/$tool.json"
70+
if [ -f "$json" ]; then
71+
jq -r --arg cycle "$version_cycle" '.pinned_versions[$cycle] // empty' "$json"
72+
fi
73+
}
74+
5975
# Get guide-specific metadata from catalog
6076
catalog_get_guide_property() {
6177
local tool="$1"

scripts/pin_version.sh

Lines changed: 66 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,45 +13,87 @@ if [ -z "$TOOL" ]; then
1313
echo "" >&2
1414
echo "Pin a tool to a specific version to suppress upgrade prompts." >&2
1515
echo "If VERSION is omitted, uses the currently installed version." >&2
16+
echo "" >&2
17+
echo "For multi-version tools (e.g., go@1.24, php@8.3):" >&2
18+
echo " $0 go@1.24 never # Never prompt for this version cycle" >&2
19+
echo " $0 php@8.3 8.3.15 # Pin to specific patch version" >&2
1620
exit 1
1721
fi
1822

19-
CATALOG_FILE="$ROOT/catalog/$TOOL.json"
23+
# Handle multi-version tools (e.g., go@1.24 -> base=go, cycle=1.24)
24+
BASE_TOOL="$TOOL"
25+
VERSION_CYCLE=""
26+
IS_MULTI_VERSION=""
27+
28+
if [[ "$TOOL" == *"@"* ]]; then
29+
BASE_TOOL="${TOOL%%@*}"
30+
VERSION_CYCLE="${TOOL#*@}"
31+
IS_MULTI_VERSION="true"
32+
fi
33+
34+
CATALOG_FILE="$ROOT/catalog/$BASE_TOOL.json"
2035
if [ ! -f "$CATALOG_FILE" ]; then
21-
echo "Error: Tool '$TOOL' not found in catalog" >&2
36+
echo "Error: Tool '$BASE_TOOL' not found in catalog" >&2
2237
exit 1
2338
fi
2439

25-
# If no version provided, get current installed version
40+
# If no version provided, get current installed version or use "never" for multi-version
2641
if [ -z "$VERSION" ]; then
27-
# Try to get version from tool
28-
BINARY_NAME="$(jq -r '.binary_name // .name' "$CATALOG_FILE")"
42+
if [ -n "$IS_MULTI_VERSION" ]; then
43+
# For multi-version tools without explicit version, default to "never"
44+
VERSION="never"
45+
else
46+
# Try to get version from tool
47+
BINARY_NAME="$(jq -r '.binary_name // .name' "$CATALOG_FILE")"
2948

30-
if command -v "$BINARY_NAME" >/dev/null 2>&1; then
31-
# Try various version command formats
32-
VERSION="$(timeout 2 "$BINARY_NAME" --version </dev/null 2>/dev/null | head -1 | grep -oE '[0-9]+\.[0-9]+(\.[0-9]+)?' | head -1 || true)"
49+
if command -v "$BINARY_NAME" >/dev/null 2>&1; then
50+
# Try various version command formats
51+
VERSION="$(timeout 2 "$BINARY_NAME" --version </dev/null 2>/dev/null | head -1 | grep -oE '[0-9]+\.[0-9]+(\.[0-9]+)?' | head -1 || true)"
3352

34-
if [ -z "$VERSION" ]; then
35-
echo "Error: Could not detect current version for '$TOOL'" >&2
53+
if [ -z "$VERSION" ]; then
54+
echo "Error: Could not detect current version for '$TOOL'" >&2
55+
echo "Please specify version explicitly: $0 $TOOL VERSION" >&2
56+
exit 1
57+
fi
58+
else
59+
echo "Error: '$BINARY_NAME' not installed, cannot detect version" >&2
3660
echo "Please specify version explicitly: $0 $TOOL VERSION" >&2
3761
exit 1
3862
fi
39-
else
40-
echo "Error: '$BINARY_NAME' not installed, cannot detect version" >&2
41-
echo "Please specify version explicitly: $0 $TOOL VERSION" >&2
42-
exit 1
4363
fi
4464
fi
4565

46-
echo "Pinning '$TOOL' to version $VERSION..."
66+
# Handle multi-version tools differently
67+
if [ -n "$IS_MULTI_VERSION" ]; then
68+
echo "Pinning '$TOOL' (version cycle $VERSION_CYCLE) to: $VERSION..."
4769

48-
# Update catalog with pinned_version field
49-
TMP_FILE=$(mktemp)
50-
jq --arg version "$VERSION" '. + {pinned_version: $version}' "$CATALOG_FILE" > "$TMP_FILE"
51-
mv "$TMP_FILE" "$CATALOG_FILE"
70+
# Update catalog with pinned_versions object
71+
TMP_FILE=$(mktemp)
72+
jq --arg cycle "$VERSION_CYCLE" --arg version "$VERSION" \
73+
'.pinned_versions = ((.pinned_versions // {}) + {($cycle): $version})' \
74+
"$CATALOG_FILE" > "$TMP_FILE"
75+
mv "$TMP_FILE" "$CATALOG_FILE"
5276

53-
echo "✓ Pinned '$TOOL' to version $VERSION"
54-
echo ""
55-
echo "This tool will no longer appear in upgrade prompts unless:"
56-
echo " - A version newer than $VERSION is available AND"
57-
echo " - You remove the pin with: ./scripts/unpin_version.sh $TOOL"
77+
echo "✓ Pinned '$TOOL' to: $VERSION"
78+
echo ""
79+
if [ "$VERSION" = "never" ]; then
80+
echo "This version cycle will never appear in upgrade prompts."
81+
else
82+
echo "This version cycle will no longer appear in upgrade prompts unless:"
83+
echo " - A version newer than $VERSION is available"
84+
fi
85+
echo "To remove the pin: ./scripts/unpin_version.sh $TOOL"
86+
else
87+
echo "Pinning '$TOOL' to version $VERSION..."
88+
89+
# Update catalog with pinned_version field
90+
TMP_FILE=$(mktemp)
91+
jq --arg version "$VERSION" '. + {pinned_version: $version}' "$CATALOG_FILE" > "$TMP_FILE"
92+
mv "$TMP_FILE" "$CATALOG_FILE"
93+
94+
echo "✓ Pinned '$TOOL' to version $VERSION"
95+
echo ""
96+
echo "This tool will no longer appear in upgrade prompts unless:"
97+
echo " - A version newer than $VERSION is available AND"
98+
echo " - You remove the pin with: ./scripts/unpin_version.sh $TOOL"
99+
fi

scripts/unpin_version.sh

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,29 +11,63 @@ if [ -z "$TOOL" ]; then
1111
echo "Usage: $0 TOOL_NAME" >&2
1212
echo "" >&2
1313
echo "Remove version pin from a tool to resume upgrade prompts." >&2
14+
echo "" >&2
15+
echo "For multi-version tools (e.g., go@1.24, php@8.3):" >&2
16+
echo " $0 go@1.24 # Remove pin for this version cycle" >&2
1417
exit 1
1518
fi
1619

17-
CATALOG_FILE="$ROOT/catalog/$TOOL.json"
20+
# Handle multi-version tools (e.g., go@1.24 -> base=go, cycle=1.24)
21+
BASE_TOOL="$TOOL"
22+
VERSION_CYCLE=""
23+
IS_MULTI_VERSION=""
24+
25+
if [[ "$TOOL" == *"@"* ]]; then
26+
BASE_TOOL="${TOOL%%@*}"
27+
VERSION_CYCLE="${TOOL#*@}"
28+
IS_MULTI_VERSION="true"
29+
fi
30+
31+
CATALOG_FILE="$ROOT/catalog/$BASE_TOOL.json"
1832
if [ ! -f "$CATALOG_FILE" ]; then
19-
echo "Error: Tool '$TOOL' not found in catalog" >&2
33+
echo "Error: Tool '$BASE_TOOL' not found in catalog" >&2
2034
exit 1
2135
fi
2236

23-
# Check if pinned
24-
PINNED_VERSION="$(jq -r '.pinned_version // empty' "$CATALOG_FILE")"
25-
if [ -z "$PINNED_VERSION" ]; then
26-
echo "Tool '$TOOL' is not pinned" >&2
27-
exit 0
28-
fi
37+
# Handle multi-version tools differently
38+
if [ -n "$IS_MULTI_VERSION" ]; then
39+
# Check if pinned in pinned_versions object
40+
PINNED_VALUE="$(jq -r --arg cycle "$VERSION_CYCLE" '.pinned_versions[$cycle] // empty' "$CATALOG_FILE")"
41+
if [ -z "$PINNED_VALUE" ]; then
42+
echo "Tool '$TOOL' is not pinned" >&2
43+
exit 0
44+
fi
2945

30-
echo "Removing version pin for '$TOOL' (was pinned to $PINNED_VERSION)..."
46+
echo "Removing version pin for '$TOOL' (was pinned to: $PINNED_VALUE)..."
3147

32-
# Remove pinned_version field from catalog
33-
TMP_FILE=$(mktemp)
34-
jq 'del(.pinned_version)' "$CATALOG_FILE" > "$TMP_FILE"
35-
mv "$TMP_FILE" "$CATALOG_FILE"
48+
# Remove specific cycle from pinned_versions object
49+
TMP_FILE=$(mktemp)
50+
jq --arg cycle "$VERSION_CYCLE" 'del(.pinned_versions[$cycle]) | if .pinned_versions == {} then del(.pinned_versions) else . end' "$CATALOG_FILE" > "$TMP_FILE"
51+
mv "$TMP_FILE" "$CATALOG_FILE"
52+
53+
echo "✓ Removed pin for '$TOOL'"
54+
else
55+
# Check if pinned
56+
PINNED_VERSION="$(jq -r '.pinned_version // empty' "$CATALOG_FILE")"
57+
if [ -z "$PINNED_VERSION" ]; then
58+
echo "Tool '$TOOL' is not pinned" >&2
59+
exit 0
60+
fi
61+
62+
echo "Removing version pin for '$TOOL' (was pinned to $PINNED_VERSION)..."
63+
64+
# Remove pinned_version field from catalog
65+
TMP_FILE=$(mktemp)
66+
jq 'del(.pinned_version)' "$CATALOG_FILE" > "$TMP_FILE"
67+
mv "$TMP_FILE" "$CATALOG_FILE"
68+
69+
echo "✓ Removed pin for '$TOOL'"
70+
fi
3671

37-
echo "✓ Removed pin for '$TOOL'"
3872
echo ""
3973
echo "This tool will now appear in upgrade prompts when updates are available."

0 commit comments

Comments
 (0)