@osdlc/repo-cleaner 0.17.2 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +691 -305
  3. package/dist/branches.d.ts +37 -36
  4. package/dist/branches.js +199 -196
  5. package/dist/clean.d.ts +179 -0
  6. package/dist/clean.js +824 -0
  7. package/dist/cli.d.ts +12 -16
  8. package/dist/cli.js +367 -478
  9. package/dist/hooks.d.ts +8 -12
  10. package/dist/hooks.js +2 -2
  11. package/dist/index.d.ts +18 -25
  12. package/dist/index.js +16 -23
  13. package/dist/landing.d.ts +3 -3
  14. package/dist/landing.js +7 -7
  15. package/dist/plan.d.ts +76 -70
  16. package/dist/plan.js +82 -77
  17. package/dist/providers/github.d.ts +2 -1
  18. package/dist/providers/github.js +2 -1
  19. package/dist/providers/gitlab.d.ts +3 -2
  20. package/dist/providers/gitlab.js +14 -8
  21. package/dist/providers/index.d.ts +5 -4
  22. package/dist/providers/index.js +8 -5
  23. package/dist/providers/types.d.ts +8 -2
  24. package/dist/prs.d.ts +35 -7
  25. package/dist/prs.js +45 -12
  26. package/dist/receipt.d.ts +46 -57
  27. package/dist/receipt.js +52 -28
  28. package/dist/reference.d.ts +12 -0
  29. package/dist/reference.js +152 -0
  30. package/dist/remote-mirror.d.ts +9 -1
  31. package/dist/remote-mirror.js +19 -1
  32. package/dist/render.d.ts +66 -61
  33. package/dist/render.js +206 -255
  34. package/dist/resolve.d.ts +3 -3
  35. package/dist/resolve.js +4 -12
  36. package/dist/status-line.d.ts +1 -1
  37. package/dist/status-line.js +5 -5
  38. package/dist/step-board.d.ts +1 -1
  39. package/dist/step-board.js +2 -5
  40. package/dist/submodules.d.ts +120 -0
  41. package/dist/submodules.js +292 -0
  42. package/dist/sweep.d.ts +107 -64
  43. package/dist/sweep.js +333 -119
  44. package/dist/types.d.ts +294 -105
  45. package/dist/types.js +106 -54
  46. package/dist/util.d.ts +13 -0
  47. package/dist/util.js +36 -0
  48. package/dist/version.generated.d.ts +1 -1
  49. package/dist/version.generated.js +1 -1
  50. package/dist/worktrees.d.ts +21 -37
  51. package/dist/worktrees.js +198 -165
  52. package/package.json +5 -5
  53. package/dist/apply.d.ts +0 -131
  54. package/dist/apply.js +0 -541
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Cleaning up: `check` a plan against an approval, then `run` what it shows.
3
+ *
4
+ * `check` resolves the approval (the rows picked, the rows spared, the risks
5
+ * allowed), refuses one that contradicts itself, sweeps every plan repository
6
+ * again and drops each selected row that is gone, cannot be deleted, moved
7
+ * since the plan, or carries a risk not allowed. It returns the steps a run
8
+ * would take. `run` sweeps once more and takes those steps in a fixed order,
9
+ * stopping at the first failure:
10
+ *
11
+ * 1. spared remote branches, each tip checked with `ls-remote`;
12
+ * 2. worktrees, each unlocked first when its lock's owner is dead, and each
13
+ * checked again for live processes just before it is unlocked or removed;
14
+ * one with submodules is removed with `--force` after its files and every
15
+ * submodule are checked again;
16
+ * 3. local branches;
17
+ * 4. remote branches.
18
+ *
19
+ * A worktree whose directory is gone goes by its own record. One left without
20
+ * its `.git` takes the repository-wide prune, last, and only while that prune
21
+ * would drop nothing the run does not select.
22
+ *
23
+ * Branch deletes are compare-and-swap on the planned sha. Every step is
24
+ * verified, and the receipt is rewritten after each.
25
+ */
26
+ import type { Annotate } from './hooks.ts';
27
+ import { type Plan } from './plan.ts';
28
+ import { type Dropped, type Receipt, type Step } from './receipt.ts';
29
+ import { type Runners } from './sweep.ts';
30
+ import { type Kind, type Risk, type RowId, type Sweep, type SweepProgress, type SweptWith, type RepoNote } from './types.ts';
31
+ /** A risk allowed for every row (`row` absent), or for one row. */
32
+ export interface Allow {
33
+ risk: Risk;
34
+ /** A row id or bare name, resolved as a pick is. */
35
+ row?: string | undefined;
36
+ }
37
+ /**
38
+ * What a person approved. Rows are named by id (`branch:feat/x`), or by a
39
+ * bare name or path when only one plan row has it.
40
+ *
41
+ * `pick` work on exactly these rows; a `review` row, or a `keep` row with
42
+ * an action, runs only when picked. Default: every `delete` row.
43
+ * `spare` leave these rows alone; a spared remote branch is still checked,
44
+ * and the run stops if it moved or is gone since the plan.
45
+ * `allow` the risks a row's action may carry.
46
+ */
47
+ export interface Approval {
48
+ pick?: readonly string[] | undefined;
49
+ spare?: readonly string[] | undefined;
50
+ allow?: readonly (Risk | Allow)[] | undefined;
51
+ }
52
+ /** A row reference resolved to one plan row. */
53
+ export interface Resolved {
54
+ repo: string;
55
+ id: RowId;
56
+ }
57
+ /** An approval with every row resolved to its plan row. */
58
+ export interface ResolvedApproval {
59
+ pick: Resolved[];
60
+ spare: Resolved[];
61
+ allow: {
62
+ risk: Risk;
63
+ row: Resolved | null;
64
+ }[];
65
+ }
66
+ interface Shared extends Runners {
67
+ /** Where the caller stands: the base for relative worktree paths, and a worktree never removed. Defaults to the process's cwd. */
68
+ cwd?: string | undefined;
69
+ /** A host's re-ranking, applied to every re-sweep as the sweep applied it. */
70
+ annotate?: Annotate | undefined;
71
+ /** Told what the re-sweep is doing, for a status line. */
72
+ onProgress?: ((progress: SweepProgress) => void) | undefined;
73
+ }
74
+ export interface CheckOptions extends Shared {
75
+ /**
76
+ * A sweep made just now, used as the re-check instead of sweeping again: for
77
+ * a preview straight after a sweep. A repository whose remote rows it read
78
+ * from disk (offline) is swept again, asking the remote. `run` always sweeps
79
+ * again.
80
+ */
81
+ sweep?: Sweep | undefined;
82
+ /** Where remote URL clones are kept; a plan repository there must still push only where it fetches from. */
83
+ cacheDir?: string | undefined;
84
+ }
85
+ export interface RunOptions extends Shared {
86
+ /** Where the receipt is rewritten after each step; none when absent. */
87
+ receiptPath?: string | undefined;
88
+ /** Where the plan came from, recorded in the receipt. Default `(memory)`. */
89
+ source?: string | undefined;
90
+ now?: (() => Date) | undefined;
91
+ /** Told once the steps are known, before the first runs; each step's `result` is updated in place. */
92
+ onStart?: ((steps: readonly Step[]) => void) | undefined;
93
+ /** Told before each step: its index, the step count and the step. */
94
+ onStep?: ((index: number, total: number, step: Step) => void) | undefined;
95
+ /** Told after each step, with its `result` set, before the receipt is saved. */
96
+ onStepDone?: ((index: number, total: number, step: Step) => void) | undefined;
97
+ /**
98
+ * Told the run's own re-check's notes, before the first step: what it judged
99
+ * without. The re-check may differ from the preview's, for example when a
100
+ * listing fails only at the run.
101
+ */
102
+ onNotes?: ((notes: RepoNote[]) => void) | undefined;
103
+ }
104
+ /** What a run would do, for a person to approve: the steps, and the rows dropped and why. */
105
+ export interface Preview {
106
+ plan: Plan;
107
+ approval: ResolvedApproval;
108
+ /** Each with `result: 'would-run'`. */
109
+ steps: Step[];
110
+ dropped: Dropped[];
111
+ /** Allowed risks no row that runs carries. Not an error: what a row carries can change between runs. */
112
+ unusedAllows: {
113
+ risk: Risk;
114
+ row: RowId | null;
115
+ }[];
116
+ /**
117
+ * `RepoSweep.notes`, with each repository's root: what the re-check judged
118
+ * without. With a sweep passed in (`CheckOptions.sweep`), every repository
119
+ * of that sweep; otherwise each plan repository the re-check swept again.
120
+ */
121
+ notes: RepoNote[];
122
+ }
123
+ /** A row reference as typed: a kind and a name, or a bare name (`kind: null`). */
124
+ export interface RowRef {
125
+ kind: Kind | null;
126
+ name: string;
127
+ }
128
+ /**
129
+ * `kind:name`, or a bare name. A word before a colon that is not a kind is an
130
+ * error (a typo such as `wt:x`), but a path is a bare name whatever colons it
131
+ * holds: a prefix with a path separator in it is never a kind.
132
+ */
133
+ export declare function parseRowRef(text: string): RowRef;
134
+ /** `<risk>` for every row, or `<risk>=<row>` for one. */
135
+ export declare function parseAllow(text: string): Allow;
136
+ /**
137
+ * What can be refused of `approval` before anything is swept: a malformed
138
+ * row or risk, a row a sweep with `options` could never hold, and a row
139
+ * picked and spared as written. A row named two ways, and an `allow` for a
140
+ * spared or unpicked row, are found when the approval is resolved against
141
+ * the plan.
142
+ */
143
+ export declare function checkApproval(options: Pick<SweptWith, 'only' | 'branch'>, approval: Approval): void;
144
+ /**
145
+ * `approval` resolved against `plan`, or a {@link RepoCleanerError} for one
146
+ * that contradicts itself or names rows the plan does not have.
147
+ */
148
+ export declare function resolveApproval(plan: Plan, approval: Approval, cwd: string): ResolvedApproval;
149
+ /**
150
+ * A network URL as `host[:port]/path`, the same for `git@host:o/r.git`,
151
+ * `ssh://git@host/o/r` and `https://host/o/r/`; the whole path is kept, so
152
+ * nested groups stay apart. Null for a path on this machine, including
153
+ * `file://` and a Windows drive path.
154
+ */
155
+ export declare function networkRemoteKey(url: string): string | null;
156
+ /**
157
+ * What running `plan` under `approval` would do now: sweeps every repository
158
+ * the selection is in again (or reads `opts.sweep`), and returns the steps
159
+ * and the rows dropped, with why. Deletes nothing.
160
+ *
161
+ * @throws RepoCleanerError for an approval that contradicts itself, names a
162
+ * row the plan does not have or names one ambiguously, or spares a remote
163
+ * branch that moved. A plain `Error`, naming the repository, when the
164
+ * re-check cannot read one: a failed fetch, or a remote `ls-remote` cannot
165
+ * reach. Nothing has been touched.
166
+ */
167
+ export declare function check(plan: Plan, approval: Approval, opts?: CheckOptions): Preview;
168
+ /**
169
+ * Take the steps `preview` showed: sweeps again, drops a row that moved since
170
+ * the preview, and runs the rest in order, compare-and-swap, verifying each
171
+ * step and stopping at the first failure. Only what the preview showed runs; a
172
+ * row it dropped stays dropped.
173
+ *
174
+ * @throws RepoCleanerError (`spared-changed`) when a spared remote branch moved
175
+ * since the preview, and a plain `Error` when the re-check cannot read a
176
+ * repository, as {@link check} does. Nothing has been touched.
177
+ */
178
+ export declare function run(preview: Preview, opts?: RunOptions): Receipt;
179
+ export {};