sfdx-git-delta 6.42.0 → 6.44.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 (116) hide show
  1. package/README.md +1 -1
  2. package/lib/adapter/GitAdapter.d.ts +50 -2
  3. package/lib/adapter/GitAdapter.js +320 -38
  4. package/lib/adapter/GitAdapter.js.map +1 -1
  5. package/lib/adapter/gitBatchCatFile.d.ts +26 -4
  6. package/lib/adapter/gitBatchCatFile.js +128 -44
  7. package/lib/adapter/gitBatchCatFile.js.map +1 -1
  8. package/lib/adapter/gitBlobReader.d.ts +58 -0
  9. package/lib/adapter/gitBlobReader.js +27 -0
  10. package/lib/adapter/gitBlobReader.js.map +1 -0
  11. package/lib/adapter/ioExecutor.d.ts +18 -6
  12. package/lib/adapter/ioExecutor.js +97 -12
  13. package/lib/adapter/ioExecutor.js.map +1 -1
  14. package/lib/main.js +25 -7
  15. package/lib/main.js.map +1 -1
  16. package/lib/metadata/MetadataRepositoryImpl.d.ts +1 -0
  17. package/lib/metadata/MetadataRepositoryImpl.js +14 -2
  18. package/lib/metadata/MetadataRepositoryImpl.js.map +1 -1
  19. package/lib/post-processor/flowTranslationProcessor.d.ts +30 -14
  20. package/lib/post-processor/flowTranslationProcessor.js +140 -53
  21. package/lib/post-processor/flowTranslationProcessor.js.map +1 -1
  22. package/lib/post-processor/packageGenerator.d.ts +1 -0
  23. package/lib/post-processor/packageGenerator.js +16 -7
  24. package/lib/post-processor/packageGenerator.js.map +1 -1
  25. package/lib/post-processor/postProcessorManager.js +3 -5
  26. package/lib/post-processor/postProcessorManager.js.map +1 -1
  27. package/lib/service/botHandler.d.ts +2 -1
  28. package/lib/service/botHandler.js +3 -3
  29. package/lib/service/botHandler.js.map +1 -1
  30. package/lib/service/containedDecomposedHandler.d.ts +3 -2
  31. package/lib/service/containedDecomposedHandler.js +6 -6
  32. package/lib/service/containedDecomposedHandler.js.map +1 -1
  33. package/lib/service/customFieldHandler.d.ts +2 -1
  34. package/lib/service/customFieldHandler.js +2 -2
  35. package/lib/service/customFieldHandler.js.map +1 -1
  36. package/lib/service/customLabelHandler.d.ts +2 -1
  37. package/lib/service/customLabelHandler.js +3 -3
  38. package/lib/service/customLabelHandler.js.map +1 -1
  39. package/lib/service/customObjectHandler.d.ts +2 -1
  40. package/lib/service/customObjectHandler.js +2 -2
  41. package/lib/service/customObjectHandler.js.map +1 -1
  42. package/lib/service/decomposedHandler.d.ts +2 -1
  43. package/lib/service/decomposedHandler.js +2 -2
  44. package/lib/service/decomposedHandler.js.map +1 -1
  45. package/lib/service/diffLineInterpreter.d.ts +1 -1
  46. package/lib/service/diffLineInterpreter.js +16 -6
  47. package/lib/service/diffLineInterpreter.js.map +1 -1
  48. package/lib/service/flowHandler.d.ts +2 -1
  49. package/lib/service/flowHandler.js +2 -2
  50. package/lib/service/flowHandler.js.map +1 -1
  51. package/lib/service/inFileHandler.d.ts +8 -7
  52. package/lib/service/inFileHandler.js +36 -31
  53. package/lib/service/inFileHandler.js.map +1 -1
  54. package/lib/service/inFolderHandler.d.ts +2 -1
  55. package/lib/service/inFolderHandler.js +2 -2
  56. package/lib/service/inFolderHandler.js.map +1 -1
  57. package/lib/service/inResourceHandler.d.ts +3 -2
  58. package/lib/service/inResourceHandler.js +5 -5
  59. package/lib/service/inResourceHandler.js.map +1 -1
  60. package/lib/service/objectTranslationHandler.d.ts +3 -3
  61. package/lib/service/objectTranslationHandler.js +15 -8
  62. package/lib/service/objectTranslationHandler.js.map +1 -1
  63. package/lib/service/reportingFolderHandler.d.ts +3 -2
  64. package/lib/service/reportingFolderHandler.js +4 -4
  65. package/lib/service/reportingFolderHandler.js.map +1 -1
  66. package/lib/service/sharedFolderHandler.d.ts +3 -2
  67. package/lib/service/sharedFolderHandler.js +4 -4
  68. package/lib/service/sharedFolderHandler.js.map +1 -1
  69. package/lib/service/standardHandler.d.ts +6 -5
  70. package/lib/service/standardHandler.js +26 -24
  71. package/lib/service/standardHandler.js.map +1 -1
  72. package/lib/service/typeHandlerFactory.d.ts +2 -0
  73. package/lib/service/typeHandlerFactory.js +15 -0
  74. package/lib/service/typeHandlerFactory.js.map +1 -1
  75. package/lib/types/handlerResult.d.ts +9 -8
  76. package/lib/types/handlerResult.js +2 -11
  77. package/lib/types/handlerResult.js.map +1 -1
  78. package/lib/utils/LoggingDecorator.js +22 -11
  79. package/lib/utils/LoggingDecorator.js.map +1 -1
  80. package/lib/utils/changeSet.d.ts +5 -0
  81. package/lib/utils/changeSet.js +84 -0
  82. package/lib/utils/changeSet.js.map +1 -1
  83. package/lib/utils/gitLfsHelper.js +9 -1
  84. package/lib/utils/gitLfsHelper.js.map +1 -1
  85. package/lib/utils/metadataDiff/index.d.ts +28 -0
  86. package/lib/utils/metadataDiff/index.js +57 -0
  87. package/lib/utils/metadataDiff/index.js.map +1 -0
  88. package/lib/utils/metadataDiff/streamingDiff.d.ts +68 -0
  89. package/lib/utils/metadataDiff/streamingDiff.js +300 -0
  90. package/lib/utils/metadataDiff/streamingDiff.js.map +1 -0
  91. package/lib/utils/metadataDiff/xmlEventReader.d.ts +28 -0
  92. package/lib/utils/metadataDiff/xmlEventReader.js +221 -0
  93. package/lib/utils/metadataDiff/xmlEventReader.js.map +1 -0
  94. package/lib/utils/metadataDiff/xmlWriter.d.ts +17 -0
  95. package/lib/utils/metadataDiff/xmlWriter.js +213 -0
  96. package/lib/utils/metadataDiff/xmlWriter.js.map +1 -0
  97. package/lib/utils/packageHelper.d.ts +8 -1
  98. package/lib/utils/packageHelper.js +25 -28
  99. package/lib/utils/packageHelper.js.map +1 -1
  100. package/lib/utils/repoGitDiff.d.ts +12 -6
  101. package/lib/utils/repoGitDiff.js +60 -57
  102. package/lib/utils/repoGitDiff.js.map +1 -1
  103. package/lib/utils/treeIndexScope.d.ts +1 -1
  104. package/lib/utils/treeIndexScope.js.map +1 -1
  105. package/lib/utils/txmlAdapter.d.ts +30 -0
  106. package/lib/utils/txmlAdapter.js +121 -0
  107. package/lib/utils/txmlAdapter.js.map +1 -0
  108. package/lib/utils/xmlHelper.d.ts +0 -5
  109. package/lib/utils/xmlHelper.js +0 -57
  110. package/lib/utils/xmlHelper.js.map +1 -1
  111. package/npm-shrinkwrap.json +431 -316
  112. package/oclif.manifest.json +1 -1
  113. package/package.json +50 -18
  114. package/lib/utils/metadataDiff.d.ts +0 -24
  115. package/lib/utils/metadataDiff.js +0 -256
  116. package/lib/utils/metadataDiff.js.map +0 -1
