@camaradesuk/git-worktree-tools 1.0.5 → 1.1.1

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 (167) hide show
  1. package/README.md +7 -0
  2. package/dist/cli/cleanpr.d.ts +1 -6
  3. package/dist/cli/cleanpr.d.ts.map +1 -1
  4. package/dist/cli/cleanpr.js +110 -302
  5. package/dist/cli/cleanpr.js.map +1 -1
  6. package/dist/cli/cleanpr.test.d.ts +2 -0
  7. package/dist/cli/cleanpr.test.d.ts.map +1 -0
  8. package/dist/cli/cleanpr.test.js +225 -0
  9. package/dist/cli/cleanpr.test.js.map +1 -0
  10. package/dist/cli/lswt.d.ts +1 -4
  11. package/dist/cli/lswt.d.ts.map +1 -1
  12. package/dist/cli/lswt.js +32 -251
  13. package/dist/cli/lswt.js.map +1 -1
  14. package/dist/cli/lswt.test.d.ts +2 -0
  15. package/dist/cli/lswt.test.d.ts.map +1 -0
  16. package/dist/cli/lswt.test.js +165 -0
  17. package/dist/cli/lswt.test.js.map +1 -0
  18. package/dist/cli/newpr.d.ts +1 -4
  19. package/dist/cli/newpr.d.ts.map +1 -1
  20. package/dist/cli/newpr.js +98 -493
  21. package/dist/cli/newpr.js.map +1 -1
  22. package/dist/cli/newpr.test.d.ts +2 -0
  23. package/dist/cli/newpr.test.d.ts.map +1 -0
  24. package/dist/cli/newpr.test.js +329 -0
  25. package/dist/cli/newpr.test.js.map +1 -0
  26. package/dist/cli/wtlink.test.d.ts +2 -0
  27. package/dist/cli/wtlink.test.d.ts.map +1 -0
  28. package/dist/cli/wtlink.test.js +148 -0
  29. package/dist/cli/wtlink.test.js.map +1 -0
  30. package/dist/e2e/cli.e2e.test.js +44 -1
  31. package/dist/e2e/cli.e2e.test.js.map +1 -1
  32. package/dist/lib/cleanpr/args.d.ts +14 -0
  33. package/dist/lib/cleanpr/args.d.ts.map +1 -0
  34. package/dist/lib/cleanpr/args.js +82 -0
  35. package/dist/lib/cleanpr/args.js.map +1 -0
  36. package/dist/lib/cleanpr/args.test.d.ts +2 -0
  37. package/dist/lib/cleanpr/args.test.d.ts.map +1 -0
  38. package/dist/lib/cleanpr/args.test.js +192 -0
  39. package/dist/lib/cleanpr/args.test.js.map +1 -0
  40. package/dist/lib/cleanpr/cleanup.d.ts +61 -0
  41. package/dist/lib/cleanpr/cleanup.d.ts.map +1 -0
  42. package/dist/lib/cleanpr/cleanup.js +97 -0
  43. package/dist/lib/cleanpr/cleanup.js.map +1 -0
  44. package/dist/lib/cleanpr/cleanup.test.d.ts +2 -0
  45. package/dist/lib/cleanpr/cleanup.test.d.ts.map +1 -0
  46. package/dist/lib/cleanpr/cleanup.test.js +264 -0
  47. package/dist/lib/cleanpr/cleanup.test.js.map +1 -0
  48. package/dist/lib/cleanpr/index.d.ts +10 -0
  49. package/dist/lib/cleanpr/index.d.ts.map +1 -0
  50. package/dist/lib/cleanpr/index.js +8 -0
  51. package/dist/lib/cleanpr/index.js.map +1 -0
  52. package/dist/lib/cleanpr/types.d.ts +49 -0
  53. package/dist/lib/cleanpr/types.d.ts.map +1 -0
  54. package/dist/lib/cleanpr/types.js +5 -0
  55. package/dist/lib/cleanpr/types.js.map +1 -0
  56. package/dist/lib/cleanpr/worktree-info.d.ts +27 -0
  57. package/dist/lib/cleanpr/worktree-info.d.ts.map +1 -0
  58. package/dist/lib/cleanpr/worktree-info.js +95 -0
  59. package/dist/lib/cleanpr/worktree-info.js.map +1 -0
  60. package/dist/lib/cleanpr/worktree-info.test.d.ts +2 -0
  61. package/dist/lib/cleanpr/worktree-info.test.d.ts.map +1 -0
  62. package/dist/lib/cleanpr/worktree-info.test.js +160 -0
  63. package/dist/lib/cleanpr/worktree-info.test.js.map +1 -0
  64. package/dist/lib/colors.test.js +73 -0
  65. package/dist/lib/colors.test.js.map +1 -1
  66. package/dist/lib/config.test.js +79 -2
  67. package/dist/lib/config.test.js.map +1 -1
  68. package/dist/lib/git.d.ts.map +1 -1
  69. package/dist/lib/git.js +4 -3
  70. package/dist/lib/git.js.map +1 -1
  71. package/dist/lib/git.test.js +7 -7
  72. package/dist/lib/git.test.js.map +1 -1
  73. package/dist/lib/github.d.ts.map +1 -1
  74. package/dist/lib/github.js +23 -30
  75. package/dist/lib/github.js.map +1 -1
  76. package/dist/lib/github.test.js +49 -12
  77. package/dist/lib/github.test.js.map +1 -1
  78. package/dist/lib/lswt/args.d.ts +14 -0
  79. package/dist/lib/lswt/args.d.ts.map +1 -0
  80. package/dist/lib/lswt/args.js +67 -0
  81. package/dist/lib/lswt/args.js.map +1 -0
  82. package/dist/lib/lswt/args.test.d.ts +2 -0
  83. package/dist/lib/lswt/args.test.d.ts.map +1 -0
  84. package/dist/lib/lswt/args.test.js +135 -0
  85. package/dist/lib/lswt/args.test.js.map +1 -0
  86. package/dist/lib/lswt/formatters.d.ts +29 -0
  87. package/dist/lib/lswt/formatters.d.ts.map +1 -0
  88. package/dist/lib/lswt/formatters.js +113 -0
  89. package/dist/lib/lswt/formatters.js.map +1 -0
  90. package/dist/lib/lswt/formatters.test.d.ts +2 -0
  91. package/dist/lib/lswt/formatters.test.d.ts.map +1 -0
  92. package/dist/lib/lswt/formatters.test.js +233 -0
  93. package/dist/lib/lswt/formatters.test.js.map +1 -0
  94. package/dist/lib/lswt/index.d.ts +9 -0
  95. package/dist/lib/lswt/index.d.ts.map +1 -0
  96. package/dist/lib/lswt/index.js +9 -0
  97. package/dist/lib/lswt/index.js.map +1 -0
  98. package/dist/lib/lswt/types.d.ts +44 -0
  99. package/dist/lib/lswt/types.d.ts.map +1 -0
  100. package/dist/lib/lswt/types.js +5 -0
  101. package/dist/lib/lswt/types.js.map +1 -0
  102. package/dist/lib/lswt/worktree-info.d.ts +23 -0
  103. package/dist/lib/lswt/worktree-info.d.ts.map +1 -0
  104. package/dist/lib/lswt/worktree-info.js +81 -0
  105. package/dist/lib/lswt/worktree-info.js.map +1 -0
  106. package/dist/lib/lswt/worktree-info.test.d.ts +2 -0
  107. package/dist/lib/lswt/worktree-info.test.d.ts.map +1 -0
  108. package/dist/lib/lswt/worktree-info.test.js +190 -0
  109. package/dist/lib/lswt/worktree-info.test.js.map +1 -0
  110. package/dist/lib/newpr/actions.d.ts +56 -0
  111. package/dist/lib/newpr/actions.d.ts.map +1 -0
  112. package/dist/lib/newpr/actions.js +130 -0
  113. package/dist/lib/newpr/actions.js.map +1 -0
  114. package/dist/lib/newpr/actions.test.d.ts +2 -0
  115. package/dist/lib/newpr/actions.test.d.ts.map +1 -0
  116. package/dist/lib/newpr/actions.test.js +254 -0
  117. package/dist/lib/newpr/actions.test.js.map +1 -0
  118. package/dist/lib/newpr/args.d.ts +17 -0
  119. package/dist/lib/newpr/args.d.ts.map +1 -0
  120. package/dist/lib/newpr/args.js +123 -0
  121. package/dist/lib/newpr/args.js.map +1 -0
  122. package/dist/lib/newpr/args.test.d.ts +2 -0
  123. package/dist/lib/newpr/args.test.d.ts.map +1 -0
  124. package/dist/lib/newpr/args.test.js +271 -0
  125. package/dist/lib/newpr/args.test.js.map +1 -0
  126. package/dist/lib/newpr/index.d.ts +10 -0
  127. package/dist/lib/newpr/index.d.ts.map +1 -0
  128. package/dist/lib/newpr/index.js +8 -0
  129. package/dist/lib/newpr/index.js.map +1 -0
  130. package/dist/lib/newpr/scenario-handler.d.ts +40 -0
  131. package/dist/lib/newpr/scenario-handler.d.ts.map +1 -0
  132. package/dist/lib/newpr/scenario-handler.js +261 -0
  133. package/dist/lib/newpr/scenario-handler.js.map +1 -0
  134. package/dist/lib/newpr/scenario-handler.test.d.ts +2 -0
  135. package/dist/lib/newpr/scenario-handler.test.d.ts.map +1 -0
  136. package/dist/lib/newpr/scenario-handler.test.js +250 -0
  137. package/dist/lib/newpr/scenario-handler.test.js.map +1 -0
  138. package/dist/lib/newpr/types.d.ts +76 -0
  139. package/dist/lib/newpr/types.d.ts.map +1 -0
  140. package/dist/lib/newpr/types.js +5 -0
  141. package/dist/lib/newpr/types.js.map +1 -0
  142. package/dist/lib/state-detection.d.ts.map +1 -1
  143. package/dist/lib/state-detection.js +12 -3
  144. package/dist/lib/state-detection.js.map +1 -1
  145. package/dist/lib/state-detection.test.js +253 -2
  146. package/dist/lib/state-detection.test.js.map +1 -1
  147. package/dist/lib/wtlink/link-configs.d.ts +40 -0
  148. package/dist/lib/wtlink/link-configs.d.ts.map +1 -1
  149. package/dist/lib/wtlink/link-configs.js +126 -11
  150. package/dist/lib/wtlink/link-configs.js.map +1 -1
  151. package/dist/lib/wtlink/link-configs.test.js +237 -84
  152. package/dist/lib/wtlink/link-configs.test.js.map +1 -1
  153. package/dist/lib/wtlink/manage-manifest.d.ts +86 -0
  154. package/dist/lib/wtlink/manage-manifest.d.ts.map +1 -1
  155. package/dist/lib/wtlink/manage-manifest.js +16 -15
  156. package/dist/lib/wtlink/manage-manifest.js.map +1 -1
  157. package/dist/lib/wtlink/manage-manifest.test.d.ts +2 -0
  158. package/dist/lib/wtlink/manage-manifest.test.d.ts.map +1 -0
  159. package/dist/lib/wtlink/manage-manifest.test.js +383 -0
  160. package/dist/lib/wtlink/manage-manifest.test.js.map +1 -0
  161. package/dist/lib/wtlink/validate-manifest.d.ts +27 -0
  162. package/dist/lib/wtlink/validate-manifest.d.ts.map +1 -1
  163. package/dist/lib/wtlink/validate-manifest.js +103 -28
  164. package/dist/lib/wtlink/validate-manifest.js.map +1 -1
  165. package/dist/lib/wtlink/validate-manifest.test.js +170 -65
  166. package/dist/lib/wtlink/validate-manifest.test.js.map +1 -1
  167. package/package.json +1 -1
