From 0b472b7aaa67477697bd522805ba9387f4cb40bc Mon Sep 17 00:00:00 2001 From: Venkumahanti Subhankar Date: Thu, 11 Jun 2026 10:36:24 +0000 Subject: [PATCH 1/2] Fix relative symlink resolution in install script --- scripts/install.sh | 2 +- scripts/install.test.sh | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/scripts/install.sh b/scripts/install.sh index e44a36712..88e853e14 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -424,7 +424,7 @@ set -e # Handle both direct execution and symlinked scenarios if [ -L "$0" ]; then # Follow symlink - SCRIPT_PATH="$(readlink "$0" 2>/dev/null || readlink -f "$0" 2>/dev/null || echo "$0")" + SCRIPT_PATH="$(readlink -f "$0" 2>/dev/null || readlink "$0" 2>/dev/null || echo "$0")" else SCRIPT_PATH="$0" fi diff --git a/scripts/install.test.sh b/scripts/install.test.sh index 2a73b883e..3e2a972d9 100755 --- a/scripts/install.test.sh +++ b/scripts/install.test.sh @@ -447,6 +447,37 @@ test_wrapper_via_symlink() { teardown } +# ── Tests: wrapper via relative symlink from different directory ── + +test_wrapper_via_relative_symlink() { + printf '%b\n' "${C_BOLD}Wrapper works via relative symlink from different directory${C_RESET}" + setup + + prefix="$TEST_TMPDIR/devcontainers" + cli_version="0.75.0" + + sh "$INSTALL_SCRIPT" --prefix "$prefix" --version "$cli_version" >/dev/null 2>&1 + + # Create a RELATIVE symlink in a different directory + link_dir="$TEST_TMPDIR/bin" + mkdir -p "$link_dir" + + # Create relative symlink that points back to the wrapper + ln -s ../devcontainers/bin/devcontainer "$link_dir/devcontainer" + assert_symlink "$link_dir/devcontainer" "relative symlink created" + + # Call from a different directory + cwd_before=$(pwd) + cd "$TEST_TMPDIR" + version_output=$("$link_dir/devcontainer" --version 2>/dev/null) && wrc=0 || wrc=$? + + cd "$cwd_before" + assert_exit_code "0" "$wrc" "relative symlink works from different directory" + assert_contains "$version_output" "$cli_version" "relative symlink wrapper reports version" + + teardown +} + # ── Tests: install to path with spaces ──────────────────────────── test_path_with_spaces() { From 5dce88c604ec0c37221e69fe988773efbecf3bf7 Mon Sep 17 00:00:00 2001 From: Venkumahanti Subhankar Date: Mon, 22 Jun 2026 08:50:32 +0000 Subject: [PATCH 2/2] fix: rewrite wrapper symlink resolution for portability and backward compatibility --- scripts/install.sh | 28 +++++++++++++++++++--------- scripts/install.test.sh | 2 ++ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/scripts/install.sh b/scripts/install.sh index 88e853e14..21bc2cfd5 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -422,16 +422,26 @@ set -e # Resolve the installation directory # Handle both direct execution and symlinked scenarios -if [ -L "$0" ]; then - # Follow symlink - SCRIPT_PATH="$(readlink -f "$0" 2>/dev/null || readlink "$0" 2>/dev/null || echo "$0")" -else - SCRIPT_PATH="$0" -fi +# Uses portable shell built-ins instead of GNU-specific readlink -f and realpath +# Ignores inherited CDPATH, then resolves the script directory and its parent path +SCRIPT_DIR="$( + CDPATH= + self=$0 + + # follow the symlink chain one hop at a time so relative targets resolve correctly + while [ -L "$self" ]; do + cd -- "${self%/*}" >/dev/null || : + self=$(readlink "${self##*/}") + done + + case "$self" in + (*/*) ;; + (*) self=./$self ;; + esac -# Get absolute path to script directory -SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_PATH")" && pwd)" -INSTALL_DIR="$(dirname "$SCRIPT_DIR")" + cd -P -- "${self%/*}" >/dev/null && pwd +)" +INSTALL_DIR="$(dirname -- "$SCRIPT_DIR")" # Paths to bundled components NODE_BIN="$INSTALL_DIR/node/current/bin/node" diff --git a/scripts/install.test.sh b/scripts/install.test.sh index 3e2a972d9..74b84fb3a 100755 --- a/scripts/install.test.sh +++ b/scripts/install.test.sh @@ -592,6 +592,8 @@ test_wrapper_missing_cli printf '\n' test_wrapper_via_symlink printf '\n' +test_wrapper_via_relative_symlink +printf '\n' test_path_with_spaces printf '\n' test_version_equals_form