index.ts 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. import { App } from "../app/app"
  2. import {
  3. add,
  4. commit,
  5. init,
  6. checkout,
  7. statusMatrix,
  8. remove,
  9. } from "isomorphic-git"
  10. import path from "path"
  11. import fs from "fs"
  12. import { Ripgrep } from "../file/ripgrep"
  13. import { Log } from "../util/log"
  14. export namespace Snapshot {
  15. const log = Log.create({ service: "snapshot" })
  16. export async function create(sessionID: string) {
  17. const app = App.info()
  18. const git = gitdir(sessionID)
  19. const files = await Ripgrep.files({
  20. cwd: app.path.cwd,
  21. limit: app.git ? undefined : 1000,
  22. })
  23. // not a git repo and too big to snapshot
  24. if (!app.git && files.length === 1000) return
  25. await init({
  26. dir: app.path.cwd,
  27. gitdir: git,
  28. fs,
  29. })
  30. const status = await statusMatrix({
  31. fs,
  32. gitdir: git,
  33. dir: app.path.cwd,
  34. })
  35. await add({
  36. fs,
  37. gitdir: git,
  38. parallel: true,
  39. dir: app.path.cwd,
  40. filepath: files,
  41. })
  42. for (const [file, _head, workdir, stage] of status) {
  43. if (workdir === 0 && stage === 1) {
  44. log.info("remove", { file })
  45. await remove({
  46. fs,
  47. gitdir: git,
  48. dir: app.path.cwd,
  49. filepath: file,
  50. })
  51. }
  52. }
  53. const result = await commit({
  54. fs,
  55. gitdir: git,
  56. dir: app.path.cwd,
  57. message: "snapshot",
  58. author: {
  59. name: "opencode",
  60. email: "[email protected]",
  61. },
  62. })
  63. log.info("commit", { result })
  64. return result
  65. }
  66. export async function restore(sessionID: string, commit: string) {
  67. log.info("restore", { commit })
  68. const app = App.info()
  69. await checkout({
  70. fs,
  71. gitdir: gitdir(sessionID),
  72. dir: app.path.cwd,
  73. ref: commit,
  74. force: true,
  75. })
  76. }
  77. function gitdir(sessionID: string) {
  78. const app = App.info()
  79. return path.join(app.path.data, "snapshot", sessionID)
  80. }
  81. }