Skip to content

Commit 571d601

Browse files
committed
improve snapshotting speed further
1 parent 167a9dc commit 571d601

3 files changed

Lines changed: 45 additions & 72 deletions

File tree

bun.lock

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/opencode/.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
node_modules
21
research
32
dist
43
gen

packages/opencode/src/snapshot/index.ts

Lines changed: 40 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,7 @@
11
import { App } from "../app/app"
2-
import {
3-
add,
4-
commit,
5-
init,
6-
checkout,
7-
statusMatrix,
8-
remove,
9-
} from "isomorphic-git"
2+
import { $ } from "bun"
103
import path from "path"
11-
import fs from "fs"
4+
import fs from "fs/promises"
125
import { Ripgrep } from "../file/ripgrep"
136
import { Log } from "../util/log"
147

@@ -19,76 +12,52 @@ export namespace Snapshot {
1912
log.info("creating snapshot")
2013
const app = App.info()
2114
const git = gitdir(sessionID)
22-
const files = await Ripgrep.files({
23-
cwd: app.path.cwd,
24-
limit: app.git ? undefined : 1000,
25-
})
26-
log.info("found files", { count: files.length })
27-
// not a git repo and too big to snapshot
28-
if (!app.git && files.length === 1000) return
29-
await init({
30-
dir: app.path.cwd,
31-
gitdir: git,
32-
fs,
33-
})
34-
log.info("initialized")
35-
const status = await statusMatrix({
36-
fs,
37-
gitdir: git,
38-
dir: app.path.cwd,
39-
})
40-
log.info("matrix", {
41-
count: status.length,
42-
})
43-
const added = []
44-
for (const [file, head, workdir, stage] of status) {
45-
if (workdir === 0 && stage === 1) {
46-
log.info("remove", { file })
47-
await remove({
48-
fs,
49-
gitdir: git,
50-
dir: app.path.cwd,
51-
filepath: file,
15+
16+
// not a git repo, check if too big to snapshot
17+
if (!app.git) {
18+
const files = await Ripgrep.files({
19+
cwd: app.path.cwd,
20+
limit: 1000,
21+
})
22+
log.info("found files", { count: files.length })
23+
if (files.length > 1000) return
24+
}
25+
26+
if (await fs.mkdir(git, { recursive: true })) {
27+
await $`git init`
28+
.env({
29+
...process.env,
30+
GIT_DIR: git,
31+
GIT_WORK_TREE: app.path.root,
5232
})
53-
continue
54-
}
55-
if (workdir !== head) {
56-
added.push(file)
57-
}
33+
.quiet()
34+
.nothrow()
35+
log.info("initialized")
5836
}
59-
log.info("removed files")
60-
await add({
61-
fs,
62-
gitdir: git,
63-
parallel: true,
64-
dir: app.path.cwd,
65-
filepath: added,
66-
})
37+
38+
await $`git --git-dir ${git} add .`.quiet().cwd(app.path.cwd).nothrow()
6739
log.info("added files")
68-
const result = await commit({
69-
fs,
70-
gitdir: git,
71-
dir: app.path.cwd,
72-
message: "snapshot",
73-
author: {
74-
name: "opencode",
75-
email: "mail@opencode.ai",
76-
},
77-
})
78-
log.info("commit", { result })
79-
return result
40+
41+
const result =
42+
await $`git --git-dir ${git} commit --allow-empty -m "snapshot" --author="opencode <mail@opencode.ai>"`
43+
.quiet()
44+
.cwd(app.path.cwd)
45+
.nothrow()
46+
log.info("commit")
47+
48+
// Extract commit hash from output like "[main abc1234] snapshot"
49+
const match = result.stdout.toString().match(/\[.+ ([a-f0-9]+)\]/)
50+
if (!match) throw new Error("Failed to extract commit hash")
51+
return match[1]
8052
}
8153

8254
export async function restore(sessionID: string, commit: string) {
8355
log.info("restore", { commit })
8456
const app = App.info()
85-
await checkout({
86-
fs,
87-
gitdir: gitdir(sessionID),
88-
dir: app.path.cwd,
89-
ref: commit,
90-
force: true,
91-
})
57+
const git = gitdir(sessionID)
58+
await $`git --git-dir=${git} checkout ${commit} --force`
59+
.quiet()
60+
.cwd(app.path.root)
9261
}
9362

9463
function gitdir(sessionID: string) {

0 commit comments

Comments
 (0)