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

Commit

Permalink
feat: deal with cycles
Browse files Browse the repository at this point in the history
Closes #11
  • Loading branch information
dominykas committed Mar 29, 2019
1 parent bbd86c6 commit abc059a
Show file tree
Hide file tree
Showing 9 changed files with 30 additions and 35 deletions.
37 changes: 9 additions & 28 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,50 +6,31 @@ const Fs = require('fs');
const Npm = require('libnpm');
const Path = require('path');
const Semver = require('semver');
const Topo = require('topo');


const internals = {};


internals.scan = (tree, parent, map = new Map(), scanned = new Set()) => {
internals.queue = (tree, queue = [], scanned = new Set()) => {

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

if (v.hasCycle()) {
console.warn(`==========> skip ${v.path()} (because it has a cycle in dependencies)`);
continue;
}

const path = v.path();
if (!map.has(path)) {
map.set(path, []);
}

const node = map.get(path);
node.push(parent);

if (!scanned.has(v)) {
scanned.add(v);
internals.scan(v, v.path(), map, scanned);
if (scanned.has(path)) {
// prevent cycles
continue;
}
}

return map;
};


internals.queue = (tree) => {

const map = internals.scan(tree);
const topo = new Topo();
for (const [group, before] of map) {
topo.add(group, { group, before });
scanned.add(path);
internals.queue(v, queue, scanned);
queue.push(v.path()); // adding deepest deps into the queue first
}

return topo.nodes;
return queue;
};


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

if (!pkg.scripts || !pkg.scripts[stage]) {
Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@
"dependencies": {
"ansicolors": "0.3.x",
"libnpm": "2.x.x",
"semver": "6.x.x",
"topo": "3.x.x"
"semver": "6.x.x"
},
"devDependencies": {
"@commitlint/cli": "7.x.x",
Expand Down
3 changes: 3 additions & 0 deletions test/fixtures/cycle-a.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,8 @@
"version": "0.0.0",
"dependencies": {
"@example/cycle-b": "*"
},
"scripts": {
"install": "echo install from cycle-a >> ${OUTPUT}"
}
}
3 changes: 3 additions & 0 deletions test/fixtures/cycle-b.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,8 @@
"version": "0.0.0",
"dependencies": {
"@example/cycle-c": "*"
},
"scripts": {
"install": "echo install from cycle-b >> ${OUTPUT}"
}
}
3 changes: 3 additions & 0 deletions test/fixtures/cycle-c.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,8 @@
"version": "0.0.0",
"dependencies": {
"@example/cycle-a": "*"
},
"scripts": {
"install": "echo install from cycle-c >> ${OUTPUT}"
}
}
3 changes: 2 additions & 1 deletion test/fixtures/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ internals.readFile = (path) => Fs.readFileSync(path).toString().trim();
exports.expectedResults = {
basicFull: internals.readFile(Path.join(__dirname, 'basic.full.txt')),
basicDryRun: internals.readFile(Path.join(__dirname, 'basic.dry-run.txt')),
deep: internals.readFile(Path.join(__dirname, 'deep.txt'))
deep: internals.readFile(Path.join(__dirname, 'deep.txt')),
withCycles: internals.readFile(Path.join(__dirname, 'with-cycles.txt'))
};


Expand Down
5 changes: 4 additions & 1 deletion test/fixtures/with-cycles.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
"@example/with-install-script": "*"
},
"allowScripts": {
"@example/with-install-script": "*"
"@example/with-install-script": "*",
"@example/cycle-a": "*",
"@example/cycle-b": "*",
"@example/cycle-c": "*"
}
}
4 changes: 4 additions & 0 deletions test/fixtures/with-cycles.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
install from cycle-c
install from cycle-b
install from cycle-a
install from with-install-script
4 changes: 1 addition & 3 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,7 @@ describe('allow-scripts', () => {

await Allow.run({});

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

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

0 comments on commit abc059a

Please sign in to comment.