@camaradesuk/git-worktree-tools 1.0.3
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/LICENSE +21 -0
- package/README.md +259 -0
- package/dist/cli/cleanpr.d.ts +13 -0
- package/dist/cli/cleanpr.d.ts.map +1 -0
- package/dist/cli/cleanpr.js +441 -0
- package/dist/cli/cleanpr.js.map +1 -0
- package/dist/cli/lswt.d.ts +11 -0
- package/dist/cli/lswt.d.ts.map +1 -0
- package/dist/cli/lswt.js +313 -0
- package/dist/cli/lswt.js.map +1 -0
- package/dist/cli/newpr.d.ts +11 -0
- package/dist/cli/newpr.d.ts.map +1 -0
- package/dist/cli/newpr.js +888 -0
- package/dist/cli/newpr.js.map +1 -0
- package/dist/cli/wtlink.d.ts +15 -0
- package/dist/cli/wtlink.d.ts.map +1 -0
- package/dist/cli/wtlink.js +124 -0
- package/dist/cli/wtlink.js.map +1 -0
- package/dist/e2e/cli.e2e.test.d.ts +2 -0
- package/dist/e2e/cli.e2e.test.d.ts.map +1 -0
- package/dist/e2e/cli.e2e.test.js +215 -0
- package/dist/e2e/cli.e2e.test.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/integration/git.integration.test.d.ts +2 -0
- package/dist/integration/git.integration.test.d.ts.map +1 -0
- package/dist/integration/git.integration.test.js +333 -0
- package/dist/integration/git.integration.test.js.map +1 -0
- package/dist/lib/colors.d.ts +59 -0
- package/dist/lib/colors.d.ts.map +1 -0
- package/dist/lib/colors.js +145 -0
- package/dist/lib/colors.js.map +1 -0
- package/dist/lib/colors.test.d.ts +2 -0
- package/dist/lib/colors.test.d.ts.map +1 -0
- package/dist/lib/colors.test.js +69 -0
- package/dist/lib/colors.test.js.map +1 -0
- package/dist/lib/config.d.ts +58 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +91 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/config.test.d.ts +2 -0
- package/dist/lib/config.test.d.ts.map +1 -0
- package/dist/lib/config.test.js +84 -0
- package/dist/lib/config.test.js.map +1 -0
- package/dist/lib/constants.d.ts +37 -0
- package/dist/lib/constants.d.ts.map +1 -0
- package/dist/lib/constants.js +37 -0
- package/dist/lib/constants.js.map +1 -0
- package/dist/lib/errors.d.ts +88 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +112 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/errors.test.d.ts +2 -0
- package/dist/lib/errors.test.d.ts.map +1 -0
- package/dist/lib/errors.test.js +117 -0
- package/dist/lib/errors.test.js.map +1 -0
- package/dist/lib/git.d.ts +224 -0
- package/dist/lib/git.d.ts.map +1 -0
- package/dist/lib/git.js +524 -0
- package/dist/lib/git.js.map +1 -0
- package/dist/lib/git.test.d.ts +2 -0
- package/dist/lib/git.test.d.ts.map +1 -0
- package/dist/lib/git.test.js +402 -0
- package/dist/lib/git.test.js.map +1 -0
- package/dist/lib/github.d.ts +82 -0
- package/dist/lib/github.d.ts.map +1 -0
- package/dist/lib/github.js +254 -0
- package/dist/lib/github.js.map +1 -0
- package/dist/lib/github.test.d.ts +2 -0
- package/dist/lib/github.test.d.ts.map +1 -0
- package/dist/lib/github.test.js +258 -0
- package/dist/lib/github.test.js.map +1 -0
- package/dist/lib/prompts.d.ts +39 -0
- package/dist/lib/prompts.d.ts.map +1 -0
- package/dist/lib/prompts.js +213 -0
- package/dist/lib/prompts.js.map +1 -0
- package/dist/lib/prompts.test.d.ts +2 -0
- package/dist/lib/prompts.test.d.ts.map +1 -0
- package/dist/lib/prompts.test.js +250 -0
- package/dist/lib/prompts.test.js.map +1 -0
- package/dist/lib/state-detection.d.ts +65 -0
- package/dist/lib/state-detection.d.ts.map +1 -0
- package/dist/lib/state-detection.js +186 -0
- package/dist/lib/state-detection.js.map +1 -0
- package/dist/lib/state-detection.test.d.ts +2 -0
- package/dist/lib/state-detection.test.d.ts.map +1 -0
- package/dist/lib/state-detection.test.js +164 -0
- package/dist/lib/state-detection.test.js.map +1 -0
- package/dist/lib/wtlink/index.d.ts +5 -0
- package/dist/lib/wtlink/index.d.ts.map +1 -0
- package/dist/lib/wtlink/index.js +7 -0
- package/dist/lib/wtlink/index.js.map +1 -0
- package/dist/lib/wtlink/link-configs.d.ts +10 -0
- package/dist/lib/wtlink/link-configs.d.ts.map +1 -0
- package/dist/lib/wtlink/link-configs.js +411 -0
- package/dist/lib/wtlink/link-configs.js.map +1 -0
- package/dist/lib/wtlink/link-configs.test.d.ts +2 -0
- package/dist/lib/wtlink/link-configs.test.d.ts.map +1 -0
- package/dist/lib/wtlink/link-configs.test.js +179 -0
- package/dist/lib/wtlink/link-configs.test.js.map +1 -0
- package/dist/lib/wtlink/main-menu.d.ts +2 -0
- package/dist/lib/wtlink/main-menu.d.ts.map +1 -0
- package/dist/lib/wtlink/main-menu.js +149 -0
- package/dist/lib/wtlink/main-menu.js.map +1 -0
- package/dist/lib/wtlink/manage-manifest.d.ts +9 -0
- package/dist/lib/wtlink/manage-manifest.d.ts.map +1 -0
- package/dist/lib/wtlink/manage-manifest.js +1262 -0
- package/dist/lib/wtlink/manage-manifest.js.map +1 -0
- package/dist/lib/wtlink/validate-manifest.d.ts +6 -0
- package/dist/lib/wtlink/validate-manifest.d.ts.map +1 -0
- package/dist/lib/wtlink/validate-manifest.js +51 -0
- package/dist/lib/wtlink/validate-manifest.js.map +1 -0
- package/dist/lib/wtlink/validate-manifest.test.d.ts +2 -0
- package/dist/lib/wtlink/validate-manifest.test.d.ts.map +1 -0
- package/dist/lib/wtlink/validate-manifest.test.js +115 -0
- package/dist/lib/wtlink/validate-manifest.test.js.map +1 -0
- package/package.json +84 -0
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import inquirer from 'inquirer';
|
|
4
|
+
import * as colors from '../colors.js';
|
|
5
|
+
import * as git from '../git.js';
|
|
6
|
+
import { COMMON_BASE_BRANCHES } from '../constants.js';
|
|
7
|
+
function parseWorktreeList(raw) {
|
|
8
|
+
const entries = [];
|
|
9
|
+
const lines = raw.split('\n');
|
|
10
|
+
let current = null;
|
|
11
|
+
for (const rawLine of lines) {
|
|
12
|
+
const line = rawLine.trim();
|
|
13
|
+
if (!line) {
|
|
14
|
+
if (current && current.path) {
|
|
15
|
+
entries.push(current);
|
|
16
|
+
}
|
|
17
|
+
current = null;
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
if (!current) {
|
|
21
|
+
current = { path: '', isBare: false };
|
|
22
|
+
}
|
|
23
|
+
if (line.startsWith('worktree ')) {
|
|
24
|
+
current.path = line.substring('worktree '.length).trim();
|
|
25
|
+
}
|
|
26
|
+
else if (line.startsWith('branch ')) {
|
|
27
|
+
current.branch = line.substring('branch '.length).trim();
|
|
28
|
+
}
|
|
29
|
+
else if (line === 'bare') {
|
|
30
|
+
current.isBare = true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (current && current.path) {
|
|
34
|
+
entries.push(current);
|
|
35
|
+
}
|
|
36
|
+
return entries;
|
|
37
|
+
}
|
|
38
|
+
function detectSourceWorktree(destinationDir) {
|
|
39
|
+
let worktreeOutput;
|
|
40
|
+
try {
|
|
41
|
+
worktreeOutput = git.exec(['worktree', 'list', '--porcelain']);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
throw new Error('Failed to inspect git worktrees automatically. Please specify the source path explicitly.');
|
|
45
|
+
}
|
|
46
|
+
const worktrees = parseWorktreeList(worktreeOutput);
|
|
47
|
+
const destinationResolved = path.resolve(destinationDir);
|
|
48
|
+
const candidates = worktrees.filter((wt) => path.resolve(wt.path) !== destinationResolved);
|
|
49
|
+
if (candidates.length === 0) {
|
|
50
|
+
throw new Error('Unable to detect an alternate worktree to use as the source. Provide the source path explicitly.');
|
|
51
|
+
}
|
|
52
|
+
const preferred = candidates.find((wt) => {
|
|
53
|
+
if (!wt.branch)
|
|
54
|
+
return false;
|
|
55
|
+
const branchName = wt.branch.replace('refs/heads/', '');
|
|
56
|
+
return COMMON_BASE_BRANCHES.includes(branchName);
|
|
57
|
+
});
|
|
58
|
+
return path.resolve((preferred ?? candidates[0]).path);
|
|
59
|
+
}
|
|
60
|
+
function resolveWorktreePaths(argv, currentRoot) {
|
|
61
|
+
const destDir = argv.destination ? path.resolve(argv.destination) : currentRoot;
|
|
62
|
+
const sourceDir = argv.source ? path.resolve(argv.source) : detectSourceWorktree(destDir);
|
|
63
|
+
return { sourceDir, destDir };
|
|
64
|
+
}
|
|
65
|
+
function isIgnored(filePath) {
|
|
66
|
+
return git.isGitIgnored(filePath);
|
|
67
|
+
}
|
|
68
|
+
function isAlreadyLinked(sourcePath, destPath) {
|
|
69
|
+
try {
|
|
70
|
+
if (!fs.existsSync(destPath)) {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
const sourceStats = fs.statSync(sourcePath);
|
|
74
|
+
const destStats = fs.statSync(destPath);
|
|
75
|
+
// Check if they're the same file (hard link) - same inode
|
|
76
|
+
if (sourceStats.ino === destStats.ino && sourceStats.dev === destStats.dev) {
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
// Check if destination is a symlink pointing to source
|
|
80
|
+
const destLstats = fs.lstatSync(destPath);
|
|
81
|
+
if (destLstats.isSymbolicLink()) {
|
|
82
|
+
const linkTarget = fs.readlinkSync(destPath);
|
|
83
|
+
const resolvedTarget = path.resolve(path.dirname(destPath), linkTarget);
|
|
84
|
+
return resolvedTarget === sourcePath;
|
|
85
|
+
}
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function detectConflicts(filesToLink, sourceDir, destDir) {
|
|
93
|
+
const safe = [];
|
|
94
|
+
const alreadyLinked = [];
|
|
95
|
+
const conflicts = [];
|
|
96
|
+
for (const file of filesToLink) {
|
|
97
|
+
const sourcePath = path.join(sourceDir, file);
|
|
98
|
+
const destPath = path.join(destDir, file);
|
|
99
|
+
if (!fs.existsSync(sourcePath)) {
|
|
100
|
+
// Source doesn't exist - skip (will be warned about later)
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (!fs.existsSync(destPath)) {
|
|
104
|
+
// No conflict - safe to link
|
|
105
|
+
safe.push({ file, status: 'safe', sourcePath, destPath });
|
|
106
|
+
}
|
|
107
|
+
else if (isAlreadyLinked(sourcePath, destPath)) {
|
|
108
|
+
// Already correctly linked - skip
|
|
109
|
+
alreadyLinked.push({ file, status: 'already_linked', sourcePath, destPath });
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
// File exists and is different - conflict!
|
|
113
|
+
conflicts.push({ file, status: 'conflict', sourcePath, destPath });
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return { safe, alreadyLinked, conflicts };
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Update manifest file by removing specified files
|
|
120
|
+
*/
|
|
121
|
+
function updateManifest(manifestPath, filesToRemove) {
|
|
122
|
+
const removeSet = new Set(filesToRemove);
|
|
123
|
+
const lines = fs.readFileSync(manifestPath, 'utf-8').split('\n');
|
|
124
|
+
const updatedLines = [];
|
|
125
|
+
for (const line of lines) {
|
|
126
|
+
const trimmed = line.trim();
|
|
127
|
+
// Keep empty lines and top-level comments
|
|
128
|
+
if (!trimmed || (trimmed.startsWith('#') && !trimmed.match(/^#\s*[^#]/))) {
|
|
129
|
+
updatedLines.push(line);
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
// Check if this line is a file we want to remove
|
|
133
|
+
let filePath = trimmed;
|
|
134
|
+
if (trimmed.startsWith('#')) {
|
|
135
|
+
// Extract file path from comment
|
|
136
|
+
const match = trimmed.match(/^#\s*(?:TRACKED:|DELETED:|STALE:)?\s*(.+)/);
|
|
137
|
+
if (match) {
|
|
138
|
+
filePath = match[1].trim();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (!removeSet.has(filePath)) {
|
|
142
|
+
updatedLines.push(line);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
fs.writeFileSync(manifestPath, updatedLines.join('\n'));
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Interactive conflict resolver - lets user decide how to handle each conflict
|
|
149
|
+
* Returns a map of file paths to resolution actions
|
|
150
|
+
*/
|
|
151
|
+
async function interactiveConflictResolver(conflicts, _sourceDir, _destDir) {
|
|
152
|
+
const resolutions = new Map();
|
|
153
|
+
const conflictFiles = conflicts.map((c) => c.file);
|
|
154
|
+
// Build folder structure for conflicts
|
|
155
|
+
const folders = new Set();
|
|
156
|
+
for (const file of conflictFiles) {
|
|
157
|
+
const parts = file.split('/');
|
|
158
|
+
for (let i = 1; i < parts.length; i++) {
|
|
159
|
+
folders.add(parts.slice(0, i).join('/'));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
console.clear();
|
|
163
|
+
console.log(colors.cyan(colors.bold('\n╔═══════════════════════════════════════════════════════════════════════════════════════╗')));
|
|
164
|
+
console.log(colors.cyan(colors.bold('║')) +
|
|
165
|
+
colors.bold(' Conflict Resolution Required ') +
|
|
166
|
+
colors.cyan(colors.bold('║')));
|
|
167
|
+
console.log(colors.cyan(colors.bold('╚═══════════════════════════════════════════════════════════════════════════════════════╝\n')));
|
|
168
|
+
console.log(colors.yellow('The following files exist at the destination with different content:\n'));
|
|
169
|
+
// Show conflicts grouped by folder
|
|
170
|
+
const byFolder = new Map();
|
|
171
|
+
for (const file of conflictFiles) {
|
|
172
|
+
const folder = path.dirname(file);
|
|
173
|
+
if (!byFolder.has(folder)) {
|
|
174
|
+
byFolder.set(folder, []);
|
|
175
|
+
}
|
|
176
|
+
byFolder.get(folder).push(file);
|
|
177
|
+
}
|
|
178
|
+
const sortedFolders = Array.from(byFolder.keys()).sort();
|
|
179
|
+
for (const folder of sortedFolders) {
|
|
180
|
+
const files = byFolder.get(folder);
|
|
181
|
+
if (folder === '.') {
|
|
182
|
+
console.log(colors.dim(' (root)'));
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
console.log(colors.dim(` ${folder}/`));
|
|
186
|
+
}
|
|
187
|
+
for (const file of files) {
|
|
188
|
+
console.log(colors.yellow(` - ${path.basename(file)}`));
|
|
189
|
+
}
|
|
190
|
+
console.log('');
|
|
191
|
+
}
|
|
192
|
+
console.log(colors.bold('Resolution Options:'));
|
|
193
|
+
console.log(colors.green(' R') + ' - Replace destination file (delete existing, create link)');
|
|
194
|
+
console.log(colors.blue(' I') + " - Ignore (keep destination file as-is, don't link)");
|
|
195
|
+
console.log(colors.red(' M') + " - Remove from manifest (won't link now or in future)");
|
|
196
|
+
console.log('');
|
|
197
|
+
console.log(colors.dim("Note: Setting a folder's resolution applies ONLY to conflicted files in that folder.\n"));
|
|
198
|
+
const answers = await inquirer.prompt([
|
|
199
|
+
{
|
|
200
|
+
type: 'list',
|
|
201
|
+
name: 'action',
|
|
202
|
+
message: 'How do you want to resolve these conflicts?',
|
|
203
|
+
choices: [
|
|
204
|
+
{
|
|
205
|
+
name: 'Resolve all conflicts the same way',
|
|
206
|
+
value: 'bulk',
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
name: 'Resolve each conflict individually',
|
|
210
|
+
value: 'individual',
|
|
211
|
+
},
|
|
212
|
+
],
|
|
213
|
+
},
|
|
214
|
+
]);
|
|
215
|
+
if (answers.action === 'bulk') {
|
|
216
|
+
const bulkAnswers = await inquirer.prompt([
|
|
217
|
+
{
|
|
218
|
+
type: 'list',
|
|
219
|
+
name: 'resolution',
|
|
220
|
+
message: `Apply this resolution to all ${conflictFiles.length} conflicting files:`,
|
|
221
|
+
choices: [
|
|
222
|
+
{ name: 'Replace all (overwrite destination files)', value: 'replace' },
|
|
223
|
+
{ name: 'Ignore all (keep destination files)', value: 'ignore' },
|
|
224
|
+
{ name: 'Remove all from manifest', value: 'remove' },
|
|
225
|
+
],
|
|
226
|
+
},
|
|
227
|
+
]);
|
|
228
|
+
for (const file of conflictFiles) {
|
|
229
|
+
resolutions.set(file, bulkAnswers.resolution);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
// Individual resolution
|
|
234
|
+
for (const conflict of conflicts) {
|
|
235
|
+
const fileAnswers = await inquirer.prompt([
|
|
236
|
+
{
|
|
237
|
+
type: 'list',
|
|
238
|
+
name: 'resolution',
|
|
239
|
+
message: `${conflict.file}:`,
|
|
240
|
+
choices: [
|
|
241
|
+
{ name: 'Replace (overwrite destination)', value: 'replace' },
|
|
242
|
+
{ name: 'Ignore (keep destination)', value: 'ignore' },
|
|
243
|
+
{ name: 'Remove from manifest', value: 'remove' },
|
|
244
|
+
],
|
|
245
|
+
},
|
|
246
|
+
]);
|
|
247
|
+
resolutions.set(conflict.file, fileAnswers.resolution);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return resolutions;
|
|
251
|
+
}
|
|
252
|
+
export async function run(argv) {
|
|
253
|
+
if (!git.checkGitInstalled()) {
|
|
254
|
+
throw new Error('Git is not installed or not found in your PATH. This tool requires Git.');
|
|
255
|
+
}
|
|
256
|
+
const gitRoot = git.getRepoRoot(); // Current worktree root
|
|
257
|
+
const mainWorktreeRoot = git.getMainWorktreeRoot(); // Main worktree root (for manifest location)
|
|
258
|
+
const manifestFile = argv.manifestFile;
|
|
259
|
+
const manifestPath = path.join(mainWorktreeRoot, manifestFile);
|
|
260
|
+
const { sourceDir, destDir } = resolveWorktreePaths(argv, gitRoot);
|
|
261
|
+
if (!fs.existsSync(manifestPath)) {
|
|
262
|
+
throw new Error(`Manifest file not found at ${manifestPath}`);
|
|
263
|
+
}
|
|
264
|
+
if (!fs.existsSync(sourceDir) || !fs.statSync(sourceDir).isDirectory()) {
|
|
265
|
+
throw new Error(`Source directory does not exist or is not a directory: ${sourceDir}`);
|
|
266
|
+
}
|
|
267
|
+
if (!fs.existsSync(destDir) || !fs.statSync(destDir).isDirectory()) {
|
|
268
|
+
throw new Error(`Destination directory does not exist or is not a directory: ${destDir}`);
|
|
269
|
+
}
|
|
270
|
+
const filesToLink = fs
|
|
271
|
+
.readFileSync(manifestPath, 'utf-8')
|
|
272
|
+
.split('\n')
|
|
273
|
+
.map((line) => line.trim())
|
|
274
|
+
.filter((line) => line && !line.startsWith('#'));
|
|
275
|
+
if (filesToLink.length === 0) {
|
|
276
|
+
console.log(colors.yellow('Manifest is empty. Nothing to link.'));
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
console.log(`\nDetecting conflicts...`);
|
|
280
|
+
// Detect conflicts BEFORE any linking
|
|
281
|
+
const conflictReport = detectConflicts(filesToLink, sourceDir, destDir);
|
|
282
|
+
console.log(colors.green(`✓ Scanned ${filesToLink.length} files`));
|
|
283
|
+
// Handle conflicts interactively (if any)
|
|
284
|
+
const resolutions = new Map();
|
|
285
|
+
const filesToRemoveFromManifest = [];
|
|
286
|
+
if (conflictReport.conflicts.length > 0 && !argv.yes && !argv.dryRun) {
|
|
287
|
+
console.log(colors.yellow(`\n⚠️ Found ${conflictReport.conflicts.length} conflicting files\n`));
|
|
288
|
+
console.log(colors.dim('Launching interactive conflict resolver...\n'));
|
|
289
|
+
const resolverResult = await interactiveConflictResolver(conflictReport.conflicts, sourceDir, destDir);
|
|
290
|
+
for (const [file, resolution] of resolverResult.entries()) {
|
|
291
|
+
resolutions.set(file, resolution);
|
|
292
|
+
if (resolution === 'remove') {
|
|
293
|
+
filesToRemoveFromManifest.push(file);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
// Build final lists of files to process
|
|
298
|
+
const safeFiles = conflictReport.safe.map((s) => s.file);
|
|
299
|
+
const replaceFiles = [];
|
|
300
|
+
const ignoreFiles = [];
|
|
301
|
+
for (const conflictFile of conflictReport.conflicts.map((c) => c.file)) {
|
|
302
|
+
const resolution = resolutions.get(conflictFile);
|
|
303
|
+
if (resolution === 'replace' || (argv.yes && !argv.dryRun)) {
|
|
304
|
+
replaceFiles.push(conflictFile);
|
|
305
|
+
}
|
|
306
|
+
else if (resolution === 'ignore') {
|
|
307
|
+
ignoreFiles.push(conflictFile);
|
|
308
|
+
}
|
|
309
|
+
// resolution === 'remove' already added to filesToRemoveFromManifest
|
|
310
|
+
}
|
|
311
|
+
const totalToLink = safeFiles.length + replaceFiles.length;
|
|
312
|
+
// Show final confirmation prompt with summary
|
|
313
|
+
if (!argv.yes && !argv.dryRun) {
|
|
314
|
+
console.log(colors.cyan(colors.bold('\n═══════════════════════════════════════')));
|
|
315
|
+
console.log(colors.cyan(colors.bold(' Conflict Resolution Complete!')));
|
|
316
|
+
console.log(colors.cyan(colors.bold('═══════════════════════════════════════\n')));
|
|
317
|
+
console.log(colors.bold('Summary:'));
|
|
318
|
+
if (conflictReport.alreadyLinked.length > 0) {
|
|
319
|
+
console.log(colors.dim(` ✓ Already linked: ${conflictReport.alreadyLinked.length} files (will skip)`));
|
|
320
|
+
}
|
|
321
|
+
if (replaceFiles.length > 0) {
|
|
322
|
+
console.log(colors.yellow(` ⚠ Replace: ${replaceFiles.length} files (will overwrite and link)`));
|
|
323
|
+
}
|
|
324
|
+
if (ignoreFiles.length > 0) {
|
|
325
|
+
console.log(colors.blue(` ℹ Ignore: ${ignoreFiles.length} files (will skip, keep destination)`));
|
|
326
|
+
}
|
|
327
|
+
if (filesToRemoveFromManifest.length > 0) {
|
|
328
|
+
console.log(colors.red(` ✗ Remove: ${filesToRemoveFromManifest.length} files (removed from manifest)`));
|
|
329
|
+
}
|
|
330
|
+
if (safeFiles.length > 0) {
|
|
331
|
+
console.log(colors.green(` ✓ Safe: ${safeFiles.length} files (no conflict)`));
|
|
332
|
+
}
|
|
333
|
+
console.log('');
|
|
334
|
+
console.log(colors.dim(' From: ') + colors.bold(sourceDir));
|
|
335
|
+
console.log(colors.dim(' To: ') + colors.bold(destDir));
|
|
336
|
+
console.log(colors.dim(' Type: ') +
|
|
337
|
+
colors.bold(argv.type === 'symbolic' ? 'symbolic links' : 'hard links'));
|
|
338
|
+
console.log('');
|
|
339
|
+
let message = `Proceed with linking ${totalToLink} files?`;
|
|
340
|
+
if (replaceFiles.length > 0) {
|
|
341
|
+
message += colors.yellow(` (${replaceFiles.length} will overwrite existing files)`);
|
|
342
|
+
}
|
|
343
|
+
const confirmAnswers = await inquirer.prompt([
|
|
344
|
+
{
|
|
345
|
+
type: 'confirm',
|
|
346
|
+
name: 'proceed',
|
|
347
|
+
message,
|
|
348
|
+
default: false,
|
|
349
|
+
},
|
|
350
|
+
]);
|
|
351
|
+
if (!confirmAnswers.proceed) {
|
|
352
|
+
console.log(colors.yellow('Operation cancelled.'));
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
console.log('');
|
|
356
|
+
}
|
|
357
|
+
// Update manifest if files were removed
|
|
358
|
+
if (filesToRemoveFromManifest.length > 0) {
|
|
359
|
+
updateManifest(manifestPath, filesToRemoveFromManifest);
|
|
360
|
+
console.log(colors.red(`Updated manifest: removed ${filesToRemoveFromManifest.length} files\n`));
|
|
361
|
+
}
|
|
362
|
+
let linkedCount = 0;
|
|
363
|
+
let errorCount = 0;
|
|
364
|
+
for (const file of filesToLink) {
|
|
365
|
+
const sourcePath = path.join(sourceDir, file);
|
|
366
|
+
const destPath = path.join(destDir, file);
|
|
367
|
+
if (!fs.existsSync(sourcePath)) {
|
|
368
|
+
console.warn(colors.yellow(` - WARNING: Source file not found, skipping: ${sourcePath}`));
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
371
|
+
// CRITICAL SAFETY CHECK: Do not link files that are not git-ignored.
|
|
372
|
+
if (!isIgnored(sourcePath)) {
|
|
373
|
+
console.error(colors.red(colors.bold(` - DANGER: File is not ignored by git, skipping for safety: ${file}`)));
|
|
374
|
+
errorCount++;
|
|
375
|
+
continue;
|
|
376
|
+
}
|
|
377
|
+
if (argv.dryRun) {
|
|
378
|
+
console.log(colors.cyan(` - [DRY RUN] Would link: ${sourcePath} -> ${destPath}`));
|
|
379
|
+
linkedCount++;
|
|
380
|
+
continue;
|
|
381
|
+
}
|
|
382
|
+
try {
|
|
383
|
+
// Ensure the destination directory exists
|
|
384
|
+
fs.mkdirSync(path.dirname(destPath), { recursive: true });
|
|
385
|
+
// If a file already exists at the destination, remove it before linking.
|
|
386
|
+
if (fs.existsSync(destPath)) {
|
|
387
|
+
fs.unlinkSync(destPath);
|
|
388
|
+
}
|
|
389
|
+
if (argv.type === 'symbolic') {
|
|
390
|
+
fs.symlinkSync(sourcePath, destPath);
|
|
391
|
+
console.log(colors.green(` - Symlinked: ${file}`));
|
|
392
|
+
}
|
|
393
|
+
else {
|
|
394
|
+
fs.linkSync(sourcePath, destPath);
|
|
395
|
+
console.log(colors.green(` - Hard-linked: ${file}`));
|
|
396
|
+
}
|
|
397
|
+
linkedCount++;
|
|
398
|
+
}
|
|
399
|
+
catch (error) {
|
|
400
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
401
|
+
console.error(colors.red(` - ERROR linking ${file}: ${errorMessage}`));
|
|
402
|
+
errorCount++;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
console.log('\n-------------------');
|
|
406
|
+
console.log(colors.green(colors.bold(`Link process complete. Linked ${linkedCount} files.`)));
|
|
407
|
+
if (errorCount > 0) {
|
|
408
|
+
console.log(colors.red(colors.bold(`Encountered ${errorCount} errors.`)));
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
//# sourceMappingURL=link-configs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"link-configs.js","sourceRoot":"","sources":["../../../src/lib/wtlink/link-configs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"link-configs.test.d.ts","sourceRoot":"","sources":["../../../src/lib/wtlink/link-configs.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,179 @@
|
|
|
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
|
|
4
|
+
describe('wtlink/link-configs', () => {
|
|
5
|
+
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
|
+
it('should parse empty worktree list', () => {
|
|
11
|
+
const raw = '';
|
|
12
|
+
const entries = parseWorktreeListHelper(raw);
|
|
13
|
+
expect(entries).toEqual([]);
|
|
14
|
+
});
|
|
15
|
+
it('should parse single worktree entry', () => {
|
|
16
|
+
const raw = `worktree /home/user/project
|
|
17
|
+
HEAD abc123
|
|
18
|
+
branch refs/heads/main
|
|
19
|
+
|
|
20
|
+
`;
|
|
21
|
+
const entries = parseWorktreeListHelper(raw);
|
|
22
|
+
expect(entries).toHaveLength(1);
|
|
23
|
+
expect(entries[0]).toEqual({
|
|
24
|
+
path: '/home/user/project',
|
|
25
|
+
branch: 'refs/heads/main',
|
|
26
|
+
isBare: false,
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
it('should parse multiple worktree entries', () => {
|
|
30
|
+
const raw = `worktree /home/user/project
|
|
31
|
+
HEAD abc123
|
|
32
|
+
branch refs/heads/main
|
|
33
|
+
|
|
34
|
+
worktree /home/user/project.pr42
|
|
35
|
+
HEAD def456
|
|
36
|
+
branch refs/heads/feature/auth
|
|
37
|
+
|
|
38
|
+
`;
|
|
39
|
+
const entries = parseWorktreeListHelper(raw);
|
|
40
|
+
expect(entries).toHaveLength(2);
|
|
41
|
+
expect(entries[0].path).toBe('/home/user/project');
|
|
42
|
+
expect(entries[0].branch).toBe('refs/heads/main');
|
|
43
|
+
expect(entries[1].path).toBe('/home/user/project.pr42');
|
|
44
|
+
expect(entries[1].branch).toBe('refs/heads/feature/auth');
|
|
45
|
+
});
|
|
46
|
+
it('should parse bare worktree entry', () => {
|
|
47
|
+
const raw = `worktree /home/user/project.git
|
|
48
|
+
bare
|
|
49
|
+
|
|
50
|
+
`;
|
|
51
|
+
const entries = parseWorktreeListHelper(raw);
|
|
52
|
+
expect(entries).toHaveLength(1);
|
|
53
|
+
expect(entries[0].isBare).toBe(true);
|
|
54
|
+
});
|
|
55
|
+
it('should handle worktree without branch (detached HEAD)', () => {
|
|
56
|
+
const raw = `worktree /home/user/project
|
|
57
|
+
HEAD abc123
|
|
58
|
+
detached
|
|
59
|
+
|
|
60
|
+
`;
|
|
61
|
+
const entries = parseWorktreeListHelper(raw);
|
|
62
|
+
expect(entries).toHaveLength(1);
|
|
63
|
+
expect(entries[0].branch).toBeUndefined();
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
describe('manifest parsing', () => {
|
|
67
|
+
it('should parse active entries', () => {
|
|
68
|
+
const manifest = `.env
|
|
69
|
+
.vscode/settings.json
|
|
70
|
+
config/local.json`;
|
|
71
|
+
const entries = parseManifestHelper(manifest);
|
|
72
|
+
expect(entries.active).toEqual(['.env', '.vscode/settings.json', 'config/local.json']);
|
|
73
|
+
expect(entries.commented).toEqual([]);
|
|
74
|
+
});
|
|
75
|
+
it('should parse commented entries', () => {
|
|
76
|
+
const manifest = `# .env.local
|
|
77
|
+
# .vscode/launch.json`;
|
|
78
|
+
const entries = parseManifestHelper(manifest);
|
|
79
|
+
expect(entries.active).toEqual([]);
|
|
80
|
+
expect(entries.commented).toEqual(['.env.local', '.vscode/launch.json']);
|
|
81
|
+
});
|
|
82
|
+
it('should handle mixed entries', () => {
|
|
83
|
+
const manifest = `.env
|
|
84
|
+
# .env.local
|
|
85
|
+
.vscode/settings.json
|
|
86
|
+
# .vscode/launch.json
|
|
87
|
+
`;
|
|
88
|
+
const entries = parseManifestHelper(manifest);
|
|
89
|
+
expect(entries.active).toEqual(['.env', '.vscode/settings.json']);
|
|
90
|
+
expect(entries.commented).toEqual(['.env.local', '.vscode/launch.json']);
|
|
91
|
+
});
|
|
92
|
+
it('should skip blank lines', () => {
|
|
93
|
+
const manifest = `.env
|
|
94
|
+
|
|
95
|
+
.vscode/settings.json
|
|
96
|
+
|
|
97
|
+
`;
|
|
98
|
+
const entries = parseManifestHelper(manifest);
|
|
99
|
+
expect(entries.active).toEqual(['.env', '.vscode/settings.json']);
|
|
100
|
+
});
|
|
101
|
+
it('should handle header comments (multiple #)', () => {
|
|
102
|
+
const manifest = `## Configuration Files
|
|
103
|
+
# This is a comment about the manifest
|
|
104
|
+
.env
|
|
105
|
+
# .env.local`;
|
|
106
|
+
const entries = parseManifestHelper(manifest);
|
|
107
|
+
// Lines starting with ## are header comments, not file entries
|
|
108
|
+
expect(entries.active).toEqual(['.env']);
|
|
109
|
+
expect(entries.commented).toEqual(['.env.local']);
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
});
|
|
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
|
+
//# sourceMappingURL=link-configs.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"link-configs.test.js","sourceRoot":"","sources":["../../../src/lib/wtlink/link-configs.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main-menu.d.ts","sourceRoot":"","sources":["../../../src/lib/wtlink/main-menu.ts"],"names":[],"mappings":"AAOA,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CA8ElD"}
|