index.ts 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. import { App } from "../app/app"
  2. import { $ } from "bun"
  3. import path from "path"
  4. import fs from "fs/promises"
  5. import { Ripgrep } from "../file/ripgrep"
  6. import { Log } from "../util/log"
  7. export namespace Snapshot {
  8. const log = Log.create({ service: "snapshot" })
  9. export async function create(sessionID: string) {
  10. log.info("creating snapshot")
  11. const app = App.info()
  12. // not a git repo, check if too big to snapshot
  13. if (!app.git) {
  14. return
  15. const files = await Ripgrep.files({
  16. cwd: app.path.cwd,
  17. limit: 1000,
  18. })
  19. log.info("found files", { count: files.length })
  20. if (files.length >= 1000) return
  21. }
  22. const git = gitdir(sessionID)
  23. if (await fs.mkdir(git, { recursive: true })) {
  24. await $`git init`
  25. .env({
  26. ...process.env,
  27. GIT_DIR: git,
  28. GIT_WORK_TREE: app.path.root,
  29. })
  30. .quiet()
  31. .nothrow()
  32. log.info("initialized")
  33. }
  34. await $`git --git-dir ${git} add .`.quiet().cwd(app.path.cwd).nothrow()
  35. log.info("added files")
  36. const result =
  37. await $`git --git-dir ${git} commit -m "snapshot" --no-gpg-sign --author="opencode <[email protected]>"`
  38. .quiet()
  39. .cwd(app.path.cwd)
  40. .nothrow()
  41. const match = result.stdout.toString().match(/\[.+ ([a-f0-9]+)\]/)
  42. if (!match) return
  43. return match![1]
  44. }
  45. export async function restore(sessionID: string, snapshot: string) {
  46. log.info("restore", { commit: snapshot })
  47. const app = App.info()
  48. const git = gitdir(sessionID)
  49. await $`git --git-dir=${git} checkout ${snapshot} --force`.quiet().cwd(app.path.root)
  50. }
  51. export async function diff(sessionID: string, commit: string) {
  52. const git = gitdir(sessionID)
  53. const result = await $`git --git-dir=${git} diff -R ${commit}`.quiet().cwd(App.info().path.root)
  54. return result.stdout.toString("utf8")
  55. }
  56. function gitdir(sessionID: string) {
  57. const app = App.info()
  58. return path.join(app.path.data, "snapshot", sessionID)
  59. }
  60. }