@docupace/pipeline 1.0.61-alpha.1 → 1.0.62
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/bitbucket-pipelines.yml +28 -0
- package/eslint.config.js +12 -0
- package/package.json +11 -8
- package/src/auth0/configure.js +88 -54
- package/src/changeset/cli.js +0 -46
- package/src/changeset/create.js +5 -15
- package/src/changeset/package-util.js +1 -2
- package/src/changeset/util.js +6 -6
- package/src/changeset/validate.js +24 -23
- package/src/micro/deploy-microservice.js +140 -0
- package/src/micro/publish-ms.js +188 -0
- package/src/next/apache.js +2 -2
- package/src/next/cli.js +9 -1
- package/src/next/connect.js +1 -2
- package/src/changeset/changelog-wiki.js +0 -313
- package/src/lib/merge-driver.js +0 -204
- package/src/merge/cli-merge-all.js +0 -472
- package/src/merge/cli-merge.js +0 -492
- package/src/merge/cli-resolve.js +0 -395
- package/src/merge/cli.js +0 -38
- package/src/merge/merge-changelog.js +0 -87
- package/src/merge/merge-package.js +0 -106
- package/src/merge/merge-types.js +0 -82
- package/src/merge/pr.js +0 -85
package/src/merge/cli-resolve.js
DELETED
|
@@ -1,395 +0,0 @@
|
|
|
1
|
-
import { mergeChangelogFile } from './merge-changelog.js';
|
|
2
|
-
import mergeTypes, { mergeTypesFile } from './merge-types.js';
|
|
3
|
-
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
|
4
|
-
import mergePackageFile from './merge-package.js';
|
|
5
|
-
import { execSync } from 'child_process';
|
|
6
|
-
|
|
7
|
-
// Default merge configuration
|
|
8
|
-
const defaultMergeConfig = {
|
|
9
|
-
'CHANGELOG.md': 'changelog',
|
|
10
|
-
'*/CHANGELOG.md': 'changelog',
|
|
11
|
-
'**/CHANGELOG.md': 'changelog',
|
|
12
|
-
'src/types/graphql.ts': 'types',
|
|
13
|
-
'codegen.ts': 'ours',
|
|
14
|
-
'package.json': 'package',
|
|
15
|
-
'*/package.json': 'package',
|
|
16
|
-
'**/package.json': 'package',
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
// Available merge strategies
|
|
20
|
-
const mergeStrategies = {
|
|
21
|
-
changelog: mergeChangelogFile,
|
|
22
|
-
package: mergePackageFile,
|
|
23
|
-
types: mergeTypesFile,
|
|
24
|
-
ours: (filePath) => {
|
|
25
|
-
// Keep our version by checking out the HEAD version (removes conflicts)
|
|
26
|
-
try {
|
|
27
|
-
execSync(`git checkout --ours ${filePath}`);
|
|
28
|
-
execSync(`git add ${filePath}`);
|
|
29
|
-
console.log(
|
|
30
|
-
`📝 Using 'ours' strategy for ${filePath} - reset to HEAD version and marked as resolved`,
|
|
31
|
-
);
|
|
32
|
-
return true;
|
|
33
|
-
} catch (error) {
|
|
34
|
-
throw new Error(`Failed to apply 'ours' strategy: ${error.message}`);
|
|
35
|
-
}
|
|
36
|
-
},
|
|
37
|
-
theirs: (filePath) => {
|
|
38
|
-
// Take their version
|
|
39
|
-
try {
|
|
40
|
-
execSync(`git checkout --theirs ${filePath}`);
|
|
41
|
-
execSync(`git add ${filePath}`);
|
|
42
|
-
console.log(
|
|
43
|
-
`📝 Using 'theirs' strategy for ${filePath} - marked as resolved`,
|
|
44
|
-
);
|
|
45
|
-
return true;
|
|
46
|
-
} catch (error) {
|
|
47
|
-
throw new Error(`Failed to apply 'theirs' strategy: ${error.message}`);
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Get list of conflicted files from git status
|
|
54
|
-
*/
|
|
55
|
-
function getConflictedFiles() {
|
|
56
|
-
try {
|
|
57
|
-
const statusOutput = execSync('git status --porcelain', {
|
|
58
|
-
encoding: 'utf-8',
|
|
59
|
-
});
|
|
60
|
-
const conflictedFiles = statusOutput
|
|
61
|
-
.split('\n')
|
|
62
|
-
.filter(
|
|
63
|
-
(line) =>
|
|
64
|
-
line.startsWith('UU ') ||
|
|
65
|
-
line.startsWith('AA ') ||
|
|
66
|
-
line.startsWith('DD '),
|
|
67
|
-
)
|
|
68
|
-
.map((line) => line.substring(3).trim())
|
|
69
|
-
.filter((file) => file.length > 0);
|
|
70
|
-
return conflictedFiles;
|
|
71
|
-
} catch (error) {
|
|
72
|
-
throw new Error(`Failed to get git status: ${error.message}`);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Load merge configuration from .mergerc file or use defaults
|
|
78
|
-
*/
|
|
79
|
-
function loadMergeConfig() {
|
|
80
|
-
const configPath = '.mergerc';
|
|
81
|
-
|
|
82
|
-
if (existsSync(configPath)) {
|
|
83
|
-
try {
|
|
84
|
-
const configContent = readFileSync(configPath, 'utf-8');
|
|
85
|
-
const config = {};
|
|
86
|
-
|
|
87
|
-
configContent.split('\n').forEach((line) => {
|
|
88
|
-
line = line.trim();
|
|
89
|
-
if (line && !line.startsWith('#')) {
|
|
90
|
-
const [pattern, strategy] = line
|
|
91
|
-
.split(/\s+merge=/)
|
|
92
|
-
.map((s) => s.trim());
|
|
93
|
-
if (pattern && strategy) {
|
|
94
|
-
config[pattern] = strategy;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
return config;
|
|
100
|
-
} catch (error) {
|
|
101
|
-
console.warn(
|
|
102
|
-
`Warning: Could not read ${configPath}, using defaults: ${error.message}`,
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return defaultMergeConfig;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Match file path against patterns (supports * and ** wildcards)
|
|
112
|
-
*/
|
|
113
|
-
function matchPattern(filePath, pattern) {
|
|
114
|
-
// Handle ** at the beginning of pattern
|
|
115
|
-
if (pattern.startsWith('**/')) {
|
|
116
|
-
// Remove the **/ and check if the path ends with the remaining pattern
|
|
117
|
-
const remainingPattern = pattern.slice(3);
|
|
118
|
-
const regexPattern = remainingPattern
|
|
119
|
-
.replace(/\*/g, '[^/]*')
|
|
120
|
-
.replace(/\./g, '\\.')
|
|
121
|
-
.replace(/\//g, '\\/');
|
|
122
|
-
|
|
123
|
-
const regex = new RegExp(`(^|/)${regexPattern}$`);
|
|
124
|
-
return regex.test(filePath);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// For other cases, convert pattern to regex
|
|
128
|
-
const regexPattern = pattern
|
|
129
|
-
.replace(/\*\*/g, '___DOUBLESTAR___')
|
|
130
|
-
.replace(/\*/g, '[^/]*')
|
|
131
|
-
.replace(/___DOUBLESTAR___/g, '.*?')
|
|
132
|
-
.replace(/\./g, '\\.')
|
|
133
|
-
.replace(/\//g, '\\/');
|
|
134
|
-
|
|
135
|
-
const regex = new RegExp(`^${regexPattern}$`);
|
|
136
|
-
return regex.test(filePath);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Find merge strategy for a given file
|
|
141
|
-
*/
|
|
142
|
-
function findMergeStrategy(filePath, config) {
|
|
143
|
-
// Check exact match first
|
|
144
|
-
if (config[filePath]) {
|
|
145
|
-
return config[filePath];
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// Check pattern matches
|
|
149
|
-
for (const [pattern, strategy] of Object.entries(config)) {
|
|
150
|
-
if (matchPattern(filePath, pattern)) {
|
|
151
|
-
return strategy;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
return null;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Create default .mergerc file
|
|
160
|
-
*/
|
|
161
|
-
function createDefaultConfig() {
|
|
162
|
-
const configContent = `# Merge configuration file
|
|
163
|
-
# Format: <file-pattern> merge=<strategy>
|
|
164
|
-
# Strategies: changelog, package, types, ours, theirs
|
|
165
|
-
|
|
166
|
-
CHANGELOG.md merge=changelog
|
|
167
|
-
*/CHANGELOG.md merge=changelog
|
|
168
|
-
**/CHANGELOG.md merge=changelog
|
|
169
|
-
src/types/graphql.ts merge=types
|
|
170
|
-
codegen.ts merge=ours
|
|
171
|
-
package.json merge=package
|
|
172
|
-
*/package.json merge=package
|
|
173
|
-
**/package.json merge=package
|
|
174
|
-
`;
|
|
175
|
-
|
|
176
|
-
writeFileSync('.mergerc', configContent);
|
|
177
|
-
console.log('✅ Created default .mergerc configuration file');
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
export async function autoResolveConflicts(options = {}) {
|
|
181
|
-
const { dryRun = false, verbose = false } = options;
|
|
182
|
-
|
|
183
|
-
// Get conflicted files
|
|
184
|
-
const conflictedFiles = getConflictedFiles();
|
|
185
|
-
|
|
186
|
-
if (conflictedFiles.length === 0) {
|
|
187
|
-
if (verbose) console.log('✅ No conflicted files found');
|
|
188
|
-
return { success: true, resolvedCount: 0, skippedCount: 0, totalCount: 0 };
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
if (verbose) {
|
|
192
|
-
console.log(`Found ${conflictedFiles.length} conflicted files:`);
|
|
193
|
-
conflictedFiles.forEach((file) => console.log(` - ${file}`));
|
|
194
|
-
console.log('');
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
// Load configuration
|
|
198
|
-
const config = loadMergeConfig();
|
|
199
|
-
|
|
200
|
-
if (verbose) {
|
|
201
|
-
console.log('Merge configuration:');
|
|
202
|
-
Object.entries(config).forEach(([pattern, strategy]) => {
|
|
203
|
-
console.log(` ${pattern} -> ${strategy}`);
|
|
204
|
-
});
|
|
205
|
-
console.log('');
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
let resolvedCount = 0;
|
|
209
|
-
let skippedCount = 0;
|
|
210
|
-
|
|
211
|
-
// Process each conflicted file
|
|
212
|
-
for (const filePath of conflictedFiles) {
|
|
213
|
-
const strategy = findMergeStrategy(filePath, config);
|
|
214
|
-
|
|
215
|
-
if (!strategy) {
|
|
216
|
-
if (verbose)
|
|
217
|
-
console.log(`⚠️ No strategy found for ${filePath} - skipping`);
|
|
218
|
-
skippedCount++;
|
|
219
|
-
continue;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
const mergeFunction = mergeStrategies[strategy];
|
|
223
|
-
if (!mergeFunction) {
|
|
224
|
-
if (verbose)
|
|
225
|
-
console.log(
|
|
226
|
-
`⚠️ Unknown strategy '${strategy}' for ${filePath} - skipping`,
|
|
227
|
-
);
|
|
228
|
-
skippedCount++;
|
|
229
|
-
continue;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
if (dryRun) {
|
|
233
|
-
if (verbose)
|
|
234
|
-
console.log(`Would apply '${strategy}' strategy to ${filePath}`);
|
|
235
|
-
continue;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
try {
|
|
239
|
-
if (verbose)
|
|
240
|
-
console.log(`🔧 Applying '${strategy}' strategy to ${filePath}`);
|
|
241
|
-
mergeFunction(filePath);
|
|
242
|
-
resolvedCount++;
|
|
243
|
-
} catch (error) {
|
|
244
|
-
console.error(`❌ Failed to resolve ${filePath}: ${error.message}`);
|
|
245
|
-
skippedCount++;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
const result = {
|
|
250
|
-
success: skippedCount === 0,
|
|
251
|
-
resolvedCount,
|
|
252
|
-
skippedCount,
|
|
253
|
-
totalCount: conflictedFiles.length,
|
|
254
|
-
};
|
|
255
|
-
|
|
256
|
-
// Summary
|
|
257
|
-
if (verbose) {
|
|
258
|
-
console.log(`\n📊 Summary:`);
|
|
259
|
-
console.log(` Resolved: ${resolvedCount}`);
|
|
260
|
-
console.log(` Skipped: ${skippedCount}`);
|
|
261
|
-
console.log(` Total: ${conflictedFiles.length}`);
|
|
262
|
-
|
|
263
|
-
if (resolvedCount > 0 && !dryRun) {
|
|
264
|
-
console.log(`\n✅ Successfully resolved ${resolvedCount} conflicts`);
|
|
265
|
-
if (skippedCount === 0) {
|
|
266
|
-
console.log(
|
|
267
|
-
'🎉 All conflicts resolved! You can now commit the changes.',
|
|
268
|
-
);
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
return result;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
export function setupResolve(program) {
|
|
277
|
-
program
|
|
278
|
-
.command('resolve-conflicts')
|
|
279
|
-
.description('Automatically resolve conflicts based on configuration')
|
|
280
|
-
.option(
|
|
281
|
-
'-c, --config <path>',
|
|
282
|
-
'Path to merge configuration file',
|
|
283
|
-
'.mergerc',
|
|
284
|
-
)
|
|
285
|
-
.option('-n, --dry-run', 'Show what would be done without making changes')
|
|
286
|
-
.option('-v, --verbose', 'Verbose output')
|
|
287
|
-
.action(async (options) => {
|
|
288
|
-
try {
|
|
289
|
-
const result = await autoResolveConflicts(options);
|
|
290
|
-
|
|
291
|
-
if (!result.success) {
|
|
292
|
-
console.error(
|
|
293
|
-
`❌ Auto-resolve failed: ${result.skippedCount} files could not be resolved`,
|
|
294
|
-
);
|
|
295
|
-
process.exit(1);
|
|
296
|
-
}
|
|
297
|
-
} catch (error) {
|
|
298
|
-
console.error(`❌ Auto-resolve failed: ${error.message}`);
|
|
299
|
-
process.exit(1);
|
|
300
|
-
}
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
// New merge command
|
|
304
|
-
|
|
305
|
-
// Individual strategy commands
|
|
306
|
-
program
|
|
307
|
-
.command('resolve-changelog-conflicts')
|
|
308
|
-
.description('Merge changelog files by removing conflict markers')
|
|
309
|
-
.argument('<file>', 'File with merge conflicts')
|
|
310
|
-
.action(async (file) => {
|
|
311
|
-
try {
|
|
312
|
-
mergeChangelogFile(file);
|
|
313
|
-
console.log('✅ Changelog merge completed successfully');
|
|
314
|
-
} catch (error) {
|
|
315
|
-
console.error(`❌ Changelog merge failed: ${error.message}`);
|
|
316
|
-
process.exit(1);
|
|
317
|
-
}
|
|
318
|
-
});
|
|
319
|
-
|
|
320
|
-
program
|
|
321
|
-
.command('resolve-package-conflicts')
|
|
322
|
-
.description('Merge package.json files by resolving version conflicts')
|
|
323
|
-
.argument('<file>', 'File with merge conflicts')
|
|
324
|
-
.action(async (file) => {
|
|
325
|
-
try {
|
|
326
|
-
await mergePackageFile(file);
|
|
327
|
-
console.log('✅ Package merge completed successfully');
|
|
328
|
-
} catch (error) {
|
|
329
|
-
console.error(`❌ Package merge failed: ${error.message}`);
|
|
330
|
-
process.exit(1);
|
|
331
|
-
}
|
|
332
|
-
});
|
|
333
|
-
|
|
334
|
-
program
|
|
335
|
-
.command('resolve-type-conflicts')
|
|
336
|
-
.description('Merge types files with balanced brace checking')
|
|
337
|
-
.argument('<file>', 'File with merge conflicts')
|
|
338
|
-
.action(async (file) => {
|
|
339
|
-
try {
|
|
340
|
-
await mergeTypes(file);
|
|
341
|
-
console.log('✅ Types merge completed successfully');
|
|
342
|
-
} catch (error) {
|
|
343
|
-
console.error(`❌ Types merge failed: ${error.message}`);
|
|
344
|
-
process.exit(1);
|
|
345
|
-
}
|
|
346
|
-
});
|
|
347
|
-
|
|
348
|
-
// Configuration commands
|
|
349
|
-
program
|
|
350
|
-
.command('init')
|
|
351
|
-
.description('Create default .mergerc configuration file')
|
|
352
|
-
.action(() => {
|
|
353
|
-
if (existsSync('.mergerc')) {
|
|
354
|
-
console.log('⚠️ .mergerc already exists. Use --force to overwrite.');
|
|
355
|
-
return;
|
|
356
|
-
}
|
|
357
|
-
createDefaultConfig();
|
|
358
|
-
});
|
|
359
|
-
|
|
360
|
-
program
|
|
361
|
-
.command('config')
|
|
362
|
-
.description('Show current merge configuration')
|
|
363
|
-
.action(() => {
|
|
364
|
-
const config = loadMergeConfig();
|
|
365
|
-
console.log('Current merge configuration:');
|
|
366
|
-
Object.entries(config).forEach(([pattern, strategy]) => {
|
|
367
|
-
console.log(` ${pattern.padEnd(30)} -> ${strategy}`);
|
|
368
|
-
});
|
|
369
|
-
});
|
|
370
|
-
|
|
371
|
-
program
|
|
372
|
-
.command('status')
|
|
373
|
-
.description('Show conflicted files and their assigned strategies')
|
|
374
|
-
.action(() => {
|
|
375
|
-
try {
|
|
376
|
-
const conflictedFiles = getConflictedFiles();
|
|
377
|
-
const config = loadMergeConfig();
|
|
378
|
-
|
|
379
|
-
if (conflictedFiles.length === 0) {
|
|
380
|
-
console.log('✅ No conflicted files found');
|
|
381
|
-
return;
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
console.log('Conflicted files and their strategies:');
|
|
385
|
-
conflictedFiles.forEach((file) => {
|
|
386
|
-
const strategy = findMergeStrategy(file, config);
|
|
387
|
-
const status = strategy ? `-> ${strategy}` : '-> no strategy';
|
|
388
|
-
console.log(` ${file.padEnd(40)} ${status}`);
|
|
389
|
-
});
|
|
390
|
-
} catch (error) {
|
|
391
|
-
console.error(`❌ Failed to get status: ${error.message}`);
|
|
392
|
-
process.exit(1);
|
|
393
|
-
}
|
|
394
|
-
});
|
|
395
|
-
}
|
package/src/merge/cli.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import dotenv from 'dotenv';
|
|
3
|
-
dotenv.config({ path: ['.env.pipeline.local', 'config/.env.pipeline.local'] });
|
|
4
|
-
|
|
5
|
-
import { Command } from 'commander';
|
|
6
|
-
import { setupMerge } from './cli-merge.js';
|
|
7
|
-
import { setupResolve } from './cli-resolve.js';
|
|
8
|
-
import { setupMergeAll } from './cli-merge-all.js';
|
|
9
|
-
|
|
10
|
-
const args = process.argv;
|
|
11
|
-
const program = new Command();
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Reusable auto-resolve function
|
|
15
|
-
* @param {Object} options - Options object with config, dryRun, verbose properties
|
|
16
|
-
* @returns {Object} - Result object with counts and success status
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
// Main program
|
|
20
|
-
program
|
|
21
|
-
.name('merge-cli')
|
|
22
|
-
.description(
|
|
23
|
-
'Automatically resolve git merge conflicts based on file patterns',
|
|
24
|
-
)
|
|
25
|
-
.version('1.0.0');
|
|
26
|
-
|
|
27
|
-
// Auto-resolve command (now uses the reusable function)
|
|
28
|
-
|
|
29
|
-
setupResolve(program);
|
|
30
|
-
setupMerge(program);
|
|
31
|
-
setupMergeAll(program);
|
|
32
|
-
// Parse command line arguments
|
|
33
|
-
program.parse(args);
|
|
34
|
-
|
|
35
|
-
// Show help if no arguments provided
|
|
36
|
-
if (!args.slice(2).length) {
|
|
37
|
-
program.outputHelp();
|
|
38
|
-
}
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import { execSync } from 'child_process';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Simple changelog merger class
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
class ChangelogMerger {
|
|
9
|
-
constructor() {
|
|
10
|
-
this.content = '';
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Parse a file with merge conflicts and clean up conflict markers
|
|
15
|
-
*/
|
|
16
|
-
parseConflict(content) {
|
|
17
|
-
const lines = content.split('\n');
|
|
18
|
-
const cleanedLines = [];
|
|
19
|
-
|
|
20
|
-
for (const line of lines) {
|
|
21
|
-
if (line.startsWith('<<<<<<<')) {
|
|
22
|
-
// Remove conflict start marker
|
|
23
|
-
continue;
|
|
24
|
-
} else if (line.startsWith('=======')) {
|
|
25
|
-
// Replace separator with empty line
|
|
26
|
-
cleanedLines.push('');
|
|
27
|
-
continue;
|
|
28
|
-
} else if (line.startsWith('>>>>>>>')) {
|
|
29
|
-
// Remove conflict end marker
|
|
30
|
-
continue;
|
|
31
|
-
} else {
|
|
32
|
-
// Keep all other lines
|
|
33
|
-
cleanedLines.push(line);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
this.content = cleanedLines.join('\n');
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Generate the merged changelog content
|
|
42
|
-
*/
|
|
43
|
-
generateMerged() {
|
|
44
|
-
return this.content;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Changelog merge strategy - removes conflict markers and combines content
|
|
50
|
-
* @param {string} conflictContent - Content with conflict markers
|
|
51
|
-
* @returns {string} - Merged content
|
|
52
|
-
*/
|
|
53
|
-
export function mergeChangelog(conflictContent) {
|
|
54
|
-
const merger = new ChangelogMerger();
|
|
55
|
-
merger.parseConflict(conflictContent);
|
|
56
|
-
return merger.generateMerged();
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Main function for processing a file with merge conflicts
|
|
61
|
-
*/
|
|
62
|
-
export function mergeChangelogFile(filePath) {
|
|
63
|
-
try {
|
|
64
|
-
// Read the file (which contains the conflict markers)
|
|
65
|
-
const fileContent = fs.readFileSync(filePath, 'utf-8');
|
|
66
|
-
const result = mergeChangelog(fileContent);
|
|
67
|
-
|
|
68
|
-
// Write result back to the same file
|
|
69
|
-
fs.writeFileSync(filePath, result);
|
|
70
|
-
|
|
71
|
-
// Add file to git staging area to mark as resolved
|
|
72
|
-
try {
|
|
73
|
-
execSync(`git add ${filePath}`);
|
|
74
|
-
console.log('📝 File added to git staging area');
|
|
75
|
-
} catch (error) {
|
|
76
|
-
console.log(
|
|
77
|
-
'⚠️ Could not add file to git (may not be in a git repository)',
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
console.log('Changelog merge completed successfully');
|
|
82
|
-
return true;
|
|
83
|
-
} catch (error) {
|
|
84
|
-
console.error(`Merge failed: ${error.message}`);
|
|
85
|
-
throw error;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import { mergeDriver } from '../lib/merge-driver.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Custom merge logic for package.json files
|
|
6
|
-
* Resolves version conflicts by taking HEAD version
|
|
7
|
-
* @param {string} headContent - Content from HEAD (current branch)
|
|
8
|
-
* @param {string} branchContent - Content from incoming branch
|
|
9
|
-
* @returns {string} - Merged content
|
|
10
|
-
* @throws {Error} - If conflicts are not version-only
|
|
11
|
-
*/
|
|
12
|
-
function packageMergeLogic(headContent, branchContent) {
|
|
13
|
-
// Check if this is a version-only conflict
|
|
14
|
-
if (isVersionOnlyConflict(headContent, branchContent)) {
|
|
15
|
-
// Take the HEAD version
|
|
16
|
-
return headContent;
|
|
17
|
-
} else {
|
|
18
|
-
// Throw error to keep the conflict unresolved
|
|
19
|
-
throw new Error('Conflict contains more than just version differences');
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Check if conflict is version-only
|
|
25
|
-
* @param {string} headContent - Content from HEAD
|
|
26
|
-
* @param {string} branchContent - Content from branch
|
|
27
|
-
* @returns {boolean} - True if only version differs
|
|
28
|
-
*/
|
|
29
|
-
function isVersionOnlyConflict(headContent, branchContent) {
|
|
30
|
-
const headVersionMatch = headContent.match(/"version"\s*:\s*"([^"]+)"/);
|
|
31
|
-
const branchVersionMatch = branchContent.match(/"version"\s*:\s*"([^"]+)"/);
|
|
32
|
-
|
|
33
|
-
if (!headVersionMatch || !branchVersionMatch) {
|
|
34
|
-
return false;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Remove version lines and check if there's any other content
|
|
38
|
-
const headWithoutVersion = headContent
|
|
39
|
-
.replace(/"version"\s*:\s*"[^"]+",?\s*/g, '')
|
|
40
|
-
.trim();
|
|
41
|
-
const branchWithoutVersion = branchContent
|
|
42
|
-
.replace(/"version"\s*:\s*"[^"]+",?\s*/g, '')
|
|
43
|
-
.trim();
|
|
44
|
-
|
|
45
|
-
// If both are empty after removing version, it's version-only
|
|
46
|
-
// Also handle case where there might be whitespace or comma differences
|
|
47
|
-
if (!headWithoutVersion && !branchWithoutVersion) {
|
|
48
|
-
return true;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Additional check: if the only difference is trailing comma or whitespace
|
|
52
|
-
const normalizeContent = (content) => {
|
|
53
|
-
return content
|
|
54
|
-
.replace(/,\s*$/, '') // Remove trailing comma
|
|
55
|
-
.replace(/\s+/g, ' ') // Normalize whitespace
|
|
56
|
-
.trim();
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
return (
|
|
60
|
-
normalizeContent(headWithoutVersion) ===
|
|
61
|
-
normalizeContent(branchWithoutVersion)
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Main function to merge package.json conflicts using merge-driver
|
|
67
|
-
* @param {string} filePath - Path to package.json file
|
|
68
|
-
* @returns {Promise<boolean>} - True if successful
|
|
69
|
-
*/
|
|
70
|
-
export async function mergePackageFile(filePath) {
|
|
71
|
-
try {
|
|
72
|
-
// Check if file exists
|
|
73
|
-
if (!fs.existsSync(filePath)) {
|
|
74
|
-
throw new Error(`File not found: ${filePath}`);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
console.log(`🔄 Merging package.json conflicts in: ${filePath}`);
|
|
78
|
-
|
|
79
|
-
// Use merge driver with custom package.json merge logic
|
|
80
|
-
const result = await mergeDriver(filePath, packageMergeLogic);
|
|
81
|
-
|
|
82
|
-
// Log results
|
|
83
|
-
if (result.success) {
|
|
84
|
-
console.log('✅ Package merge completed successfully');
|
|
85
|
-
if (result.totalConflicts > 0) {
|
|
86
|
-
console.log(
|
|
87
|
-
` Resolved ${result.resolvedConflicts} version-only conflicts`,
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
} else {
|
|
91
|
-
console.log('⚠️ Package merge partially completed');
|
|
92
|
-
console.log(
|
|
93
|
-
` ${result.resolvedConflicts} of ${result.totalConflicts} conflicts resolved`,
|
|
94
|
-
);
|
|
95
|
-
console.log(' Non-version conflicts require manual resolution');
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
return result.success;
|
|
99
|
-
} catch (error) {
|
|
100
|
-
console.error(`❌ Merge failed: ${error.message}`);
|
|
101
|
-
throw error;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Default export
|
|
106
|
-
export default mergePackageFile;
|
package/src/merge/merge-types.js
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import { mergeDriver } from '../lib/merge-driver.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Codegen-specific merge logic for handling balanced braces and removing duplicates
|
|
5
|
-
* @param {string} headContent - Content from HEAD (current branch)
|
|
6
|
-
* @param {string} branchContent - Content from the incoming branch
|
|
7
|
-
* @returns {string} - Merged content
|
|
8
|
-
* @throws {Error} - If conflicts cannot be automatically merged
|
|
9
|
-
*/
|
|
10
|
-
function codegenMergeLogic(headContent, branchContent) {
|
|
11
|
-
// Check if braces are balanced in both head and branch content
|
|
12
|
-
const headOpenBraces = (headContent.match(/\{/g) || []).length;
|
|
13
|
-
const headCloseBraces = (headContent.match(/\}/g) || []).length;
|
|
14
|
-
const branchOpenBraces = (branchContent.match(/\{/g) || []).length;
|
|
15
|
-
const branchCloseBraces = (branchContent.match(/\}/g) || []).length;
|
|
16
|
-
|
|
17
|
-
// Check if head content has balanced braces
|
|
18
|
-
const headHasBraces = headOpenBraces > 0 || headCloseBraces > 0;
|
|
19
|
-
const headBalanced = headOpenBraces === headCloseBraces;
|
|
20
|
-
|
|
21
|
-
// Check if branch content has balanced braces
|
|
22
|
-
const branchHasBraces = branchOpenBraces > 0 || branchCloseBraces > 0;
|
|
23
|
-
const branchBalanced = branchOpenBraces === branchCloseBraces;
|
|
24
|
-
|
|
25
|
-
// If either has braces and they're not balanced, we can't merge
|
|
26
|
-
if (
|
|
27
|
-
(headHasBraces && !headBalanced) ||
|
|
28
|
-
(branchHasBraces && !branchBalanced)
|
|
29
|
-
) {
|
|
30
|
-
throw new Error('Unbalanced braces detected - cannot merge automatically');
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// If both have balanced braces, combine them as-is
|
|
34
|
-
if (headHasBraces && branchHasBraces && headBalanced && branchBalanced) {
|
|
35
|
-
return headContent + '\n' + branchContent;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// If neither has braces, combine and remove duplicates
|
|
39
|
-
if (!headHasBraces && !branchHasBraces) {
|
|
40
|
-
const headLines = headContent.split('\n').filter((line) => line);
|
|
41
|
-
const branchLines = branchContent.split('\n').filter((line) => line);
|
|
42
|
-
|
|
43
|
-
// Use Set to remove duplicates while preserving order
|
|
44
|
-
const uniqueLines = [...new Set([...headLines, ...branchLines])];
|
|
45
|
-
|
|
46
|
-
return uniqueLines.join('\n');
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Mixed case: one has braces, one doesn't - combine as-is
|
|
50
|
-
return headContent + '\n' + branchContent;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Main function to merge codegen conflicts in a types file
|
|
55
|
-
* @param {string} filePath - Path to the file with conflicts
|
|
56
|
-
* @returns {Promise<Object>} - Result object with merge details
|
|
57
|
-
*/
|
|
58
|
-
export async function mergeTypesFile(filePath) {
|
|
59
|
-
try {
|
|
60
|
-
console.log('Starting codegen merge for types file...');
|
|
61
|
-
|
|
62
|
-
// Use the merge driver with our custom codegen logic
|
|
63
|
-
const result = await mergeDriver(filePath, codegenMergeLogic);
|
|
64
|
-
|
|
65
|
-
if (result.success) {
|
|
66
|
-
console.log('✅ Codegen merge completed successfully');
|
|
67
|
-
} else {
|
|
68
|
-
console.log('⚠️ Codegen merge completed with unresolved conflicts');
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return result;
|
|
72
|
-
} catch (error) {
|
|
73
|
-
console.error(`Codegen merge failed: ${error.message}`);
|
|
74
|
-
throw error;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Export the merge logic function for direct use if needed
|
|
79
|
-
export { codegenMergeLogic };
|
|
80
|
-
|
|
81
|
-
// Default export
|
|
82
|
-
export default mergeTypesFile;
|