| /* |
| * Copyright 2015-2016 IBM Corporation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| var fs = require('fs'), |
| JsDiff = require('diff'); |
| |
| var outstandingDiffs = {}; |
| |
| function entityKey(namespace, name) { |
| return '/' + namespace + '/' + name; |
| } |
| |
| exports.getOutstandingDiff = function getOutstandingDiff(entity, namespace) { |
| namespace = namespace || entity.namespace; |
| var name = entity.name || entity; |
| return outstandingDiffs[entityKey(namespace, name)]; |
| }; |
| exports.clearOutstandingDiff = function clearOutstandingDiff(entity, namespace) { |
| namespace = namespace || entity.namespace; |
| var name = entity.name || entity; |
| delete outstandingDiffs[entityKey(namespace, name)]; |
| }; |
| |
| exports.applyPatch = function applyPatch(data, patch) { |
| var lines = data.split('\n'); |
| var newLines = []; |
| var dataIndex = 1; |
| |
| if (!patch.hunks) { |
| // |
| // patch is a textual unified diff. parse it |
| // |
| patch = JsDiff.parsePatch(patch)[0]; |
| } |
| |
| patch.hunks.forEach((hunk, hunkIndex) => { |
| for (var i = dataIndex; i < hunk.oldStart; i++) { |
| newLines.push(lines[i - 1]); |
| } |
| |
| hunk.lines.forEach( (line, index) => { |
| if (line.charAt(0) === '+') { |
| // new line |
| newLines.push(line.slice(1)); |
| |
| } else if (line.charAt(0) === '-') { |
| // removed line |
| dataIndex++; |
| |
| } else if (line.charAt(0) !== '\\') { |
| // patch doesn't say anything about this line |
| newLines.push(lines[dataIndex++ - 1]); |
| } |
| }); |
| |
| dataIndex = hunk.oldStart + hunk.oldLines + 1; |
| |
| if (hunkIndex === patch.hunks.length - 1) { |
| for (i = dataIndex - 1; i < lines.length; i++) { |
| newLines.push(lines[i]); |
| } |
| } |
| }); |
| |
| return newLines.join('\n'); |
| }; |
| |
| exports.checkIfFileChanged = function checkIfFileChanged(data1, f2, removeBootstrapPatch) { |
| return new Promise((resolve, reject) => { |
| fs.readFile(f2, (err2, data2) => { |
| try { |
| if (err2) { |
| console.error('Error reading file', err2); |
| reject(err2); |
| } else { |
| data2 = data2.toString(); |
| |
| if (removeBootstrapPatch) { |
| try { |
| data2 = exports.applyPatch(data2, removeBootstrapPatch); |
| } catch (err) { |
| console.error('Error applying patch', err); |
| console.error(removeBootstrapPatch); |
| console.error(err.stack); |
| } |
| } |
| |
| var comparo; |
| try { |
| comparo = JsDiff.createPatch('wskdb', data1, data2); |
| } catch (err) { |
| console.error('Error creating patch', err); |
| console.error('D1', data1); |
| console.error('D2', data2); |
| console.error(err.stack); |
| } |
| if (comparo && comparo.indexOf('@@') >= 0) { |
| resolve(comparo); |
| } else { |
| reject(false); |
| } |
| } |
| } catch (err) { |
| console.error('Error creating diff', err); |
| reject(err); |
| } |
| }); |
| }); |
| }; |
| |
| exports.removeIfNotChanged = function removeIfNotChanged(data1, f2, cleanupF2, removeBootstrapPatch) { |
| return exports.checkIfFileChanged(data1, f2, removeBootstrapPatch).catch(cleanupF2); |
| }; |
| |
| exports.rememberIfChanged = function rememberIfChanged(action, f2, cleanupF2, removeBootstrapPatch) { |
| return exports.removeIfNotChanged(action.exec.code, f2, cleanupF2, removeBootstrapPatch) |
| .then(comparo => { |
| if (comparo) { |
| outstandingDiffs[entityKey(action.namespace, action.name)] = { |
| action: action, |
| comparo: comparo |
| }; |
| } |
| }); |
| }; |
| |
| exports.createPatch = function(data1, data2) { |
| return JsDiff.structuredPatch('wskdb', 'wskdb', data1, data2); |
| }; |