Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ cargo install --locked cargo-nextest
# Install a local codex binary with reuse of previous build artifacts.
./install.sh

# If your main volume is tight on space, keep Cargo build artifacts on another disk.
CARGO_TARGET_DIR=/path/on/larger/disk/codex-target ./install.sh

# Or build Codex manually from the Rust workspace.
cd codex-rs
cargo build
Expand Down
37 changes: 30 additions & 7 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Environment knobs:
CODEX_SOURCE_BIN Prebuilt binary path to install (skips build unless CODEX_REBUILD=always)
CODEX_INSTALL_LOCK_DIR Lock dir to prevent concurrent installers
CARGO_TARGET_DIR Build cache/output directory (default: codex-rs/target)
Set this to a path on another disk when local space is tight.
EOF
}

Expand Down Expand Up @@ -68,6 +69,23 @@ case "$target_dir" in
esac
build_stamp_file="$target_dir/release/.codex-install-build-stamp"

existing_dir_for_path() {
path=$1
while [ ! -e "$path" ]; do
parent=$(dirname -- "$path")
if [ "$parent" = "$path" ]; then
break
fi
path=$parent
done

if [ -d "$path" ]; then
printf '%s\n' "$path"
else
dirname -- "$path"
fi
}

collect_source_files() {
find "$ROOT_DIR/codex-rs" \
-path "$ROOT_DIR/codex-rs/target" -prune -o \
Expand Down Expand Up @@ -271,16 +289,21 @@ fi

if [ "$should_build" -eq 1 ]; then
required_kb=${CODEX_MIN_FREE_KB:-3145728}
available_kb=$(df -Pk "$ROOT_DIR" | awk 'NR==2 {print $4}')
space_check_dir=$(existing_dir_for_path "$target_dir")
available_kb=$(df -Pk "$space_check_dir" | awk 'NR==2 {print $4}')
if [ "$available_kb" -lt "$required_kb" ]; then
echo "Low free disk space detected (${available_kb} KB). Running cargo clean..." >&2
cargo clean --manifest-path "$ROOT_DIR/codex-rs/Cargo.toml" >/dev/null 2>&1 || true
available_kb=$(df -Pk "$ROOT_DIR" | awk 'NR==2 {print $4}')
echo "Low free disk space detected for build target (${available_kb} KB at $space_check_dir)." >&2
echo "Running cargo clean for CARGO_TARGET_DIR=$target_dir..." >&2
CARGO_TARGET_DIR="$target_dir" cargo clean --manifest-path "$ROOT_DIR/codex-rs/Cargo.toml" >/dev/null 2>&1 || true
available_kb=$(df -Pk "$space_check_dir" | awk 'NR==2 {print $4}')
fi
if [ "$available_kb" -lt "$required_kb" ]; then
echo "error: not enough free disk space to build codex release" >&2
echo "available: ${available_kb} KB, required: ${required_kb} KB" >&2
echo "free space and retry (or lower threshold with CODEX_MIN_FREE_KB)." >&2
echo "target dir: $target_dir" >&2
echo "free space and retry, or point CARGO_TARGET_DIR at a larger disk, for example:" >&2
echo " CARGO_TARGET_DIR=/path/on/larger/disk/codex-target ./install.sh" >&2
echo "You can also lower the threshold with CODEX_MIN_FREE_KB." >&2
exit 1
fi

Expand All @@ -297,9 +320,9 @@ if [ "$should_build" -eq 1 ]; then
fi

if [ -n "$build_reason" ]; then
echo "Building codex release binary (mode=$build_mode jobs=$build_jobs incremental=$resolved_build_incremental reason=$build_reason)..."
echo "Building codex release binary (mode=$build_mode jobs=$build_jobs incremental=$resolved_build_incremental target=$target_dir reason=$build_reason)..."
else
echo "Building codex release binary (mode=$build_mode jobs=$build_jobs incremental=$resolved_build_incremental)..."
echo "Building codex release binary (mode=$build_mode jobs=$build_jobs incremental=$resolved_build_incremental target=$target_dir)..."
fi
if [ -n "$profile_overrides" ]; then
env $profile_overrides CARGO_PROFILE_RELEASE_DEBUG=0 CARGO_INCREMENTAL="$resolved_build_incremental" \
Expand Down
108 changes: 107 additions & 1 deletion scripts/install/test-source-build-install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ assert_file_exists() {
fi
}

assert_contains() {
haystack=$1
needle=$2
context=$3
printf '%s' "$haystack" | grep -F -- "$needle" >/dev/null || fail "$context: missing '$needle'"
}

make_fake_workspace() {
workspace=$1

Expand All @@ -41,11 +48,15 @@ EOF
fn main() {}
EOF

cat >"$workspace/fake-bin/cargo" <<'EOF'
cat >"$workspace/fake-bin/cargo" <<'EOF'
#!/bin/sh
set -eu

test_log=${TEST_LOG:?}
command=${1:-}
if [ -n "$command" ]; then
shift
fi
manifest_path=""
while [ "$#" -gt 0 ]; do
case "$1" in
Expand All @@ -66,6 +77,14 @@ fi

manifest_dir=$(dirname -- "$manifest_path")
target_dir=${CARGO_TARGET_DIR:-"$manifest_dir/target"}
if [ "$command" = "clean" ]; then
rm -rf "$target_dir"
exit 0
fi
if [ "$command" != "build" ]; then
echo "unexpected cargo invocation: $command" >&2
exit 1
fi
mkdir -p "$target_dir/release"
printf 'incremental=%s\n' "${CARGO_INCREMENTAL:-unset}" >>"$test_log"
cat >"$target_dir/release/codex" <<'BIN'
Expand All @@ -76,6 +95,34 @@ chmod +x "$target_dir/release/codex"
EOF
chmod +x "$workspace/fake-bin/cargo"

cat >"$workspace/fake-bin/df" <<'EOF'
#!/bin/sh
set -eu

path=""
for arg in "$@"; do
path=$arg
done

default_kb=${TEST_DF_DEFAULT_KB:-10485760}
low_path=${TEST_DF_LOW_PATH:-}
low_kb=${TEST_DF_LOW_KB:-1}
high_path=${TEST_DF_HIGH_PATH:-}
high_kb=${TEST_DF_HIGH_KB:-10485760}

available_kb=$default_kb
if [ -n "$high_path" ] && [ "$path" = "$high_path" ]; then
available_kb=$high_kb
fi
if [ -n "$low_path" ] && [ "$path" = "$low_path" ]; then
available_kb=$low_kb
fi

printf 'Filesystem 1024-blocks Used Available Capacity Mounted on\n'
printf 'testfs 9999999 0 %s 0%% %s\n' "$available_kb" "$path"
EOF
chmod +x "$workspace/fake-bin/df"

cat >"$workspace/fake-bin/git" <<'EOF'
#!/bin/sh
set -eu
Expand Down Expand Up @@ -123,6 +170,7 @@ assert_help_mentions_new_knobs() {
help_output=$(sh "$ROOT_DIR/install.sh" --help)
printf '%s\n' "$help_output" | grep "CODEX_BUILD_INCREMENTAL" >/dev/null || fail "--help should mention CODEX_BUILD_INCREMENTAL"
printf '%s\n' "$help_output" | grep "CARGO_TARGET_DIR" >/dev/null || fail "--help should mention CARGO_TARGET_DIR"
printf '%s\n' "$help_output" | grep "another disk" >/dev/null || fail "--help should explain when to move CARGO_TARGET_DIR"
}

test_skips_rebuild_when_source_content_is_unchanged() {
Expand Down Expand Up @@ -174,6 +222,64 @@ test_honors_custom_target_dir() {
trap - EXIT INT TERM
}

test_uses_custom_target_dir_filesystem_for_space_check() {
workspace=$(mktemp -d)
test_log="$workspace/cargo.log"
target_dir="$workspace/shared-target"
trap 'rm -rf "$workspace"' EXIT INT TERM

make_fake_workspace "$workspace"
mkdir -p "$target_dir"

run_install "$workspace" "$test_log" \
CARGO_TARGET_DIR="$target_dir" \
CODEX_MIN_FREE_KB=100 \
TEST_DF_DEFAULT_KB=10 \
TEST_DF_LOW_PATH="$workspace" \
TEST_DF_LOW_KB=10 \
TEST_DF_HIGH_PATH="$target_dir" \
TEST_DF_HIGH_KB=1000
assert_eq "1" "$(count_builds "$test_log")" "custom target dir filesystem should satisfy the space check"
assert_file_exists "$target_dir/release/codex"

rm -rf "$workspace"
trap - EXIT INT TERM
}

test_low_space_error_mentions_external_target_dir() {
workspace=$(mktemp -d)
test_log="$workspace/cargo.log"
trap 'rm -rf "$workspace"' EXIT INT TERM

make_fake_workspace "$workspace"

set +e
output=$(
cd "$workspace" && env PATH="$workspace/fake-bin:$PATH" \
TEST_LOG="$test_log" \
CODEX_INSTALL_DIR="$workspace/bin" \
CODEX_MIN_FREE_KB=100 \
TEST_DF_DEFAULT_KB=10 \
TEST_DF_LOW_PATH="$workspace/codex-rs/target" \
TEST_DF_LOW_KB=10 \
./install.sh 2>&1
)
status=$?
set -e

if [ "$status" -eq 0 ]; then
fail "install should fail when the build target filesystem remains full"
fi

assert_contains "$output" "target dir: $workspace/codex-rs/target" "low-space error should show the target dir"
assert_contains "$output" "CARGO_TARGET_DIR=/path/on/larger/disk/codex-target ./install.sh" "low-space error should suggest using another disk"

rm -rf "$workspace"
trap - EXIT INT TERM
}

assert_help_mentions_new_knobs
test_skips_rebuild_when_source_content_is_unchanged
test_honors_custom_target_dir
test_uses_custom_target_dir_filesystem_for_space_check
test_low_space_error_mentions_external_target_dir
Loading