diff --git a/src/lib/protect/apply-patch.js b/src/lib/protect/apply-patch.js index dd032a99ef..690ce052ef 100644 --- a/src/lib/protect/apply-patch.js +++ b/src/lib/protect/apply-patch.js @@ -8,7 +8,7 @@ var fs = require('fs'); var uuid = require('uuid/v4'); var errorAnalytics = require('../analytics').single; -function applyPatch(patch, vuln, live, patchUrl) { +function applyPatch(patchFileName, vuln, live, patchUrl) { var cwd = vuln.source; return new Promise(function (resolve, reject) { @@ -27,7 +27,7 @@ function applyPatch(patch, vuln, live, patchUrl) { debug('Failed loading package.json of package about to be patched', err); } - var patchContent = fs.readFileSync(path.resolve(relative, patch), 'utf8'); + var patchContent = fs.readFileSync(path.resolve(relative, patchFileName), 'utf8'); jsDiff(patchContent, relative, live).then(function () { debug('patch succeed'); @@ -49,7 +49,15 @@ function jsDiff(patchContent, relative, live) { if (patchedFiles[fileName]) { return callback(null, patchedFiles[fileName]); } - var content = fs.readFileSync(path.resolve(relative, fileName), 'utf8'); + + var filePath = path.resolve(relative, fileName); + var content = fs.readFileSync(filePath, 'utf8'); + + // create an `.orig` copy of the file prior to patching it + // used in case we need to revert a patch + var origFilePath = filePath + '.orig'; + fs.writeFileSync(origFilePath, content); + callback(null, content); } catch (err) { // collect patch metadata for error analysis @@ -92,7 +100,7 @@ function jsDiff(patchContent, relative, live) { } try { // write patched files back to disk, unlink files completely removed by patching - for (var fileName of patchedFiles) { + for (var fileName in patchedFiles) { if (typeof patchedFiles[fileName] === 'string') { fs.writeFileSync(path.resolve(relative, fileName), patchedFiles[fileName]); } else { diff --git a/src/lib/protect/patch.js b/src/lib/protect/patch.js index 26513cb787..e349a3c43d 100644 --- a/src/lib/protect/patch.js +++ b/src/lib/protect/patch.js @@ -72,15 +72,17 @@ function patch(vulns, live) { return reject(error); } - resolve(Promise.all(files.filter(function (file) { + var origFiles = files.filter(function (file) { return file.slice(-5) === '.orig'; - }).map(function (file) { - return fs.rename(file, path.dirname(file) + '/' + + }); + + for (var file of origFiles) { + fs.renameSync(file, path.dirname(file) + '/' + path.basename(file).slice(0, -5)); - }))); + } + + resolve(patch); }); - }).then(function () { - return patch; }); }); }).then(function (patch) { diff --git a/test/protect-apply-same-patch-again.test.js b/test/protect-apply-same-patch-again.test.js index 473070a838..d513bcbc6e 100644 --- a/test/protect-apply-same-patch-again.test.js +++ b/test/protect-apply-same-patch-again.test.js @@ -32,8 +32,8 @@ const patch = proxyquire('../src/lib/protect/patch', { }); test('setup', (t) => { - fs.createReadStream(fixturesModuleFolder + '/node-fixture.js') - .pipe(fs.createWriteStream(fixturesModuleFolder + '/node.js')); + var fixture = fs.readFileSync(fixturesModuleFolder + '/node-fixture.js'); + fs.writeFileSync(fixturesModuleFolder + '/node.js', fixture); t.pass(); t.end(); }); @@ -44,13 +44,13 @@ test('Same patch is applied multiple times without issue', (t) => { fs.readdir(fixturesBaseFolder, (err, fileNames) => { const fixturesBaseFolderFiles = fileNames || []; - if (err || fixturesBaseFolderFiles.length == 0) { + if (err || fixturesBaseFolderFiles.length === 0) { console.log(`ERROR: Could not remove the .snyk-***.flag | ${err}`); return; } fixturesBaseFolderFiles.forEach((file) => { - const flagMatch = file.match(/\.snyk.*\.flag/) + const flagMatch = file.match(/\.snyk.*\.flag/); if (flagMatch) { fs.unlink(fixturesBaseFolder + file); } @@ -60,7 +60,7 @@ test('Same patch is applied multiple times without issue', (t) => { fs.readdir(fixturesModuleFolder, (err, fileNames) => { const fixturesModuleFolderFiles = fileNames || []; - if (err || fixturesModuleFolderFiles.length == 0) { + if (err || fixturesModuleFolderFiles.length === 0) { return; } @@ -100,5 +100,5 @@ test('Same patch is applied multiple times without issue', (t) => { t.pass(); t.end(); }) - .catch(t.threw); + .catch(t.fail); });