From d27e318072aca74e95be0d30ddf6bc7efecb5a8b Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 14 Aug 2026 14:38:21 -0700 Subject: [PATCH] improve: make git installs use a blobless clone (#123835) * perf: use blobless clone in git installer * refactor(install): move clone-filter rationale above the call Keep the file's comment convention (comments on their own lines) instead of a 150-column trailing comment, and record why blob:none is preferred over --depth 1 plus why no fallback is needed. Narrow the ordering test's source needle to the stable prefix so it stops duplicating the behavioral flag assertion and no longer breaks whenever the clone flags change. --- scripts/install.sh | 6 ++++- test/scripts/install-sh.test.ts | 39 ++++++++++++++++++++++++++++++--- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/scripts/install.sh b/scripts/install.sh index eb6bdfe300b4..92c077bd6fd5 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -2874,7 +2874,11 @@ install_openclaw_from_git() { validate_git_checkout_head "$repo_dir" || return 1 if [[ ! -d "$repo_dir" ]]; then mkdir -p "$(dirname "$repo_dir")" - run_quiet_step "Cloning OpenClaw" git clone "$repo_url" "$repo_dir" + # Blobless clone: the installer checks out one release tag, so full blob + # history is downloaded and then discarded. blob:none keeps ref metadata + # (unlike --depth 1) so ref switching and later updates still work, and + # git warns and falls back to a full clone if the server cannot filter. + run_quiet_step "Cloning OpenClaw" git clone --filter=blob:none "$repo_url" "$repo_dir" fi local git_ref diff --git a/test/scripts/install-sh.test.ts b/test/scripts/install-sh.test.ts index 0ca86ca542db..bce15156e364 100644 --- a/test/scripts/install-sh.test.ts +++ b/test/scripts/install-sh.test.ts @@ -1017,14 +1017,47 @@ NODE const output = result?.stdout ?? ""; expect(output).toContain(`git=${join(openclawHome, "openclaw")}`); const mkdirParentIndex = script.indexOf('mkdir -p "$(dirname "$repo_dir")"'); - const cloneIndex = script.indexOf( - 'run_quiet_step "Cloning OpenClaw" git clone "$repo_url" "$repo_dir"', - ); + // Ordering only. The clone flags are asserted behaviorally below, so this + // needle stays short enough to survive future changes to them. + const cloneIndex = script.indexOf('run_quiet_step "Cloning OpenClaw" git clone'); expect(mkdirParentIndex).toBeGreaterThan(-1); expect(cloneIndex).toBeGreaterThan(-1); expect(mkdirParentIndex).toBeLessThan(cloneIndex); }); + it("uses a blobless partial clone for new git installs", () => { + const result = runInstallShell(` + set -euo pipefail + source "${SCRIPT_PATH}" + repo="$HOME/openclaw" + check_git() { return 0; } + ensure_pnpm() { :; } + ensure_pnpm_binary_for_scripts() { :; } + resolve_git_openclaw_ref() { printf 'main\\n'; } + checkout_git_openclaw_ref() { :; } + cleanup_legacy_submodules() { :; } + activate_repo_pnpm_version() { :; } + git_install_lockfile_flag() { printf '%s\\n' '--frozen-lockfile'; } + run_quiet_step() { + printf 'step:%s|%s\\n' "$1" "\${*:2}" + [[ "$1" == "Cloning OpenClaw" ]] && mkdir -p "$repo" + return 0 + } + ensure_user_local_bin_on_path() { mkdir -p "$HOME/.local/bin"; } + ui_info() { :; } + ui_success() { :; } + ui_error() { printf 'error:%s\\n' "$*"; } + git() { return 0; } + + install_openclaw_from_git "$repo" + `); + + expect(result.status).toBe(0); + expect(result.stdout).toContain( + "step:Cloning OpenClaw|git clone --filter=blob:none https://github.com/openclaw/openclaw.git", + ); + }); + it("does not treat OS HOME config as active when OPENCLAW_HOME is set", () => { const tmp = mkdtempSync(join(tmpdir(), "openclaw-install-legacy-config-")); const osHome = join(tmp, "os-home");