Skip to content

Commit e8312bd

Browse files
fix(acfs): canonicalize offline pack resume paths
1 parent 41f0c3d commit e8312bd

2 files changed

Lines changed: 113 additions & 3 deletions

File tree

install.sh

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1415,6 +1415,55 @@ acfs_require_ref_arg_value() {
14151415
esac
14161416
}
14171417

1418+
acfs_resolve_offline_pack_dir() {
1419+
local flag="$1"
1420+
local value="${2:-}"
1421+
local candidate=""
1422+
local resolved=""
1423+
1424+
if [[ -z "$value" || "$value" == -* ]]; then
1425+
log_fatal "$flag requires a directory"
1426+
fi
1427+
if [[ "$value" == *$'\n'* || "$value" == *$'\r'* ]]; then
1428+
log_fatal "$flag requires a single-line directory"
1429+
fi
1430+
1431+
case "$value" in
1432+
/*) candidate="$value" ;;
1433+
*) candidate="$PWD/$value" ;;
1434+
esac
1435+
candidate="${candidate%/}"
1436+
1437+
if [[ -z "$candidate" || ! -d "$candidate" ]]; then
1438+
log_fatal "$flag must point to an existing extracted offline pack directory (got: $value)"
1439+
fi
1440+
1441+
resolved="$(cd "$candidate" && pwd -P)" || {
1442+
log_fatal "$flag could not resolve directory: $value"
1443+
}
1444+
1445+
if [[ ! -r "$resolved/manifest.json" && ! -r "$resolved/acfs-offline-pack/manifest.json" ]]; then
1446+
log_fatal "$flag must point to acfs-offline-pack/ or its parent directory with manifest.json"
1447+
fi
1448+
1449+
printf '%s\n' "$resolved"
1450+
}
1451+
1452+
acfs_normalize_offline_pack_configuration() {
1453+
if [[ -z "${ACFS_OFFLINE_PACK:-}" ]]; then
1454+
return 0
1455+
fi
1456+
1457+
ACFS_OFFLINE_PACK="$(acfs_resolve_offline_pack_dir "ACFS_OFFLINE_PACK" "$ACFS_OFFLINE_PACK")"
1458+
if [[ -z "${ACFS_OFFLINE_NETWORK_MODE:-}" ]]; then
1459+
ACFS_OFFLINE_NETWORK_MODE=offline
1460+
fi
1461+
if [[ "${ACFS_OFFLINE_NETWORK_MODE:-}" == "offline" && -z "${ACFS_OFFLINE_PACK_REQUIRED:-}" ]]; then
1462+
ACFS_OFFLINE_PACK_REQUIRED=true
1463+
fi
1464+
export ACFS_OFFLINE_PACK ACFS_OFFLINE_NETWORK_MODE ACFS_OFFLINE_PACK_REQUIRED
1465+
}
1466+
14181467
parse_args() {
14191468
while [[ $# -gt 0 ]]; do
14201469
case $1 in
@@ -1530,9 +1579,6 @@ parse_args() {
15301579
fi
15311580
shift
15321581
fi
1533-
if [[ "$ACFS_OFFLINE_PACK" == *$'\n'* || "$ACFS_OFFLINE_PACK" == *$'\r'* ]]; then
1534-
log_fatal "--offline-pack requires a single-line directory"
1535-
fi
15361582
ACFS_OFFLINE_NETWORK_MODE=offline
15371583
ACFS_OFFLINE_PACK_REQUIRED=true
15381584
export ACFS_OFFLINE_PACK ACFS_OFFLINE_NETWORK_MODE ACFS_OFFLINE_PACK_REQUIRED
@@ -7883,6 +7929,8 @@ main() {
78837929
exit 0
78847930
fi
78857931

7932+
acfs_normalize_offline_pack_configuration
7933+
78867934
if [[ -z "${SCRIPT_DIR:-}" ]]; then
78877935
# Resolve ACFS_REF to a specific commit SHA early to prevent mixed-ref installs.
78887936
# Without this, we could download a tarball for one commit and later fetch commit metadata

tests/unit/test_resume_hint.sh

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,14 @@ extract_ref_arg_value_helper() {
9090
sed -n '/^acfs_require_ref_arg_value()/,/^}$/p' "$REPO_ROOT/install.sh"
9191
}
9292

93+
extract_offline_pack_dir_helper() {
94+
sed -n '/^acfs_resolve_offline_pack_dir()/,/^}$/p' "$REPO_ROOT/install.sh"
95+
}
96+
97+
extract_offline_pack_normalizer() {
98+
sed -n '/^acfs_normalize_offline_pack_configuration()/,/^}$/p' "$REPO_ROOT/install.sh"
99+
}
100+
93101
# Actually, let's just define our test environment and source install.sh functions
94102
setup_test_env() {
95103
# Reset all variables to defaults
@@ -110,6 +118,9 @@ setup_test_env() {
110118
DRY_RUN=false
111119
PRINT_MODE=false
112120
AUTO_FIX_MODE="prompt"
121+
ACFS_OFFLINE_PACK=""
122+
ACFS_OFFLINE_NETWORK_MODE=""
123+
ACFS_OFFLINE_PACK_REQUIRED=""
113124
}
114125

115126
setup_parse_args_env() {
@@ -143,6 +154,10 @@ eval "$(extract_normalize_read_only_modes_function)"
143154
# shellcheck disable=SC1090
144155
eval "$(extract_ref_arg_value_helper)"
145156
# shellcheck disable=SC1090
157+
eval "$(extract_offline_pack_dir_helper)"
158+
# shellcheck disable=SC1090
159+
eval "$(extract_offline_pack_normalizer)"
160+
# shellcheck disable=SC1090
146161
eval "$(extract_parse_args_function)"
147162

148163
STATE_SET_RESUME_HINT_CALLS=0
@@ -375,6 +390,52 @@ test_custom_checksums_ref_resume_hint() {
375390
return 0
376391
}
377392

393+
test_offline_pack_relative_path_is_normalized_for_resume_hint() {
394+
setup_test_env
395+
396+
local temp_root=""
397+
local old_pwd=""
398+
local result=""
399+
local expected_pack=""
400+
local expected_pack_q=""
401+
402+
temp_root="$(mktemp -d "${TMPDIR:-/tmp}/acfs-resume-pack.XXXXXX")" || return 1
403+
mkdir -p "$temp_root/work/pack with spaces/acfs-offline-pack" || return 1
404+
printf '{}\n' > "$temp_root/work/pack with spaces/acfs-offline-pack/manifest.json" || return 1
405+
406+
old_pwd="$PWD"
407+
cd "$temp_root/work" || return 1
408+
ACFS_OFFLINE_PACK="pack with spaces"
409+
acfs_normalize_offline_pack_configuration || {
410+
cd "$old_pwd" || true
411+
return 1
412+
}
413+
cd "$old_pwd" || return 1
414+
415+
expected_pack="$temp_root/work/pack with spaces"
416+
if [[ "$ACFS_OFFLINE_PACK" != "$expected_pack" ]]; then
417+
log " Expected ACFS_OFFLINE_PACK=$expected_pack, got: $ACFS_OFFLINE_PACK"
418+
return 1
419+
fi
420+
if [[ "$ACFS_OFFLINE_NETWORK_MODE" != "offline" ]]; then
421+
log " Expected ACFS_OFFLINE_NETWORK_MODE=offline, got: $ACFS_OFFLINE_NETWORK_MODE"
422+
return 1
423+
fi
424+
if [[ "$ACFS_OFFLINE_PACK_REQUIRED" != "true" ]]; then
425+
log " Expected ACFS_OFFLINE_PACK_REQUIRED=true, got: $ACFS_OFFLINE_PACK_REQUIRED"
426+
return 1
427+
fi
428+
429+
result="$(generate_resume_hint "" "")"
430+
printf -v expected_pack_q '%q' "$expected_pack"
431+
if [[ "$result" != *"--offline-pack $expected_pack_q"* ]]; then
432+
log " Expected absolute --offline-pack in resume hint, got: $result"
433+
return 1
434+
fi
435+
436+
return 0
437+
}
438+
378439
# Test: Safe mode
379440
test_safe_mode() {
380441
setup_test_env
@@ -716,6 +777,7 @@ main() {
716777
run_test test_custom_ref_shell_escaped
717778
run_test test_checksums_ref_survives_ref_parse_order
718779
run_test test_custom_checksums_ref_resume_hint
780+
run_test test_offline_pack_relative_path_is_normalized_for_resume_hint
719781
run_test test_safe_mode
720782
run_test test_skip_flags
721783
run_test test_all_skip_flags

0 commit comments

Comments
 (0)