diff --git a/lib/cli/commands/build.js b/lib/cli/commands/build.js index 9c5bf6c7..0e1d3bed 100644 --- a/lib/cli/commands/build.js +++ b/lib/cli/commands/build.js @@ -65,6 +65,11 @@ build.builder = function(cli) { describe: "Overrides the framework version defined by the project", type: "string" }) + .option("x-graph-mode", { + describe: "Uses an experimental project graph instead of a dependency tree", + default: false, + type: "boolean" + }) .example("ui5 build --all", "Preload build for project and dependencies to \"./dist\"") .example("ui5 build --all --exclude-task=* --include-task=createDebugFiles generateAppPreload", "Build project and dependencies but only apply the createDebugFiles- and generateAppPreload tasks") @@ -97,9 +102,16 @@ async function handleBuild(argv) { }; } - const tree = await normalizer.generateProjectTree(normalizerOptions); + let tree; + let graph; + if (argv.xGraphMode) { + graph = await normalizer.generateProjectGraph(normalizerOptions); + } else { + tree = await normalizer.generateProjectTree(normalizerOptions); + } await builder.build({ tree: tree, + graph: graph, destPath: argv.dest, cleanDest: argv["clean-dest"], buildDependencies: argv.all, diff --git a/lib/cli/commands/tree.js b/lib/cli/commands/tree.js index 2f6df1cc..166e6240 100644 --- a/lib/cli/commands/tree.js +++ b/lib/cli/commands/tree.js @@ -28,7 +28,18 @@ tree.builder = function(cli) { describe: "Overrides the framework version defined by the project. Only supported in combination with --full", type: "string" - }).check((argv) => { + }) + .option("x-graph-mode", { + describe: "Uses an experimental project graph instead of a dependency tree", + default: false, + type: "boolean" + }) + .option("x-perf", { + describe: "Outputs performance measurements", + default: false, + type: "boolean" + }) + .check((argv) => { if (argv.frameworkVersion && !argv.full) { throw new Error(`"framework-version" can only be used in combination with option "--full"`); } else { @@ -42,6 +53,7 @@ tree.builder = function(cli) { tree.handler = async function(argv) { const normalizer = require("@ui5/project").normalizer; const treeify = require("treeify"); + const chalk = require("chalk"); const options = { translatorName: argv.translator, @@ -57,15 +69,91 @@ tree.handler = async function(argv) { }; } - let projectTree; - if (argv.full) { - projectTree = await normalizer.generateProjectTree(options); + let startTime; + let elapsedTime; + if (argv.xPerf) { + startTime = process.hrtime(); + } + if (argv.xGraphMode) { + const graph = await normalizer.generateProjectGraph(options); + + if (argv.xPerf) { + elapsedTime = getElapsedTime(startTime); + } + + const projects = {}; + const indentWidth = 4; + await graph.traverseBreadthFirst(async ({project, getDependencies}) => { + const deps = getDependencies().map((dep) => { + return dep.getName(); + }); + projects[project.getName()] = { + render: function(indentation, connectorIndices, lastChild) { + let baseString = " ".repeat(indentation * indentWidth); + connectorIndices.forEach((idx) => { + baseString = `${baseString.slice(0, idx)}│${baseString.slice(idx + 1)}`; + }); + const connectorString = lastChild ? "╰─" : "├─"; + console.log( + `${baseString}${connectorString} ${chalk.bold(project.getName())} ` + + chalk.dim(`(${project.getVersion()}, ${project.getType()}) `) + + chalk.dim.italic(`${project.getPath()}`) + ); + + const lastIdx = deps.length -1; + const newConnectorIndices = [...connectorIndices]; + if (!lastChild) { + newConnectorIndices.push(indentation * indentWidth); + } + deps.forEach((dep, i) => { + projects[dep].render(indentation + 1, newConnectorIndices, i === lastIdx); + }); + } + }; + }); + + const projectKeys = Object.keys(projects); + console.log(chalk.bold.underline(`Dependencies (${projectKeys.length}):`)); + projects[projectKeys[0]].render(0, [], true); + console.log(""); + + const extensions = Object.entries(graph.getAllExtensions()); + console.log(chalk.bold.underline(`Extensions (${extensions.length}):`)); + if (extensions.length) { + extensions.forEach((extension) => { + console.log( + `${" ".repeat(indentWidth)} ├─ ${extension.getName()}` + + chalk.dim(`(${extension.getVersion()}, ${extension.getType()}) `) + + chalk.dim.italic(`${extension.getPath()}`)); + }); + } else { + console.log(chalk.italic(`None`)); + } } else { - projectTree = await normalizer.generateDependencyTree(options); + let projectTree; + if (argv.full) { + projectTree = await normalizer.generateProjectTree(options); + } else { + projectTree = await normalizer.generateDependencyTree(options); + } + if (argv.xPerf) { + elapsedTime = getElapsedTime(startTime); + } + + + const output = argv.json ? JSON.stringify(projectTree, null, 4) : treeify.asTree(projectTree, true); + console.log(output); } - const output = argv.json ? JSON.stringify(projectTree, null, 4) : treeify.asTree(projectTree, true); - console.log(output); + if (argv.xPerf) { + console.log(""); + console.log(chalk.blue(`Normalizer took ${chalk.bold(elapsedTime)}`)); + } }; +function getElapsedTime(startTime) { + const timeDiff = process.hrtime(startTime); + const prettyHrtime = require("pretty-hrtime"); + return prettyHrtime(timeDiff); +} module.exports = tree;