diff options
Diffstat (limited to 'extensions/Splinter/web')
-rw-r--r-- | extensions/Splinter/web/splinter.css | 5 | ||||
-rw-r--r-- | extensions/Splinter/web/splinter.js | 80 |
2 files changed, 69 insertions, 16 deletions
diff --git a/extensions/Splinter/web/splinter.css b/extensions/Splinter/web/splinter.css index 014751b08..9f994eac9 100644 --- a/extensions/Splinter/web/splinter.css +++ b/extensions/Splinter/web/splinter.css @@ -235,6 +235,11 @@ div.review-patch-comment-text { font-weight: bold; } +.file-label-extra { + font-size: 90%; + font-style: italic; +} + .hunk-header td { background: #ddccbb; font-family: "DejaVu Sans Mono", monospace; diff --git a/extensions/Splinter/web/splinter.js b/extensions/Splinter/web/splinter.js index 18f445325..8902a3d74 100644 --- a/extensions/Splinter/web/splinter.js +++ b/extensions/Splinter/web/splinter.js @@ -232,11 +232,21 @@ Splinter.Patch = { NEW_NONEWLINE : 1 << 3, OLD_NONEWLINE : 1 << 4, - FILE_START_RE : /^(?:(?:Index|index|===|RCS|diff).*\n)*\-\-\-[ \t]*(\S+).*\n\+\+\+[ \t]*(\S+).*\n(?=@@)/mg, + FILE_START_RE : new RegExp( + '^(?:' + // start of optional header + '(?:Index|index|===|RCS|diff)[^\\n]*\\n' + // header + '(?:(?:copy|rename) from [^\\n]+\\n)?' + // git copy/rename from + '(?:(?:copy|rename) to [^\\n]+\\n)?' + // git copy/rename to + ')*' + // end of optional header + '\\-\\-\\-[ \\t]*(\\S+).*\\n' + // --- line + '\\+\\+\\+[ \\t]*(\\S+).*\\n' + // +++ line + '(?=@@)', // @@ line + 'mg' + ), HUNK_START_RE : /^@@[ \t]+-(\d+),(\d+)[ \t]+\+(\d+),(\d+)[ \t]+@@(.*)\n/mg, HUNK_RE : /((?:[ +\\-].*(?:\n|$))*)/mg, - GIT_FILE_RE : /^diff --git a\/(\S+).*\n(?:(new|deleted) file mode \d+\n)?(?:index.*\n)?GIT binary patch\n(delta )?/mg, + GIT_BINARY_RE : /^diff --git a\/(\S+).*\n(?:(new|deleted) file mode \d+\n)?(?:index.*\n)?GIT binary patch\n(delta )?/mg, _cleanIntro : function(intro) { var m; @@ -389,14 +399,15 @@ Splinter.Patch.Hunk.prototype = { } }; -Splinter.Patch.File = function(filename, status, hunks) { - this._init(filename, status, hunks); +Splinter.Patch.File = function(filename, status, extra, hunks) { + this._init(filename, status, extra, hunks); }; Splinter.Patch.File.prototype = { - _init : function(filename, status, hunks) { + _init : function(filename, status, extra, hunks) { this.filename = filename; this.status = status; + this.extra = extra; this.hunks = hunks; this.fileReviewed = false; @@ -474,7 +485,7 @@ Splinter.Patch.Patch.prototype = { this.files = []; var m = Splinter.Patch.FILE_START_RE.exec(text); - var bm = Splinter.Patch.GIT_FILE_RE.exec(text); + var bm = Splinter.Patch.GIT_BINARY_RE.exec(text); if (m == null && bm == null) throw "Not a patch"; this.intro = m == null ? '' : Splinter.Patch._cleanIntro(text.substring(0, m.index)); @@ -491,18 +502,19 @@ Splinter.Patch.Patch.prototype = { // delta this.intro += 'Modified Binary File: ' + bm[1] + "\n"; } - bm = Splinter.Patch.GIT_FILE_RE.exec(text); + bm = Splinter.Patch.GIT_BINARY_RE.exec(text); } while (m != null) { - // git and hg show a diff between a/foo/bar.c and b/foo/bar.c - // or between a/foo/bar.c and /dev/null for removals and the - // reverse for additions. + // git shows a diff between a/foo/bar.c and b/foo/bar.c or between + // a/foo/bar.c and /dev/null for removals and the reverse for + // additions. var filename; var status = undefined; + var extra = undefined; if (/^a\//.test(m[1]) && /^b\//.test(m[2])) { - filename = m[1].substring(2); + filename = m[2].substring(2); status = Splinter.Patch.CHANGED; } else if (/^a\//.test(m[1]) && /^\/dev\/null/.test(m[2])) { filename = m[1].substring(2); @@ -510,7 +522,7 @@ Splinter.Patch.Patch.prototype = { } else if (/^\/dev\/null/.test(m[1]) && /^b\//.test(m[2])) { filename = m[2].substring(2); status = Splinter.Patch.ADDED; - // Handle non-git and non-hg cases as well + // Handle non-git cases as well } else if (!/^\/dev\/null/.test(m[1]) && /^\/dev\/null/.test(m[2])) { filename = m[1]; status = Splinter.Patch.REMOVED; @@ -521,6 +533,25 @@ Splinter.Patch.Patch.prototype = { filename = m[1]; } + // look for rename/copy + if (/^diff /.test(m[0])) { + // possibly git + var lines = m[0].split(/\n/); + for (var i = 0, il = lines.length; i < il && !extra; i++) { + var line = lines[i]; + if (line != '' && !/^(?:diff|---|\+\+\+) /.test(line)) { + if (/^copy from /.test(line)) + extra = 'copied from ' + m[1].substring(2); + if (/^rename from /.test(line)) + extra = 'renamed from ' + m[1].substring(2); + } + } + } else if (/^=== renamed /.test(m[0])) { + // bzr + filename = m[2]; + extra = 'renamed from ' + m[1]; + } + var hunks = []; var pos = Splinter.Patch.FILE_START_RE.lastIndex; while (true) { @@ -547,9 +578,10 @@ Splinter.Patch.Patch.prototype = { } if (status === undefined) { - // For non-Hg/Git we use assume patch was generated non-zero context - // and just look at the patch to detect added/removed. Bzr actually - // says added/removed in the diff, but SVN/CVS don't + // For non-Git we use assume patch was generated non-zero + // context and just look at the patch to detect added/removed. + // Bzr actually says added/removed in the diff, but SVN/CVS + // don't if (hunks.length == 1 && hunks[0].oldCount == 0) { status = Splinter.Patch.ADDED; } else if (hunks.length == 1 && hunks[0].newCount == 0) { @@ -559,7 +591,7 @@ Splinter.Patch.Patch.prototype = { } } - this.files.push(new Splinter.Patch.File(filename, status, hunks)); + this.files.push(new Splinter.Patch.File(filename, status, extra, hunks)); Splinter.Patch.FILE_START_RE.lastIndex = pos; m = Splinter.Patch.FILE_START_RE.exec(text); @@ -1961,6 +1993,20 @@ Splinter.addPatchFile = function (file) { fileReviewedLabel.appendChild(document.createTextNode(' Reviewed')); fileReviewedLabel.appendTo(fileReviewed); + if (file.extra) { + var extraContainer = new Element(document.createElement('div')); + Dom.addClass(extraContainer, 'file-extra-container'); + var extraMargin = new Element(document.createElement('span')); + Dom.addClass(extraMargin, 'file-label-collapse'); + extraMargin.appendChild(document.createTextNode('\u00a0\u00a0\u00a0')); + extraMargin.appendTo(extraContainer); + var extraLabel = new Element(document.createElement('span')); + Dom.addClass(extraLabel, 'file-label-extra'); + extraLabel.appendChild(document.createTextNode(file.extra)); + extraLabel.appendTo(extraContainer); + extraContainer.appendTo(fileLabel); + } + var lastHunk = file.hunks[file.hunks.length - 1]; var lastLine = Math.max(lastHunk.oldStart + lastHunk.oldCount - 1, lastHunk.newStart + lastHunk.newCount - 1); @@ -2145,11 +2191,13 @@ Splinter.toggleCollapsed = function (filename, display) { var file = Splinter.thePatch.files[i]; if (!filename || filename == file.filename) { var fileTableContainer = file.div.getElementsByClassName('file-table-container')[0]; + var fileExtraContainer = file.div.getElementsByClassName('file-extra-container')[0]; var fileCollapseLink = file.div.getElementsByClassName('file-label-collapse')[0]; if (!display) { display = Dom.getStyle(fileTableContainer, 'display') == 'block' ? 'none' : 'block'; } Dom.setStyle(fileTableContainer, 'display', display); + Dom.setStyle(fileExtraContainer, 'display', display); fileCollapseLink.innerHTML = display == 'block' ? '[-]' : '[+]'; } } |