Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
22eb2a8
Add --with-llama-cpp-dir flag to install.ps1 and install.sh
LeoBorcherding Jun 17, 2026
35542c6
test: add static wiring test for --with-llama-cpp-dir flag
LeoBorcherding Jun 19, 2026
fe4b43d
Address review feedback on --with-llama-cpp-dir flag
LeoBorcherding Jun 23, 2026
b2587dc
Merge remote-tracking branch 'upstream/main' into with-llamacpp-dir-flag
LeoBorcherding Jun 23, 2026
0d16c6a
Merge branch 'main' into with-llamacpp-dir-flag
LeoBorcherding Jun 26, 2026
56b1e3c
Harden --with-llama-cpp-dir against Codex/Gemini review findings
LeoBorcherding Jun 29, 2026
d5e9f51
Validate/reuse local llama.cpp tree and guard the in-use case
LeoBorcherding Jun 29, 2026
43f2082
Merge branch 'main' into with-llamacpp-dir-flag
Imagineer99 Jun 30, 2026
d254f7e
Accept all backend llama-server layouts in --with-llama-cpp-dir valid…
LeoBorcherding Jun 30, 2026
5252163
Treat --with-llama-cpp-dir local links as externally managed
LeoBorcherding Jun 30, 2026
1206943
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 30, 2026
be8a3c3
Add behavioral shell test for --with-llama-cpp-dir linking
LeoBorcherding Jun 30, 2026
48b37bb
Install psutil in backend CI so orphan-cleanup tests run
LeoBorcherding Jun 30, 2026
829b3b1
Merge branch 'main' into with-llamacpp-dir-flag
Imagineer99 Jul 2, 2026
9a365dc
Merge branch 'main' into with-llamacpp-dir-flag
Imagineer99 Jul 2, 2026
3877bea
Merge branch 'main' into with-llamacpp-dir-flag
Imagineer99 Jul 2, 2026
8d398a2
Merge branch 'main' into with-llamacpp-dir-flag
Imagineer99 Jul 2, 2026
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: 2 additions & 1 deletion .github/workflows/studio-backend-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,8 @@ jobs:
tests/sh/test_nvcc_meets_llama_minimum.sh \
tests/sh/test_tauri_install_exit_order.sh \
tests/sh/test_torch_constraint.sh \
tests/sh/test_torch_flavor.sh; do
tests/sh/test_torch_flavor.sh \
tests/sh/test_with_llama_cpp_dir_flag.sh; do
echo "::group::$s"
bash "$s"
echo "::endgroup::"
Expand Down
17 changes: 17 additions & 0 deletions install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ function Install-UnslothStudio {
$TauriMode = $false
$SkipTorch = $false
$ShortcutsOnly = $false
$WithLlamaCppDir = ""
$argList = $args
for ($i = 0; $i -lt $argList.Count; $i++) {
switch ($argList[$i]) {
Expand All @@ -116,6 +117,14 @@ function Install-UnslothStudio {
}
$PackageName = $argList[$i]
}
"--with-llama-cpp-dir" {
$i++
if ($i -ge $argList.Count) {
Write-Host "[ERROR] --with-llama-cpp-dir requires a path argument." -ForegroundColor Red
return (Exit-InstallFailure "--with-llama-cpp-dir requires a path argument.")
}
$WithLlamaCppDir = $argList[$i]
}
}
}

