| 25 | let _id = 1; |
| 26 | |
| 27 | export class ActionList implements Iterable<Action> { |
| 28 | private _actions: Action[] = []; |
| 29 | |
| 30 | protected _action(action: Partial<Action>): void { |
| 31 | this._actions.push({ |
| 32 | ...(action as Action), |
| 33 | id: _id++, |
| 34 | parent: this._actions.at(-1)?.id ?? 0, |
| 35 | }); |
| 36 | } |
| 37 | |
| 38 | create(path: Path, content: Buffer): void { |
| 39 | this._action({ kind: 'c', path, content }); |
| 40 | } |
| 41 | overwrite(path: Path, content: Buffer): void { |
| 42 | this._action({ kind: 'o', path, content }); |
| 43 | } |
| 44 | rename(path: Path, to: Path): void { |
| 45 | this._action({ kind: 'r', path, to }); |
| 46 | } |
| 47 | delete(path: Path): void { |
| 48 | this._action({ kind: 'd', path }); |
| 49 | } |
| 50 | |
| 51 | optimize(): void { |
| 52 | const toCreate = new Map<Path, Buffer>(); |
| 53 | const toRename = new Map<Path, Path>(); |
| 54 | const toOverwrite = new Map<Path, Buffer>(); |
| 55 | const toDelete = new Set<Path>(); |
| 56 | |
| 57 | for (const action of this._actions) { |
| 58 | switch (action.kind) { |
| 59 | case 'c': |
| 60 | toCreate.set(action.path, action.content); |
| 61 | break; |
| 62 | |
| 63 | case 'o': |
| 64 | if (toCreate.has(action.path)) { |
| 65 | toCreate.set(action.path, action.content); |
| 66 | } else { |
| 67 | toOverwrite.set(action.path, action.content); |
| 68 | } |
| 69 | break; |
| 70 | |
| 71 | case 'd': |
| 72 | toDelete.add(action.path); |
| 73 | break; |
| 74 | |
| 75 | case 'r': { |
| 76 | const maybeCreate = toCreate.get(action.path); |
| 77 | const maybeOverwrite = toOverwrite.get(action.path); |
| 78 | if (maybeCreate) { |
| 79 | toCreate.delete(action.path); |
| 80 | toCreate.set(action.to, maybeCreate); |
| 81 | } |
| 82 | if (maybeOverwrite) { |
| 83 | toOverwrite.delete(action.path); |
| 84 | toOverwrite.set(action.to, maybeOverwrite); |
nothing calls this directly
no outgoing calls
no test coverage detected