ts-repo-utils 7.8.1 → 7.9.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.
- package/README.md +10 -0
- package/dist/cmd/assert-repo-is-clean.mjs +2 -1
- package/dist/cmd/assert-repo-is-clean.mjs.map +1 -1
- package/dist/cmd/check-should-run-type-checks.mjs +2 -1
- package/dist/cmd/check-should-run-type-checks.mjs.map +1 -1
- package/dist/cmd/format-diff-from.mjs +2 -1
- package/dist/cmd/format-diff-from.mjs.map +1 -1
- package/dist/cmd/format-uncommitted.mjs +2 -1
- package/dist/cmd/format-uncommitted.mjs.map +1 -1
- package/dist/cmd/gen-index-ts.mjs +2 -1
- package/dist/cmd/gen-index-ts.mjs.map +1 -1
- package/dist/entry-point.d.mts.map +1 -1
- package/dist/functions/assert-ext.d.mts +0 -1
- package/dist/functions/assert-ext.d.mts.map +1 -1
- package/dist/functions/assert-ext.mjs.map +1 -1
- package/dist/functions/assert-path-exists.d.mts.map +1 -1
- package/dist/functions/assert-path-exists.mjs.map +1 -1
- package/dist/functions/assert-repo-is-clean.d.mts.map +1 -1
- package/dist/functions/assert-repo-is-clean.mjs.map +1 -1
- package/dist/functions/create-result-assert.d.mts +0 -1
- package/dist/functions/create-result-assert.d.mts.map +1 -1
- package/dist/functions/create-result-assert.mjs.map +1 -1
- package/dist/functions/diff.d.mts +0 -1
- package/dist/functions/diff.d.mts.map +1 -1
- package/dist/functions/exec-async.d.mts +0 -1
- package/dist/functions/exec-async.d.mts.map +1 -1
- package/dist/functions/exec-async.mjs.map +1 -1
- package/dist/functions/format.d.mts +4 -5
- package/dist/functions/format.d.mts.map +1 -1
- package/dist/functions/format.mjs +3 -3
- package/dist/functions/format.mjs.map +1 -1
- package/dist/functions/gen-index.d.mts +0 -1
- package/dist/functions/gen-index.d.mts.map +1 -1
- package/dist/functions/gen-index.mjs.map +1 -1
- package/dist/functions/should-run.d.mts.map +1 -1
- package/dist/functions/should-run.mjs.map +1 -1
- package/dist/functions/workspace-utils/execute-parallel.d.mts.map +1 -1
- package/dist/functions/workspace-utils/execute-parallel.mjs +4 -5
- package/dist/functions/workspace-utils/execute-parallel.mjs.map +1 -1
- package/dist/functions/workspace-utils/get-workspace-packages.d.mts.map +1 -1
- package/dist/functions/workspace-utils/get-workspace-packages.mjs.map +1 -1
- package/dist/functions/workspace-utils/run-cmd-in-parallel.d.mts.map +1 -1
- package/dist/functions/workspace-utils/run-cmd-in-parallel.mjs +2 -1
- package/dist/functions/workspace-utils/run-cmd-in-parallel.mjs.map +1 -1
- package/dist/functions/workspace-utils/run-cmd-in-stages.d.mts.map +1 -1
- package/dist/functions/workspace-utils/run-cmd-in-stages.mjs +2 -1
- package/dist/functions/workspace-utils/run-cmd-in-stages.mjs.map +1 -1
- package/dist/node-global.d.mts +0 -1
- package/dist/node-global.d.mts.map +1 -1
- package/package.json +25 -26
- package/src/cmd/assert-repo-is-clean.mts +2 -1
- package/src/cmd/check-should-run-type-checks.mts +2 -1
- package/src/cmd/format-diff-from.mts +2 -1
- package/src/cmd/format-uncommitted.mts +3 -1
- package/src/cmd/gen-index-ts.mts +8 -2
- package/src/entry-point.mts +1 -0
- package/src/functions/assert-ext.mts +4 -0
- package/src/functions/assert-path-exists.mts +2 -0
- package/src/functions/assert-repo-is-clean.mts +9 -0
- package/src/functions/create-result-assert.mts +1 -0
- package/src/functions/diff.test.mts +136 -8
- package/src/functions/exec-async.mts +4 -0
- package/src/functions/exec-async.test.mts +59 -2
- package/src/functions/format.mts +26 -7
- package/src/functions/format.test.mts +166 -9
- package/src/functions/gen-index.mts +16 -0
- package/src/functions/should-run.mts +2 -0
- package/src/functions/workspace-utils/execute-parallel.mts +27 -5
- package/src/functions/workspace-utils/get-workspace-packages.mts +5 -0
- package/src/functions/workspace-utils/run-cmd-in-parallel.mts +7 -1
- package/src/functions/workspace-utils/run-cmd-in-stages.mts +7 -1
- package/src/functions/workspace-utils/run-cmd-in-stages.test.mts +17 -3
- package/src/node-global.mts +7 -1
|
@@ -21,6 +21,7 @@ describe('diff', () => {
|
|
|
21
21
|
) => Promise<Result<{ stdout: string; stderr: string }, unknown>>;
|
|
22
22
|
}> => {
|
|
23
23
|
const tempDir = await fs.mkdtemp(path.join(tmpdir(), 'temp-repo-'));
|
|
24
|
+
|
|
24
25
|
const repoPath = tempDir;
|
|
25
26
|
|
|
26
27
|
// Initialize git repository
|
|
@@ -29,9 +30,12 @@ describe('diff', () => {
|
|
|
29
30
|
options?: Readonly<{ silent?: boolean }>,
|
|
30
31
|
): Promise<ExecResult<string>> => {
|
|
31
32
|
const originalCwd = process.cwd();
|
|
33
|
+
|
|
32
34
|
process.chdir(repoPath);
|
|
35
|
+
|
|
33
36
|
try {
|
|
34
37
|
const result = await $(cmd, { silent: options?.silent ?? false });
|
|
38
|
+
|
|
35
39
|
return result;
|
|
36
40
|
} finally {
|
|
37
41
|
process.chdir(originalCwd);
|
|
@@ -39,7 +43,9 @@ describe('diff', () => {
|
|
|
39
43
|
};
|
|
40
44
|
|
|
41
45
|
await execInRepo('git init', { silent: true });
|
|
46
|
+
|
|
42
47
|
await execInRepo('git config user.name "Test User"', { silent: true });
|
|
48
|
+
|
|
43
49
|
await execInRepo('git config user.email "test@example.com"', {
|
|
44
50
|
silent: true,
|
|
45
51
|
});
|
|
@@ -60,7 +66,9 @@ describe('diff', () => {
|
|
|
60
66
|
const createRepoFunctions = (repoPath: string) => {
|
|
61
67
|
const executeInRepo = async <T,>(fn: () => Promise<T>): Promise<T> => {
|
|
62
68
|
const originalCwd = process.cwd();
|
|
69
|
+
|
|
63
70
|
process.chdir(repoPath);
|
|
71
|
+
|
|
64
72
|
try {
|
|
65
73
|
return await fn();
|
|
66
74
|
} finally {
|
|
@@ -82,15 +90,17 @@ describe('diff', () => {
|
|
|
82
90
|
};
|
|
83
91
|
};
|
|
84
92
|
|
|
85
|
-
describe(
|
|
93
|
+
describe(getUntrackedFiles, () => {
|
|
86
94
|
test('should return empty array when no files are changed', async () => {
|
|
87
95
|
const { repoPath, cleanup } = await createTempRepo();
|
|
96
|
+
|
|
88
97
|
const repoFunctions = createRepoFunctions(repoPath);
|
|
89
98
|
|
|
90
99
|
try {
|
|
91
100
|
const result = await repoFunctions.getUntrackedFiles({ silent: true });
|
|
92
101
|
|
|
93
102
|
expect(Result.isOk(result)).toBe(true);
|
|
103
|
+
|
|
94
104
|
if (Result.isOk(result)) {
|
|
95
105
|
expect(Array.isArray(result.value)).toBe(true);
|
|
96
106
|
}
|
|
@@ -101,11 +111,13 @@ describe('diff', () => {
|
|
|
101
111
|
|
|
102
112
|
test('should detect newly created files', async () => {
|
|
103
113
|
const { repoPath, cleanup } = await createTempRepo();
|
|
114
|
+
|
|
104
115
|
const repoFunctions = createRepoFunctions(repoPath);
|
|
105
116
|
|
|
106
117
|
try {
|
|
107
118
|
// Create a new file in the temp repository
|
|
108
119
|
const testFileName = `test-new-file-${crypto.randomUUID()}.tmp`;
|
|
120
|
+
|
|
109
121
|
const testFilePath = path.join(repoPath, testFileName);
|
|
110
122
|
|
|
111
123
|
await fs.writeFile(testFilePath, 'test content');
|
|
@@ -113,8 +125,10 @@ describe('diff', () => {
|
|
|
113
125
|
const result = await repoFunctions.getUntrackedFiles({ silent: true });
|
|
114
126
|
|
|
115
127
|
expect(Result.isOk(result)).toBe(true);
|
|
128
|
+
|
|
116
129
|
if (Result.isOk(result)) {
|
|
117
130
|
const files = result.value;
|
|
131
|
+
|
|
118
132
|
expect(files).toContain(testFileName);
|
|
119
133
|
}
|
|
120
134
|
} finally {
|
|
@@ -124,11 +138,13 @@ describe('diff', () => {
|
|
|
124
138
|
|
|
125
139
|
test('should detect modified existing files', async () => {
|
|
126
140
|
const { repoPath, cleanup, execInRepo } = await createTempRepo();
|
|
141
|
+
|
|
127
142
|
const repoFunctions = createRepoFunctions(repoPath);
|
|
128
143
|
|
|
129
144
|
try {
|
|
130
145
|
// Create and track a file first
|
|
131
146
|
const testFileName = `test-modify-file-${crypto.randomUUID()}.tmp`;
|
|
147
|
+
|
|
132
148
|
const testFilePath = path.join(repoPath, testFileName);
|
|
133
149
|
|
|
134
150
|
await fs.writeFile(testFilePath, 'initial content');
|
|
@@ -142,8 +158,10 @@ describe('diff', () => {
|
|
|
142
158
|
const result = await repoFunctions.getUntrackedFiles({ silent: true });
|
|
143
159
|
|
|
144
160
|
expect(Result.isOk(result)).toBe(true);
|
|
161
|
+
|
|
145
162
|
if (Result.isOk(result)) {
|
|
146
163
|
const files = result.value;
|
|
164
|
+
|
|
147
165
|
expect(files).not.toContain(testFileName);
|
|
148
166
|
}
|
|
149
167
|
} finally {
|
|
@@ -153,14 +171,19 @@ describe('diff', () => {
|
|
|
153
171
|
|
|
154
172
|
test('should detect multiple types of changes', async () => {
|
|
155
173
|
const { repoPath, cleanup, execInRepo } = await createTempRepo();
|
|
174
|
+
|
|
156
175
|
const repoFunctions = createRepoFunctions(repoPath);
|
|
157
176
|
|
|
158
177
|
try {
|
|
159
178
|
// Create multiple test files
|
|
160
179
|
const uuid = crypto.randomUUID();
|
|
180
|
+
|
|
161
181
|
const newFile = `test-new-file-${uuid}.tmp`;
|
|
182
|
+
|
|
162
183
|
const modifyFile = `test-modify-file-${uuid}.tmp`;
|
|
184
|
+
|
|
163
185
|
const newFilePath = path.join(repoPath, newFile);
|
|
186
|
+
|
|
164
187
|
const modifyFilePath = path.join(repoPath, modifyFile);
|
|
165
188
|
|
|
166
189
|
// Create new file
|
|
@@ -168,6 +191,7 @@ describe('diff', () => {
|
|
|
168
191
|
|
|
169
192
|
// Create and track another file
|
|
170
193
|
await fs.writeFile(modifyFilePath, 'initial content');
|
|
194
|
+
|
|
171
195
|
await execInRepo(`git add ${modifyFile}`, { silent: true });
|
|
172
196
|
|
|
173
197
|
// Modify the tracked file
|
|
@@ -176,9 +200,12 @@ describe('diff', () => {
|
|
|
176
200
|
const result = await repoFunctions.getUntrackedFiles({ silent: true });
|
|
177
201
|
|
|
178
202
|
expect(Result.isOk(result)).toBe(true);
|
|
203
|
+
|
|
179
204
|
if (Result.isOk(result)) {
|
|
180
205
|
const files = result.value;
|
|
206
|
+
|
|
181
207
|
expect(files).toContain(newFile);
|
|
208
|
+
|
|
182
209
|
expect(files).not.toContain(modifyFile);
|
|
183
210
|
}
|
|
184
211
|
} finally {
|
|
@@ -188,17 +215,21 @@ describe('diff', () => {
|
|
|
188
215
|
|
|
189
216
|
test('should exclude deleted files from results', async () => {
|
|
190
217
|
const { repoPath, cleanup } = await createTempRepo();
|
|
218
|
+
|
|
191
219
|
const repoFunctions = createRepoFunctions(repoPath);
|
|
192
220
|
|
|
193
221
|
try {
|
|
194
222
|
const result = await repoFunctions.getUntrackedFiles({ silent: true });
|
|
195
223
|
|
|
196
224
|
expect(Result.isOk(result)).toBe(true);
|
|
225
|
+
|
|
197
226
|
if (Result.isOk(result)) {
|
|
198
227
|
const files = result.value;
|
|
228
|
+
|
|
199
229
|
// Verify no deleted files are included (status 'D')
|
|
200
230
|
for (const file of files) {
|
|
201
|
-
|
|
231
|
+
expectTypeOf(file).toBeString();
|
|
232
|
+
|
|
202
233
|
expect(file.length).toBeGreaterThan(0);
|
|
203
234
|
}
|
|
204
235
|
}
|
|
@@ -209,6 +240,7 @@ describe('diff', () => {
|
|
|
209
240
|
|
|
210
241
|
test('should handle git command errors gracefully', async () => {
|
|
211
242
|
const { repoPath, cleanup } = await createTempRepo();
|
|
243
|
+
|
|
212
244
|
const repoFunctions = createRepoFunctions(repoPath);
|
|
213
245
|
|
|
214
246
|
try {
|
|
@@ -223,19 +255,23 @@ describe('diff', () => {
|
|
|
223
255
|
|
|
224
256
|
test('should parse git status output correctly', async () => {
|
|
225
257
|
const { repoPath, cleanup } = await createTempRepo();
|
|
258
|
+
|
|
226
259
|
const repoFunctions = createRepoFunctions(repoPath);
|
|
227
260
|
|
|
228
261
|
try {
|
|
229
262
|
const result = await repoFunctions.getUntrackedFiles({ silent: true });
|
|
230
263
|
|
|
231
264
|
expect(Result.isOk(result)).toBe(true);
|
|
265
|
+
|
|
232
266
|
if (Result.isOk(result)) {
|
|
233
267
|
const files = result.value;
|
|
234
268
|
|
|
235
269
|
// Each file should be a non-empty string
|
|
236
270
|
for (const file of files) {
|
|
237
|
-
|
|
271
|
+
expectTypeOf(file).toBeString();
|
|
272
|
+
|
|
238
273
|
expect(file.trim()).toBe(file); // No leading/trailing whitespace
|
|
274
|
+
|
|
239
275
|
expect(file.length).toBeGreaterThan(0);
|
|
240
276
|
}
|
|
241
277
|
}
|
|
@@ -246,12 +282,14 @@ describe('diff', () => {
|
|
|
246
282
|
|
|
247
283
|
test('should work with silent option', async () => {
|
|
248
284
|
const { repoPath, cleanup } = await createTempRepo();
|
|
285
|
+
|
|
249
286
|
const repoFunctions = createRepoFunctions(repoPath);
|
|
250
287
|
|
|
251
288
|
try {
|
|
252
289
|
const result = await repoFunctions.getUntrackedFiles({ silent: true });
|
|
253
290
|
|
|
254
291
|
expect(Result.isOk(result)).toBe(true);
|
|
292
|
+
|
|
255
293
|
if (Result.isOk(result)) {
|
|
256
294
|
expect(Array.isArray(result.value)).toBe(true);
|
|
257
295
|
}
|
|
@@ -261,14 +299,17 @@ describe('diff', () => {
|
|
|
261
299
|
});
|
|
262
300
|
});
|
|
263
301
|
|
|
264
|
-
describe(
|
|
302
|
+
describe(getStagedFiles, () => {
|
|
265
303
|
test('should return empty array when no files are staged', async () => {
|
|
266
304
|
const { repoPath, cleanup } = await createTempRepo();
|
|
305
|
+
|
|
267
306
|
const repoFunctions = createRepoFunctions(repoPath);
|
|
268
307
|
|
|
269
308
|
try {
|
|
270
309
|
const result = await repoFunctions.getStagedFiles({ silent: true });
|
|
310
|
+
|
|
271
311
|
expect(Result.isOk(result)).toBe(true);
|
|
312
|
+
|
|
272
313
|
if (Result.isOk(result)) {
|
|
273
314
|
expect(Array.isArray(result.value)).toBe(true);
|
|
274
315
|
}
|
|
@@ -279,20 +320,27 @@ describe('diff', () => {
|
|
|
279
320
|
|
|
280
321
|
test('should detect staged files', async () => {
|
|
281
322
|
const { repoPath, cleanup, execInRepo } = await createTempRepo();
|
|
323
|
+
|
|
282
324
|
const repoFunctions = createRepoFunctions(repoPath);
|
|
283
325
|
|
|
284
326
|
try {
|
|
285
327
|
// Create a new file
|
|
286
328
|
const testFileName = `test-staged-file-${crypto.randomUUID()}.tmp`;
|
|
329
|
+
|
|
287
330
|
const testFilePath = path.join(repoPath, testFileName);
|
|
331
|
+
|
|
288
332
|
await fs.writeFile(testFilePath, 'staged file content');
|
|
333
|
+
|
|
289
334
|
// Stage the file
|
|
290
335
|
await execInRepo(`git add ${testFileName}`, { silent: true });
|
|
291
336
|
|
|
292
337
|
const result = await repoFunctions.getStagedFiles({ silent: true });
|
|
338
|
+
|
|
293
339
|
expect(Result.isOk(result)).toBe(true);
|
|
340
|
+
|
|
294
341
|
if (Result.isOk(result)) {
|
|
295
342
|
const files = result.value;
|
|
343
|
+
|
|
296
344
|
expect(files).toContain(testFileName);
|
|
297
345
|
}
|
|
298
346
|
} finally {
|
|
@@ -302,26 +350,37 @@ describe('diff', () => {
|
|
|
302
350
|
|
|
303
351
|
test('should detect multiple staged files', async () => {
|
|
304
352
|
const { repoPath, cleanup, execInRepo } = await createTempRepo();
|
|
353
|
+
|
|
305
354
|
const repoFunctions = createRepoFunctions(repoPath);
|
|
306
355
|
|
|
307
356
|
try {
|
|
308
357
|
// Create multiple test files
|
|
309
358
|
const uuid = crypto.randomUUID();
|
|
359
|
+
|
|
310
360
|
const file1 = `test-staged-file1-${uuid}.tmp`;
|
|
361
|
+
|
|
311
362
|
const file2 = `test-staged-file2-${uuid}.tmp`;
|
|
363
|
+
|
|
312
364
|
const filePath1 = path.join(repoPath, file1);
|
|
365
|
+
|
|
313
366
|
const filePath2 = path.join(repoPath, file2);
|
|
314
367
|
|
|
315
368
|
await fs.writeFile(filePath1, 'staged file 1 content');
|
|
369
|
+
|
|
316
370
|
await fs.writeFile(filePath2, 'staged file 2 content');
|
|
371
|
+
|
|
317
372
|
// Stage both files
|
|
318
373
|
await execInRepo(`git add ${file1} ${file2}`, { silent: true });
|
|
319
374
|
|
|
320
375
|
const result = await repoFunctions.getStagedFiles({ silent: true });
|
|
376
|
+
|
|
321
377
|
expect(Result.isOk(result)).toBe(true);
|
|
378
|
+
|
|
322
379
|
if (Result.isOk(result)) {
|
|
323
380
|
const files = result.value;
|
|
381
|
+
|
|
324
382
|
expect(files).toContain(file1);
|
|
383
|
+
|
|
325
384
|
expect(files).toContain(file2);
|
|
326
385
|
}
|
|
327
386
|
} finally {
|
|
@@ -331,15 +390,19 @@ describe('diff', () => {
|
|
|
331
390
|
|
|
332
391
|
test('should exclude deleted files by default', async () => {
|
|
333
392
|
const { repoPath, cleanup, execInRepo } = await createTempRepo();
|
|
393
|
+
|
|
334
394
|
const repoFunctions = createRepoFunctions(repoPath);
|
|
335
395
|
|
|
336
396
|
try {
|
|
337
397
|
const testFileName = `test-deleted-file-${crypto.randomUUID()}.tmp`;
|
|
398
|
+
|
|
338
399
|
const testFilePath = path.join(repoPath, testFileName);
|
|
339
400
|
|
|
340
401
|
// Create a file and commit it
|
|
341
402
|
await fs.writeFile(testFilePath, 'file to be deleted');
|
|
403
|
+
|
|
342
404
|
await execInRepo(`git add ${testFileName}`, { silent: true });
|
|
405
|
+
|
|
343
406
|
await execInRepo(
|
|
344
407
|
`git commit -m "Add test file for deletion" --no-verify`,
|
|
345
408
|
{
|
|
@@ -349,15 +412,19 @@ describe('diff', () => {
|
|
|
349
412
|
|
|
350
413
|
// Delete the file and stage the deletion
|
|
351
414
|
await fs.rm(testFilePath, { force: true });
|
|
415
|
+
|
|
352
416
|
await execInRepo(`git add ${testFileName}`, { silent: true });
|
|
353
417
|
|
|
354
418
|
// Test with excludeDeleted = true (default)
|
|
355
419
|
const resultExclude = await repoFunctions.getStagedFiles({
|
|
356
420
|
silent: true,
|
|
357
421
|
});
|
|
422
|
+
|
|
358
423
|
expect(Result.isOk(resultExclude)).toBe(true);
|
|
424
|
+
|
|
359
425
|
if (Result.isOk(resultExclude)) {
|
|
360
426
|
const files = resultExclude.value;
|
|
427
|
+
|
|
361
428
|
expect(files).not.toContain(testFileName);
|
|
362
429
|
}
|
|
363
430
|
|
|
@@ -366,6 +433,7 @@ describe('diff', () => {
|
|
|
366
433
|
const gitStatusResult = await execInRepo(`git status --porcelain`, {
|
|
367
434
|
silent: true,
|
|
368
435
|
});
|
|
436
|
+
|
|
369
437
|
const hasDeletion =
|
|
370
438
|
Result.isOk(gitStatusResult) &&
|
|
371
439
|
gitStatusResult.value.stdout.includes(`D ${testFileName}`);
|
|
@@ -375,9 +443,12 @@ describe('diff', () => {
|
|
|
375
443
|
excludeDeleted: false,
|
|
376
444
|
silent: true,
|
|
377
445
|
});
|
|
446
|
+
|
|
378
447
|
expect(Result.isOk(resultInclude)).toBe(true);
|
|
448
|
+
|
|
379
449
|
if (Result.isOk(resultInclude)) {
|
|
380
450
|
const files = resultInclude.value;
|
|
451
|
+
|
|
381
452
|
expect(files).toContain(testFileName);
|
|
382
453
|
}
|
|
383
454
|
} else {
|
|
@@ -393,16 +464,21 @@ describe('diff', () => {
|
|
|
393
464
|
|
|
394
465
|
test('should parse staged files output correctly', async () => {
|
|
395
466
|
const { repoPath, cleanup } = await createTempRepo();
|
|
467
|
+
|
|
396
468
|
const repoFunctions = createRepoFunctions(repoPath);
|
|
397
469
|
|
|
398
470
|
try {
|
|
399
471
|
const result = await repoFunctions.getStagedFiles({ silent: true });
|
|
472
|
+
|
|
400
473
|
expect(Result.isOk(result)).toBe(true);
|
|
474
|
+
|
|
401
475
|
if (Result.isOk(result)) {
|
|
402
476
|
const files = result.value;
|
|
477
|
+
|
|
403
478
|
// Each file should be a non-empty string
|
|
404
479
|
for (const file of files) {
|
|
405
|
-
|
|
480
|
+
expectTypeOf(file).toBeString();
|
|
481
|
+
|
|
406
482
|
expect(file.trim()).toBe(file); // No leading/trailing whitespace
|
|
407
483
|
}
|
|
408
484
|
}
|
|
@@ -413,11 +489,14 @@ describe('diff', () => {
|
|
|
413
489
|
|
|
414
490
|
test('should work with silent option', async () => {
|
|
415
491
|
const { repoPath, cleanup } = await createTempRepo();
|
|
492
|
+
|
|
416
493
|
const repoFunctions = createRepoFunctions(repoPath);
|
|
417
494
|
|
|
418
495
|
try {
|
|
419
496
|
const result = await repoFunctions.getStagedFiles({ silent: true });
|
|
497
|
+
|
|
420
498
|
expect(Result.isOk(result)).toBe(true);
|
|
499
|
+
|
|
421
500
|
if (Result.isOk(result)) {
|
|
422
501
|
expect(Array.isArray(result.value)).toBe(true);
|
|
423
502
|
}
|
|
@@ -428,10 +507,12 @@ describe('diff', () => {
|
|
|
428
507
|
|
|
429
508
|
test('should handle git command errors gracefully', async () => {
|
|
430
509
|
const { repoPath, cleanup } = await createTempRepo();
|
|
510
|
+
|
|
431
511
|
const repoFunctions = createRepoFunctions(repoPath);
|
|
432
512
|
|
|
433
513
|
try {
|
|
434
514
|
const result = await repoFunctions.getStagedFiles({ silent: true });
|
|
515
|
+
|
|
435
516
|
// Should always return a Result, either Ok or Err
|
|
436
517
|
expect(Result.isOk(result) || Result.isErr(result)).toBe(true);
|
|
437
518
|
} finally {
|
|
@@ -440,14 +521,17 @@ describe('diff', () => {
|
|
|
440
521
|
});
|
|
441
522
|
});
|
|
442
523
|
|
|
443
|
-
describe(
|
|
524
|
+
describe(getModifiedFiles, () => {
|
|
444
525
|
test('should return empty array when no files are modified', async () => {
|
|
445
526
|
const { repoPath, cleanup } = await createTempRepo();
|
|
527
|
+
|
|
446
528
|
const repoFunctions = createRepoFunctions(repoPath);
|
|
447
529
|
|
|
448
530
|
try {
|
|
449
531
|
const result = await repoFunctions.getModifiedFiles({ silent: true });
|
|
532
|
+
|
|
450
533
|
expect(Result.isOk(result)).toBe(true);
|
|
534
|
+
|
|
451
535
|
if (Result.isOk(result)) {
|
|
452
536
|
expect(Array.isArray(result.value)).toBe(true);
|
|
453
537
|
}
|
|
@@ -458,15 +542,19 @@ describe('diff', () => {
|
|
|
458
542
|
|
|
459
543
|
test('should detect modified files', async () => {
|
|
460
544
|
const { repoPath, cleanup, execInRepo } = await createTempRepo();
|
|
545
|
+
|
|
461
546
|
const repoFunctions = createRepoFunctions(repoPath);
|
|
462
547
|
|
|
463
548
|
try {
|
|
464
549
|
// Create a new file and commit it first
|
|
465
550
|
const testFileName = `test-modified-file-${crypto.randomUUID()}.tmp`;
|
|
551
|
+
|
|
466
552
|
const testFilePath = path.join(repoPath, testFileName);
|
|
467
553
|
|
|
468
554
|
await fs.writeFile(testFilePath, 'initial content');
|
|
555
|
+
|
|
469
556
|
await execInRepo(`git add ${testFileName}`, { silent: true });
|
|
557
|
+
|
|
470
558
|
await execInRepo(
|
|
471
559
|
`git commit -m "Add file for modification test" --no-verify`,
|
|
472
560
|
{ silent: true },
|
|
@@ -476,9 +564,12 @@ describe('diff', () => {
|
|
|
476
564
|
await fs.writeFile(testFilePath, 'modified content');
|
|
477
565
|
|
|
478
566
|
const result = await repoFunctions.getModifiedFiles({ silent: true });
|
|
567
|
+
|
|
479
568
|
expect(Result.isOk(result)).toBe(true);
|
|
569
|
+
|
|
480
570
|
if (Result.isOk(result)) {
|
|
481
571
|
const files = result.value;
|
|
572
|
+
|
|
482
573
|
expect(files).toContain(testFileName);
|
|
483
574
|
}
|
|
484
575
|
} finally {
|
|
@@ -488,19 +579,27 @@ describe('diff', () => {
|
|
|
488
579
|
|
|
489
580
|
test('should detect multiple modified files', async () => {
|
|
490
581
|
const { repoPath, cleanup, execInRepo } = await createTempRepo();
|
|
582
|
+
|
|
491
583
|
const repoFunctions = createRepoFunctions(repoPath);
|
|
492
584
|
|
|
493
585
|
try {
|
|
494
586
|
const uuid = crypto.randomUUID();
|
|
587
|
+
|
|
495
588
|
const file1 = `test-modified-file1-${uuid}.tmp`;
|
|
589
|
+
|
|
496
590
|
const file2 = `test-modified-file2-${uuid}.tmp`;
|
|
591
|
+
|
|
497
592
|
const filePath1 = path.join(repoPath, file1);
|
|
593
|
+
|
|
498
594
|
const filePath2 = path.join(repoPath, file2);
|
|
499
595
|
|
|
500
596
|
// Create and commit both files
|
|
501
597
|
await fs.writeFile(filePath1, 'initial content 1');
|
|
598
|
+
|
|
502
599
|
await fs.writeFile(filePath2, 'initial content 2');
|
|
600
|
+
|
|
503
601
|
await execInRepo(`git add ${file1} ${file2}`, { silent: true });
|
|
602
|
+
|
|
504
603
|
await execInRepo(
|
|
505
604
|
`git commit -m "Add files for modification test" --no-verify`,
|
|
506
605
|
{ silent: true },
|
|
@@ -508,13 +607,18 @@ describe('diff', () => {
|
|
|
508
607
|
|
|
509
608
|
// Modify both files
|
|
510
609
|
await fs.writeFile(filePath1, 'modified content 1');
|
|
610
|
+
|
|
511
611
|
await fs.writeFile(filePath2, 'modified content 2');
|
|
512
612
|
|
|
513
613
|
const result = await repoFunctions.getModifiedFiles({ silent: true });
|
|
614
|
+
|
|
514
615
|
expect(Result.isOk(result)).toBe(true);
|
|
616
|
+
|
|
515
617
|
if (Result.isOk(result)) {
|
|
516
618
|
const files = result.value;
|
|
619
|
+
|
|
517
620
|
expect(files).toContain(file1);
|
|
621
|
+
|
|
518
622
|
expect(files).toContain(file2);
|
|
519
623
|
}
|
|
520
624
|
} finally {
|
|
@@ -524,15 +628,19 @@ describe('diff', () => {
|
|
|
524
628
|
|
|
525
629
|
test('should exclude deleted files by default', async () => {
|
|
526
630
|
const { repoPath, cleanup, execInRepo } = await createTempRepo();
|
|
631
|
+
|
|
527
632
|
const repoFunctions = createRepoFunctions(repoPath);
|
|
528
633
|
|
|
529
634
|
try {
|
|
530
635
|
const testFileName = `test-deleted-modified-file-${crypto.randomUUID()}.tmp`;
|
|
636
|
+
|
|
531
637
|
const testFilePath = path.join(repoPath, testFileName);
|
|
532
638
|
|
|
533
639
|
// Create a file and commit it
|
|
534
640
|
await fs.writeFile(testFilePath, 'file to be deleted');
|
|
641
|
+
|
|
535
642
|
await execInRepo(`git add ${testFileName}`, { silent: true });
|
|
643
|
+
|
|
536
644
|
await execInRepo(
|
|
537
645
|
`git commit -m "Add test file for deletion" --no-verify`,
|
|
538
646
|
{ silent: true },
|
|
@@ -545,9 +653,12 @@ describe('diff', () => {
|
|
|
545
653
|
const resultExclude = await repoFunctions.getModifiedFiles({
|
|
546
654
|
silent: true,
|
|
547
655
|
});
|
|
656
|
+
|
|
548
657
|
expect(Result.isOk(resultExclude)).toBe(true);
|
|
658
|
+
|
|
549
659
|
if (Result.isOk(resultExclude)) {
|
|
550
660
|
const files = resultExclude.value;
|
|
661
|
+
|
|
551
662
|
expect(files).not.toContain(testFileName);
|
|
552
663
|
}
|
|
553
664
|
|
|
@@ -556,9 +667,12 @@ describe('diff', () => {
|
|
|
556
667
|
excludeDeleted: false,
|
|
557
668
|
silent: true,
|
|
558
669
|
});
|
|
670
|
+
|
|
559
671
|
expect(Result.isOk(resultInclude)).toBe(true);
|
|
672
|
+
|
|
560
673
|
if (Result.isOk(resultInclude)) {
|
|
561
674
|
const files = resultInclude.value;
|
|
675
|
+
|
|
562
676
|
expect(files).toContain(testFileName);
|
|
563
677
|
}
|
|
564
678
|
} finally {
|
|
@@ -568,16 +682,21 @@ describe('diff', () => {
|
|
|
568
682
|
|
|
569
683
|
test('should parse modified files output correctly', async () => {
|
|
570
684
|
const { repoPath, cleanup } = await createTempRepo();
|
|
685
|
+
|
|
571
686
|
const repoFunctions = createRepoFunctions(repoPath);
|
|
572
687
|
|
|
573
688
|
try {
|
|
574
689
|
const result = await repoFunctions.getModifiedFiles({ silent: true });
|
|
690
|
+
|
|
575
691
|
expect(Result.isOk(result)).toBe(true);
|
|
692
|
+
|
|
576
693
|
if (Result.isOk(result)) {
|
|
577
694
|
const files = result.value;
|
|
695
|
+
|
|
578
696
|
// Each file should be a non-empty string
|
|
579
697
|
for (const file of files) {
|
|
580
|
-
|
|
698
|
+
expectTypeOf(file).toBeString();
|
|
699
|
+
|
|
581
700
|
expect(file.trim()).toBe(file); // No leading/trailing whitespace
|
|
582
701
|
}
|
|
583
702
|
}
|
|
@@ -588,11 +707,14 @@ describe('diff', () => {
|
|
|
588
707
|
|
|
589
708
|
test('should work with silent option', async () => {
|
|
590
709
|
const { repoPath, cleanup } = await createTempRepo();
|
|
710
|
+
|
|
591
711
|
const repoFunctions = createRepoFunctions(repoPath);
|
|
592
712
|
|
|
593
713
|
try {
|
|
594
714
|
const result = await repoFunctions.getModifiedFiles({ silent: true });
|
|
715
|
+
|
|
595
716
|
expect(Result.isOk(result)).toBe(true);
|
|
717
|
+
|
|
596
718
|
if (Result.isOk(result)) {
|
|
597
719
|
expect(Array.isArray(result.value)).toBe(true);
|
|
598
720
|
}
|
|
@@ -603,10 +725,12 @@ describe('diff', () => {
|
|
|
603
725
|
|
|
604
726
|
test('should handle git command errors gracefully', async () => {
|
|
605
727
|
const { repoPath, cleanup } = await createTempRepo();
|
|
728
|
+
|
|
606
729
|
const repoFunctions = createRepoFunctions(repoPath);
|
|
607
730
|
|
|
608
731
|
try {
|
|
609
732
|
const result = await repoFunctions.getModifiedFiles({ silent: true });
|
|
733
|
+
|
|
610
734
|
// Should always return a Result, either Ok or Err
|
|
611
735
|
expect(Result.isOk(result) || Result.isErr(result)).toBe(true);
|
|
612
736
|
} finally {
|
|
@@ -615,18 +739,22 @@ describe('diff', () => {
|
|
|
615
739
|
});
|
|
616
740
|
});
|
|
617
741
|
|
|
618
|
-
describe(
|
|
742
|
+
describe(getDiffFrom, () => {
|
|
619
743
|
test('should work with silent option', async () => {
|
|
620
744
|
const { repoPath, cleanup, execInRepo } = await createTempRepo();
|
|
745
|
+
|
|
621
746
|
const repoFunctions = createRepoFunctions(repoPath);
|
|
622
747
|
|
|
623
748
|
try {
|
|
624
749
|
// Create an initial commit to have something to diff against
|
|
625
750
|
const testFileName = `test-initial-file-${crypto.randomUUID()}.tmp`;
|
|
751
|
+
|
|
626
752
|
const testFilePath = path.join(repoPath, testFileName);
|
|
627
753
|
|
|
628
754
|
await fs.writeFile(testFilePath, 'initial content');
|
|
755
|
+
|
|
629
756
|
await execInRepo(`git add ${testFileName}`, { silent: true });
|
|
757
|
+
|
|
630
758
|
await execInRepo(`git commit -m "Initial commit" --no-verify`, {
|
|
631
759
|
silent: true,
|
|
632
760
|
});
|
|
@@ -62,6 +62,7 @@ export function $(
|
|
|
62
62
|
options?: ExecOptionsWithStringEncoding | ExecOptionsWithBufferEncoding,
|
|
63
63
|
): Promise<ExecResult<string | Buffer>> {
|
|
64
64
|
const { silent = false, ...restOptions } = options ?? {};
|
|
65
|
+
|
|
65
66
|
const normalizedOptions: NormalizedExecOptions = restOptions;
|
|
66
67
|
|
|
67
68
|
if (!silent) {
|
|
@@ -79,6 +80,7 @@ export function $(
|
|
|
79
80
|
if (!isEmpty(stdout)) {
|
|
80
81
|
echo(stdout);
|
|
81
82
|
}
|
|
83
|
+
|
|
82
84
|
if (!isEmpty(stderr)) {
|
|
83
85
|
console.error(stderr);
|
|
84
86
|
}
|
|
@@ -86,6 +88,7 @@ export function $(
|
|
|
86
88
|
|
|
87
89
|
if (error !== null) {
|
|
88
90
|
resolve(Result.err(error));
|
|
91
|
+
|
|
89
92
|
return;
|
|
90
93
|
}
|
|
91
94
|
|
|
@@ -106,6 +109,7 @@ export function $(
|
|
|
106
109
|
handleResult(error, stdout, stderr);
|
|
107
110
|
},
|
|
108
111
|
);
|
|
112
|
+
|
|
109
113
|
return;
|
|
110
114
|
}
|
|
111
115
|
|