resynth()

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,
      },
    });
  }