Expand Down Expand Up @@ -2339,6 +2348,13 @@ exit 0
}
$studioArgs = @('studio', 'setup')
if ($script:UnslothVerbose) { $studioArgs += '--verbose' }
if ($WithLlamaCppDir) {
if (-not (Test-Path -LiteralPath $WithLlamaCppDir -PathType Container)) {
Write-Host "[ERROR] --with-llama-cpp-dir path does not exist: $WithLlamaCppDir" -ForegroundColor Red
return (Exit-InstallFailure "--with-llama-cpp-dir path does not exist.")
Comment on lines +2443 to +2445

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restore the environment on invalid local llama.cpp paths

When --with-llama-cpp-dir is mistyped in a PowerShell session that already has UNSLOTH_STUDIO_HOME or the installer state env vars set, this validation returns after the code above has removed/overwritten those env vars but before the try/finally that restores them starts. That leaves the caller's session pointed back at the default Studio home (or with stale STUDIO_LOCAL_INSTALL/skip flags), so a subsequent setup in the same shell can install into the wrong root; move this validation before mutating env vars or include it inside the restore finally.

Useful? React with 👍 / 👎.

}
$env:UNSLOTH_LOCAL_LLAMA_CPP_DIR = (Resolve-Path -LiteralPath $WithLlamaCppDir).Path
}
$env:UNSLOTH_INSTALL_ROLLBACK_MANAGED = "1"
# Hand the venv interpreter to setup.ps1 so it reuses the Python we already
# resolved and built the venv with, instead of re-probing the system (which
Expand All @@ -2354,6 +2370,7 @@ exit 0
} else {
Remove-Item Env:UNSLOTH_STUDIO_HOME -ErrorAction SilentlyContinue
}
Remove-Item Env:UNSLOTH_LOCAL_LLAMA_CPP_DIR -ErrorAction SilentlyContinue
Remove-Item Env:UNSLOTH_INSTALL_ROLLBACK_MANAGED -ErrorAction SilentlyContinue
Remove-Item Env:UNSLOTH_SETUP_PYTHON -ErrorAction SilentlyContinue
}
Expand Down
17 changes: 17 additions & 0 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ _VERBOSE=false
_SHORTCUTS_ONLY=false
_next_is_package=false
_next_is_python=false
_next_is_llama_cpp_dir=false
_WITH_LLAMA_CPP_DIR=""
for arg in "$@"; do
if [ "$_next_is_package" = true ]; then
PACKAGE_NAME="$arg"
Expand All @@ -64,6 +66,11 @@ for arg in "$@"; do
_next_is_python=false
continue
fi
if [ "$_next_is_llama_cpp_dir" = true ]; then
_WITH_LLAMA_CPP_DIR="$arg"
_next_is_llama_cpp_dir=false
continue
fi
case "$arg" in
--local) STUDIO_LOCAL_INSTALL=true ;;
--package) _next_is_package=true ;;
Expand All @@ -72,6 +79,7 @@ for arg in "$@"; do
--no-torch) _NO_TORCH_FLAG=true ;;
--verbose|-v) _VERBOSE=true ;;
--shortcuts-only) _SHORTCUTS_ONLY=true ;;
--with-llama-cpp-dir) _next_is_llama_cpp_dir=true ;;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject a missing llama.cpp path in the shell parser

If --with-llama-cpp-dir is the final argument, _next_is_llama_cpp_dir remains true after the loop and no error is raised, so _WITH_LLAMA_CPP_DIR stays empty and the installer silently falls back to the normal prebuilt/source install path. This makes a mistyped invocation behave as if the new flag was not supplied; add a post-loop check for the pending argument state, as the PowerShell installer does.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3 Badge Forward the local llama.cpp flag during WSL reroutes

This parser records --with-llama-cpp-dir, but the Strix Halo WSL reroute path later reconstructs _rr_args for the Ubuntu-24.04 child install without appending this option or exporting UNSLOTH_LOCAL_LLAMA_CPP_DIR. On those rerouted installs, a user-provided local llama.cpp directory is silently ignored and the child falls back to downloading/building instead of reusing the requested cache.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If --with-llama-cpp-dir is passed as the last argument to install.sh, the loop terminates with _next_is_llama_cpp_dir set to true but without assigning any value to _WITH_LLAMA_CPP_DIR. Unlike --package and --python, there is no post-loop validation to catch this, which can lead to silent failures or unexpected behavior.

Consider adding a validation check after the loop (around line 268) to ensure that _next_is_llama_cpp_dir is not left as true.

esac
done

