Comparing version 1.6.1-alpha5 to 1.6.1-alpha6
@@ -53,3 +53,2 @@ module.exports = { | ||
debug('%s > %s', pua.version, pub.version); | ||
res = semver.compare(pua.version, pub.version) * -1; | ||
@@ -80,2 +79,6 @@ | ||
return vulns.map(function (vuln) { | ||
// strip verbose meta | ||
delete vuln.description; | ||
delete vuln.credit; | ||
if (vuln.patches) { | ||
@@ -119,3 +122,3 @@ vuln.patches = vuln.patches.filter(function (patch) { | ||
var copy = null; | ||
var copy = {}; | ||
var offset = 0; | ||
@@ -126,30 +129,68 @@ // mutate our objects so we can try to group them | ||
// it's feet | ||
res.slice(0).reduce(function (acc, curr, i) { | ||
// TODO allow for cross over patches on modules (i.e. patch can work | ||
// on A-1 and A-2) | ||
var last = curr.from.slice(-1).pop(); | ||
if (!acc[last]) { | ||
// only copy the biggest change | ||
copy = _.cloneDeep(curr); | ||
acc[last] = curr; | ||
return acc; | ||
} | ||
res.slice(0).reduce(function (acc, curr, i, all) { | ||
var upgrades = curr.upgradePath[1]; | ||
// otherwise it's a patch and that's hidden for now | ||
if (!upgrades && curr.patches.length) { | ||
debug('ok1'); | ||
if (!upgrades && curr.patches && curr.patches.length) { | ||
// TODO allow for cross over patches on modules (i.e. patch can work | ||
// on A-1 and A-2) | ||
var last = curr.id; //curr.from.slice(-1).pop(); | ||
if (acc[curr.id]) { | ||
last = curr.id; | ||
} else { | ||
// try to find the right vuln id based on the | ||
last = (all.filter(function (vuln) { | ||
var patch = vuln.patches[0]; | ||
// don't select the one we're looking at | ||
if (curr.id === vuln.id) { | ||
return false; | ||
} | ||
// only look at packages with the same name | ||
if (curr.name !== vuln.name || !patch) { | ||
return false; | ||
} | ||
// and ensure the patch can be applied to *our* module version | ||
if (semver.satisfies(curr.version, patch.version)) { | ||
// finally make sure the publicationTime is newer than the curr | ||
// vulnerability | ||
if (curr.publicationTime < vuln.publicationTime) { | ||
debug('found alternative location for %s@%s (%s by %s) in vuln %s', | ||
curr.name, curr.version, patch.version, curr.id, vuln.id); | ||
return true; | ||
} | ||
} | ||
}).shift() || curr).id; | ||
} | ||
if (!acc[last]) { | ||
// only copy the biggest change | ||
copy[last] = _.cloneDeep(curr); | ||
acc[last] = curr; | ||
return acc; | ||
} | ||
var full = curr.name + '@' + curr.version; | ||
// only happens on the 2nd time around | ||
if (!acc[last].grouped) { | ||
acc[last].grouped = { | ||
affected: moduleToObject(last), | ||
affected: moduleToObject(acc[last].name + '@' + acc[last].version), | ||
main: true, | ||
id: acc[last].id + '-' + i, | ||
count: 1, | ||
upgrades: [], | ||
upgrades: [acc[last].from], | ||
patch: true, | ||
}; | ||
acc[last].grouped.affected.full = last; | ||
acc[last].grouped.affected.full = acc[last].name; | ||
// splice this vuln into the list again so if the user choses to review | ||
// they'll get this individual vuln and remediation | ||
copy.grouped = { | ||
copy[last].grouped = { | ||
main: false, | ||
@@ -159,7 +200,10 @@ requires: acc[last].grouped.id, | ||
res.splice(i + offset, 0, copy); | ||
res.splice(i + offset, 0, copy[last]); | ||
offset++; | ||
} | ||
debug('vuln found on group'); | ||
// if (acc[last].grouped.affected.full.indexOf(curr.version) === -1) { | ||
// acc[last].grouped.affected.full += ' / ' + curr.version; | ||
// } | ||
acc[last].grouped.count++; | ||
@@ -172,8 +216,9 @@ | ||
var p = moduleToObject(last); | ||
if (p.name !== acc[last].grouped.affected.name && | ||
(' ' + acc[last].grouped.upgrades.join(' ') + ' ') | ||
.indexOf(p.name + '@') === -1) { | ||
debug('+ adding %s to upgrades', last); | ||
acc[last].grouped.upgrades.push(last); | ||
// add the from path to our group upgrades if we don't have it already | ||
var have = !!acc[last].grouped.upgrades.filter(function (from) { | ||
return from.join(' ') === curr.from.join(' '); | ||
}).length; | ||
if (!have) { | ||
acc[last].grouped.upgrades.push(curr.from); | ||
} | ||
@@ -284,3 +329,2 @@ } | ||
debug('vuln found on group'); | ||
acc[from].grouped.count++; | ||
@@ -381,3 +425,4 @@ | ||
group.affected.version; | ||
messageIntro = group.count + ' vulnerabilities introduced via ' + | ||
var joiningText = group.patch ? ' in ' : ' via '; | ||
messageIntro = group.count + ' vulnerabilities introduced' + joiningText + | ||
group.affected.full; | ||
@@ -394,3 +439,7 @@ } else { | ||
if (vuln.note) { | ||
note = '- note: ' + vuln.note; | ||
if (group && group.patch) { | ||
} else { | ||
note = '- note: ' + vuln.note; | ||
} | ||
} | ||
@@ -401,3 +450,2 @@ | ||
var res = true; | ||
// console.log(answers); | ||
// only show this question if the user chose to review the details | ||
@@ -417,2 +465,3 @@ // of the vuln | ||
if (!groupAnswer.length) { | ||
debug('no group answer: show %s when %s', vuln.id, false); | ||
return false; | ||
@@ -434,3 +483,2 @@ } | ||
console.log(['', messageIntro, infoLink, via].join('\n')); | ||
// console.log(updatedTo); | ||
} | ||
@@ -442,2 +490,5 @@ } | ||
} | ||
debug('final show %s when %s', vuln.id, res); | ||
return res; // true = show next | ||
@@ -476,8 +527,21 @@ }, | ||
var out = 'Upgrade to ' + toPackage; | ||
if (group) { | ||
out += ' (triggers upgrade to ' + group.upgrades.join(', ') + ')'; | ||
var toPackageVersion = moduleToObject(toPackage).version; | ||
var diff = semver.diff(moduleToObject(from).version, toPackageVersion); | ||
var lead = ''; | ||
var breaking = 'potentially breaking change'; | ||
if (diff === 'major') { | ||
lead = ' (' + breaking + ', '; | ||
} else { | ||
lead = ' ('; | ||
} | ||
lead += 'triggers upgrade to '; | ||
if (group && group.upgrades.length) { | ||
out += lead + group.upgrades.join(', ') + ')'; | ||
} else { | ||
var last = vuln.upgradePath.slice(-1).shift(); | ||
if (toPackage !== last) { | ||
out += ' (triggers upgrade to ' + last + ')'; | ||
out += lead + last + ')'; | ||
} else if (diff === 'major') { | ||
out += ' (' + breaking + ')'; | ||
} | ||
@@ -648,7 +712,2 @@ } | ||
type: 'confirm', | ||
when: function (answers) { | ||
return Object.keys(answers).some(function (key) { | ||
return answers[key].choice === 'patch'; | ||
}); | ||
}, | ||
default: true, | ||
@@ -655,0 +714,0 @@ }); |
@@ -122,3 +122,6 @@ module.exports = wizard; | ||
}).then(function (answers) { | ||
var prompts = allPrompts.nextSteps(pkg, test.ok); | ||
var skipProtect = Object.keys(answers).some(function (key) { | ||
return answers[key].choice === 'patch'; | ||
}); | ||
var prompts = allPrompts.nextSteps(pkg, test.ok || skipProtect); | ||
return inquire(prompts, answers); | ||
@@ -174,2 +177,12 @@ }); | ||
if (task === 'patch' && answer.vuln.grouped) { | ||
// ignore the first as it's the same one as this particular answer | ||
var additionalPatches = answer.vuln.grouped.upgrades.slice(1); | ||
additionalPatches.forEach(function (from) { | ||
var copy = _.cloneDeep(answer.vuln); | ||
copy.from = from; | ||
tasks.patch.push(copy); | ||
}); | ||
} | ||
if (task === 'ignore') { | ||
@@ -176,0 +189,0 @@ answer.meta.reason = answers[key + '-reason']; |
@@ -5,3 +5,3 @@ { | ||
"main": "lib/index.js", | ||
"version": "1.6.1-alpha5", | ||
"version": "1.6.1-alpha6", | ||
"directories": { | ||
@@ -15,3 +15,3 @@ "test": "test" | ||
"lint": "jscs cli/*.js cli/**/*.js lib/*.js -v", | ||
"test": "npm run lint && tap test/*.test.js --cov --timeout=60 && node cli/index.js test > /dev/null", | ||
"test": "npm run lint && tap test/*.test.js -R=spec --cov --timeout=60 && node cli/index.js test > /dev/null", | ||
"watch": "nodemon -q -x 'for FILE in test/*.test.js; do echo $FILE; tape $FILE | tap-spec; if [ $? -ne 0 ]; then exit 1; fi; done'", | ||
@@ -18,0 +18,0 @@ "semantic-release": "semantic-release pre && npm publish && semantic-release post" |
Sorry, the diff of this file is not supported yet
3677282
3965