From 571d60182a011cc2c71c451d3ddb3243b72cbbd8 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Thu, 3 Jul 2025 21:17:15 -0400 Subject: improve snapshotting speed further --- packages/opencode/.gitignore | 1 - packages/opencode/src/snapshot/index.ts | 111 ++++++++++++-------------------- 2 files changed, 40 insertions(+), 72 deletions(-) (limited to 'packages') diff --git a/packages/opencode/.gitignore b/packages/opencode/.gitignore index 66857d897..e057ca61f 100644 --- a/packages/opencode/.gitignore +++ b/packages/opencode/.gitignore @@ -1,4 +1,3 @@ -node_modules research dist gen diff --git a/packages/opencode/src/snapshot/index.ts b/packages/opencode/src/snapshot/index.ts index fcf77c459..95d7776c6 100644 --- a/packages/opencode/src/snapshot/index.ts +++ b/packages/opencode/src/snapshot/index.ts @@ -1,14 +1,7 @@ import { App } from "../app/app" -import { - add, - commit, - init, - checkout, - statusMatrix, - remove, -} from "isomorphic-git" +import { $ } from "bun" import path from "path" -import fs from "fs" +import fs from "fs/promises" import { Ripgrep } from "../file/ripgrep" import { Log } from "../util/log" @@ -19,76 +12,52 @@ export namespace Snapshot { log.info("creating snapshot") const app = App.info() const git = gitdir(sessionID) - const files = await Ripgrep.files({ - cwd: app.path.cwd, - limit: app.git ? undefined : 1000, - }) - log.info("found files", { count: files.length }) - // not a git repo and too big to snapshot - if (!app.git && files.length === 1000) return - await init({ - dir: app.path.cwd, - gitdir: git, - fs, - }) - log.info("initialized") - const status = await statusMatrix({ - fs, - gitdir: git, - dir: app.path.cwd, - }) - log.info("matrix", { - count: status.length, - }) - const added = [] - for (const [file, head, workdir, stage] of status) { - if (workdir === 0 && stage === 1) { - log.info("remove", { file }) - await remove({ - fs, - gitdir: git, - dir: app.path.cwd, - filepath: file, + + // not a git repo, check if too big to snapshot + if (!app.git) { + const files = await Ripgrep.files({ + cwd: app.path.cwd, + limit: 1000, + }) + log.info("found files", { count: files.length }) + if (files.length > 1000) return + } + + if (await fs.mkdir(git, { recursive: true })) { + await $`git init` + .env({ + ...process.env, + GIT_DIR: git, + GIT_WORK_TREE: app.path.root, }) - continue - } - if (workdir !== head) { - added.push(file) - } + .quiet() + .nothrow() + log.info("initialized") } - log.info("removed files") - await add({ - fs, - gitdir: git, - parallel: true, - dir: app.path.cwd, - filepath: added, - }) + + await $`git --git-dir ${git} add .`.quiet().cwd(app.path.cwd).nothrow() log.info("added files") - const result = await commit({ - fs, - gitdir: git, - dir: app.path.cwd, - message: "snapshot", - author: { - name: "opencode", - email: "mail@opencode.ai", - }, - }) - log.info("commit", { result }) - return result + + const result = + await $`git --git-dir ${git} commit --allow-empty -m "snapshot" --author="opencode "` + .quiet() + .cwd(app.path.cwd) + .nothrow() + log.info("commit") + + // Extract commit hash from output like "[main abc1234] snapshot" + const match = result.stdout.toString().match(/\[.+ ([a-f0-9]+)\]/) + if (!match) throw new Error("Failed to extract commit hash") + return match[1] } export async function restore(sessionID: string, commit: string) { log.info("restore", { commit }) const app = App.info() - await checkout({ - fs, - gitdir: gitdir(sessionID), - dir: app.path.cwd, - ref: commit, - force: true, - }) + const git = gitdir(sessionID) + await $`git --git-dir=${git} checkout ${commit} --force` + .quiet() + .cwd(app.path.root) } function gitdir(sessionID: string) { -- cgit v1.2.3