fix: add apt lock timeout and official portable scrcpy fallback across Linux and Windows

- Handle Debian/Ubuntu apt-get lock contention with DPkg::Lock::Timeout
- Decouple apt update from apt install so locks on update do not block installation
- Add official portable scrcpy v4.1 fallback download for Linux (x64/arm64) and Windows (win64)
- Add scrcpy user directories to standard PATH discovery
This commit is contained in:
somew1nd committed 2026-09-04 17:07:54 -07:00
1 parent 29622bae52
commit afbc402225
4 files changed
+149 -4

No files matched your search

+39 -1
View File
@@ -46,8 +46,10 @@ function Update-EnvironmentPath {
"${env:ProgramFiles(x86)}\nodejs",
"$env:APPDATA\npm",
"$env:LOCALAPPDATA\Programs\platform-tools",
"$env:LOCALAPPDATA\Programs\scrcpy",
"$env:LOCALAPPDATA\Programs\node",
"$env:USERPROFILE\.local\share\platform-tools",
"$env:USERPROFILE\.local\share\scrcpy",
"$env:USERPROFILE\.local\share\node",
"$env:LOCALAPPDATA\nvm",
"$env:ProgramData\nvm",
@@ -107,6 +109,39 @@ function Install-PortablePlatformTools {
return $false
}
function Install-PortableScrcpy {
$scrcpyDir = "$env:LOCALAPPDATA\Programs\scrcpy"
if (Test-Path "$scrcpyDir\scrcpy.exe") {
$env:PATH = "$scrcpyDir;$env:PATH"
return $true
}
Write-Host " [INFO] Installing portable scrcpy in user space..." -ForegroundColor Cyan
try {
$zipPath = "$env:TEMP\scrcpy-win64.zip"
Invoke-WebRequest -Uri "https://github.com/Genymobile/scrcpy/releases/download/v4.1/scrcpy-win64-v4.1.zip" -OutFile $zipPath -UseBasicParsing
$extractDir = "$env:TEMP\scrcpy_extract"
if (Test-Path $extractDir) { Remove-Item $extractDir -Recurse -Force -ErrorAction SilentlyContinue }
New-Item -ItemType Directory -Path $extractDir -Force | Out-Null
Expand-Archive -Path $zipPath -DestinationPath $extractDir -Force
$extractedFolder = Get-ChildItem -Path $extractDir -Directory | Select-Object -First 1
if ($extractedFolder) {
New-Item -ItemType Directory -Path "$env:LOCALAPPDATA\Programs" -Force | Out-Null
if (Test-Path $scrcpyDir) { Remove-Item $scrcpyDir -Recurse -Force -ErrorAction SilentlyContinue }
Move-Item -Path $extractedFolder.FullName -Destination $scrcpyDir -Force
}
Remove-Item $zipPath -Force -ErrorAction SilentlyContinue
Remove-Item $extractDir -Recurse -Force -ErrorAction SilentlyContinue
if (Test-Path "$scrcpyDir\scrcpy.exe") {
$env:PATH = "$scrcpyDir;$env:PATH"
Write-Host " ✔ Portable scrcpy installed in user space." -ForegroundColor Green
return $true
}
} catch {
Write-Host " ⚠ Failed to install portable scrcpy: $_" -ForegroundColor DarkYellow
}
return $false
}
function Test-NodeCompatible {
if (-not (Test-CommandExists "node") -or -not (Test-CommandExists "npm")) { return $false }
try {
@@ -219,10 +254,13 @@ if ($missingTools.Count -eq 0) {
Update-EnvironmentPath
}
# Zero-admin user-space fallback for adb if still missing
# Zero-admin user-space fallback for adb and scrcpy if still missing
if (-not (Test-CommandExists "adb")) {
Install-PortablePlatformTools
}
if (-not (Test-CommandExists "scrcpy")) {
Install-PortableScrcpy
}
# Ensure local ADB daemon is warm & listening
Start-LocalAdbServer
+35 -1
View File
@@ -52,6 +52,7 @@ STANDARD_PATHS=(
"${HOME}/.local/bin"
"${HOME}/.local/share/node/bin"
"${HOME}/.local/share/platform-tools"
"${HOME}/.local/share/scrcpy"
"${HOME}/.cargo/bin"
"${HOME}/Library/Android/sdk/platform-tools"
"${HOME}/Android/Sdk/platform-tools"
@@ -231,7 +232,8 @@ install_system_packages() {
if has_cmd apt-get; then
echo -e " ${CYAN}Detected Debian/Ubuntu (apt-get). Synchronizing and installing...${NC}"
${SUDO_PREFIX} apt-get update -qq && ${SUDO_PREFIX} apt-get install -y "${PKGS[@]}" || true
${SUDO_PREFIX} apt-get -o DPkg::Lock::Timeout=60 update -qq 2>/dev/null || true
${SUDO_PREFIX} apt-get -o DPkg::Lock::Timeout=60 install -y "${PKGS[@]}" 2>/dev/null || true
elif has_cmd dnf; then
echo -e " ${CYAN}Detected Fedora/RHEL (dnf). Installing packages...${NC}"
local DNF_PKGS=()
@@ -249,6 +251,38 @@ install_system_packages() {
fi
fi
# Fallback: if scrcpy is still missing, try snap or install portable scrcpy in user space
if ! has_cmd scrcpy; then
if has_cmd snap && request_sudo "install scrcpy via snap"; then
local SUDO_PREFIX=""
if [ "$(id -u)" -ne 0 ]; then SUDO_PREFIX="sudo"; fi
${SUDO_PREFIX} snap install scrcpy 2>/dev/null || true
fi
fi
if ! has_cmd scrcpy; then
local SCRCPY_ARCH=""
case "${ARCH_TYPE}" in
x86_64|amd64) SCRCPY_ARCH="x86_64" ;;
aarch64|arm64) SCRCPY_ARCH="aarch64" ;;
esac
if [ -n "${SCRCPY_ARCH}" ]; then
local SCRCPY_DIR="${HOME}/.local/share/scrcpy"
if [ ! -x "${SCRCPY_DIR}/scrcpy" ]; then
echo -e " ${CYAN}📦 Installing portable scrcpy in user space (~/.local)...${NC}"
mkdir -p "${SCRCPY_DIR}" "${HOME}/.local/bin"
local SCRCPY_URL="https://github.com/Genymobile/scrcpy/releases/download/v4.1/scrcpy-linux-${SCRCPY_ARCH}-v4.1.tar.gz"
if curl -fsSL "${SCRCPY_URL}" | tar -xz -C "${SCRCPY_DIR}" --strip-components=1 2>/dev/null; then
ln -sf "${SCRCPY_DIR}/scrcpy" "${HOME}/.local/bin/scrcpy"
export PATH="${SCRCPY_DIR}:${PATH}"
echo -e " ${GREEN}✓ scrcpy installed in user space.${NC}"
fi
else
ln -sf "${SCRCPY_DIR}/scrcpy" "${HOME}/.local/bin/scrcpy"
export PATH="${SCRCPY_DIR}:${PATH}"
fi
fi
fi
# User-space fallback for adb if missing and no root privileges
if ! has_cmd adb; then
if [[ "${ARCH_TYPE}" = "x86_64" || "${ARCH_TYPE}" = "amd64" ]]; then
+39 -1
View File
@@ -41,8 +41,10 @@ function Update-EnvironmentPath {
"${env:ProgramFiles(x86)}\nodejs",
"$env:APPDATA\npm",
"$env:LOCALAPPDATA\Programs\platform-tools",
"$env:LOCALAPPDATA\Programs\scrcpy",
"$env:LOCALAPPDATA\Programs\node",
"$env:USERPROFILE\.local\share\platform-tools",
"$env:USERPROFILE\.local\share\scrcpy",
"$env:USERPROFILE\.local\share\node",
"$env:LOCALAPPDATA\nvm",
"$env:ProgramData\nvm",
@@ -102,6 +104,39 @@ function Install-PortablePlatformTools {
return $false
}
function Install-PortableScrcpy {
$scrcpyDir = "$env:LOCALAPPDATA\Programs\scrcpy"
if (Test-Path "$scrcpyDir\scrcpy.exe") {
$env:PATH = "$scrcpyDir;$env:PATH"
return $true
}
Write-Host " [INFO] Installing portable scrcpy in user space..." -ForegroundColor Cyan
try {
$zipPath = "$env:TEMP\scrcpy-win64.zip"
Invoke-WebRequest -Uri "https://github.com/Genymobile/scrcpy/releases/download/v4.1/scrcpy-win64-v4.1.zip" -OutFile $zipPath -UseBasicParsing
$extractDir = "$env:TEMP\scrcpy_extract"
if (Test-Path $extractDir) { Remove-Item $extractDir -Recurse -Force -ErrorAction SilentlyContinue }
New-Item -ItemType Directory -Path $extractDir -Force | Out-Null
Expand-Archive -Path $zipPath -DestinationPath $extractDir -Force
$extractedFolder = Get-ChildItem -Path $extractDir -Directory | Select-Object -First 1
if ($extractedFolder) {
New-Item -ItemType Directory -Path "$env:LOCALAPPDATA\Programs" -Force | Out-Null
if (Test-Path $scrcpyDir) { Remove-Item $scrcpyDir -Recurse -Force -ErrorAction SilentlyContinue }
Move-Item -Path $extractedFolder.FullName -Destination $scrcpyDir -Force
}
Remove-Item $zipPath -Force -ErrorAction SilentlyContinue
Remove-Item $extractDir -Recurse -Force -ErrorAction SilentlyContinue
if (Test-Path "$scrcpyDir\scrcpy.exe") {
$env:PATH = "$scrcpyDir;$env:PATH"
Write-Host " ✔ Portable scrcpy installed in user space." -ForegroundColor Green
return $true
}
} catch {
Write-Host " ⚠ Failed to install portable scrcpy: $_" -ForegroundColor DarkYellow
}
return $false
}
function Test-NodeCompatible {
if (-not (Test-CommandExists "node") -or -not (Test-CommandExists "npm")) { return $false }
try {
@@ -205,10 +240,13 @@ if ($missingCore.Count -gt 0) {
Update-EnvironmentPath
}
# Zero-admin user-space fallback for adb if still missing
# Zero-admin user-space fallback for adb and scrcpy if still missing
if (-not (Test-CommandExists "adb")) {
Install-PortablePlatformTools
}
if (-not (Test-CommandExists "scrcpy")) {
Install-PortableScrcpy
}
}
# Ensure local ADB daemon is warm & listening so probes do not hit 'Connection refused'
+36 -1
View File
@@ -39,6 +39,7 @@ STANDARD_PATHS=(
"${HOME}/.local/bin"
"${HOME}/.local/share/node/bin"
"${HOME}/.local/share/platform-tools"
"${HOME}/.local/share/scrcpy"
"${HOME}/.cargo/bin"
"${HOME}/Library/Android/sdk/platform-tools"
"${HOME}/Android/Sdk/platform-tools"
@@ -177,7 +178,8 @@ if [ ${#MISSING_CORE[@]} -gt 0 ]; then
SUDO_PREFIX=""
if [ "$(id -u)" -ne 0 ]; then SUDO_PREFIX="sudo"; fi
if command -v apt-get >/dev/null 2>&1; then
${SUDO_PREFIX} apt-get update -qq && ${SUDO_PREFIX} apt-get install -y -qq "${MISSING_CORE[@]}" || true
${SUDO_PREFIX} apt-get -o DPkg::Lock::Timeout=60 update -qq 2>/dev/null || true
${SUDO_PREFIX} apt-get -o DPkg::Lock::Timeout=60 install -y -qq "${MISSING_CORE[@]}" 2>/dev/null || true
elif command -v dnf >/dev/null 2>&1; then
${SUDO_PREFIX} dnf install -y "${MISSING_CORE[@]}" || true
elif command -v pacman >/dev/null 2>&1; then
@@ -185,6 +187,39 @@ if [ ${#MISSING_CORE[@]} -gt 0 ]; then
fi
fi
# Fallback: if scrcpy is still missing, try snap or install portable scrcpy in user space
if ! command -v scrcpy >/dev/null 2>&1; then
if command -v snap >/dev/null 2>&1 && request_sudo "install scrcpy via snap"; then
local SUDO_PREFIX=""
if [ "$(id -u)" -ne 0 ]; then SUDO_PREFIX="sudo"; fi
${SUDO_PREFIX} snap install scrcpy 2>/dev/null || true
fi
fi
if ! command -v scrcpy >/dev/null 2>&1; then
ARCH="$(uname -m)"
SCRCPY_ARCH=""
case "${ARCH}" in
x86_64|amd64) SCRCPY_ARCH="x86_64" ;;
aarch64|arm64) SCRCPY_ARCH="aarch64" ;;
esac
if [ -n "${SCRCPY_ARCH}" ]; then
SCRCPY_DIR="${HOME}/.local/share/scrcpy"
if [ ! -x "${SCRCPY_DIR}/scrcpy" ]; then
echo -e " ${CYAN}📦 Installing portable scrcpy in user space (~/.local)...${NC}"
mkdir -p "${SCRCPY_DIR}" "${HOME}/.local/bin"
SCRCPY_URL="https://github.com/Genymobile/scrcpy/releases/download/v4.1/scrcpy-linux-${SCRCPY_ARCH}-v4.1.tar.gz"
if curl -fsSL "${SCRCPY_URL}" | tar -xz -C "${SCRCPY_DIR}" --strip-components=1 2>/dev/null; then
ln -sf "${SCRCPY_DIR}/scrcpy" "${HOME}/.local/bin/scrcpy"
export PATH="${SCRCPY_DIR}:${PATH}"
echo -e " ${GREEN}✓ scrcpy installed in user space.${NC}"
fi
else
ln -sf "${SCRCPY_DIR}/scrcpy" "${HOME}/.local/bin/scrcpy"
export PATH="${SCRCPY_DIR}:${PATH}"
fi
fi
fi
# Fallback: if adb is missing on Linux without root/sudo, install platform-tools in user space
if ! command -v adb >/dev/null 2>&1; then
ARCH="$(uname -m)"