worktree.ts 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. const normalize = (directory: string) => directory.replace(/[\\/]+$/, "")
  2. type State =
  3. | {
  4. status: "pending"
  5. }
  6. | {
  7. status: "ready"
  8. }
  9. | {
  10. status: "failed"
  11. message: string
  12. }
  13. const state = new Map<string, State>()
  14. const waiters = new Map<string, Array<(state: State) => void>>()
  15. export const Worktree = {
  16. get(directory: string) {
  17. return state.get(normalize(directory))
  18. },
  19. pending(directory: string) {
  20. const key = normalize(directory)
  21. const current = state.get(key)
  22. if (current && current.status !== "pending") return
  23. state.set(key, { status: "pending" })
  24. },
  25. ready(directory: string) {
  26. const key = normalize(directory)
  27. state.set(key, { status: "ready" })
  28. const list = waiters.get(key)
  29. if (!list) return
  30. waiters.delete(key)
  31. for (const fn of list) fn({ status: "ready" })
  32. },
  33. failed(directory: string, message: string) {
  34. const key = normalize(directory)
  35. state.set(key, { status: "failed", message })
  36. const list = waiters.get(key)
  37. if (!list) return
  38. waiters.delete(key)
  39. for (const fn of list) fn({ status: "failed", message })
  40. },
  41. wait(directory: string) {
  42. const key = normalize(directory)
  43. const current = state.get(key)
  44. if (current && current.status !== "pending") return Promise.resolve(current)
  45. return new Promise<State>((resolve) => {
  46. const list = waiters.get(key)
  47. if (!list) {
  48. waiters.set(key, [resolve])
  49. return
  50. }
  51. list.push(resolve)
  52. })
  53. },
  54. }