mirror of
https://github.com/Alishahryar1/free-claude-code.git
synced 2026-06-01 22:09:04 +02:00
fix installer dependency checks
This commit is contained in:
@@ -50,7 +50,7 @@ Free Claude Code routes Anthropic Messages API traffic from Claude Code to any p
|
||||
|
||||
### 1. Fast Install
|
||||
|
||||
Install or update Claude Code, uv, Python 3.14.0, and Free Claude Code:
|
||||
Install Claude Code if missing, install or update uv, then install Python 3.14.0 and Free Claude Code:
|
||||
|
||||
macOS/Linux:
|
||||
|
||||
|
||||
+20
-10
@@ -20,7 +20,7 @@ function Show-Usage {
|
||||
@"
|
||||
Usage: install.ps1 [options]
|
||||
|
||||
Installs or updates Claude Code, uv, Python 3.14.0, and Free Claude Code.
|
||||
Installs Claude Code if missing, installs or updates uv, Python 3.14.0, and Free Claude Code.
|
||||
|
||||
Options:
|
||||
-VoiceNim Install NVIDIA NIM voice transcription support.
|
||||
@@ -103,19 +103,30 @@ function Assert-CommandAvailable {
|
||||
}
|
||||
}
|
||||
|
||||
function Install-ClaudeIfMissing {
|
||||
if (Get-Command claude -ErrorAction SilentlyContinue) {
|
||||
Write-Host "Claude Code already found on PATH; skipping install."
|
||||
return
|
||||
}
|
||||
|
||||
Assert-CommandAvailable "npm"
|
||||
Invoke-InstallCommand -FilePath "npm" -Arguments @("install", "-g", "@anthropic-ai/claude-code")
|
||||
}
|
||||
|
||||
function Install-OrUpdateUv {
|
||||
Add-UvToPath
|
||||
|
||||
if (-not (Get-Command uv -ErrorAction SilentlyContinue)) {
|
||||
Invoke-UvInstaller
|
||||
Add-UvToPath
|
||||
if (Get-Command uv -ErrorAction SilentlyContinue) {
|
||||
Invoke-InstallCommand -FilePath "uv" -Arguments @("self", "update")
|
||||
return
|
||||
}
|
||||
|
||||
Invoke-UvInstaller
|
||||
Add-UvToPath
|
||||
|
||||
if ((-not $DryRun) -and (-not (Get-Command uv -ErrorAction SilentlyContinue))) {
|
||||
throw "uv was installed, but it is not available on PATH. Open a new terminal or add uv's bin directory to PATH."
|
||||
}
|
||||
|
||||
Invoke-InstallCommand -FilePath "uv" -Arguments @("self", "update")
|
||||
}
|
||||
|
||||
function Get-PackageSpec {
|
||||
@@ -172,11 +183,10 @@ if ((-not [string]::IsNullOrWhiteSpace($TorchBackend)) -and (-not ($VoiceLocal -
|
||||
throw "-TorchBackend requires -VoiceLocal or -VoiceAll."
|
||||
}
|
||||
|
||||
Write-Step "Installing or updating Claude Code"
|
||||
Assert-CommandAvailable "npm"
|
||||
Invoke-InstallCommand -FilePath "npm" -Arguments @("install", "-g", "@anthropic-ai/claude-code")
|
||||
Write-Step "Installing Claude Code if missing"
|
||||
Install-ClaudeIfMissing
|
||||
|
||||
Write-Step "Installing or updating uv"
|
||||
Write-Step "Installing uv if missing, updating if present"
|
||||
Install-OrUpdateUv
|
||||
|
||||
Write-Step "Installing Python $PythonVersion"
|
||||
|
||||
+20
-10
@@ -15,7 +15,7 @@ show_usage() {
|
||||
cat <<'USAGE'
|
||||
Usage: install.sh [options]
|
||||
|
||||
Installs or updates Claude Code, uv, Python 3.14.0, and Free Claude Code.
|
||||
Installs Claude Code if missing, installs or updates uv, Python 3.14.0, and Free Claude Code.
|
||||
|
||||
Options:
|
||||
--voice-nim Install NVIDIA NIM voice transcription support.
|
||||
@@ -99,19 +99,30 @@ require_command() {
|
||||
fi
|
||||
}
|
||||
|
||||
install_claude_if_missing() {
|
||||
if command -v claude >/dev/null 2>&1; then
|
||||
printf 'Claude Code already found on PATH; skipping install.\n'
|
||||
return 0
|
||||
fi
|
||||
|
||||
require_command npm
|
||||
run npm install -g @anthropic-ai/claude-code
|
||||
}
|
||||
|
||||
install_or_update_uv() {
|
||||
add_uv_to_path
|
||||
|
||||
if ! command -v uv >/dev/null 2>&1; then
|
||||
run_uv_installer
|
||||
add_uv_to_path
|
||||
if command -v uv >/dev/null 2>&1; then
|
||||
run uv self update
|
||||
return 0
|
||||
fi
|
||||
|
||||
run_uv_installer
|
||||
add_uv_to_path
|
||||
|
||||
if [ "$dry_run" -eq 0 ] && ! command -v uv >/dev/null 2>&1; then
|
||||
fail "uv was installed, but it is not available on PATH. Open a new terminal or add uv's bin directory to PATH."
|
||||
fi
|
||||
|
||||
run uv self update
|
||||
}
|
||||
|
||||
parse_args() {
|
||||
@@ -201,11 +212,10 @@ install_free_claude_code() {
|
||||
parse_args "$@"
|
||||
validate_args
|
||||
|
||||
step "Installing or updating Claude Code"
|
||||
require_command npm
|
||||
run npm install -g @anthropic-ai/claude-code
|
||||
step "Installing Claude Code if missing"
|
||||
install_claude_if_missing
|
||||
|
||||
step "Installing or updating uv"
|
||||
step "Installing uv if missing, updating if present"
|
||||
install_or_update_uv
|
||||
|
||||
step "Installing Python $PYTHON_VERSION"
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def _repo_root() -> Path:
|
||||
return Path(__file__).resolve().parents[2]
|
||||
|
||||
|
||||
def _script_text(name: str) -> str:
|
||||
return (_repo_root() / "scripts" / name).read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def _braced_body(text: str, declaration: str) -> str:
|
||||
start = text.index(declaration)
|
||||
brace_start = text.index("{", start)
|
||||
depth = 0
|
||||
|
||||
for index, char in enumerate(text[brace_start:], start=brace_start):
|
||||
if char == "{":
|
||||
depth += 1
|
||||
elif char == "}":
|
||||
depth -= 1
|
||||
if depth == 0:
|
||||
return text[brace_start + 1 : index]
|
||||
|
||||
raise AssertionError(f"Unclosed function body for {declaration}")
|
||||
|
||||
|
||||
def test_install_sh_installs_claude_only_when_missing() -> None:
|
||||
text = _script_text("install.sh")
|
||||
body = _braced_body(text, "install_claude_if_missing()")
|
||||
main = text[text.index('parse_args "$@"') :]
|
||||
|
||||
assert "Installs Claude Code if missing" in text
|
||||
assert "if command -v claude >/dev/null 2>&1; then" in body
|
||||
assert "Claude Code already found on PATH; skipping install." in body
|
||||
assert "require_command npm" in body
|
||||
assert "run npm install -g @anthropic-ai/claude-code" in body
|
||||
assert body.index("command -v claude") < body.index("run npm install")
|
||||
assert body.index("return 0") < body.index("run npm install")
|
||||
assert 'step "Installing Claude Code if missing"\ninstall_claude_if_missing' in main
|
||||
assert "npm install -g @anthropic-ai/claude-code" not in main
|
||||
|
||||
|
||||
def test_install_sh_installs_missing_uv_without_self_update() -> None:
|
||||
body = _braced_body(_script_text("install.sh"), "install_or_update_uv()")
|
||||
|
||||
assert "if command -v uv >/dev/null 2>&1; then" in body
|
||||
assert body.count("run uv self update") == 1
|
||||
|
||||
update_index = body.index("run uv self update")
|
||||
return_index = body.index("return 0", update_index)
|
||||
installer_index = body.index("run_uv_installer")
|
||||
verification_index = body.index('if [ "$dry_run" -eq 0 ] && ! command -v uv')
|
||||
|
||||
assert update_index < return_index < installer_index < verification_index
|
||||
|
||||
|
||||
def test_install_ps1_installs_claude_only_when_missing() -> None:
|
||||
text = _script_text("install.ps1")
|
||||
body = _braced_body(text, "function Install-ClaudeIfMissing")
|
||||
|
||||
assert "Installs Claude Code if missing" in text
|
||||
assert "if (Get-Command claude -ErrorAction SilentlyContinue)" in body
|
||||
assert "Claude Code already found on PATH; skipping install." in body
|
||||
assert 'Assert-CommandAvailable "npm"' in body
|
||||
assert (
|
||||
'Invoke-InstallCommand -FilePath "npm" '
|
||||
'-Arguments @("install", "-g", "@anthropic-ai/claude-code")'
|
||||
) in body
|
||||
assert body.index("Get-Command claude") < body.index("Invoke-InstallCommand")
|
||||
assert body.index("return") < body.index("Invoke-InstallCommand")
|
||||
assert (
|
||||
'Write-Step "Installing Claude Code if missing"\nInstall-ClaudeIfMissing'
|
||||
in text
|
||||
)
|
||||
|
||||
|
||||
def test_install_ps1_installs_missing_uv_without_self_update() -> None:
|
||||
body = _braced_body(_script_text("install.ps1"), "function Install-OrUpdateUv")
|
||||
self_update = 'Invoke-InstallCommand -FilePath "uv" -Arguments @("self", "update")'
|
||||
|
||||
assert "if (Get-Command uv -ErrorAction SilentlyContinue)" in body
|
||||
assert body.count(self_update) == 1
|
||||
|
||||
update_index = body.index(self_update)
|
||||
return_index = body.index("return", update_index)
|
||||
installer_index = body.index("Invoke-UvInstaller")
|
||||
verification_index = body.index("if ((-not $DryRun)")
|
||||
|
||||
assert update_index < return_index < installer_index < verification_index
|
||||
Reference in New Issue
Block a user