index.ts 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  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. const files = await Ripgrep.files({
  15. cwd: app.path.cwd,
  16. limit: 1000,
  17. })
  18. log.info("found files", { count: files.length })
  19. if (files.length >= 1000) return
  20. }
  21. const git = gitdir(sessionID)
  22. if (await fs.mkdir(git, { recursive: true })) {
  23. await $`git init`
  24. .env({
  25. ...process.env,
  26. GIT_DIR: git,
  27. GIT_WORK_TREE: app.path.root,
  28. })
  29. .quiet()
  30. .nothrow()
  31. log.info("initialized")
  32. }
  33. await $`git --git-dir ${git} add .`.quiet().cwd(app.path.cwd).nothrow()
  34. log.info("added files")
  35. const result =
  36. await $`git --git-dir ${git} commit -m "snapshot" --no-gpg-sign --author="opencode <[email protected]>"`
  37. .quiet()
  38. .cwd(app.path.cwd)
  39. .nothrow()
  40. const match = result.stdout.toString().match(/\[.+ ([a-f0-9]+)\]/)
  41. if (!match) return
  42. return match![1]
  43. }
  44. export async function restore(sessionID: string, snapshot: string) {
  45. log.info("restore", { commit: snapshot })
  46. const app = App.info()
  47. const git = gitdir(sessionID)
  48. await $`git --git-dir=${git} checkout ${snapshot} --force`.quiet().cwd(app.path.root)
  49. }
  50. export async function diff(sessionID: string, commit: string) {
  51. const git = gitdir(sessionID)
  52. const result = await $`git --git-dir=${git} diff -R ${commit}`.quiet().cwd(App.info().path.root)
  53. return result.stdout.toString("utf8")
  54. }
  55. function gitdir(sessionID: string) {
  56. const app = App.info()
  57. return path.join(app.path.data, "snapshot", sessionID)
  58. }
  59. }