fix(core): with-deps should handle circular dependencies

This commit is contained in:
Victor Savkin 2020-07-23 16:29:53 -04:00 committed by Victor Savkin
parent 4ec68d3464
commit 78275ef892
3 changed files with 91 additions and 19 deletions

View File

@ -499,16 +499,6 @@ forEachCli((cliName) => {
)
);
expect(resWithDeps.tasks).toEqual([
{
id: `${mypublishablelib}:build`,
overrides: {},
target: {
project: mypublishablelib,
target: 'build',
},
command: `npm run ${cliCommand} -- build ${mypublishablelib}`,
outputs: [`dist/libs/${mypublishablelib}`],
},
{
id: `${myapp}:build`,
overrides: {},
@ -519,6 +509,16 @@ forEachCli((cliName) => {
command: `npm run ${cliCommand} -- build ${myapp}`,
outputs: [`dist/apps/${myapp}`],
},
{
id: `${mypublishablelib}:build`,
overrides: {},
target: {
project: mypublishablelib,
target: 'build',
},
command: `npm run ${cliCommand} -- build ${mypublishablelib}`,
outputs: [`dist/libs/${mypublishablelib}`],
},
]);
compareTwoArrays(resWithDeps.projects, [
mylib,

View File

@ -173,6 +173,65 @@ describe('withDeps', () => {
},
});
});
it('should handle circular deps', () => {
const graph: ProjectGraph = {
nodes: {
lib1: { name: 'lib1', type: 'lib', data: null },
lib2: { name: 'lib2', type: 'lib', data: null },
},
dependencies: {
lib1: [
{
type: DependencyType.static,
source: 'lib1',
target: 'lib2',
},
],
lib2: [
{
type: DependencyType.static,
source: 'lib2',
target: 'lib1',
},
],
},
};
const affectedNodes = [{ name: 'lib1', type: 'lib', data: null }];
const result = withDeps(graph, affectedNodes);
expect(result).toEqual({
nodes: {
lib1: {
name: 'lib1',
type: 'lib',
data: null,
},
lib2: {
name: 'lib2',
type: 'lib',
data: null,
},
},
dependencies: {
lib2: [
{
type: 'static',
source: 'lib2',
target: 'lib1',
},
],
lib1: [
{
type: 'static',
source: 'lib1',
target: 'lib2',
},
],
},
});
});
});
describe('filterNodes', () => {

View File

@ -80,22 +80,35 @@ export function withDeps(
subsetNodes: ProjectGraphNode[]
): ProjectGraph {
const builder = new ProjectGraphBuilder();
Object.values(subsetNodes).forEach(recur);
const visitedNodes = [];
const visitedEdges = [];
Object.values(subsetNodes).forEach(recurNodes);
Object.values(subsetNodes).forEach(recurEdges);
return builder.build();
// ---------------------------------------------------------------------------
function recur(node) {
const ds = original.dependencies[node.name];
// 1. Recursively add all source nodes
ds.forEach((n) => {
recur(original.nodes[n.target]);
});
// 2. Add current node
function recurNodes(node) {
if (visitedNodes.indexOf(node.name) > -1) return;
builder.addNode(node);
// 3. Add all source dependencies
visitedNodes.push(node.name);
original.dependencies[node.name].forEach((n) => {
recurNodes(original.nodes[n.target]);
});
}
function recurEdges(node) {
if (visitedEdges.indexOf(node.name) > -1) return;
visitedEdges.push(node.name);
const ds = original.dependencies[node.name];
ds.forEach((n) => {
builder.addDependency(n.type, n.source, n.target);
});
ds.forEach((n) => {
recurEdges(original.nodes[n.target]);
});
}
}