in packages/blueprints/blueprint/src/blueprint.ts [153:236]
resynth(ancestorBundle: string, existingBundle: string, proposedBundle: string) {
ancestorBundle = path.resolve(ancestorBundle);
existingBundle = path.resolve(existingBundle);
proposedBundle = path.resolve(proposedBundle);
//1. find the merge strategies from the exisiting codebase, deserialize and match against strategies in memory
const overriddenStrategies: StrategyLocations = deserializeStrategies(existingBundle, this.strategies || {});
const validStrategies = merge(this.strategies || {}, filterStrategies(overriddenStrategies, this.context.package));
// used for pretty formatting
let maxIdlength = 0;
console.log('<<STRATEGY>> Last <<STRATEGY>> Wins:');
console.log(`<<STRATEGY>> [SYS-FALLBACK] [${FALLBACK_STRATEGY_ID}] matches [*]`);
for (const [ownershipFile, strategies] of Object.entries(validStrategies)) {
for (const strategy of strategies) {
console.log(
structureStrategyReport(ownershipFile, strategy, {
overriden: ownershipFile.includes(Ownership.DEFAULT_FILE_NAME),
}),
);
maxIdlength = Math.max(strategy.identifier.length, maxIdlength);
}
}
maxIdlength = Math.max(maxIdlength, FALLBACK_STRATEGY_ID.length);
/**
* copy all non-src file from proposedBundle into the resolved bundle
* only src is merge constructed.
*/
const supersetNonSourceNonIssuesPaths: string[] = filepathSet([proposedBundle], ['**/*', '!src/**', '!issues/**']);
for (const filepath of supersetNonSourceNonIssuesPaths) {
this.writeNonSourceFile(filepath, proposedBundle);
}
/**
* copy all issue src files that are unique to the proposedBundle into the resolved bundle
* to prevent duplicate issue creation
*/
const setUniqueToProposedBundle = filepathDifferenceSet(ancestorBundle, proposedBundle, ['issues/**']);
for (const filepath of setUniqueToProposedBundle) {
this.writeNonSourceFile(filepath, proposedBundle);
}
//2. construct the superset of files between [ancestorBundle, existingBundle, proposedBundle]/src
// only consider files under the source code 'src'
const supersetSourcePaths: string[] = filepathSet([ancestorBundle, existingBundle, proposedBundle], ['src/**']);
supersetSourcePaths.forEach(sourcePath => {
//3. for each file, match it with a merge strategy
const strategy = match(sourcePath, validStrategies);
const { resourcePrefix, subdirectory, filepath } = destructurePath(sourcePath, '');
const repositoryTitle = subdirectory;
const ancestorContextFile = createContextFile(ancestorBundle, resourcePrefix!, repositoryTitle!, filepath!);
const existingContextFile = createContextFile(existingBundle, resourcePrefix!, repositoryTitle!, filepath!);
const proposedContextFile = createContextFile(proposedBundle, resourcePrefix!, repositoryTitle!, filepath!);
const resolvedFile = strategy.strategy(ancestorContextFile, existingContextFile, proposedContextFile);
console.debug(structureMatchReport(maxIdlength, strategy, repositoryTitle!, filepath!));
if (resolvedFile) {
//4. write the result of the merge strategy to the outdir/src/repo/path
let mode: fs.Mode | undefined;
if (existingContextFile) {
mode = fs.statSync(getAbsoluteContextFilePath(existingBundle, resourcePrefix!, existingContextFile)).mode;
}
this.write(resolvedFile, { mode });
} else {
console.debug('\t -> removed');
}
});
// generate pull requests
createLifecyclePullRequest(this.outdir, existingBundle, {
originBranch: this.resynthPullRequest.originBranch,
targetBranch: this.resynthPullRequest.targetBranch,
pullRequest: {
id: this.resynthPullRequest.originBranch,
title: this.resynthPullRequest.title,
description: this.resynthPullRequest.description,
},
});
}