-
Notifications
You must be signed in to change notification settings - Fork 510
Allow access to structured object representation of patch data #62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
b257c31
bc11bcc
8209a6b
cf44025
b49299a
30189fb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -398,39 +398,22 @@ | |
callback | ||
); | ||
}, | ||
|
||
createTwoFilesPatch: function(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader) { | ||
var ret = []; | ||
|
||
if (oldFileName == newFileName) { | ||
ret.push('Index: ' + oldFileName); | ||
|
||
structuredPatch: function(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) { | ||
if(!options) { | ||
options = { context: 4 }; | ||
} | ||
ret.push('==================================================================='); | ||
ret.push('--- ' + oldFileName + (typeof oldHeader === 'undefined' ? '' : '\t' + oldHeader)); | ||
ret.push('+++ ' + newFileName + (typeof newHeader === 'undefined' ? '' : '\t' + newHeader)); | ||
|
||
|
||
var diff = PatchDiff.diff(oldStr, newStr); | ||
diff.push({value: '', lines: []}); // Append an empty value to make cleanup easier | ||
|
||
// Formats a given set of lines for printing as context lines in a patch | ||
|
||
function contextLines(lines) { | ||
return map(lines, function(entry) { return ' ' + entry; }); | ||
} | ||
|
||
// Outputs the no newline at end of file warning if needed | ||
function eofNL(curRange, i, current) { | ||
var last = diff[diff.length - 2], | ||
isLast = i === diff.length - 2, | ||
isLastOfType = i === diff.length - 3 && current.added !== last.added; | ||
|
||
// Figure out if this is the last line for the given file and missing NL | ||
if (!(/\n$/.test(current.value)) && (isLast || isLastOfType)) { | ||
curRange.push('\\ No newline at end of file'); | ||
} | ||
} | ||
|
||
var hunks = []; | ||
var oldRangeStart = 0, newRangeStart = 0, curRange = [], | ||
oldLine = 1, newLine = 1; | ||
oldLine = 1, newLine = 1; | ||
for (var i = 0; i < diff.length; i++) { | ||
var current = diff[i], | ||
lines = current.lines || current.value.replace(/\n$/, '').split('\n'); | ||
|
@@ -444,7 +427,7 @@ | |
newRangeStart = newLine; | ||
|
||
if (prev) { | ||
curRange = contextLines(prev.lines.slice(-4)); | ||
curRange = options.context > 0 ? contextLines(prev.lines.slice(-options.context)) : []; | ||
oldRangeStart -= curRange.length; | ||
newRangeStart -= curRange.length; | ||
} | ||
|
@@ -454,7 +437,6 @@ | |
curRange.push.apply(curRange, map(lines, function(entry) { | ||
return (current.added ? '+' : '-') + entry; | ||
})); | ||
eofNL(curRange, i, current); | ||
|
||
// Track the updated file position | ||
if (current.added) { | ||
|
@@ -466,21 +448,34 @@ | |
// Identical context lines. Track line changes | ||
if (oldRangeStart) { | ||
// Close out any changes that have been output (or join overlapping) | ||
if (lines.length <= 8 && i < diff.length - 2) { | ||
if (lines.length <= options.context * 2 && i < diff.length - 2) { | ||
// Overlapping | ||
curRange.push.apply(curRange, contextLines(lines)); | ||
} else { | ||
// end the range and output | ||
var contextSize = Math.min(lines.length, 4); | ||
ret.push( | ||
'@@ -' + oldRangeStart + ',' + (oldLine - oldRangeStart + contextSize) | ||
+ ' +' + newRangeStart + ',' + (newLine - newRangeStart + contextSize) | ||
+ ' @@'); | ||
ret.push.apply(ret, curRange); | ||
ret.push.apply(ret, contextLines(lines.slice(0, contextSize))); | ||
if (lines.length <= 4) { | ||
eofNL(ret, i, current); | ||
var contextSize = Math.min(lines.length, options.context); | ||
var hunklines = []; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why was this removed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had trouble adapting its logic to the hunk'd format. Since trying to add no-nl each time we have an add/delete entry seemed inefficient, I opted for a rewrite. |
||
hunklines.push.apply(hunklines, curRange); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just do a |
||
hunklines.push.apply(hunklines, contextLines(lines.slice(0, contextSize))); | ||
|
||
var hunk = { | ||
oldStart: oldRangeStart, | ||
oldLines: (oldLine - oldRangeStart + contextSize), | ||
newStart: newRangeStart, | ||
newLines: (newLine - newRangeStart + contextSize), | ||
lines: hunklines | ||
} | ||
if(i >= diff.length - 2 && lines.length <= options.context) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Style is to have spaces after |
||
// EOF is inside this hunk | ||
var oldEOFNewline = /\n$/.test(oldStr); | ||
var newEOFNewline = /\n$/.test(newStr); | ||
if(lines.length == 0 && !oldEOFNewline) { | ||
hunklines.splice(hunk.oldLines, 0, '\\ No newline at end of file') | ||
} else if (!oldEOFNewline || !newEOFNewline) { | ||
hunklines.push('\\ No newline at end of file') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the difference between these two cases here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. lines.length == 0 && !oldEOFNewline is the special case where no-nl ends up in the middle of hunk. Will add comment to this effect. |
||
} | ||
} | ||
hunks.push(hunk); | ||
|
||
oldRangeStart = 0; | ||
newRangeStart = 0; | ||
|
@@ -491,12 +486,40 @@ | |
newLine += lines.length; | ||
} | ||
} | ||
|
||
return { | ||
oldFileName: oldFileName, newFileName: newFileName, | ||
oldHeader: oldHeader, newHeader: newHeader, | ||
hunks: hunks | ||
}; | ||
}, | ||
|
||
createTwoFilesPatch: function(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) { | ||
var diff = JsDiff.structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options); | ||
|
||
var ret = []; | ||
if (oldFileName == newFileName) { | ||
ret.push('Index: ' + oldFileName); | ||
} | ||
ret.push('==================================================================='); | ||
ret.push('--- ' + diff.oldFileName + (typeof diff.oldHeader === 'undefined' ? '' : '\t' + diff.oldHeader)); | ||
ret.push('+++ ' + diff.newFileName + (typeof diff.newHeader === 'undefined' ? '' : '\t' + diff.newHeader)); | ||
|
||
for(var i = 0; i < diff.hunks.length; i++) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Space after |
||
var hunk = diff.hunks[i]; | ||
ret.push( | ||
'@@ -' + hunk.oldStart + ',' + hunk.oldLines | ||
+ ' +' + hunk.newStart + ',' + hunk.newLines | ||
+ ' @@' | ||
); | ||
ret.push.apply(ret, hunk.lines); | ||
} | ||
|
||
return ret.join('\n') + '\n'; | ||
}, | ||
|
||
createPatch: function(fileName, oldStr, newStr, oldHeader, newHeader) { | ||
return JsDiff.createTwoFilesPatch(fileName, fileName, oldStr, newStr, oldHeader, newHeader); | ||
createPatch: function(fileName, oldStr, newStr, oldHeader, newHeader, options) { | ||
return JsDiff.createTwoFilesPatch(fileName, fileName, oldStr, newStr, oldHeader, newHeader, options); | ||
}, | ||
|
||
applyPatch: function(oldStr, uniDiff) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
const VERBOSE = false; | ||
|
||
var diff = require('../diff'); | ||
|
||
function log() { | ||
VERBOSE && console.log.apply(console, arguments); | ||
} | ||
|
||
describe('#structuredPatch', function() { | ||
it('should handle files with the last line changed', function() { | ||
var res = diff.structuredPatch( | ||
'oldfile', 'newfile', | ||
'line2\nline3\nline4\n', 'line2\nline3\nline5', | ||
'header1', 'header2' | ||
); | ||
res.should.eql({ | ||
oldFileName: 'oldfile', newFileName: 'newfile', | ||
oldHeader: 'header1', newHeader: 'header2', | ||
hunks: [{ | ||
oldStart: 1, oldLines: 3, newStart: 1, newLines: 3, | ||
lines: [' line2', ' line3', '-line4', '+line5', '\\ No newline at end of file'], | ||
}] | ||
}); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This formatting was intentional. Style is to chain vars with
,
and to double indent when newlines are used to line up the var names.