@@ -1,15 +1,13 @@
1
- import { describe, it, expect } from 'vitest';
2
- // We need to test internal functions, so we'll import the module
3
- // and use vi.mock to access internals where needed
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import * as fs from 'fs';
3
+ import * as path from 'path';
4
+ import * as os from 'os';
5
+ import { parseWorktreeList, parseManifest, isAlreadyLinked, detectConflicts, updateManifest, isBaseBranch, } from './link-configs.js';
4
6
  describe('wtlink/link-configs', () => {
5
7
  describe('parseWorktreeList', () => {
6
- // Since parseWorktreeList is not exported, we test it indirectly
7
- // by testing the behavior of functions that use it
8
- // or we create a separate testable module
9
- // For now, let's document the expected parsing behavior
10
8
  it('should parse empty worktree list', () => {
11
9
  const raw = '';
12
- const entries = parseWorktreeListHelper(raw);
10
+ const entries = parseWorktreeList(raw);
13
11
  expect(entries).toEqual([]);
14
12
  });
15
13
  it('should parse single worktree entry', () => {
@@ -18,7 +16,7 @@ HEAD abc123
18
16
  branch refs/heads/main
19
17
 
20
18
  `;
21
- const entries = parseWorktreeListHelper(raw);
19
+ const entries = parseWorktreeList(raw);
22
20
  expect(entries).toHaveLength(1);
23
21
  expect(entries[0]).toEqual({
24
22
  path: '/home/user/project',
@@ -36,7 +34,7 @@ HEAD def456
36
34
  branch refs/heads/feature/auth
37
35
 
38
36
  `;
39
- const entries = parseWorktreeListHelper(raw);
37
+ const entries = parseWorktreeList(raw);
40
38
  expect(entries).toHaveLength(2);
41
39
  expect(entries[0].path).toBe('/home/user/project');
42
40
  expect(entries[0].branch).toBe('refs/heads/main');
@@ -48,7 +46,7 @@ branch refs/heads/feature/auth
48
46
  bare
49
47
 
50
48
  `;
51
- const entries = parseWorktreeListHelper(raw);
49
+ const entries = parseWorktreeList(raw);
52
50
  expect(entries).toHaveLength(1);
53
51
  expect(entries[0].isBare).toBe(true);
54
52
  });
@@ -58,24 +56,32 @@ HEAD abc123
58
56
  detached
59
57
 
60
58
  `;
61
- const entries = parseWorktreeListHelper(raw);
59
+ const entries = parseWorktreeList(raw);
62
60
  expect(entries).toHaveLength(1);
63
61
  expect(entries[0].branch).toBeUndefined();
64
62
  });
63
+ it('should handle worktree entry without trailing newlines', () => {
64
+ const raw = `worktree /home/user/project
65
+ HEAD abc123
66
+ branch refs/heads/main`;
67
+ const entries = parseWorktreeList(raw);
68
+ expect(entries).toHaveLength(1);
69
+ expect(entries[0].path).toBe('/home/user/project');
70
+ });
65
71
  });
66
- describe('manifest parsing', () => {
72
+ describe('parseManifest', () => {
67
73
  it('should parse active entries', () => {
68
74
  const manifest = `.env
69
75
  .vscode/settings.json
70
76
  config/local.json`;
71
- const entries = parseManifestHelper(manifest);
77
+ const entries = parseManifest(manifest);
72
78
  expect(entries.active).toEqual(['.env', '.vscode/settings.json', 'config/local.json']);
73
79
  expect(entries.commented).toEqual([]);
74
80
  });
75
81
  it('should parse commented entries', () => {
76
82
  const manifest = `# .env.local
77
83
  # .vscode/launch.json`;
78
- const entries = parseManifestHelper(manifest);
84
+ const entries = parseManifest(manifest);
79
85
  expect(entries.active).toEqual([]);
80
86
  expect(entries.commented).toEqual(['.env.local', '.vscode/launch.json']);
81
87
  });
@@ -85,7 +91,7 @@ config/local.json`;
85
91
  .vscode/settings.json
86
92
  # .vscode/launch.json
87
93
  `;
88
- const entries = parseManifestHelper(manifest);
94
+ const entries = parseManifest(manifest);
89
95
  expect(entries.active).toEqual(['.env', '.vscode/settings.json']);
90
96
  expect(entries.commented).toEqual(['.env.local', '.vscode/launch.json']);
91
97
  });
@@ -95,7 +101,7 @@ config/local.json`;
95
101
  .vscode/settings.json
96
102
 
97
103
  `;
98
- const entries = parseManifestHelper(manifest);
104
+ const entries = parseManifest(manifest);
99
105
  expect(entries.active).toEqual(['.env', '.vscode/settings.json']);
100
106
  });
101
107
  it('should handle header comments (multiple #)', () => {
@@ -103,77 +109,224 @@ config/local.json`;
103
109
  # This is a comment about the manifest
104
110
  .env
105
111
  # .env.local`;
106
- const entries = parseManifestHelper(manifest);
112
+ const entries = parseManifest(manifest);
107
113
  // Lines starting with ## are header comments, not file entries
114
+ // "This is a comment about the manifest" doesn't look like a file path, so skipped
108
115
  expect(entries.active).toEqual(['.env']);
109
116
  expect(entries.commented).toEqual(['.env.local']);
110
117
  });
118
+ it('should detect file paths with extensions', () => {
119
+ const manifest = `# config.yaml
120
+ # data.json`;
121
+ const entries = parseManifest(manifest);
122
+ expect(entries.commented).toEqual(['config.yaml', 'data.json']);
123
+ });
124
+ it('should skip descriptive comments', () => {
125
+ const manifest = `# This is just a regular comment
126
+ # Remember to update this file
127
+ .env`;
128
+ const entries = parseManifest(manifest);
129
+ expect(entries.active).toEqual(['.env']);
130
+ expect(entries.commented).toEqual([]);
131
+ });
132
+ });
133
+ describe('isAlreadyLinked', () => {
134
+ let tempDir;
135
+ beforeEach(() => {
136
+ tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'link-configs-test-'));
137
+ });
138
+ afterEach(() => {
139
+ fs.rmSync(tempDir, { recursive: true, force: true });
140
+ });
141
+ it('should return false when dest does not exist', () => {
142
+ const sourcePath = path.join(tempDir, 'source.txt');
143
+ const destPath = path.join(tempDir, 'dest.txt');
144
+ fs.writeFileSync(sourcePath, 'content');
145
+ expect(isAlreadyLinked(sourcePath, destPath)).toBe(false);
146
+ });
147
+ it('should return true for hard-linked files', () => {
148
+ const sourcePath = path.join(tempDir, 'source.txt');
149
+ const destPath = path.join(tempDir, 'dest.txt');
150
+ fs.writeFileSync(sourcePath, 'content');
151
+ fs.linkSync(sourcePath, destPath);
152
+ expect(isAlreadyLinked(sourcePath, destPath)).toBe(true);
153
+ });
154
+ it('should return true for symbolic links pointing to source', () => {
155
+ const sourcePath = path.join(tempDir, 'source.txt');
156
+ const destPath = path.join(tempDir, 'dest.txt');
157
+ fs.writeFileSync(sourcePath, 'content');
158
+ fs.symlinkSync(sourcePath, destPath);
159
+ expect(isAlreadyLinked(sourcePath, destPath)).toBe(true);
160
+ });
161
+ it('should return false for different files with same content', () => {
162
+ const sourcePath = path.join(tempDir, 'source.txt');
163
+ const destPath = path.join(tempDir, 'dest.txt');
164
+ fs.writeFileSync(sourcePath, 'content');
165
+ fs.writeFileSync(destPath, 'content');
166
+ expect(isAlreadyLinked(sourcePath, destPath)).toBe(false);
167
+ });
168
+ it('should return false for different files', () => {
169
+ const sourcePath = path.join(tempDir, 'source.txt');
170
+ const destPath = path.join(tempDir, 'dest.txt');
171
+ fs.writeFileSync(sourcePath, 'source content');
172
+ fs.writeFileSync(destPath, 'dest content');
173
+ expect(isAlreadyLinked(sourcePath, destPath)).toBe(false);
174
+ });
175
+ it('should return false on error', () => {
176
+ // Non-existent paths should return false, not throw
177
+ expect(isAlreadyLinked('/nonexistent/source', '/nonexistent/dest')).toBe(false);
178
+ });
179
+ });
180
+ describe('detectConflicts', () => {
181
+ let tempDir;
182
+ let sourceDir;
183
+ let destDir;
184
+ beforeEach(() => {
185
+ tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'link-configs-test-'));
186
+ sourceDir = path.join(tempDir, 'source');
187
+ destDir = path.join(tempDir, 'dest');
188
+ fs.mkdirSync(sourceDir, { recursive: true });
189
+ fs.mkdirSync(destDir, { recursive: true });
190
+ });
191
+ afterEach(() => {
192
+ fs.rmSync(tempDir, { recursive: true, force: true });
193
+ });
194
+ it('should detect safe files (no conflict)', () => {
195
+ fs.writeFileSync(path.join(sourceDir, 'file.txt'), 'content');
196
+ const report = detectConflicts(['file.txt'], sourceDir, destDir);
197
+ expect(report.safe).toHaveLength(1);
198
+ expect(report.safe[0].file).toBe('file.txt');
199
+ expect(report.alreadyLinked).toHaveLength(0);
200
+ expect(report.conflicts).toHaveLength(0);
201
+ });
202
+ it('should detect already linked files', () => {
203
+ const sourceFile = path.join(sourceDir, 'file.txt');
204
+ const destFile = path.join(destDir, 'file.txt');
205
+ fs.writeFileSync(sourceFile, 'content');
206
+ fs.linkSync(sourceFile, destFile);
207
+ const report = detectConflicts(['file.txt'], sourceDir, destDir);
208
+ expect(report.safe).toHaveLength(0);
209
+ expect(report.alreadyLinked).toHaveLength(1);
210
+ expect(report.alreadyLinked[0].file).toBe('file.txt');
211
+ expect(report.conflicts).toHaveLength(0);
212
+ });
213
+ it('should detect conflicts', () => {
214
+ fs.writeFileSync(path.join(sourceDir, 'file.txt'), 'source content');
215
+ fs.writeFileSync(path.join(destDir, 'file.txt'), 'different content');
216
+ const report = detectConflicts(['file.txt'], sourceDir, destDir);
217
+ expect(report.safe).toHaveLength(0);
218
+ expect(report.alreadyLinked).toHaveLength(0);
219
+ expect(report.conflicts).toHaveLength(1);
220
+ expect(report.conflicts[0].file).toBe('file.txt');
221
+ });
222
+ it('should skip files that do not exist in source', () => {
223
+ const report = detectConflicts(['nonexistent.txt'], sourceDir, destDir);
224
+ expect(report.safe).toHaveLength(0);
225
+ expect(report.alreadyLinked).toHaveLength(0);
226
+ expect(report.conflicts).toHaveLength(0);
227
+ });
228
+ it('should handle multiple files with mixed states', () => {
229
+ // Safe file
230
+ fs.writeFileSync(path.join(sourceDir, 'safe.txt'), 'content');
231
+ // Already linked file
232
+ const linkedSource = path.join(sourceDir, 'linked.txt');
233
+ const linkedDest = path.join(destDir, 'linked.txt');
234
+ fs.writeFileSync(linkedSource, 'linked content');
235
+ fs.linkSync(linkedSource, linkedDest);
236
+ // Conflict file
237
+ fs.writeFileSync(path.join(sourceDir, 'conflict.txt'), 'source');
238
+ fs.writeFileSync(path.join(destDir, 'conflict.txt'), 'dest');
239
+ const report = detectConflicts(['safe.txt', 'linked.txt', 'conflict.txt'], sourceDir, destDir);
240
+ expect(report.safe).toHaveLength(1);
241
+ expect(report.safe[0].file).toBe('safe.txt');
242
+ expect(report.alreadyLinked).toHaveLength(1);
243
+ expect(report.alreadyLinked[0].file).toBe('linked.txt');
244
+ expect(report.conflicts).toHaveLength(1);
245
+ expect(report.conflicts[0].file).toBe('conflict.txt');
246
+ });
247
+ });
248
+ describe('updateManifest', () => {
249
+ let tempDir;
250
+ let manifestPath;
251
+ beforeEach(() => {
252
+ tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'link-configs-test-'));
253
+ manifestPath = path.join(tempDir, '.wtlink');
254
+ });
255
+ afterEach(() => {
256
+ fs.rmSync(tempDir, { recursive: true, force: true });
257
+ });
258
+ it('should remove specified files from manifest', () => {
259
+ fs.writeFileSync(manifestPath, `.env
260
+ .vscode/settings.json
261
+ config/local.json`);
262
+ updateManifest(manifestPath, ['.vscode/settings.json']);
263
+ const result = fs.readFileSync(manifestPath, 'utf-8');
264
+ expect(result).toBe(`.env
265
+ config/local.json`);
266
+ });
267
+ it('should keep empty lines and header comments', () => {
268
+ fs.writeFileSync(manifestPath, `## Header
269
+ .env
270
+
271
+ .vscode/settings.json`);
272
+ updateManifest(manifestPath, ['.vscode/settings.json']);
273
+ const result = fs.readFileSync(manifestPath, 'utf-8');
274
+ expect(result).toBe(`## Header
275
+ .env
276
+ `);
277
+ });
278
+ it('should remove commented entries when they match', () => {
279
+ fs.writeFileSync(manifestPath, `.env
280
+ # .env.local
281
+ .vscode/settings.json`);
282
+ updateManifest(manifestPath, ['.env.local']);
283
+ const result = fs.readFileSync(manifestPath, 'utf-8');
284
+ expect(result).toBe(`.env
285
+ .vscode/settings.json`);
286
+ });
287
+ it('should handle entries with TRACKED/DELETED/STALE prefixes', () => {
288
+ fs.writeFileSync(manifestPath, `.env
289
+ # TRACKED: old-file.txt
290
+ # DELETED: removed.txt
291
+ .vscode/settings.json`);
292
+ updateManifest(manifestPath, ['old-file.txt', 'removed.txt']);
293
+ const result = fs.readFileSync(manifestPath, 'utf-8');
294
+ expect(result).toBe(`.env
295
+ .vscode/settings.json`);
296
+ });
297
+ it('should handle empty removal list', () => {
298
+ const original = `.env
299
+ .vscode/settings.json`;
300
+ fs.writeFileSync(manifestPath, original);
301
+ updateManifest(manifestPath, []);
302
+ const result = fs.readFileSync(manifestPath, 'utf-8');
303
+ expect(result).toBe(original);
304
+ });
305
+ });
306
+ describe('isBaseBranch', () => {
307
+ it('should return true for main branch', () => {
308
+ expect(isBaseBranch('main')).toBe(true);
309
+ });
310
+ it('should return true for master branch', () => {
311
+ expect(isBaseBranch('master')).toBe(true);
312
+ });
313
+ it('should return true for develop branch', () => {
314
+ expect(isBaseBranch('develop')).toBe(true);
315
+ });
316
+ it('should return false for feature branches', () => {
317
+ expect(isBaseBranch('feature/auth')).toBe(false);
318
+ expect(isBaseBranch('feature-123')).toBe(false);
319
+ });
320
+ it('should return false for PR branches', () => {
321
+ expect(isBaseBranch('claude/fix-issue-123')).toBe(false);
322
+ expect(isBaseBranch('pr-42')).toBe(false);
323
+ });
324
+ it('should return false for null', () => {
325
+ expect(isBaseBranch(null)).toBe(false);
326
+ });
327
+ it('should return false for empty string', () => {
328
+ expect(isBaseBranch('')).toBe(false);
329
+ });
111
330
  });
