chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
#!/usr/bin/env bash
|
||||
# install-code-server.sh - Install or update code-server (browser IDE) on Termux
|
||||
# Usage: bash install-code-server.sh [install|update]
|
||||
#
|
||||
# Workarounds applied:
|
||||
# 1. Replace bundled glibc node with Termux node
|
||||
# 2. Patch argon2 native module with JS stub (--auth none makes it unused)
|
||||
# 3. Ignore tar hard link errors (Android restriction) and recover .node files
|
||||
#
|
||||
# This script is WARN-level: failure does not abort the parent installer.
|
||||
set -euo pipefail
|
||||
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
MODE="${1:-install}"
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
INSTALL_DIR="$HOME/.local/lib"
|
||||
BIN_DIR="$HOME/.local/bin"
|
||||
|
||||
# ── Helper ────────────────────────────────────
|
||||
|
||||
fail_warn() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# ── Pre-checks ────────────────────────────────
|
||||
|
||||
if [ -z "${PREFIX:-}" ]; then
|
||||
fail_warn "Not running in Termux (\$PREFIX not set)"
|
||||
fi
|
||||
|
||||
if ! command -v node &>/dev/null; then
|
||||
fail_warn "node not found — code-server requires Node.js"
|
||||
fi
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
fail_warn "curl not found — cannot download code-server"
|
||||
fi
|
||||
|
||||
# ── Check current installation ────────────────
|
||||
|
||||
CURRENT_VERSION=""
|
||||
if [ -x "$BIN_DIR/code-server" ]; then
|
||||
# code-server --version may include i18next ad text before the version line.
|
||||
# Use regex to extract X.Y.Z directly, ignoring any noise lines.
|
||||
CURRENT_VERSION=$("$BIN_DIR/code-server" --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || true)
|
||||
fi
|
||||
|
||||
# ── Determine target version ──────────────────
|
||||
|
||||
if [ "$MODE" = "install" ] && [ -n "$CURRENT_VERSION" ]; then
|
||||
echo -e "${GREEN}[SKIP]${NC} code-server already installed ($CURRENT_VERSION)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Fetch latest version from GitHub API
|
||||
echo "Checking latest code-server version..."
|
||||
LATEST_VERSION=$(curl -sfL --max-time 10 \
|
||||
"https://api.github.com/repos/coder/code-server/releases/latest" \
|
||||
| grep '"tag_name"' | head -1 | sed 's/.*"v\([^"]*\)".*/\1/') || true
|
||||
|
||||
if [ -z "$LATEST_VERSION" ]; then
|
||||
fail_warn "Failed to fetch latest code-server version from GitHub"
|
||||
fi
|
||||
|
||||
echo " Latest: v$LATEST_VERSION"
|
||||
|
||||
if [ "$MODE" = "update" ] && [ -n "$CURRENT_VERSION" ]; then
|
||||
if [ "$CURRENT_VERSION" = "$LATEST_VERSION" ]; then
|
||||
echo -e "${GREEN}[SKIP]${NC} code-server $CURRENT_VERSION is already the latest"
|
||||
exit 0
|
||||
fi
|
||||
echo " Current: v$CURRENT_VERSION → updating to v$LATEST_VERSION"
|
||||
fi
|
||||
|
||||
VERSION="$LATEST_VERSION"
|
||||
|
||||
# ── Download ──────────────────────────────────
|
||||
|
||||
TARBALL="code-server-${VERSION}-linux-arm64.tar.gz"
|
||||
DOWNLOAD_URL="https://github.com/coder/code-server/releases/download/v${VERSION}/${TARBALL}"
|
||||
TMP_DIR=$(mktemp -d "$PREFIX/tmp/code-server-install.XXXXXX") || fail_warn "Failed to create temp directory"
|
||||
trap 'rm -rf "$TMP_DIR"' EXIT
|
||||
|
||||
echo "Downloading code-server v${VERSION}..."
|
||||
echo " (File size ~121MB — this may take several minutes depending on network speed)"
|
||||
if ! curl -fL --max-time 300 "$DOWNLOAD_URL" -o "$TMP_DIR/$TARBALL"; then
|
||||
fail_warn "Failed to download code-server v${VERSION}"
|
||||
fi
|
||||
echo -e "${GREEN}[OK]${NC} Downloaded $TARBALL"
|
||||
|
||||
# ── Extract (ignore hard link errors) ─────────
|
||||
|
||||
echo "Extracting code-server... (this may take a moment)"
|
||||
# Android's filesystem does not support hard links, so tar will report errors
|
||||
# for hardlinked .node files. We extract what we can and recover them below.
|
||||
tar -xzf "$TMP_DIR/$TARBALL" -C "$TMP_DIR" 2>/dev/null || true
|
||||
|
||||
EXTRACTED_DIR="$TMP_DIR/code-server-${VERSION}-linux-arm64"
|
||||
if [ ! -d "$EXTRACTED_DIR" ]; then
|
||||
fail_warn "Extraction failed — directory not found"
|
||||
fi
|
||||
|
||||
# ── Recover hard-linked .node files ───────────
|
||||
# The obj.target/ directories contain the original .node files that tar
|
||||
# couldn't hard-link into Release/. Copy them manually.
|
||||
|
||||
find "$EXTRACTED_DIR" -path "*/obj.target/*.node" -type f 2>/dev/null | while read -r OBJ_FILE; do
|
||||
# obj.target/foo.node → Release/foo.node
|
||||
RELEASE_DIR="$(dirname "$(dirname "$OBJ_FILE")")/Release"
|
||||
BASENAME="$(basename "$OBJ_FILE")"
|
||||
if [ -d "$RELEASE_DIR" ] && [ ! -f "$RELEASE_DIR/$BASENAME" ]; then
|
||||
cp "$OBJ_FILE" "$RELEASE_DIR/$BASENAME"
|
||||
fi
|
||||
done
|
||||
echo -e "${GREEN}[OK]${NC} Extracted and recovered .node files"
|
||||
|
||||
# ── Install to ~/.local/lib ───────────────────
|
||||
|
||||
mkdir -p "$INSTALL_DIR" "$BIN_DIR"
|
||||
|
||||
# Remove previous code-server versions
|
||||
rm -rf "$INSTALL_DIR"/code-server-*
|
||||
|
||||
# Move extracted directory to install location
|
||||
mv "$EXTRACTED_DIR" "$INSTALL_DIR/code-server-${VERSION}"
|
||||
echo -e "${GREEN}[OK]${NC} Installed to $INSTALL_DIR/code-server-${VERSION}"
|
||||
|
||||
CS_DIR="$INSTALL_DIR/code-server-${VERSION}"
|
||||
|
||||
# ── Replace bundled node with Termux node ─────
|
||||
# The standalone release bundles a glibc-linked node binary that cannot
|
||||
# run on Termux (Bionic libc). Swap it with the system node.
|
||||
|
||||
if [ -f "$CS_DIR/lib/node" ] || [ -L "$CS_DIR/lib/node" ]; then
|
||||
rm -f "$CS_DIR/lib/node"
|
||||
fi
|
||||
ln -s "$PREFIX/bin/node" "$CS_DIR/lib/node"
|
||||
echo -e "${GREEN}[OK]${NC} Replaced bundled node → Termux node"
|
||||
|
||||
# ── Patch argon2 native module ────────────────
|
||||
# argon2 ships a .node binary compiled against glibc. Since we run
|
||||
# code-server with --auth none, argon2 is never called. Replace the
|
||||
# module entry point with a JS stub.
|
||||
|
||||
ARGON2_STUB=""
|
||||
# Check multiple possible locations for the stub
|
||||
if [ -f "$SCRIPT_DIR/../patches/argon2-stub.js" ]; then
|
||||
ARGON2_STUB="$SCRIPT_DIR/../patches/argon2-stub.js"
|
||||
elif [ -f "$HOME/.openclaw-android/patches/argon2-stub.js" ]; then
|
||||
ARGON2_STUB="$HOME/.openclaw-android/patches/argon2-stub.js"
|
||||
fi
|
||||
|
||||
if [ -n "$ARGON2_STUB" ]; then
|
||||
# Find argon2 module entry point in code-server
|
||||
# Entry point varies by version: argon2.cjs (v4.109+), argon2.js, or index.js
|
||||
ARGON2_INDEX=""
|
||||
for PATTERN in "*/argon2/argon2.cjs" "*/argon2/argon2.js" "*/node_modules/argon2/index.js"; do
|
||||
ARGON2_INDEX=$(find "$CS_DIR" -path "$PATTERN" -type f 2>/dev/null | head -1 || true)
|
||||
[ -n "$ARGON2_INDEX" ] && break
|
||||
done
|
||||
if [ -n "$ARGON2_INDEX" ]; then
|
||||
cp "$ARGON2_STUB" "$ARGON2_INDEX"
|
||||
echo -e "${GREEN}[OK]${NC} Patched argon2 module with JS stub ($(basename "$ARGON2_INDEX"))"
|
||||
else
|
||||
echo -e "${YELLOW}[WARN]${NC} argon2 module not found in code-server (may not be needed)"
|
||||
fi
|
||||
else
|
||||
echo -e "${YELLOW}[WARN]${NC} argon2-stub.js not found — skipping argon2 patch"
|
||||
fi
|
||||
|
||||
# ── Create symlink ────────────────────────────
|
||||
|
||||
rm -f "$BIN_DIR/code-server"
|
||||
ln -s "$CS_DIR/bin/code-server" "$BIN_DIR/code-server"
|
||||
echo -e "${GREEN}[OK]${NC} Symlinked $BIN_DIR/code-server"
|
||||
|
||||
# ── Verify ────────────────────────────────────
|
||||
|
||||
# Add ~/.local/bin to PATH for this session so we can verify with just "code-server"
|
||||
export PATH="$BIN_DIR:$PATH"
|
||||
|
||||
echo ""
|
||||
if code-server --version &>/dev/null; then
|
||||
INSTALLED_VER=$(code-server --version 2>/dev/null | head -1 || true)
|
||||
echo -e "${GREEN}[OK]${NC} code-server ${INSTALLED_VER:-unknown} installed successfully"
|
||||
else
|
||||
echo -e "${YELLOW}[WARN]${NC} code-server installed but --version check failed"
|
||||
echo " This may work once ~/.local/bin is on PATH (restart shell or: source ~/.bashrc)"
|
||||
fi
|
||||
Reference in New Issue
Block a user