Expand Down Expand Up @@ -2894,6 +2902,13 @@ _run_setup_with_studio_home() {
"$@"
fi
}
if [ -n "$_WITH_LLAMA_CPP_DIR" ]; then
if [ ! -d "$_WITH_LLAMA_CPP_DIR" ]; then
echo "[ERROR] --with-llama-cpp-dir path does not exist: $_WITH_LLAMA_CPP_DIR" >&2
exit 1
fi
_WITH_LLAMA_CPP_DIR="$(cd "$_WITH_LLAMA_CPP_DIR" && pwd)"
Comment thread
Imagineer99 marked this conversation as resolved.
Outdated
fi
if [ "$STUDIO_LOCAL_INSTALL" = true ]; then
_run_setup_with_studio_home env \
SKIP_STUDIO_BASE="$_SKIP_BASE" \
Expand All @@ -2902,6 +2917,7 @@ if [ "$STUDIO_LOCAL_INSTALL" = true ]; then
STUDIO_LOCAL_INSTALL=1 \
STUDIO_LOCAL_REPO="$_REPO_ROOT" \
UNSLOTH_NO_TORCH="$SKIP_TORCH" \
UNSLOTH_LOCAL_LLAMA_CPP_DIR="$_WITH_LLAMA_CPP_DIR" \

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the env-provided local llama.cpp path

When the POSIX installer is used in the documented piped-install style with UNSLOTH_LOCAL_LLAMA_CPP_DIR=/path sh (or the variable is otherwise exported before invoking install.sh), _WITH_LLAMA_CPP_DIR remains empty unless the CLI flag is used, and this assignment shadows the caller's value with an empty string before setup.sh runs. That makes the env-var path that setup.sh now supports unreachable through install.sh, so web installs silently download/build llama.cpp instead of reusing the requested local directory.

Useful? React with 👍 / 👎.

bash "$SETUP_SH" </dev/null || _SETUP_EXIT=$?
else
# Explicitly reset STUDIO_LOCAL_INSTALL / STUDIO_LOCAL_REPO so a stale
Expand All @@ -2916,6 +2932,7 @@ else
STUDIO_LOCAL_INSTALL=0 \
STUDIO_LOCAL_REPO= \
UNSLOTH_NO_TORCH="$SKIP_TORCH" \
UNSLOTH_LOCAL_LLAMA_CPP_DIR="$_WITH_LLAMA_CPP_DIR" \
bash "$SETUP_SH" </dev/null || _SETUP_EXIT=$?
fi

Expand Down
35 changes: 33 additions & 2 deletions studio/setup.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -2754,7 +2754,38 @@ if ($LlamaPr) {
$SkipPrebuiltInstall = $true
}