112
331
  });
113
- function parseWorktreeListHelper(raw) {
114
- const entries = [];
115
- const lines = raw.split('\n');
116
- let current = null;
117
- for (const rawLine of lines) {
118
- const line = rawLine.trim();
119
- if (!line) {
120
- if (current && current.path) {
121
- entries.push(current);
122
- }
123
- current = null;
124
- continue;
125
- }
126
- if (!current) {
127
- current = { path: '', isBare: false };
128
- }
129
- if (line.startsWith('worktree ')) {
130
- current.path = line.substring('worktree '.length).trim();
131
- }
132
- else if (line.startsWith('branch ')) {
133
- current.branch = line.substring('branch '.length).trim();
134
- }
135
- else if (line === 'bare') {
136
- current.isBare = true;
137
- }
138
- }
139
- if (current && current.path) {
140
- entries.push(current);
141
- }
142
- return entries;
143
- }
144
- function parseManifestHelper(content) {
145
- const active = [];
146
- const commented = [];
147
- for (const rawLine of content.split('\n')) {
148
- const line = rawLine.trim();
149
- if (!line) {
150
- continue;
151
- }
152
- // Skip header comments (lines starting with ##)
153
- if (line.startsWith('##')) {
154
- continue;
155
- }
156
- if (line.startsWith('#')) {
157
- // Extract file path from comment
158
- const filePath = line.substring(1).trim();
159
- // Skip if it's another comment marker or empty
160
- if (!filePath || filePath.startsWith('#')) {
161
- continue;
162
- }
163
- // Only count as a commented file entry if it looks like a file path
164
- // (starts with . or / or contains / or has a file extension)
165
- if (filePath.startsWith('.') ||
166
- filePath.startsWith('/') ||
167
- filePath.includes('/') ||
168
- /\.\w+$/.test(filePath)) {
169
- commented.push(filePath);
170
- }
171
- // Otherwise it's a descriptive comment, skip it
172
- }
173
- else {
174
- active.push(line);
175
- }
176
- }
177
- return { active, commented };
178
- }
179
332
  //# sourceMappingURL=link-configs.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"link-configs.test.js","sourceRoot":"","sources":["../../../src/lib/wtlink/link-configs.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"link-configs.test.js","sourceRoot":"","sources":["../../../src/lib/wtlink/link-configs.test.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,27 @@
