From e99febb52ddbc95e888ac76d5ee2d2412516e679 Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Sat, 27 May 2017 02:39:10 -0400 Subject: [PATCH] Adds diff info to active line hover always --- src/blameActiveLineController.ts | 33 ++++++++++++--------------- src/git/models/diff.ts | 19 ++++++++-------- src/git/parsers/diffParser.ts | 39 ++++++++++++++++++++++++-------- src/gitService.ts | 29 ++++++++++++++++++++---- 4 files changed, 78 insertions(+), 42 deletions(-) diff --git a/src/blameActiveLineController.ts b/src/blameActiveLineController.ts index 5f93462..6577f82 100644 --- a/src/blameActiveLineController.ts +++ b/src/blameActiveLineController.ts @@ -298,30 +298,25 @@ export class BlameActiveLineController extends Disposable { if (!commit.isUncommitted && (!possibleDuplicate || !this.annotationController.isAnnotating(editor))) { hoverMessage = BlameAnnotationFormatter.getAnnotationHover(cfg, blameLine, logCommit || commit); - // if (commit.previousSha !== undefined) { - // const changes = await this.git.getDiffForLine(this._uri, blameLine.line + offset, commit.previousSha); - // if (changes !== undefined) { - // const previous = changes[0]; - // if (previous !== undefined) { - // hoverMessage += `\n\n\`Before ${commit.shortSha}\`\n\`\`\`\n${previous.trim().replace(/\n/g, '\`\n>\n> \`')}\n\`\`\``; - // } - // else { - // hoverMessage += `\n\n\`Added in ${commit.shortSha}\``; - // } - // } - // } + if (commit.previousSha !== undefined) { + const changes = await this.git.getDiffForLine(this._uri, blameLine.line + offset, commit.previousSha); + if (changes !== undefined) { + let previous = changes[0]; + if (previous !== undefined) { + previous = previous.replace(/\n/g, '\`\n>\n> \`').trim(); + hoverMessage += `\n\n---\n\`\`\`\n${previous}\n\`\`\``; + } + } + } } else if (commit.isUncommitted) { const changes = await this.git.getDiffForLine(this._uri, blameLine.line + offset); if (changes !== undefined) { - let original = changes[0]; - if (original !== undefined) { - original = original.replace(/\n/g, '\`\n>\n> \`').trim(); - hoverMessage = `\`${'0'.repeat(8)}\`   __Uncommitted change__\n\n\---\n\`\`\`\n${original}\n\`\`\``; + let previous = changes[0]; + if (previous !== undefined) { + previous = previous.replace(/\n/g, '\`\n>\n> \`').trim(); + hoverMessage = `\`${'0'.repeat(8)}\`   __Uncommitted change__\n\n---\n\`\`\`\n${previous}\n\`\`\``; } - // else { - // hoverMessage = `\`${'0'.repeat(8)}\`   __Uncommitted change__\n\n\`Added\``; - // } } } } diff --git a/src/git/models/diff.ts b/src/git/models/diff.ts index 6bda031..a52cf5d 100644 --- a/src/git/models/diff.ts +++ b/src/git/models/diff.ts @@ -1,18 +1,19 @@ 'use strict'; export interface IGitDiffChunk { + current: (string | undefined)[]; + currentStart: number; + currentEnd: number; + + previous: (string | undefined)[]; + previousStart: number; + previousEnd: number; + chunk?: string; - - original: (string | undefined)[]; - originalStart: number; - originalEnd: number; - - changes: (string | undefined)[]; - changesStart: number; - changesEnd: number; } export interface IGitDiff { - diff?: string; chunks: IGitDiffChunk[]; + + diff?: string; } \ No newline at end of file diff --git a/src/git/parsers/diffParser.ts b/src/git/parsers/diffParser.ts index 44f6c3d..0d96cb7 100644 --- a/src/git/parsers/diffParser.ts +++ b/src/git/parsers/diffParser.ts @@ -15,22 +15,41 @@ export class GitDiffParser { match = unifiedDiffRegex.exec(`${data}\n@@`); if (match == null) break; - const originalStart = +match[1]; - const changedStart = +match[3]; + const previousStart = +match[1]; + const currentStart = +match[3]; const chunk = match[5]; const lines = chunk.split('\n').slice(1); - const original = lines.filter(l => l[0] !== '+').map(l => (l[0] === '-') ? l.substring(1) : undefined); - const changed = lines.filter(l => l[0] !== '-').map(l => (l[0] === '+') ? l.substring(1) : undefined); + + const current = []; + const previous = []; + for (const l of lines) { + switch (l[0]) { + case '+': + current.push(` ${l.substring(1)}`); + previous.push(undefined); + break; + + case '-': + current.push(undefined); + previous.push(` ${l.substring(1)}`); + break; + + default: + current.push(l); + previous.push(l); + break; + } + } chunks.push({ chunk: debug ? chunk : undefined, - original: original, - originalStart: originalStart, - originalEnd: originalStart + +match[2], - changes: changed, - changesStart: changedStart, - changesEnd: changedStart + +match[4] + current: current, + currentStart: currentStart, + currentEnd: currentStart + +match[4], + previous: previous, + previousStart: previousStart, + previousEnd: previousStart + +match[2] }); } while (match != null); diff --git a/src/gitService.ts b/src/gitService.ts index 3e0b92c..670d434 100644 --- a/src/gitService.ts +++ b/src/gitService.ts @@ -570,6 +570,10 @@ export class GitService extends Disposable { } async getDiffForFile(uri: GitUri, sha1?: string, sha2?: string): Promise { + if (sha1 !== undefined && sha2 === undefined && uri.sha !== undefined) { + sha2 = uri.sha; + } + let key = 'diff'; if (sha1 !== undefined) { key += `:${sha1}`; @@ -620,7 +624,7 @@ export class GitService extends Disposable { try { const data = await Git.diff(root, file, sha1, sha2); - return GitDiffParser.parse(data, this.config.debug); + return GitDiffParser.parse(data); } catch (ex) { // Trap and cache expected diff errors @@ -645,12 +649,29 @@ export class GitService extends Disposable { const diff = await this.getDiffForFile(uri, sha1, sha2); if (diff === undefined) return undefined; - const chunk = diff.chunks.find(_ => Math.min(_.originalStart, _.changesStart) <= line && Math.max(_.originalEnd, _.changesEnd) >= line); + const chunk = diff.chunks.find(_ => _.currentStart <= line && _.currentEnd >= line); if (chunk === undefined) return undefined; + // Search for the line (skipping deleted lines -- since they don't currently exist in the editor) + // Keep track of the deleted lines for the original version + line = line - chunk.currentStart + 1; + let count = 0; + let deleted = 0; + for (const l of chunk.current) { + if (l === undefined) { + deleted++; + if (count === line) break; + + continue; + } + + if (count === line) break; + count++; + } + return [ - chunk.original[line - chunk.originalStart + 1], - chunk.changes[line - chunk.changesStart + 1] + chunk.previous[line + deleted - 1], + chunk.current[line + deleted] ]; } catch (ex) {