@@ -2,38 +2,53 @@
2
2
  import { spawn } from 'node:child_process';
3
3
  import { getErrorMessage } from '../utils/errorUtils.js';
4
4
  import { Logger, lazy } from '../utils/LoggingService.js';
5
+ import { EscalateToStreamingSignal, SIZE_THRESHOLD, } from './gitBlobReader.js';
5
6
  export class GitBatchCatFile {
7
+ cwd;
6
8
  process;
7
9
  queue = [];
8
10
  chunks = [];
9
11
  totalLength = 0;
10
12
  pendingSize = -1;
11
- constructor(cwd) {
12
- this.process = spawn('git', ['cat-file', '--batch'], {
13
- cwd,
14
- stdio: ['pipe', 'pipe', 'pipe'],
15
- });
16
- this.process.stdout.on('data', (chunk) => this._onData(chunk));
17
- this.process.stderr.on('data', (chunk) => {
18
- Logger.debug(lazy `GitBatchCatFile stderr: ${() => chunk.toString()}`);
19
- });
20
- this.process.on('error', (err) => {
21
- Logger.debug(lazy `GitBatchCatFile process error: ${() => getErrorMessage(err)}`);
22
- });
23
- this.process.on('close', (code) => {
24
- if (code !== 0 && this.queue.length > 0) {
25
- const error = new Error(`git cat-file exited with code ${code}`);
26
- for (const entry of this.queue) {
27
- entry.reject(error);
28
- }
29
- this.queue = [];
30
- }
31
- });
13
+ sizeThreshold;
14
+ spawnFn;
15
+ constructor(cwd, options = {}) {
16
+ this.cwd = cwd;
17
+ this.sizeThreshold = options.sizeThreshold ?? SIZE_THRESHOLD;
18
+ this.spawnFn = options.spawnFn ?? spawn;
19
+ this.process = this._spawnSubprocess();
20
+ }
21
+ async getContent(oid, path) {
22
+ return this._enqueue(oid, path, false);
32
23
  }
33
- async getContent(revision, path) {
24
+ /**
25
+ * Like getContent, but rejects with EscalateToStreamingSignal when the
26
+ * blob size (from the git cat-file header) is at or above SIZE_THRESHOLD.
27
+ * The subprocess is then recycled so queued reads keep flowing.
28
+ */
29
+ async getContentOrEscalate(oid, path) {
30
+ return this._enqueue(oid, path, true);
31
+ }
32
+ close() {
33
+ if (!this.process.killed) {
34
+ this.process.stdin.end();
35
+ this.process.kill();
36
+ }
37
+ for (const entry of this.queue) {
38
+ entry.reject(new Error('GitBatchCatFile closed'));
39
+ }
40
+ this.queue = [];
41
+ }
42
+ _enqueue(oid, path, allowStreamingEscalation) {
34
43
  return new Promise((resolve, reject) => {
35
- this.queue.push({ resolve, reject });
36
- this.process.stdin.write(`${revision}:${path}\n`);
44
+ this.queue.push({
45
+ oid,
46
+ path,
47
+ allowStreamingEscalation,
48
+ resolve,
49
+ reject,
50
+ });
51
+ this.process.stdin.write(`${oid}:${path}\n`);
37
52
  });
38
53
  }
39
54
  _onData(chunk) {
@@ -64,20 +79,11 @@ export class GitBatchCatFile {
64
79
  let buffer = this._materializeBuffer();
65
80
  while (this.queue.length > 0) {
66
81
  if (this.pendingSize === -1) {
67
- const newlineIdx = buffer.indexOf(0x0a);
68
- if (newlineIdx === -1)
82
+ const outcome = this._parseHeader(buffer);
83
+ if (outcome === 'need-more-data')
69
84
  return;
70
- const header = buffer.subarray(0, newlineIdx).toString();
71
- buffer = this._advance(buffer, newlineIdx + 1);
72
- if (header.endsWith('missing')) {
73
- this.queue.shift().reject(new Error(`Object not found: ${header}`));
74
- continue;
75
- }
76
- const parts = header.split(' ');
77
- this.pendingSize = parseInt(parts[2], 10);
78
- if (isNaN(this.pendingSize)) {
79
- this.pendingSize = -1;
80
- this.queue.shift().reject(new Error(`Invalid header: ${header}`));
85
+ buffer = outcome.remaining;
86
+ if (outcome.action === 'reject' || outcome.action === 'escalated') {
81
87
  continue;
82
88
  }
83
89
  }
@@ -89,15 +95,93 @@ export class GitBatchCatFile {
89
95
  this.queue.shift().resolve(content);
90
96
  }
91
97
  }
92
- close() {
93
- if (!this.process.killed) {
94
- this.process.stdin.end();
95
- this.process.kill();
98
+ _parseHeader(buffer) {
99
+ const newlineIdx = buffer.indexOf(0x0a);
100
+ if (newlineIdx === -1)
101
+ return 'need-more-data';
102
+ const header = buffer.subarray(0, newlineIdx).toString();
103
+ const remaining = this._advance(buffer, newlineIdx + 1);
104
+ if (header.endsWith('missing')) {
105
+ this.queue.shift().reject(new Error(`Object not found: ${header}`));
106
+ return { remaining, action: 'reject' };
96
107
  }
97
- for (const entry of this.queue) {
98
- entry.reject(new Error('GitBatchCatFile closed'));
108
+ const parts = header.split(' ');
109
+ const parsedSize = Number.parseInt(parts[2], 10);
110
+ if (Number.isNaN(parsedSize)) {
111
+ this.queue.shift().reject(new Error(`Invalid header: ${header}`));
112
+ return { remaining, action: 'reject' };
99
113
  }
100
- this.queue = [];
114
+ const head = this.queue[0];
115
+ if (head.allowStreamingEscalation && parsedSize >= this.sizeThreshold) {
116
+ this._escalateHead(parsedSize);
117
+ return { remaining: Buffer.alloc(0), action: 'escalated' };
118
+ }
119
+ this.pendingSize = parsedSize;
120
+ return { remaining, action: 'await-body' };
121
+ }
122
+ _escalateHead(size) {
123
+ const escalated = this.queue.shift();
124
+ escalated.reject(new EscalateToStreamingSignal(size, {
125
+ oid: escalated.oid,
126
+ path: escalated.path,
127
+ }));
128
+ const pending = this.queue.splice(0);
129
+ this._recycleSubprocess();
130
+ for (const request of pending) {
131
+ this.queue.push(request);
132
+ this.process.stdin.write(`${request.oid}:${request.path}\n`);
133
+ }
134
+ }
135
+ _recycleSubprocess() {
136
+ const stale = this.process;
137
+ // Detach listeners BEFORE kill: Node may have already queued stdout
138
+ // `data` events for bytes read before the escalation header was
139
+ // parsed. Those events would still fire on `_onData` and corrupt the
140
+ // fresh subprocess's header state via the shared chunks/pendingSize
141
+ // fields.
142
+ stale.stdout.removeAllListeners('data');
143
+ stale.stderr.removeAllListeners('data');
144
+ stale.removeAllListeners('close');
145
+ stale.removeAllListeners('error');
146
+ if (!stale.killed) {
147
+ try {
148
+ stale.stdin.end();
149
+ }
150
+ catch {
151
+ // ignore broken pipe while recycling
152
+ }
153
+ stale.kill();
154
+ }
155
+ this.chunks = [];
156
+ this.totalLength = 0;
157
+ this.pendingSize = -1;
158
+ this.process = this._spawnSubprocess();
159
+ }
160
+ _spawnSubprocess() {
161
+ const child = this.spawnFn('git', ['cat-file', '--batch'], {
162
+ cwd: this.cwd,
163
+ stdio: ['pipe', 'pipe', 'pipe'],
164
+ });
165
+ child.stdout.on('data', (chunk) => this._onData(chunk));
166
+ child.stderr.on('data', (chunk) => {
167
+ Logger.debug(lazy `GitBatchCatFile stderr: ${() => chunk.toString()}`);
168
+ });
169
+ child.on('error', (err) => {
170
+ Logger.debug(lazy `GitBatchCatFile process error: ${() => getErrorMessage(err)}`);
171
+ });
172
+ child.on('close', (code) => {
173
+ /* v8 ignore next -- defensive: the close listener is bound to the active process; only fires for `this.process` in practice */
174
+ if (child !== this.process)
175
+ return;
176
+ if (code !== 0 && this.queue.length > 0) {
177
+ const error = new Error(`git cat-file exited with code ${code}`);
178
+ for (const entry of this.queue) {
179
+ entry.reject(error);
180
+ }
181
+ this.queue = [];
182
+ }
183
+ });
184
+ return child;
101
185
  }
102
186
  }
103
187
  //# sourceMappingURL=gitBatchCatFile.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"gitBatchCatFile.js","sourceRoot":"","sources":["../../src/adapter/gitBatchCatFile.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gitBatchCatFile.js","sourceRoot":"","sources":["../../src/adapter/gitBatchCatFile.ts"],"names":[],"mappings":"AAAA,YAAY,CAAA;AACZ,OAAO,EAAuC,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAE/E,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAA;AACzD,OAAO,EACL,yBAAyB,EACzB,cAAc,GAEf,MAAM,oBAAoB,CAAA;AAe3B,MAAM,OAAO,eAAe;IAUL;IATX,OAAO,CAAgC;IACvC,KAAK,GAAqB,EAAE,CAAA;IAC5B,MAAM,GAAa,EAAE,CAAA;IACrB,WAAW,GAAW,CAAC,CAAA;IACvB,WAAW,GAAW,CAAC,CAAC,CAAA;IACjB,aAAa,CAAQ;IACrB,OAAO,CAAS;IAEjC,YACqB,GAAW,EAC9B,UAAkC,EAAE;QADjB,QAAG,GAAH,GAAG,CAAQ;QAG9B,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,cAAc,CAAA;QAC5D,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAK,KAAiB,CAAA;QACpD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAA;IACxC,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,GAAW,EAAE,IAAY;QACxC,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;IACxC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,oBAAoB,CAAC,GAAW,EAAE,IAAY;QAClD,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,CAAA;IACvC,CAAC;IAED,KAAK;QACH,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YACzB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,CAAA;YACxB,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAA;QACrB,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC/B,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC,CAAA;QACnD,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,EAAE,CAAA;IACjB,CAAC;IAEO,QAAQ,CACd,GAAW,EACX,IAAY,EACZ,wBAAiC;QAEjC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;gBACd,GAAG;gBACH,IAAI;gBACJ,wBAAwB;gBACxB,OAAO;gBACP,MAAM;aACP,CAAC,CAAA;YACF,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,IAAI,IAAI,CAAC,CAAA;QAC9C,CAAC,CAAC,CAAA;IACJ,CAAC;IAES,OAAO,CAAC,KAAa;QAC7B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACvB,IAAI,CAAC,WAAW,IAAI,KAAK,CAAC,MAAM,CAAA;QAChC,IAAI,CAAC,cAAc,EAAE,CAAA;IACvB,CAAC;IAES,kBAAkB;QAC1B,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QACnD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,WAAW,CAAC,CAAA;QAC3D,IAAI,CAAC,MAAM,GAAG,CAAC,MAAM,CAAC,CAAA;QACtB,OAAO,MAAM,CAAA;IACf,CAAC;IAES,QAAQ,CAAC,MAAc,EAAE,QAAgB;QACjD,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;QACtC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,IAAI,CAAC,MAAM,GAAG,EAAE,CAAA;YAChB,IAAI,CAAC,WAAW,GAAG,CAAC,CAAA;QACtB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAA;YACpB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,MAAM,CAAA;QAChC,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAES,cAAc;QACtB,IAAI,MAAM,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAA;QACtC,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,IAAI,IAAI,CAAC,WAAW,KAAK,CAAC,CAAC,EAAE,CAAC;gBAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAA;gBACzC,IAAI,OAAO,KAAK,gBAAgB;oBAAE,OAAM;gBACxC,MAAM,GAAG,OAAO,CAAC,SAAS,CAAA;gBAC1B,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;oBAClE,SAAQ;gBACV,CAAC;YACH,CAAC;YACD,IAAI,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,WAAW,GAAG,CAAC;gBAAE,OAAM;YAChD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAA;YACjE,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,CAAA;YACpD,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,CAAA;YACrB,IAAI,CAAC,KAAK,CAAC,KAAK,EAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;QACtC,CAAC;IACH,CAAC;IAEO,YAAY,CAClB,MAAc;QAId,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QACvC,IAAI,UAAU,KAAK,CAAC,CAAC;YAAE,OAAO,gBAAgB,CAAA;QAC9C,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,QAAQ,EAAE,CAAA;QACxD,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,CAAC,CAAC,CAAA;QACvD,IAAI,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YAC/B,IAAI,CAAC,KAAK,CAAC,KAAK,EAAG,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,qBAAqB,MAAM,EAAE,CAAC,CAAC,CAAA;YACpE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAA;QACxC,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAC/B,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;QAChD,IAAI,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC,KAAK,CAAC,KAAK,EAAG,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,mBAAmB,MAAM,EAAE,CAAC,CAAC,CAAA;YAClE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAA;QACxC,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QAC1B,IAAI,IAAI,CAAC,wBAAwB,IAAI,UAAU,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACtE,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,CAAA;YAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAA;QAC5D,CAAC;QACD,IAAI,CAAC,WAAW,GAAG,UAAU,CAAA;QAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,CAAA;IAC5C,CAAC;IAEO,aAAa,CAAC,IAAY;QAChC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAG,CAAA;QACrC,SAAS,CAAC,MAAM,CACd,IAAI,yBAAyB,CAAC,IAAI,EAAE;YAClC,GAAG,EAAE,SAAS,CAAC,GAAG;YAClB,IAAI,EAAE,SAAS,CAAC,IAAI;SACrB,CAAC,CACH,CAAA;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QACpC,IAAI,CAAC,kBAAkB,EAAE,CAAA;QACzB,KAAK,MAAM,OAAO,IAAI,OAAO,EAAE,CAAC;YAC9B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YACxB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,IAAI,IAAI,CAAC,CAAA;QAC9D,CAAC;IACH,CAAC;IAEO,kBAAkB;QACxB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAA;QAC1B,oEAAoE;QACpE,gEAAgE;QAChE,qEAAqE;QACrE,oEAAoE;QACpE,UAAU;QACV,KAAK,CAAC,MAAM,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAA;QACvC,KAAK,CAAC,MAAM,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAA;QACvC,KAAK,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAA;QACjC,KAAK,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAA;QACjC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAClB,IAAI,CAAC;gBACH,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,CAAA;YACnB,CAAC;YAAC,MAAM,CAAC;gBACP,qCAAqC;YACvC,CAAC;YACD,KAAK,CAAC,IAAI,EAAE,CAAA;QACd,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,EAAE,CAAA;QAChB,IAAI,CAAC,WAAW,GAAG,CAAC,CAAA;QACpB,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,CAAA;QACrB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAA;IACxC,CAAC;IAEO,gBAAgB;QACtB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,EAAE;YACzD,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAA;QACF,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA;QAC/D,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YACxC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAA,2BAA2B,GAAG,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAA;QACvE,CAAC,CAAC,CAAA;QACF,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAU,EAAE,EAAE;YAC/B,MAAM,CAAC,KAAK,CACV,IAAI,CAAA,kCAAkC,GAAG,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,CACnE,CAAA;QACH,CAAC,CAAC,CAAA;QACF,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAmB,EAAE,EAAE;YACxC,+HAA+H;YAC/H,IAAI,KAAK,KAAK,IAAI,CAAC,OAAO;gBAAE,OAAM;YAClC,IAAI,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACxC,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,iCAAiC,IAAI,EAAE,CAAC,CAAA;gBAChE,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;oBAC/B,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;gBACrB,CAAC;gBACD,IAAI,CAAC,KAAK,GAAG,EAAE,CAAA;YACjB,CAAC;QACH,CAAC,CAAC,CAAA;QACF,OAAO,KAAK,CAAA;IACd,CAAC;CACF"}
@@ -0,0 +1,58 @@
1
+ import type { ChildProcessWithoutNullStreams, SpawnOptions } from 'node:child_process';
2
+ import type { Readable } from 'node:stream';
3
+ import type { FileGitRef } from '../types/git.js';
4
+ export type SpawnFn = (cmd: string, args: string[], opts: SpawnOptions) => ChildProcessWithoutNullStreams;
5
+ /**
6
+ * Signal (not Error) used to redirect _executeGitFileCopy from the buffered
7
+ * batch-cat-file path to the dedicated streaming path. Carries the offending
8
+ * blob's size for size-tiered dispatch telemetry.
9
+ *
10
+ * Deliberately not an Error subclass: zero stack trace allocation, clear
11
+ * flow-control-not-exception semantics at call sites that catch it.
12
+ */
13
+ export declare class EscalateToStreamingSignal {
14
+ readonly size: number;
15
+ readonly ref: FileGitRef;
16
+ readonly name = "EscalateToStreamingSignal";
17
+ constructor(size: number, ref: FileGitRef);
18
+ }
19
+ /**
20
+ * Narrow adapter-boundary port consumed by IOExecutor. GitAdapter implements
21
+ * it. The port lets unit tests swap in a fake blob reader without spawning
22
+ * real `git cat-file` subprocesses, while integration tests exercise the
23
+ * real GitAdapter end-to-end.
24
+ */
25
+ export interface GitBlobReader {
26
+ getBufferContent(ref: FileGitRef): Promise<Buffer>;
27
+ /**
28
+ * Reads ref's blob via the batched cat-file subprocess. Rejects with
29
+ * `EscalateToStreamingSignal` when the blob exceeds `SIZE_THRESHOLD` — the
30
+ * caller is expected to catch that signal and route the copy through
31
+ * `streamContent` instead.
32
+ */
33
+ getBufferContentOrEscalate(ref: FileGitRef): Promise<Buffer>;
34
+ /**
35
+ * Spawns a dedicated `git cat-file blob <oid>` subprocess, peeks the LFS
36
+ * pointer magic, and returns a Readable that either forwards the blob
37
+ * stream or (on LFS match) opens the underlying LFS object file.
38
+ */
39
+ streamContent(ref: FileGitRef): Readable;
40
+ /**
41
+ * Streams `git archive --format=tar <revision> -- <path>` and yields one
42
+ * `{ path, stream }` per file entry. Directories are filtered out.
43
+ * Callers must consume every yielded stream (or call stream.resume() to
44
+ * drain-and-discard) otherwise tar-stream back-pressures.
45
+ */
46
+ streamArchive(path: string, revision: string): AsyncIterable<{
47
+ path: string;
48
+ stream: Readable;
49
+ }>;
50
+ }
51
+ /**
52
+ * Directory size above which `_executeGitDirCopy` switches to the
53
+ * git-archive streaming path. Small directories keep the existing
54
+ * batch-cat-file loop (fork+exec cost of git archive isn't worth
55
+ * paying for a handful of files).
56
+ */
57
+ export declare const GIT_ARCHIVE_DIR_THRESHOLD = 25;
58
+ export declare const SIZE_THRESHOLD: number;
@@ -0,0 +1,27 @@
1
+ 'use strict';
2
+ /**
3
+ * Signal (not Error) used to redirect _executeGitFileCopy from the buffered
4
+ * batch-cat-file path to the dedicated streaming path. Carries the offending
5
+ * blob's size for size-tiered dispatch telemetry.
6
+ *
7
+ * Deliberately not an Error subclass: zero stack trace allocation, clear
8
+ * flow-control-not-exception semantics at call sites that catch it.
9
+ */
10
+ export class EscalateToStreamingSignal {
11
+ size;
12
+ ref;
13
+ name = 'EscalateToStreamingSignal';
14
+ constructor(size, ref) {
15
+ this.size = size;
16
+ this.ref = ref;
17
+ }
18
+ }
19
+ /**
20
+ * Directory size above which `_executeGitDirCopy` switches to the
21
+ * git-archive streaming path. Small directories keep the existing
22
+ * batch-cat-file loop (fork+exec cost of git archive isn't worth
23
+ * paying for a handful of files).
24
+ */
25
+ export const GIT_ARCHIVE_DIR_THRESHOLD = 25;
26
+ export const SIZE_THRESHOLD = 1 * 1024 * 1024;
27
+ //# sourceMappingURL=gitBlobReader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitBlobReader.js","sourceRoot":"","sources":["../../src/adapter/gitBlobReader.ts"],"names":[],"mappings":"AAAA,YAAY,CAAA;AAeZ;;;;;;;GAOG;AACH,MAAM,OAAO,yBAAyB;IAGlB;IACA;IAHF,IAAI,GAAG,2BAA2B,CAAA;IAClD,YACkB,IAAY,EACZ,GAAe;QADf,SAAI,GAAJ,IAAI,CAAQ;QACZ,QAAG,GAAH,GAAG,CAAY;IAC9B,CAAC;CACL;AAmCD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,CAAA;AAE3C,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAA"}
@@ -1,12 +1,17 @@
1
+ import type { Writable } from 'node:stream';
1
2
  import type { Config } from '../types/config.js';
2
- import type { CopyOperation } from '../types/handlerResult.js';
3
+ import type { FileGitRef } from '../types/git.js';
4
+ import type { CopyOperation, StreamedContentOperation } from '../types/handlerResult.js';
3
5
  import { type IgnoreHelper } from '../utils/ignoreHelper.js';
4
6
  import GitAdapter from './GitAdapter.js';
7
+ import { type GitBlobReader } from './gitBlobReader.js';
5
8
  export default class IOExecutor {
6
9
  protected readonly config: Config;
10
+ protected readonly blobReaderForRevision: (revision: string) => GitBlobReader;
7
11
  protected readonly processedPaths: Set<string>;
8
12
  protected ignoreHelper: IgnoreHelper;
9
- constructor(config: Config);
13
+ constructor(config: Config, blobReaderForRevision?: (revision: string) => GitBlobReader);
14
+ private static _defaultBlobReaderForRevision;
10
15
  execute(copies: CopyOperation[]): Promise<void>;
11
16
  protected _executeOperation(op: CopyOperation): Promise<void>;
12
17
  protected _getGitAdapter(revision: string): GitAdapter;
@@ -14,12 +19,19 @@ export default class IOExecutor {
14
19
  path: string;
15
20
  revision: string;
16
21
  }): Promise<void>;
22
+ protected _streamCopyWithAtomicRename(reader: GitBlobReader, ref: FileGitRef, dst: string): Promise<void>;
17
23
  protected _executeGitDirCopy(op: {
18
24
  path: string;
19
25
  revision: string;
20
26
  }): Promise<void>;
21
- protected _executeComputedContent(op: {
22
- path: string;
23
- content: string;
24
- }): Promise<void>;
27
+ /**
28
+ * Streams a directory via `git archive --format=tar` + tar-stream. One
29
+ * subprocess replaces N batch-cat-file round trips for large dirs
30
+ * (ExperienceBundle, static resource folders). Each entry pipes
31
+ * directly into a sibling .tmp + rename; a per-entry
32
+ * processedPaths.has check matches today's dedup contract.
33
+ */
34
+ private _executeGitDirCopyViaArchive;
35
+ protected _executeStreamedContent(op: StreamedContentOperation): Promise<void>;
36
+ protected _writeAtomicallyViaTmp(dst: string, producer: (ws: Writable) => Promise<void>): Promise<void>;
25
37
  }
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
- import { join } from 'node:path/posix';
2
+ import { createWriteStream, promises as fsPromises } from 'node:fs';
3
+ import { dirname, join } from 'node:path/posix';
4
+ import { pipeline } from 'node:stream/promises';
3
5
  import { eachLimit } from 'async';
4
6
  import { outputFile } from 'fs-extra';
5
7
  import { CopyOperationKind } from '../types/handlerResult.js';
@@ -8,12 +10,20 @@ import { getErrorMessage } from '../utils/errorUtils.js';
8
10
  import { buildIgnoreHelper } from '../utils/ignoreHelper.js';
9
11
  import { Logger, lazy } from '../utils/LoggingService.js';
10
12
  import GitAdapter from './GitAdapter.js';
13
+ import { EscalateToStreamingSignal, GIT_ARCHIVE_DIR_THRESHOLD, } from './gitBlobReader.js';
14
+ const TMP_SUFFIX = '.tmp';
11
15
  export default class IOExecutor {
12
16
  config;
17
+ blobReaderForRevision;
13
18
  processedPaths = new Set();
14
19
  ignoreHelper;
15
- constructor(config) {
20
+ constructor(config, blobReaderForRevision = revision => IOExecutor._defaultBlobReaderForRevision(config, revision)) {
16
21
  this.config = config;
22
+ this.blobReaderForRevision = blobReaderForRevision;
23
+ }
24
+ static _defaultBlobReaderForRevision(config, revision) {
25
+ const adapterConfig = revision !== config.to ? { ...config, to: revision } : config;
26
+ return GitAdapter.getInstance(adapterConfig);
17
27
  }
18
28
  async execute(copies) {
19
29
  this.ignoreHelper = await buildIgnoreHelper(this.config);
@@ -36,8 +46,8 @@ export default class IOExecutor {
36
46
  case CopyOperationKind.GitDirCopy:
37
47
  await this._executeGitDirCopy(op);
38
48
  break;
39
- case CopyOperationKind.ComputedContent:
40
- await this._executeComputedContent(op);
49
+ case CopyOperationKind.StreamedContent:
50
+ await this._executeStreamedContent(op);
41
51
  break;
42
52
  }
43
53
  }
@@ -48,23 +58,34 @@ export default class IOExecutor {
48
58
  return GitAdapter.getInstance(config);
49
59
  }
50
60
  async _executeGitFileCopy(op) {
61
+ const ref = { path: op.path, oid: op.revision };
62
+ const dst = join(this.config.output, op.path);
63
+ const reader = this.blobReaderForRevision(op.revision);
51
64
  try {
52
- const gitAdapter = this._getGitAdapter(op.revision);
53
- const content = await gitAdapter.getBufferContent({
54
- path: op.path,
55
- oid: op.revision,
56
- });
57
- const dst = join(this.config.output, op.path);
65
+ const content = await reader.getBufferContentOrEscalate(ref);
58
66
  await outputFile(dst, content);
59
67
  }
60
68
  catch (error) {
69
+ if (error instanceof EscalateToStreamingSignal) {
70
+ await this._streamCopyWithAtomicRename(reader, ref, dst);
71
+ return;
72
+ }
61
73
  Logger.debug(lazy `IOExecutor gitFileCopy failed for ${op.path}: ${() => getErrorMessage(error)}`);
62
74
  }
63
75
  }
76
+ async _streamCopyWithAtomicRename(reader, ref, dst) {
77
+ await this._writeAtomicallyViaTmp(dst, async (ws) => {
78
+ await pipeline(reader.streamContent(ref), ws, { end: false });
79
+ });
80
+ }
64
81
  async _executeGitDirCopy(op) {
65
82
  try {
66
83
  const gitAdapter = this._getGitAdapter(op.revision);
67
84
  const filePaths = await gitAdapter.getFilesPath(op.path);
85
+ if (filePaths.length > GIT_ARCHIVE_DIR_THRESHOLD) {
86
+ await this._executeGitDirCopyViaArchive(gitAdapter, op, filePaths);
87
+ return;
88
+ }
68
89
  for (const filePath of filePaths) {
69
90
  if (this.ignoreHelper.globalIgnore.ignores(filePath)) {
70
91
  continue;
@@ -82,8 +103,72 @@ export default class IOExecutor {
82
103
  Logger.debug(lazy `IOExecutor gitDirCopy failed for ${op.path}: ${() => getErrorMessage(error)}`);
83
104
  }
84
105
  }
85
- async _executeComputedContent(op) {
86
- await outputFile(join(this.config.output, op.path), op.content);
106
+ /**
107
+ * Streams a directory via `git archive --format=tar` + tar-stream. One
108
+ * subprocess replaces N batch-cat-file round trips for large dirs
109
+ * (ExperienceBundle, static resource folders). Each entry pipes
110
+ * directly into a sibling .tmp + rename; a per-entry
111
+ * processedPaths.has check matches today's dedup contract.
112
+ */
113
+ async _executeGitDirCopyViaArchive(gitAdapter, op, filePaths) {
114
+ const wanted = new Set(filePaths);
115
+ const outputPrefix = this.config.output.endsWith('/')
116
+ ? this.config.output
117
+ : `${this.config.output}/`;
118
+ for await (const entry of gitAdapter.streamArchive(op.path, op.revision)) {
119
+ if (!wanted.has(entry.path)) {
120
+ entry.stream.resume();
121
+ continue;
122
+ }
123
+ if (this.processedPaths.has(entry.path)) {
124
+ entry.stream.resume();
125
+ continue;
126
+ }
127
+ if (this.ignoreHelper.globalIgnore.ignores(entry.path)) {
128
+ entry.stream.resume();
129
+ continue;
130
+ }
131
+ const dst = join(this.config.output, entry.path);
132
+ // Defense-in-depth: reject any tar entry whose resolved destination
133
+ // escapes `config.output` (zip-slip). git-archive itself does not
134
+ // produce such entries, but a future streamArchive caller or a
135
+ // mutated registry could; failing here keeps the invariant local.
136
+ if (!dst.startsWith(outputPrefix)) {
137
+ entry.stream.resume();
138
+ continue;
139
+ }
140
+ this.processedPaths.add(entry.path);
141
+ await this._writeAtomicallyViaTmp(dst, async (ws) => {
142
+ await pipeline(entry.stream, ws, { end: false });
143
+ });
144
+ }
145
+ }
146
+ async _executeStreamedContent(op) {
147
+ const dst = join(this.config.output, op.path);
148
+ await this._writeAtomicallyViaTmp(dst, op.writer);
149
+ }
150
+ // Writes `producer` output to a sibling `.tmp` file, then atomically renames
151
+ // on success. Same-directory tmp avoids EXDEV on cross-filesystem moves
152
+ // (Docker-on-CI overlayfs + tmpfs /tmp scenario). Errors destroy the stream,
153
+ // unlink the tmp, and log at debug — matching _executeGitFileCopy precedent.
154
+ async _writeAtomicallyViaTmp(dst, producer) {
155
+ const tmp = `${dst}${TMP_SUFFIX}`;
156
+ await fsPromises.mkdir(dirname(dst), { recursive: true });
157
+ const ws = createWriteStream(tmp);
158
+ try {
159
+ await producer(ws);
160
+ await new Promise((resolve, reject) => {
161
+ /* v8 ignore next -- defensive: createWriteStream's end-callback fires with err only on synchronous fd write failure */
162
+ ws.end((err) => (err ? reject(err) : resolve()));
163
+ });
164
+ await fsPromises.rename(tmp, dst);
165
+ }
166
+ catch (error) {
167
+ ws.destroy();
168
+ /* v8 ignore next -- defensive cleanup: best-effort tmp removal swallows ENOENT and permission errors */
169
+ await fsPromises.unlink(tmp).catch(() => undefined);
170
+ Logger.debug(lazy `IOExecutor atomicWrite failed for ${dst}: ${() => getErrorMessage(error)}`);
171
+ }
87
172
  }
88
173
  }
89
174
  //# sourceMappingURL=ioExecutor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ioExecutor.js","sourceRoot":"","sources":["../../src/adapter/ioExecutor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ioExecutor.js","sourceRoot":"","sources":["../../src/adapter/ioExecutor.ts"],"names":[],"mappings":"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"}
package/lib/main.js CHANGED
@@ -25,12 +25,30 @@ export default async (config) => {
25
25
  await configValidator.validateConfig();
26
26
  const metadata = await getDefinition(config);
27
27
  const repoGitDiffHelper = new RepoGitDiff(config, metadata);
28
- const lines = await repoGitDiffHelper.getLines();
28
+ // The treeIndex scope read needs the full path set up front, so when
29
+ // generateDelta is on without an include override we materialize the
30
+ // streamed diff once. Otherwise we feed the async iterable straight
31
+ // into DiffLineInterpreter so handlers start firing while git is
32
+ // still emitting lines.
33
+ const needsScopeFromDiff = config.generateDelta && !config.include && !config.includeDestructive;
34
+ let lines;
35
+ if (needsScopeFromDiff) {
36
+ const materialized = [];
37
+ for await (const line of repoGitDiffHelper.getLines()) {
38
+ materialized.push(line);
39
+ }
40
+ lines = materialized;
41
+ }
42
+ else {
43
+ lines = repoGitDiffHelper.getLines();
44
+ }
29
45
  if (config.generateDelta) {
30
46
  const gitAdapter = GitAdapter.getInstance(config);
31
47
  let scopePaths = config.source;
32
- if (!config.include && !config.includeDestructive) {
33
- scopePaths = [...computeTreeIndexScope(lines, metadata)];
48
+ if (needsScopeFromDiff) {
49
+ scopePaths = [
50
+ ...computeTreeIndexScope(lines, metadata),
51
+ ];
34
52
  }
35
53
  if (scopePaths.length > 0) {
36
54
  await Promise.all([
@@ -43,13 +61,13 @@ export default async (config) => {
43
61
  const postProcessors = getPostProcessors(work, metadata);
44
62
  // First pass: build the ChangeSet from handler output so collectors
45
63
  // (e.g. FlowTranslationProcessor) can introspect the package view via
46
- // work.changes.forPackageManifest() before emitting their own manifests.
64
+ // work.changes.forPackageManifest() before emitting their own changes.
47
65
  const handlerResult = await lineProcessor.process(lines);
48
- work.changes = ChangeSet.from(handlerResult.manifests);
49
- // Second pass: rebuild once collector output is merged in.
66
+ work.changes = handlerResult.changes;
67
+ // Second pass: fold collector output into the same ChangeSet.
50
68
  const postResult = await postProcessors.collectAll();
51
69
  const combinedResult = mergeResults(handlerResult, postResult);
52
- work.changes = ChangeSet.from(combinedResult.manifests);
70
+ work.changes = combinedResult.changes;
53
71
  // Apply git-detected renames: resolve the `{fromPath, toPath}` pairs that
54
72
  // RepoGitDiff captured from `-M` output into (type, from, to) triples and
55
73
  // re-group them into the ChangeSet's rename bucket. Pairs for ignored
package/lib/main.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,7 @@ export declare class MetadataRepositoryImpl implements MetadataRepository {
5
5
  protected readonly metadataPerExt: Map<string, Metadata>;
6
6
  protected readonly metadataPerDir: Map<string, Metadata>;
7
7
  protected readonly metadataPerXmlName: Map<string, Metadata>;
8
+ private readonly pathCache;
8
9
  constructor(metadatas: Metadata[]);
9
10
  protected addSuffix(metadata: Metadata): void;
10
11
  protected addSharedFolderSuffix(metadata: Metadata): void;