1
+ export type FileDecision = 'add' | 'comment' | 'skip';
2
+ export type ItemState = FileDecision | 'undecided';
3
+ export type ViewMode = 'flat' | 'hierarchical';
4
+ export interface FileNode {
5
+ readonly path: string;
6
+ readonly isDirectory: boolean;
7
+ readonly children: ReadonlyArray<FileNode>;
8
+ }
9
+ export interface AppState {
10
+ readonly fileTree: FileNode;
11
+ readonly decisions: ReadonlyMap<string, FileDecision>;
12
+ readonly viewMode: ViewMode;
13
+ readonly activeFilters: ReadonlySet<ItemState>;
14
+ readonly showHelp: boolean;
15
+ readonly navigationStack: ReadonlyArray<string>;
16
+ readonly cursorIndex: number;
17
+ readonly scrollOffset: number;
18
+ }
19
+ export interface DisplayItem {
20
+ readonly path: string;
21
+ readonly isDirectory: boolean;
22
+ readonly node?: FileNode;
23
+ readonly states: ReadonlySet<ItemState>;
24
+ }
1
25
  export interface ManageArgv {
2
26
  nonInteractive: boolean;
3
27
  clean: boolean;
@@ -5,5 +29,67 @@ export interface ManageArgv {
5
29
  manifestFile: string;
6
30
  backup: boolean;
7
31
  }
32
+ /**
33
+ * Get all file paths from a node (recursively)
34
+ */
35
+ export declare function getAllFiles(node: FileNode): string[];
36
+ /**
37
+ * Get all directory nodes from a tree (recursively)
38
+ */
39
+ export declare function getAllDirectories(node: FileNode): FileNode[];
40
+ /**
41
+ * Get the computed state for a single file
42
+ * Returns 'undecided' (explicit state) if file not in decisions map
43
+ */
44
+ export declare function getFileDecision(decisions: ReadonlyMap<string, FileDecision>, filePath: string): ItemState;
45
+ /**
46
+ * Get all computed states present in a folder's descendants
47
+ * A folder can have multiple states if children have different states
48
+ * This is DERIVED from children - folders don't have their own decision
49
+ * 'undecided' is an explicit state for items with no decision
50
+ */
51
+ export declare function getFolderStates(node: FileNode, decisions: ReadonlyMap<string, FileDecision>): ReadonlySet<ItemState>;
52
+ /**
53
+ * Get state breakdown counts for a folder
54
+ */
55
+ export declare function getFolderStateBreakdown(node: FileNode, decisions: ReadonlyMap<string, FileDecision>): {
56
+ add: number;
57
+ comment: number;
58
+ skip: number;
59
+ undecided: number;
60
+ };
61
+ /**
62
+ * Check if an item should be visible based on current filters
63
+ * An item is visible if it has at least one state matching the active filters
64
+ * Default: only 'undecided' filter is active (shows undecided items)
65
+ */
66
+ export declare function isItemVisible(item: DisplayItem, activeFilters: ReadonlySet<ItemState>): boolean;
67
+ /**
68
+ * Build file tree from flat list of file paths
69
+ */
70
+ export declare function buildFileTree(filePaths: string[]): FileNode;
71
+ /**
72
+ * Find a node by path in the tree
73
+ */
74
+ export declare function findNodeByPath(tree: FileNode, targetPath: string): FileNode | null;
75
+ /**
76
+ * Get items to display in hierarchical view
77
+ * Folders appear first, then files (both alphabetically sorted within their groups)
78
+ */
79
+ export declare function getHierarchicalViewItems(tree: FileNode, navigationStack: ReadonlyArray<string>, decisions: ReadonlyMap<string, FileDecision>): DisplayItem[];
80
+ /**
81
+ * Get items to display in flat view
82
+ */
83
+ export declare function getFlatViewItems(tree: FileNode, decisions: ReadonlyMap<string, FileDecision>): DisplayItem[];
84
+ /**
85
+ * Get all visible items for current state (SINGLE SOURCE OF TRUTH)
86
+ */
87
+ export declare function getVisibleItems(state: AppState): DisplayItem[];
88
+ /**
89
+ * Get display items with back navigation if needed
90
+ */
91
+ export declare function getDisplayItems(state: AppState): DisplayItem[];
92
+ export declare const COMMON_IGNORE_DIRS: string[];
93
+ export declare function isCommonIgnoreDir(dirPath: string): boolean;
8
94
  export declare function run(argv: ManageArgv): Promise<void>;
9
95
  //# sourceMappingURL=manage-manifest.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"manage-manifest.d.ts","sourceRoot":"","sources":["../../../src/lib/wtlink/manage-manifest.ts"],"names":[],"mappings":"AA8CA,MAAM,WAAW,UAAU;IACzB,cAAc,EAAE,OAAO,CAAC;IACxB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;CACjB;AAi0CD,wBAAsB,GAAG,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CA+LzD"}
1
+ {"version":3,"file":"manage-manifest.d.ts","sourceRoot":"","sources":["../../../src/lib/wtlink/manage-manifest.ts"],"names":[],"mappings":"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"}
@@ -13,7 +13,7 @@ import { signal, computed } from '@preact/signals-core';
13
13
  /**
14
14
  * Get all file paths from a node (recursively)
15
15
  */
16
- function getAllFiles(node) {
16
+ export function getAllFiles(node) {
17
17
  if (!node.isDirectory) {
18
18
  return [node.path];
19
19
  }
@@ -22,7 +22,7 @@ function getAllFiles(node) {
22
22
  /**
23
23
  * Get all directory nodes from a tree (recursively)
24
24
  */
25
- function getAllDirectories(node) {
25
+ export function getAllDirectories(node) {
26
26
  if (!node.isDirectory) {
27
27
  return [];
28
28
  }
@@ -39,7 +39,7 @@ function getAllDirectories(node) {
39
39
  * Get the computed state for a single file
40
40
  * Returns 'undecided' (explicit state) if file not in decisions map
41
41
  */
42
- function getFileDecision(decisions, filePath) {
42
+ export function getFileDecision(decisions, filePath) {
43
43
  return decisions.get(filePath) ?? 'undecided';
44
44
  }
45
45
  /**
@@ -48,7 +48,7 @@ function getFileDecision(decisions, filePath) {
48
48
  * This is DERIVED from children - folders don't have their own decision
49
49
  * 'undecided' is an explicit state for items with no decision
50
50
  */
51
- function getFolderStates(node, decisions) {
51
+ export function getFolderStates(node, decisions) {
52
52
  if (!node.isDirectory) {
53
53
  return new Set([getFileDecision(decisions, node.path)]);
54
54
  }
@@ -62,7 +62,7 @@ function getFolderStates(node, decisions) {
62
62
  /**
63
63
  * Get state breakdown counts for a folder
64
64
  */
65
- function getFolderStateBreakdown(node, decisions) {
65
+ export function getFolderStateBreakdown(node, decisions) {
66
66
  const breakdown = { add: 0, comment: 0, skip: 0, undecided: 0 };
67
67
  const allFiles = getAllFiles(node);
68
68
  for (const filePath of allFiles) {
@@ -76,7 +76,7 @@ function getFolderStateBreakdown(node, decisions) {
76
76
  * An item is visible if it has at least one state matching the active filters
77
77
  * Default: only 'undecided' filter is active (shows undecided items)
78
78
  */
79
- function isItemVisible(item, activeFilters) {
79
+ export function isItemVisible(item, activeFilters) {
80
80
  // If no filters active, nothing is visible (edge case)
81
81
  if (activeFilters.size === 0) {
82
82
  return false;
@@ -92,7 +92,7 @@ function isItemVisible(item, activeFilters) {
92
92
  /**
93
93
  * Build file tree from flat list of file paths
94
94
  */
95
- function buildFileTree(filePaths) {
95
+ export function buildFileTree(filePaths) {
96
96
  const root = {
97
97
  path: '',
98
98
  isDirectory: true,
@@ -134,7 +134,7 @@ function buildFileTree(filePaths) {
134
134
  /**
135
135
  * Find a node by path in the tree
136
136
  */
137
- function findNodeByPath(tree, targetPath) {
137
+ export function findNodeByPath(tree, targetPath) {
138
138
  if (tree.path === targetPath) {
139
139
  return tree;
140
140
  }
@@ -149,7 +149,7 @@ function findNodeByPath(tree, targetPath) {
149
149
  * Get items to display in hierarchical view
150
150
  * Folders appear first, then files (both alphabetically sorted within their groups)
151
151
  */
152
- function getHierarchicalViewItems(tree, navigationStack, decisions) {
152
+ export function getHierarchicalViewItems(tree, navigationStack, decisions) {
153
153
  // Navigate to current directory
154
154
  let currentNode = tree;
155
155
  for (const dirPath of navigationStack) {
@@ -177,7 +177,7 @@ function getHierarchicalViewItems(tree, navigationStack, decisions) {
177
177
  /**
178
178
  * Get items to display in flat view
179
179
  */
180
- function getFlatViewItems(tree, decisions) {
180
+ export function getFlatViewItems(tree, decisions) {
181
181
  const items = [];
182
182
  // Add all directories
183
183
  const allDirs = getAllDirectories(tree);
@@ -205,7 +205,7 @@ function getFlatViewItems(tree, decisions) {
205
205
  /**
206
206
  * Get all visible items for current state (SINGLE SOURCE OF TRUTH)
207
207
  */
208
- function getVisibleItems(state) {
208
+ export function getVisibleItems(state) {
209
209
  // Get items based on view mode
210
210
  const allItems = state.viewMode === 'flat'
211
211
  ? getFlatViewItems(state.fileTree, state.decisions)
@@ -216,7 +216,7 @@ function getVisibleItems(state) {
216
216
  /**
217
217
  * Get display items with back navigation if needed
218
218
  */
219
- function getDisplayItems(state) {
219
+ export function getDisplayItems(state) {
220
220
  const items = getVisibleItems(state);
221
221
  // Add back navigation in hierarchical view when in default undecided-only mode
222
222
  const showingUndecidedOnly = state.activeFilters.size === 1 && state.activeFilters.has('undecided');
@@ -332,7 +332,8 @@ function _updateScroll(state) {
332
332
  const headerLines = 8;
333
333
  const footerLines = 3;
334
334
  const maxVisibleItems = Math.max(5, terminalHeight - headerLines - footerLines);
335
- let { scrollOffset, cursorIndex } = state;
335
+ const { cursorIndex } = state;
336
+ let { scrollOffset } = state;
336
337
  // Auto-scroll to keep cursor in view
337
338
  if (cursorIndex < scrollOffset) {
338
339
  scrollOffset = cursorIndex;
@@ -347,7 +348,7 @@ function _updateScroll(state) {
347
348
  // ============================================================================
348
349
  // COMMON DIRECTORIES
349
350
  // ============================================================================
350
- const COMMON_IGNORE_DIRS = [
351
+ export const COMMON_IGNORE_DIRS = [
351
352
  'node_modules',
352
353
  'bin',
353
354
  'obj',
@@ -367,7 +368,7 @@ const COMMON_IGNORE_DIRS = [
367
368
  '.gradle',
368
369
  'vendor',
369
370
  ];
370
- function isCommonIgnoreDir(dirPath) {
371
+ export function isCommonIgnoreDir(dirPath) {
371
372
  const parts = dirPath.split('/');
372
373
  return COMMON_IGNORE_DIRS.some((ignoreDir) => parts.includes(ignoreDir));
373
374
  }