From b08044fc1842388ac2ebe7783504b9ead6230ed1 Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Wed, 10 Aug 2016 03:08:18 -0400 Subject: [PATCH] Adds blame "references" (wip) --- blame.png | Bin 0 -> 3340 bytes package.json | 6 +++ src/codeLensProvider.ts | 72 ++++++++++++++++++++++------------ src/constants.ts | 15 ++++++++ src/contentProvider.ts | 81 +++++++++++++++++++++++++++++++++++++++ src/definitionProvider.ts | 21 ++++++++++ src/extension.ts | 12 +++++- src/git.ts | 75 ++++++++++++++++++++++++++++-------- typings.json | 5 +++ typings/globals/tmp/index.d.ts | 45 ++++++++++++++++++++++ typings/globals/tmp/typings.json | 8 ++++ typings/index.d.ts | 1 + 12 files changed, 298 insertions(+), 43 deletions(-) create mode 100644 blame.png create mode 100644 src/constants.ts create mode 100644 src/contentProvider.ts create mode 100644 src/definitionProvider.ts create mode 100644 typings.json create mode 100644 typings/globals/tmp/index.d.ts create mode 100644 typings/globals/tmp/typings.json create mode 100644 typings/index.d.ts diff --git a/blame.png b/blame.png new file mode 100644 index 0000000000000000000000000000000000000000..2152961cf1942aa7db2170539bd42a7f6659d15e GIT binary patch literal 3340 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 literal 0 HcmV?d00001 diff --git a/package.json b/package.json index 32c72b8..21936f2 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,11 @@ ], "main": "./out/src/extension", "contributes": { + "commands": [{ + "command": "git.codelen.showBlameHistory", + "title": "Show Blame History", + "category": "Git" + }] }, "scripts": { "vscode:prepublish": "node ./node_modules/vscode/bin/compile", @@ -26,6 +31,7 @@ "postinstall": "node ./node_modules/vscode/bin/install && tsc" }, "dependencies": { + "tmp": "^0.0.28" }, "devDependencies": { "typescript": "^1.8.10", diff --git a/src/codeLensProvider.ts b/src/codeLensProvider.ts index 20a60a4..e385f4f 100644 --- a/src/codeLensProvider.ts +++ b/src/codeLensProvider.ts @@ -1,15 +1,21 @@ 'use strict'; -import {CancellationToken, CodeLens, CodeLensProvider, commands, Range, SymbolInformation, SymbolKind, TextDocument, Uri} from 'vscode'; -import {IBlameLine, gitBlame} from './git'; +import {CancellationToken, CodeLens, CodeLensProvider, commands, Location, Range, SymbolInformation, SymbolKind, TextDocument, Uri} from 'vscode'; +import {Commands, VsCodeCommands} from './constants'; +import {IGitBlameLine, gitBlame} from './git'; +import {toGitBlameUri} from './contentProvider'; import * as moment from 'moment'; export class GitCodeLens extends CodeLens { - constructor(public blame: Promise, public fileName: string, public blameRange: Range, range: Range) { + constructor(private blame: Promise, public repoPath: string, public fileName: string, private blameRange: Range, range: Range) { super(range); + } + + getBlameLines(): Promise { + return this.blame.then(allLines => allLines.slice(this.blameRange.start.line, this.blameRange.end.line + 1)); + } - this.blame = blame; - this.fileName = fileName; - this.blameRange = blameRange; + static toUri(lens: GitCodeLens, line: IGitBlameLine, lines: IGitBlameLine[]): Uri { + return toGitBlameUri(Object.assign({ repoPath: lens.repoPath, range: lens.blameRange, lines: lines }, line)); } } @@ -20,14 +26,14 @@ export default class GitCodeLensProvider implements CodeLensProvider { // TODO: Should I wait here? let blame = gitBlame(document.fileName); - return (commands.executeCommand('vscode.executeDocumentSymbolProvider', document.uri) as Promise).then(symbols => { + return (commands.executeCommand(VsCodeCommands.ExecuteDocumentSymbolProvider, document.uri) as Promise).then(symbols => { let lenses: CodeLens[] = []; symbols.forEach(sym => this._provideCodeLens(document, sym, blame, lenses)); return lenses; }); } - private _provideCodeLens(document: TextDocument, symbol: SymbolInformation, blame: Promise, lenses: CodeLens[]): void { + private _provideCodeLens(document: TextDocument, symbol: SymbolInformation, blame: Promise, lenses: CodeLens[]): void { switch (symbol.kind) { case SymbolKind.Module: case SymbolKind.Class: @@ -43,30 +49,46 @@ export default class GitCodeLensProvider implements CodeLensProvider { } var line = document.lineAt(symbol.location.range.start); - // if (line.text.includes(symbol.name)) { - // } - - let lens = new GitCodeLens(blame, document.fileName, symbol.location.range, line.range); + let lens = new GitCodeLens(blame, this.repoPath, document.fileName, symbol.location.range, line.range); lenses.push(lens); } - resolveCodeLens(codeLens: CodeLens, token: CancellationToken): Thenable { - if (codeLens instanceof GitCodeLens) { - return codeLens.blame.then(allLines => { - let lines = allLines.slice(codeLens.blameRange.start.line, codeLens.blameRange.end.line + 1); - let line = lines[0]; + resolveCodeLens(lens: CodeLens, token: CancellationToken): Thenable { + if (lens instanceof GitCodeLens) { + return lens.getBlameLines().then(lines => { + let recentLine = lines[0]; + + let locations: Location[] = []; if (lines.length > 1) { - let sorted = lines.sort((a, b) => b.date.getTime() - a.date.getTime()); - line = sorted[0]; + let sorted = lines.sort((a, b) => a.date.getTime() - b.date.getTime()); + recentLine = sorted[sorted.length - 1]; + + console.log(lens.fileName, 'Blame lines:', sorted); + + let map: Map = new Map(); + sorted.forEach(l => { + let item = map.get(l.sha); + if (item) { + item.push(l); + } else { + map.set(l.sha, [l]); + } + }); + + locations = Array.from(map.values()).map(l => new Location(GitCodeLens.toUri(lens, l[0], l), lens.range.start)) + } else { + locations = [new Location(GitCodeLens.toUri(lens, recentLine, lines), lens.range.start)]; } - codeLens.command = { - title: `${line.author}, ${moment(line.date).fromNow()}`, - command: 'git.viewFileHistory', - arguments: [Uri.file(codeLens.fileName)] + lens.command = { + title: `${recentLine.author}, ${moment(recentLine.date).fromNow()}`, + command: Commands.ShowBlameHistory, + arguments: [Uri.file(lens.fileName), lens.range.start, locations] + // command: 'git.viewFileHistory', + // arguments: [Uri.file(codeLens.fileName)] }; - return codeLens; - });//.catch(ex => Promise.reject(ex)); // TODO: Figure out a better way to stop the codelens from appearing + return lens; + }).catch(ex => Promise.reject(ex)); // TODO: Figure out a better way to stop the codelens from appearing } } } diff --git a/src/constants.ts b/src/constants.ts new file mode 100644 index 0000000..43d3d8d --- /dev/null +++ b/src/constants.ts @@ -0,0 +1,15 @@ +export type Commands = 'git.action.showBlameHistory'; +export const Commands = { + ShowBlameHistory: 'git.action.showBlameHistory' as Commands +} + +export type DocumentSchemes = 'gitblame'; +export const DocumentSchemes = { + GitBlame: 'gitblame' as DocumentSchemes +} + +export type VsCodeCommands = 'vscode.executeDocumentSymbolProvider' | 'editor.action.showReferences'; +export const VsCodeCommands = { + ExecuteDocumentSymbolProvider: 'vscode.executeDocumentSymbolProvider' as VsCodeCommands, + ShowReferences: 'editor.action.showReferences' as VsCodeCommands +} \ No newline at end of file diff --git a/src/contentProvider.ts b/src/contentProvider.ts new file mode 100644 index 0000000..269a2d1 --- /dev/null +++ b/src/contentProvider.ts @@ -0,0 +1,81 @@ +'use strict'; +import {Disposable, EventEmitter, ExtensionContext, Location, OverviewRulerLane, Range, TextEditorDecorationType, TextDocumentContentProvider, Uri, window, workspace} from 'vscode'; +import {DocumentSchemes} from './constants'; +import {gitGetVersionFile, gitGetVersionText, IGitBlameLine} from './git'; +import {basename, dirname, extname} from 'path'; +import * as moment from 'moment'; + +export default class GitBlameContentProvider implements TextDocumentContentProvider { + static scheme = DocumentSchemes.GitBlame; + + private _blameDecoration: TextEditorDecorationType; + private _onDidChange = new EventEmitter(); + + constructor(context: ExtensionContext) { + let image = context.asAbsolutePath('blame.png'); + this._blameDecoration = window.createTextEditorDecorationType({ + backgroundColor: 'rgba(21, 251, 126, 0.7)', + gutterIconPath: image, + gutterIconSize: 'auto' + }); + } + + dispose() { + this._onDidChange.dispose(); + } + + get onDidChange() { + return this._onDidChange.event; + } + + public update(uri: Uri) { + this._onDidChange.fire(uri); + } + + provideTextDocumentContent(uri: Uri): string | Thenable { + const data = fromGitBlameUri(uri); + + console.log('provideTextDocumentContent', uri, data); + return gitGetVersionText(data.repoPath, data.sha, data.file).then(text => { + this.update(uri); + + setTimeout(() => { + let uriString = uri.toString(); + let editor = window.visibleTextEditors.find((e: any) => (e._documentData && e._documentData._uri && e._documentData._uri.toString()) === uriString); + if (editor) { + editor.setDecorations(this._blameDecoration, data.lines.map(l => new Range(l.line, 0, l.line, 1))); + } + }, 1500); + + // let foo = text.split('\n'); + // return foo.slice(data.range.start.line, data.range.end.line).join('\n') + return text; + }); + + // return gitGetVersionFile(data.repoPath, data.sha, data.file).then(dst => { + // let uri = Uri.parse(`file:${dst}`) + // return workspace.openTextDocument(uri).then(doc => { + // this.update(uri); + // return doc.getText(); + // }); + // }); + } +} + +export interface IGitBlameUriData extends IGitBlameLine { + repoPath: string, + range: Range, + lines: IGitBlameLine[] +} + +export function toGitBlameUri(data: IGitBlameUriData) { + let ext = extname(data.file); + let path = `${dirname(data.file)}/${data.sha}: ${basename(data.file, ext)}${ext}`; + return Uri.parse(`${DocumentSchemes.GitBlame}:${path}?${JSON.stringify(data)}`); +} + +export function fromGitBlameUri(uri: Uri): IGitBlameUriData { + let data = JSON.parse(uri.query); + data.range = new Range(data.range[0].line, data.range[0].character, data.range[1].line, data.range[1].character); + return data; +} \ No newline at end of file diff --git a/src/definitionProvider.ts b/src/definitionProvider.ts new file mode 100644 index 0000000..8382657 --- /dev/null +++ b/src/definitionProvider.ts @@ -0,0 +1,21 @@ +// 'use strict'; +// import {CancellationToken, CodeLens, commands, DefinitionProvider, Position, Location, TextDocument, Uri} from 'vscode'; +// import {GitCodeLens} from './codeLensProvider'; + +// export default class GitDefinitionProvider implements DefinitionProvider { +// public provideDefinition(document: TextDocument, position: Position, token: CancellationToken): Promise { +// return (commands.executeCommand('vscode.executeCodeLensProvider', document.uri) as Promise).then(lenses => { +// let matches: CodeLens[] = []; +// lenses.forEach(lens => { +// if (lens instanceof GitCodeLens && lens.blameRange.contains(position)) { +// matches.push(lens); +// } +// }); + +// if (matches.length) { +// return new Location(Uri.parse(), position); +// } +// return null; +// }); +// } +// } diff --git a/src/extension.ts b/src/extension.ts index ade6af3..0c0f268 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,7 +1,9 @@ 'use strict'; -import {DocumentSelector, ExtensionContext, languages, workspace} from 'vscode'; +import {commands, DocumentSelector, ExtensionContext, languages, workspace} from 'vscode'; import GitCodeLensProvider from './codeLensProvider'; -import {gitRepoPath} from './git' +import GitContentProvider from './contentProvider'; +import {gitRepoPath} from './git'; +import {Commands, VsCodeCommands} from './constants'; // this method is called when your extension is activated export function activate(context: ExtensionContext) { @@ -11,6 +13,12 @@ export function activate(context: ExtensionContext) { } gitRepoPath(workspace.rootPath).then(repoPath => { + context.subscriptions.push(workspace.registerTextDocumentContentProvider(GitContentProvider.scheme, new GitContentProvider(context))); + + context.subscriptions.push(commands.registerCommand(Commands.ShowBlameHistory, (...args) => { + return commands.executeCommand(VsCodeCommands.ShowReferences, ...args); + })); + let selector: DocumentSelector = { scheme: 'file' }; context.subscriptions.push(languages.registerCodeLensProvider(selector, new GitCodeLensProvider(repoPath))); }).catch(reason => console.warn(reason)); diff --git a/src/git.ts b/src/git.ts index 8f2f94a..0ff3acb 100644 --- a/src/git.ts +++ b/src/git.ts @@ -1,13 +1,17 @@ 'use strict'; import {spawn} from 'child_process'; -import {dirname} from 'path'; +import {basename, dirname, extname} from 'path'; +import * as fs from 'fs'; +import * as tmp from 'tmp'; -export declare interface IBlameLine { - line: number; +export declare interface IGitBlameLine { + sha: string; + file: string; + originalLine: number; author: string; date: Date; - sha: string; - //code: string; + line: number; + code: string; } export function gitRepoPath(cwd) { @@ -22,33 +26,72 @@ export function gitRepoPath(cwd) { }); } -const blameMatcher = /^(.*)\t\((.*)\t(.*)\t(.*?)\)(.*)$/gm; +//const blameMatcher = /^(.*)\t\((.*)\t(.*)\t(.*?)\)(.*)$/gm; +const blameMatcher = /^([0-9a-fA-F]{8})\s([\S]*)\s([0-9\S]+)\s\((.*?)\s([0-9]{4}-[0-9]{2}-[0-9]{2}\s[0-9]{2}:[0-9]{2}:[0-9]{2}\s[-|+][0-9]{4})\s([0-9]+)\)(.*)$/gm; -export function gitBlame(fileName: string) { +export function gitBlame(fileName: string): Promise { const mapper = (input, output) => { + let blame = input.toString(); + console.log(fileName, 'Blame:', blame); + let m: Array; - while ((m = blameMatcher.exec(input.toString())) != null) { + while ((m = blameMatcher.exec(blame)) != null) { output.push({ - line: parseInt(m[4], 10), - author: m[2], - date: new Date(m[3]), - sha: m[1] - //code: m[5] + sha: m[1], + file: m[2].trim(), + originalLine: parseInt(m[3], 10), + author: m[4].trim(), + date: new Date(m[5]), + line: parseInt(m[6], 10), + code: m[7] }); } }; - return gitCommand(dirname(fileName), mapper, 'blame', '-c', '-M', '-w', '--', fileName) as Promise; + return gitCommand(dirname(fileName), mapper, 'blame', '-fnw', '--', fileName); +} + +export function gitGetVersionFile(repoPath: string, sha: string, source: string): Promise { + const mapper = (input, output) => output.push(input); + + return new Promise((resolve, reject) => { + (gitCommand(repoPath, mapper, 'show', `${sha}:${source.replace(/\\/g, '/')}`) as Promise>).then(o => { + let ext = extname(source); + tmp.file({ prefix: `${basename(source, ext)}-${sha}_`, postfix: ext }, (err, destination, fd, cleanupCallback) => { + if (err) { + reject(err); + return; + } + + console.log("File: ", destination); + console.log("Filedescriptor: ", fd); + + fs.appendFile(destination, o.join(), err => { + if (err) { + reject(err); + return; + } + resolve(destination); + }); + }); + }); + }); +} + +export function gitGetVersionText(repoPath: string, sha: string, source: string): Promise { + const mapper = (input, output) => output.push(input.toString()); + + return new Promise((resolve, reject) => (gitCommand(repoPath, mapper, 'show', `${sha}:${source.replace(/\\/g, '/')}`) as Promise>).then(o => resolve(o.join()))); } -function gitCommand(cwd: string, map: (input: Buffer, output: Array) => void, ...args): Promise { +function gitCommand(cwd: string, mapper: (input: Buffer, output: Array) => void, ...args): Promise { return new Promise((resolve, reject) => { let spawn = require('child_process').spawn; let process = spawn('git', args, { cwd: cwd }); let output: Array = []; process.stdout.on('data', data => { - map(data, output); + mapper(data, output); }); let errors: Array = []; diff --git a/typings.json b/typings.json new file mode 100644 index 0000000..89a1408 --- /dev/null +++ b/typings.json @@ -0,0 +1,5 @@ +{ + "globalDependencies": { + "tmp": "registry:dt/tmp#0.0.0+20160514170650" + } +} diff --git a/typings/globals/tmp/index.d.ts b/typings/globals/tmp/index.d.ts new file mode 100644 index 0000000..5ae8593 --- /dev/null +++ b/typings/globals/tmp/index.d.ts @@ -0,0 +1,45 @@ +// Generated by typings +// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/5d6115f046550714a28caa3555f47a1aec114fe5/tmp/tmp.d.ts +declare module "tmp" { + + namespace tmp { + interface Options extends SimpleOptions { + mode?: number; + } + + interface SimpleOptions { + prefix?: string; + postfix?: string; + template?: string; + dir?: string; + tries?: number; + keep?: boolean; + unsafeCleanup?: boolean; + } + + interface SynchrounousResult { + name: string; + fd: number; + removeCallback: () => void; + } + + function file(callback: (err: any, path: string, fd: number, cleanupCallback: () => void) => void): void; + function file(config: Options, callback?: (err: any, path: string, fd: number, cleanupCallback: () => void) => void): void; + + function fileSync(config?: Options): SynchrounousResult; + + function dir(callback: (err: any, path: string, cleanupCallback: () => void) => void): void; + function dir(config: Options, callback?: (err: any, path: string, cleanupCallback: () => void) => void): void; + + function dirSync(config?: Options): SynchrounousResult; + + function tmpName(callback: (err: any, path: string) => void): void; + function tmpName(config: SimpleOptions, callback?: (err: any, path: string) => void): void; + + function tmpNameSync(config?: SimpleOptions): string; + + function setGracefulCleanup(): void; + } + + export = tmp; +} diff --git a/typings/globals/tmp/typings.json b/typings/globals/tmp/typings.json new file mode 100644 index 0000000..f69d10a --- /dev/null +++ b/typings/globals/tmp/typings.json @@ -0,0 +1,8 @@ +{ + "resolution": "main", + "tree": { + "src": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/5d6115f046550714a28caa3555f47a1aec114fe5/tmp/tmp.d.ts", + "raw": "registry:dt/tmp#0.0.0+20160514170650", + "typings": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/5d6115f046550714a28caa3555f47a1aec114fe5/tmp/tmp.d.ts" + } +} diff --git a/typings/index.d.ts b/typings/index.d.ts new file mode 100644 index 0000000..f98d791 --- /dev/null +++ b/typings/index.d.ts @@ -0,0 +1 @@ +///