Skip to content
This repository was archived by the owner on Aug 18, 2024. It is now read-only.

Commit abc059a

Browse files
committed
feat: deal with cycles
Closes #11
1 parent bbd86c6 commit abc059a

File tree

9 files changed

+30
-35
lines changed

9 files changed

+30
-35
lines changed

lib/index.js

Lines changed: 9 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,50 +6,31 @@ const Fs = require('fs');
66
const Npm = require('libnpm');
77
const Path = require('path');
88
const Semver = require('semver');
9-
const Topo = require('topo');
109

1110

1211
const internals = {};
1312

1413

15-
internals.scan = (tree, parent, map = new Map(), scanned = new Set()) => {
14+
internals.queue = (tree, queue = [], scanned = new Set()) => {
1615

1716
for (const [, v] of tree.dependencies) {
1817

19-
if (v.hasCycle()) {
20-
console.warn(`==========> skip ${v.path()} (because it has a cycle in dependencies)`);
21-
continue;
22-
}
23-
2418
const path = v.path();
25-
if (!map.has(path)) {
26-
map.set(path, []);
27-
}
28-
29-
const node = map.get(path);
30-
node.push(parent);
3119

32-
if (!scanned.has(v)) {
33-
scanned.add(v);
34-
internals.scan(v, v.path(), map, scanned);
20+
if (scanned.has(path)) {
21+
// prevent cycles
22+
continue;
3523
}
36-
}
37-
38-
return map;
39-
};
4024

41-
42-
internals.queue = (tree) => {
43-
44-
const map = internals.scan(tree);
45-
const topo = new Topo();
46-
for (const [group, before] of map) {
47-
topo.add(group, { group, before });
25+
scanned.add(path);
26+
internals.queue(v, queue, scanned);
27+
queue.push(v.path()); // adding deepest deps into the queue first
4828
}
4929

50-
return topo.nodes;
30+
return queue;
5131
};
5232

33+
5334
internals.runScript = (stage, { pkg, path, cwd, unsafePerm }, options) => {
5435

5536
if (!pkg.scripts || !pkg.scripts[stage]) {

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@
1818
"dependencies": {
1919
"ansicolors": "0.3.x",
2020
"libnpm": "2.x.x",
21-
"semver": "6.x.x",
22-
"topo": "3.x.x"
21+
"semver": "6.x.x"
2322
},
2423
"devDependencies": {
2524
"@commitlint/cli": "7.x.x",

test/fixtures/cycle-a.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,8 @@
44
"version": "0.0.0",
55
"dependencies": {
66
"@example/cycle-b": "*"
7+
},
8+
"scripts": {
9+
"install": "echo install from cycle-a >> ${OUTPUT}"
710
}
811
}

test/fixtures/cycle-b.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,8 @@
44
"version": "0.0.0",
55
"dependencies": {
66
"@example/cycle-c": "*"
7+
},
8+
"scripts": {
9+
"install": "echo install from cycle-b >> ${OUTPUT}"
710
}
811
}

test/fixtures/cycle-c.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,8 @@
44
"version": "0.0.0",
55
"dependencies": {
66
"@example/cycle-a": "*"
7+
},
8+
"scripts": {
9+
"install": "echo install from cycle-c >> ${OUTPUT}"
710
}
811
}

test/fixtures/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ internals.readFile = (path) => Fs.readFileSync(path).toString().trim();
1919
exports.expectedResults = {
2020
basicFull: internals.readFile(Path.join(__dirname, 'basic.full.txt')),
2121
basicDryRun: internals.readFile(Path.join(__dirname, 'basic.dry-run.txt')),
22-
deep: internals.readFile(Path.join(__dirname, 'deep.txt'))
22+
deep: internals.readFile(Path.join(__dirname, 'deep.txt')),
23+
withCycles: internals.readFile(Path.join(__dirname, 'with-cycles.txt'))
2324
};
2425

2526

test/fixtures/with-cycles.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
"@example/with-install-script": "*"
99
},
1010
"allowScripts": {
11-
"@example/with-install-script": "*"
11+
"@example/with-install-script": "*",
12+
"@example/cycle-a": "*",
13+
"@example/cycle-b": "*",
14+
"@example/cycle-c": "*"
1215
}
1316
}

test/fixtures/with-cycles.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
install from cycle-c
2+
install from cycle-b
3+
install from cycle-a
4+
install from with-install-script

test/index.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,7 @@ describe('allow-scripts', () => {
9494

9595
await Allow.run({});
9696

97-
expect(fixture.getActualResult()).to.equal('install from with-install-script');
98-
expect(fixture.getLog()).to.contain('skip node_modules/@example/cycle-a (because it has a cycle in dependencies)');
99-
expect(fixture.getLog()).to.contain('skip node_modules/@example/cycle-b (because it has a cycle in dependencies)');
97+
expect(fixture.getActualResult()).to.equal(Fixtures.expectedResults.withCycles);
10098
});
10199

102100
it('executes allowed scripts (existing shrinkwrap)', async () => {

0 commit comments

Comments
 (0)