if ($env:UNSLOTH_LLAMA_FORCE_COMPILE -eq "1") {
$LocalLlamaCppLinked = $false
$LocalLlamaCppSrc = $env:UNSLOTH_LOCAL_LLAMA_CPP_DIR
if ($LocalLlamaCppSrc) {
if (-not (Test-Path -LiteralPath $LocalLlamaCppSrc -PathType Container)) {
step "llama.cpp" "UNSLOTH_LOCAL_LLAMA_CPP_DIR does not exist: $LocalLlamaCppSrc" "Red"
exit 1
}
$ResolvedLocal = (Resolve-Path -LiteralPath $LocalLlamaCppSrc).Path
if ($ResolvedLocal -eq $LlamaCppDir) {
substep "UNSLOTH_LOCAL_LLAMA_CPP_DIR points to the canonical install location; ignoring" "Yellow"
Comment thread
Imagineer99 marked this conversation as resolved.
Outdated
} else {
if ($StudioHomeIsCustom) {
Assert-StudioOwnedOrAbsent -Path $LlamaCppDir -Label "llama.cpp install"
}
if (Test-Path -LiteralPath $LlamaCppDir) {
Remove-Item -Recurse -Force -LiteralPath $LlamaCppDir -ErrorAction SilentlyContinue
}
Comment on lines +3237 to +3247

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

Critical Bug: Potential Data Loss via Remove-Item -Recurse on Junctions

In PowerShell (especially 5.1), running Remove-Item -Recurse -Force on a directory junction or symbolic link can traverse the link and delete the contents of the target directory (the user's actual local llama.cpp directory) instead of just deleting the junction/link itself. This can lead to catastrophic data loss for users utilizing the --with-llama-cpp-dir flag.

To prevent this, check if the target is a ReparsePoint (junction/symlink) and delete it safely using the .Delete() method of the DirectoryInfo object, which deletes only the link itself.

        if (Test-Path -LiteralPath $LlamaCppDir) {
            $item = Get-Item -LiteralPath $LlamaCppDir
            if ($item.Attributes -band [System.IO.FileAttributes]::ReparsePoint) {
                $item.Delete()
            } else {
                Remove-Item -Recurse -Force -LiteralPath $LlamaCppDir -ErrorAction SilentlyContinue
            }
        }

Comment on lines +3237 to +3247

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Abort when old Windows runtime cannot be removed

When the existing $LlamaCppDir is in use on Windows, locked files can make this removal fail, but -ErrorAction SilentlyContinue masks the failure and the code proceeds to mklink/Copy-Item with the old directory still present. In that scenario the local runtime is not cleanly linked and the installer can leave a partially deleted or merged llama.cpp tree instead of reporting the active-process condition like the prebuilt path does.

Useful? React with 👍 / 👎.

cmd /c "mklink /J `"$LlamaCppDir`" `"$ResolvedLocal`"" 2>&1 | Out-Null
if ($LASTEXITCODE -ne 0) {
substep "Could not create directory junction; copying instead..." "Yellow"
Copy-Item -Recurse -Path $ResolvedLocal -Destination $LlamaCppDir
Comment thread
Imagineer99 marked this conversation as resolved.
Outdated
}
Write-Host ""
step "llama.cpp" "linked local directory: $ResolvedLocal"
$LocalLlamaCppLinked = $true
$NeedLlamaSourceBuild = $false
}
}

if ($LocalLlamaCppLinked) {
# local directory linked above; skip prebuilt install
} elseif ($env:UNSLOTH_LLAMA_FORCE_COMPILE -eq "1") {
Write-Host ""
substep "UNSLOTH_LLAMA_FORCE_COMPILE=1 -- skipping prebuilt llama.cpp install" "Yellow"
$NeedLlamaSourceBuild = $true
Expand Down Expand Up @@ -2962,7 +2993,7 @@ if (Test-Path -LiteralPath $LlamaServerBin) {
}
}

if (-not $NeedLlamaSourceBuild) {
if (-not $NeedLlamaSourceBuild -and -not $LocalLlamaCppLinked) {
Write-Host ""
step "llama.cpp" "prebuilt (validated)"
} elseif ((Test-Path -LiteralPath $LlamaServerBin) -and -not $NeedRebuild -and $RequestedLlamaTag -ne "master") {
Comment thread
Imagineer99 marked this conversation as resolved.
Outdated
Expand Down
26 changes: 25 additions & 1 deletion studio/setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1086,7 +1086,31 @@ fi

verbose_substep "requested llama.cpp tag: $_REQUESTED_LLAMA_TAG (repo: $_HELPER_RELEASE_REPO)"

if [ "$_LLAMA_FORCE_COMPILE" = "1" ]; then
_LOCAL_LLAMA_CPP_LINKED=false
if [ -n "${UNSLOTH_LOCAL_LLAMA_CPP_DIR:-}" ]; then
if [ ! -d "$UNSLOTH_LOCAL_LLAMA_CPP_DIR" ]; then
step "llama.cpp" "UNSLOTH_LOCAL_LLAMA_CPP_DIR does not exist: $UNSLOTH_LOCAL_LLAMA_CPP_DIR" "$C_ERR"
exit 1
fi
_RESOLVED_LOCAL="$(cd "$UNSLOTH_LOCAL_LLAMA_CPP_DIR" && pwd)"
Comment thread
Imagineer99 marked this conversation as resolved.
Outdated
if [ "$_RESOLVED_LOCAL" = "$LLAMA_CPP_DIR" ]; then
substep "UNSLOTH_LOCAL_LLAMA_CPP_DIR points to the canonical install location; ignoring"
else
Comment thread
Imagineer99 marked this conversation as resolved.
Outdated
if [ "$_STUDIO_HOME_IS_CUSTOM" = true ]; then
_assert_studio_owned_or_absent "$LLAMA_CPP_DIR" "llama.cpp install"
fi
rm -rf "$LLAMA_CPP_DIR"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Canonicalize the target before deleting it

When $HOME contains a symlink, install.sh canonicalizes --with-llama-cpp-dir ~/.unsloth/llama.cpp before forwarding it, but LLAMA_CPP_DIR here is still the textual $HOME/.unsloth/llama.cpp. The self-check can therefore miss the canonical install directory and this rm -rf deletes the very local llama.cpp tree the user asked to reuse, then replaces it with a broken/self-referential symlink. Compare against a resolved canonical form of LLAMA_CPP_DIR before removing it.

Useful? React with 👍 / 👎.

ln -sfn "$_RESOLVED_LOCAL" "$LLAMA_CPP_DIR"
Comment on lines +1342 to +1346

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Allow custom-home local links to be re-run

For a custom UNSLOTH_STUDIO_HOME, the first --with-llama-cpp-dir run creates $LLAMA_CPP_DIR as a symlink to the user's local directory without adding the Studio-owned marker. On the next run with the same flag, this ownership assertion follows that symlink and rejects the user's directory as unowned before it can simply replace or reuse the link, making the installer non-idempotent for custom-home local llama.cpp installs.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Mark local links as unmanaged for updates

This creates the managed $LLAMA_CPP_DIR as a symlink to the user's checkout without any marker that it is externally managed. The in-app updater treats a markerless active binary under a parent named llama.cpp as a manageable source build in studio/backend/utils/llama_cpp_update.py::_llama_install_root, so the “Update llama.cpp” action can install a prebuilt into this path and replace the link instead of continuing to use the requested checkout; add a marker or make the updater skip these local-link installs.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid treating linked local checkouts as owned

For local-dir installs that create this symlink, the backend's orphan cleanup resolves known install roots before comparing process executables (core/inference/llama_cpp.py lines 7140-7176). If the user already has their own llama-server running from the same checkout, the resolved Studio root becomes $_RESOLVED_LOCAL, so LlamaCppBackend.__init__ classifies that external process as ours and kills it on startup; keep local-link roots out of the orphan allowlist or mark them unmanaged.

Useful? React with 👍 / 👎.

step "llama.cpp" "linked local directory: $_RESOLVED_LOCAL"
_LOCAL_LLAMA_CPP_LINKED=true
_NEED_LLAMA_SOURCE_BUILD=false
_SKIP_PREBUILT_INSTALL=true
Comment on lines +1349 to +1351

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restore the quantize shim for local source builds

For a normal local llama.cpp source build on Linux/macOS, build/bin/llama-quantize exists but the root-level llama-quantize shim usually does not. Setting _NEED_LLAMA_SOURCE_BUILD=false here skips the existing source-build reuse block that creates that shim, while the setup comments later note GGUF export's check_llama_cpp() looks for it at the root, so export can remain unavailable even though the linked build contains the binary.

Useful? React with 👍 / 👎.

Comment on lines +1348 to +1351

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate the linked runtime before disabling installs

When UNSLOTH_LOCAL_LLAMA_CPP_DIR points at an existing but unbuilt or wrong-platform llama.cpp checkout, this branch still marks it linked and disables both the prebuilt download and the source build. Studio later only discovers llama-server in the managed root/build layouts, so this installer run can report success while leaving GGUF inference/export unusable; fail here unless the linked tree contains a supported llama-server binary.

Useful? React with 👍 / 👎.

fi
fi

if [ "$_LOCAL_LLAMA_CPP_LINKED" = true ]; then
: # local directory linked above; skip prebuilt install
elif [ "$_LLAMA_FORCE_COMPILE" = "1" ]; then
step "llama.cpp" "UNSLOTH_LLAMA_FORCE_COMPILE=1 -- skipping prebuilt" "$C_WARN"
_NEED_LLAMA_SOURCE_BUILD=true
elif [ "${_SKIP_PREBUILT_INSTALL:-false}" = true ]; then
Expand Down
155 changes: 155 additions & 0 deletions tests/sh/test_with_llama_cpp_dir_flag.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
#!/bin/bash
# Static analysis: the --with-llama-cpp-dir flag must be wired consistently
# across both installers (install.sh / install.ps1) and both setup scripts
# (studio/setup.sh / studio/setup.ps1).
#
# The flag lets a user point the installer at a local llama.cpp directory so it
# skips BOTH the prebuilt download (Phase 3) and the source build (Phase 4),
# linking the local dir into the canonical install location instead. The path
# crosses the installer->setup boundary via the UNSLOTH_LOCAL_LLAMA_CPP_DIR env
# var. These checks pin that contract so a future refactor of either side can't
# silently break it (e.g. installer parses the flag but setup never reads the
# env var, or setup links the dir but still runs the build).
#
# This is a shape/wiring test, not a behavioral one: it greps the committed
# scripts. It needs no Python, no GPU, no network.
set -e

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
INSTALL_SH="$SCRIPT_DIR/../../install.sh"
INSTALL_PS1="$SCRIPT_DIR/../../install.ps1"
SETUP_SH="$SCRIPT_DIR/../../studio/setup.sh"
SETUP_PS1="$SCRIPT_DIR/../../studio/setup.ps1"
ENV_VAR="UNSLOTH_LOCAL_LLAMA_CPP_DIR"
PASS=0
FAIL=0

assert_contains() {
_label="$1"; _file="$2"; _needle="$3"
if grep -qF -- "$_needle" "$_file"; then
echo " PASS: $_label"
PASS=$((PASS + 1))
else
echo " FAIL: $_label (expected to find '$_needle' in $(basename "$_file"))"
FAIL=$((FAIL + 1))
fi
}

# Count of distinct lines matching a regex, used to assert a guard appears
# in more than one place (e.g. env var forwarded on both setup invocations).
assert_min_count() {
_label="$1"; _file="$2"; _pattern="$3"; _min="$4"
_n=$(grep -cE -- "$_pattern" "$_file" || true)
if [ "$_n" -ge "$_min" ]; then
echo " PASS: $_label (found $_n, need >= $_min)"
PASS=$((PASS + 1))
else
echo " FAIL: $_label (found $_n in $(basename "$_file"), need >= $_min)"
FAIL=$((FAIL + 1))
fi
}

echo ""
echo "=== install.sh: parses --with-llama-cpp-dir and forwards the env var ==="

assert_contains \
"install.sh: accepts --with-llama-cpp-dir flag" \
"$INSTALL_SH" "--with-llama-cpp-dir"
assert_contains \
"install.sh: validates the path exists before forwarding" \
"$INSTALL_SH" 'if [ ! -d "$_WITH_LLAMA_CPP_DIR" ]; then'
# The path must be forwarded to setup.sh on BOTH the local and the
# non-local setup invocations, else --local users (the documented path)
# would silently lose the flag.
assert_min_count \
"install.sh: forwards $ENV_VAR on both setup invocations" \
"$INSTALL_SH" "$ENV_VAR=\"\\\$_WITH_LLAMA_CPP_DIR\"" 2

echo ""
echo "=== install.ps1: parses --with-llama-cpp-dir and forwards the env var ==="

assert_contains \
"install.ps1: accepts --with-llama-cpp-dir flag" \
"$INSTALL_PS1" '"--with-llama-cpp-dir"'
assert_contains \
"install.ps1: errors when flag is given with no path argument" \
"$INSTALL_PS1" "--with-llama-cpp-dir requires a path argument"
assert_contains \
"install.ps1: validates the path exists before forwarding" \
"$INSTALL_PS1" "--with-llama-cpp-dir path does not exist"
assert_contains \
"install.ps1: exports $ENV_VAR for setup.ps1" \
"$INSTALL_PS1" "\$env:$ENV_VAR ="
# The exported env var must be cleaned up so a later setup invocation in the
# same shell session doesn't inherit a stale local-dir link.
assert_contains \
"install.ps1: clears $ENV_VAR after the setup run" \
"$INSTALL_PS1" "Remove-Item Env:$ENV_VAR"

echo ""
echo "=== studio/setup.sh: reads the env var, links, and skips download+build ==="

assert_contains \
"setup.sh: reads $ENV_VAR" \
"$SETUP_SH" "$ENV_VAR"
assert_contains \
"setup.sh: symlinks the local dir into the canonical install location" \
"$SETUP_SH" 'ln -sfn "$_RESOLVED_LOCAL" "$LLAMA_CPP_DIR"'
assert_contains \
"setup.sh: disables the source build when the local dir is linked" \
"$SETUP_SH" "_NEED_LLAMA_SOURCE_BUILD=false"
assert_contains \
"setup.sh: skips the prebuilt download when the local dir is linked" \
"$SETUP_SH" "_SKIP_PREBUILT_INSTALL=true"
# The link branch must short-circuit the FORCE_COMPILE / prebuilt chain rather
# than fall through into it.
assert_contains \
"setup.sh: link branch gates the prebuilt/compile chain" \
"$SETUP_SH" 'if [ "$_LOCAL_LLAMA_CPP_LINKED" = true ]; then'

echo ""
echo "=== studio/setup.ps1: reads the env var, junctions, and skips download+build ==="

assert_contains \
"setup.ps1: reads $ENV_VAR" \
"$SETUP_PS1" "\$env:$ENV_VAR"
assert_contains \
"setup.ps1: creates a directory junction into the canonical location" \
"$SETUP_PS1" "mklink /J"
assert_contains \
"setup.ps1: falls back to a copy when the junction can't be created" \
"$SETUP_PS1" "Copy-Item -Recurse -Path \$ResolvedLocal -Destination \$LlamaCppDir"
Comment thread
Imagineer99 marked this conversation as resolved.
Outdated
assert_contains \
"setup.ps1: disables the source build when the local dir is linked" \
"$SETUP_PS1" '$NeedLlamaSourceBuild = $false'
# The link branch must gate the prebuilt-install chain (the elseif on
# FORCE_COMPILE), and the 'prebuilt (validated)' banner must be suppressed
# when we linked a local dir instead of validating a real prebuilt.
assert_contains \
"setup.ps1: link branch gates the prebuilt/compile chain" \
"$SETUP_PS1" 'if ($LocalLlamaCppLinked) {'
assert_contains \
"setup.ps1: 'prebuilt (validated)' banner excludes the linked-dir case" \
"$SETUP_PS1" '-not $NeedLlamaSourceBuild -and -not $LocalLlamaCppLinked'

echo ""
echo "=== both setup scripts: a local dir pointing at the canonical path is a no-op ==="

# Guard against the self-link footgun: if the user passes the canonical install
# dir itself, neither script should delete-then-link it onto itself.
assert_contains \
"setup.sh: ignores a local dir equal to the canonical install location" \
"$SETUP_SH" 'if [ "$_RESOLVED_LOCAL" = "$LLAMA_CPP_DIR" ]; then'
assert_contains \
"setup.ps1: ignores a local dir equal to the canonical install location" \
"$SETUP_PS1" 'if ($ResolvedLocal -eq $LlamaCppDir) {'

echo ""
echo "=== Results ==="
echo " PASS: $PASS"
echo " FAIL: $FAIL"
if [ "$FAIL" -gt 0 ]; then
echo "FAILED"
exit 1
fi
echo "ALL PASSED"
Loading