Skip to content

Commit

Permalink
Adds blame and active line annotation support to git diff split view
Browse files Browse the repository at this point in the history
Adds command (compare, copy sha/message, etc) support to git diff split view
Fixes #41 - Toggle Blame annotations on compare files page
  • Loading branch information
eamodio committed Mar 3, 2017
1 parent a3a4a5b commit 4da21c3
Show file tree
Hide file tree
Showing 22 changed files with 65 additions and 47 deletions.
19 changes: 14 additions & 5 deletions src/blameActiveLineController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,15 +107,24 @@ export class BlameActiveLineController extends Disposable {
this._onActiveTextEditorChanged(window.activeTextEditor);
}

private _onActiveTextEditorChanged(editor: TextEditor) {
private isEditorBlameable(editor: TextEditor): boolean {
if (!editor || !editor.document) return false;

const scheme = editor.document.uri.scheme;
if (scheme !== DocumentSchemes.File && scheme !== DocumentSchemes.Git && scheme !== DocumentSchemes.GitLensGit) return false;

if (editor.document.isUntitled && scheme !== DocumentSchemes.Git && scheme !== DocumentSchemes.GitLensGit) return false;

return this.git.isEditorBlameable(editor);
}

private async _onActiveTextEditorChanged(editor: TextEditor) {
this._currentLine = -1;

const previousEditor = this._editor;
previousEditor && previousEditor.setDecorations(activeLineDecoration, []);

if (!editor || !editor.document || (editor.document.isUntitled && editor.document.uri.scheme !== DocumentSchemes.Git) ||
(editor.document.uri.scheme !== DocumentSchemes.File && editor.document.uri.scheme !== DocumentSchemes.Git) ||
(editor.viewColumn === undefined && !this.git.hasGitUriForFile(editor))) {
if (!this.isEditorBlameable(editor)) {
this.clear(editor);

this._editor = undefined;
Expand All @@ -125,7 +134,7 @@ export class BlameActiveLineController extends Disposable {

this._blameable = editor && editor.document && !editor.document.isDirty;
this._editor = editor;
this._uri = GitUri.fromUri(editor.document.uri, this.git);
this._uri = await GitUri.fromUri(editor.document.uri, this.git);
const maxLines = this._config.advanced.caching.statusBar.maxLines;
this._useCaching = this._config.advanced.caching.enabled && (maxLines <= 0 || editor.document.lineCount <= maxLines);
if (this._useCaching) {
Expand Down
14 changes: 6 additions & 8 deletions src/blameAnnotationController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { BlameabilityChangeEvent, BlameabilityTracker } from './blameabilityTrac
import { BlameAnnotationProvider } from './blameAnnotationProvider';
import { TextDocumentComparer, TextEditorComparer } from './comparers';
import { IBlameConfig } from './configuration';
import { GitProvider } from './gitProvider';
import { GitProvider, GitUri } from './gitProvider';
import { Logger } from './logger';
import { WhitespaceController } from './whitespaceController';

Expand Down Expand Up @@ -153,16 +153,16 @@ export class BlameAnnotationController extends Disposable {
}

async showBlameAnnotation(editor: TextEditor, shaOrLine?: string | number): Promise<boolean> {
if (!editor || !editor.document) return false;
if (editor.viewColumn === undefined && !this.git.hasGitUriForFile(editor)) return false;
if (!editor || !editor.document || !this.git.isEditorBlameable(editor)) return false;

const currentProvider = this._annotationProviders.get(editor.viewColumn || -1);
if (currentProvider && TextEditorComparer.equals(currentProvider.editor, editor)) {
await currentProvider.setSelection(shaOrLine);
return true;
}

const provider = new BlameAnnotationProvider(this.context, this.git, this._whitespaceController, editor);
const gitUri = await GitUri.fromUri(editor.document.uri, this.git);
const provider = new BlameAnnotationProvider(this.context, this.git, this._whitespaceController, editor, gitUri);
if (!await provider.supportsBlame()) return false;

if (currentProvider) {
Expand Down Expand Up @@ -191,15 +191,13 @@ export class BlameAnnotationController extends Disposable {
}

isAnnotating(editor: TextEditor): boolean {
if (!editor || !editor.document) return false;
if (editor.viewColumn === undefined && !this.git.hasGitUriForFile(editor)) return false;
if (!editor || !editor.document || !this.git.isEditorBlameable(editor)) return false;

return !!this._annotationProviders.get(editor.viewColumn || -1);
}

async toggleBlameAnnotation(editor: TextEditor, shaOrLine?: string | number): Promise<boolean> {
if (!editor || !editor.document) return false;
if (editor.viewColumn === undefined && !this.git.hasGitUriForFile(editor)) return false;
if (!editor || !editor.document || !this.git.isEditorBlameable(editor)) return false;

let provider = this._annotationProviders.get(editor.viewColumn || -1);
if (!provider) return this.showBlameAnnotation(editor, shaOrLine);
Expand Down
12 changes: 5 additions & 7 deletions src/blameAnnotationProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,13 @@ export class BlameAnnotationProvider extends Disposable {
private _blame: Promise<IGitBlame>;
private _config: IBlameConfig;
private _disposable: Disposable;
private _uri: GitUri;

constructor(context: ExtensionContext, private git: GitProvider, private whitespaceController: WhitespaceController | undefined, public editor: TextEditor) {
constructor(context: ExtensionContext, private git: GitProvider, private whitespaceController: WhitespaceController | undefined, public editor: TextEditor, private uri: GitUri) {
super(() => this.dispose());

this.document = this.editor.document;
this._uri = GitUri.fromUri(this.document.uri, this.git);

this._blame = this.git.getBlameForFile(this._uri.fsPath, this._uri.sha, this._uri.repoPath);
this._blame = this.git.getBlameForFile(this.uri.fsPath, this.uri.sha, this.uri.repoPath);

this._config = workspace.getConfiguration('gitlens').get<IBlameConfig>('blame');

Expand Down Expand Up @@ -104,7 +102,7 @@ export class BlameAnnotationProvider extends Disposable {
private _setSelection(blame: IGitBlame, shaOrLine?: string | number) {
if (!BlameDecorations.highlight) return;

const offset = this._uri.offset;
const offset = this.uri.offset;

let sha: string;
if (typeof shaOrLine === 'string') {
Expand Down Expand Up @@ -134,7 +132,7 @@ export class BlameAnnotationProvider extends Disposable {
}

private _getCompactGutterDecorations(blame: IGitBlame): DecorationOptions[] {
const offset = this._uri.offset;
const offset = this.uri.offset;

let count = 0;
let lastSha: string;
Expand Down Expand Up @@ -195,7 +193,7 @@ export class BlameAnnotationProvider extends Disposable {
}

private _getExpandedGutterDecorations(blame: IGitBlame, trailing: boolean = false): DecorationOptions[] {
const offset = this._uri.offset;
const offset = this.uri.offset;

let width = 0;
if (!trailing) {
Expand Down
2 changes: 1 addition & 1 deletion src/commands/copyMessageToClipboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export class CopyMessageToClipboardCommand extends ActiveEditorCommand {
return undefined;
}

const gitUri = GitUri.fromUri(uri, this.git);
const gitUri = await GitUri.fromUri(uri, this.git);

if (!message) {
if (!sha) {
Expand Down
2 changes: 1 addition & 1 deletion src/commands/copyShaToClipboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export class CopyShaToClipboardCommand extends ActiveEditorCommand {
return undefined;
}

const gitUri = GitUri.fromUri(uri, this.git);
const gitUri = await GitUri.fromUri(uri, this.git);

if (!sha) {
if (editor && editor.document && editor.document.isDirty) return undefined;
Expand Down
2 changes: 1 addition & 1 deletion src/commands/diffLineWithPrevious.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export class DiffLineWithPreviousCommand extends ActiveEditorCommand {
uri = editor.document.uri;
}

const gitUri = GitUri.fromUri(uri, this.git);
const gitUri = await GitUri.fromUri(uri, this.git);
line = line || (editor && editor.selection.active.line) || gitUri.offset;

if (!commit || GitProvider.isUncommitted(commit.sha)) {
Expand Down
2 changes: 1 addition & 1 deletion src/commands/diffLineWithWorking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export class DiffLineWithWorkingCommand extends ActiveEditorCommand {
uri = editor.document.uri;
}

const gitUri = GitUri.fromUri(uri, this.git);
const gitUri = await GitUri.fromUri(uri, this.git);
line = line || (editor && editor.selection.active.line) || gitUri.offset;

if (!commit || GitProvider.isUncommitted(commit.sha)) {
Expand Down
2 changes: 1 addition & 1 deletion src/commands/diffWithPrevious.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export class DiffWithPreviousCommand extends ActiveEditorCommand {
}

if (!commit || rangeOrLine instanceof Range) {
const gitUri = GitUri.fromUri(uri, this.git);
const gitUri = await GitUri.fromUri(uri, this.git);

try {
if (!gitUri.sha) {
Expand Down
4 changes: 2 additions & 2 deletions src/commands/diffWithWorking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export class DiffWithWorkingCommand extends ActiveEditorCommand {
line = line || (editor && editor.selection.active.line) || 0;

if (!commit || GitProvider.isUncommitted(commit.sha)) {
const gitUri = GitUri.fromUri(uri, this.git);
const gitUri = await GitUri.fromUri(uri, this.git);

try {
const log = await this.git.getLogForFile(gitUri.fsPath, gitUri.sha, gitUri.repoPath, undefined, gitUri.sha ? undefined : 1);
Expand All @@ -38,7 +38,7 @@ export class DiffWithWorkingCommand extends ActiveEditorCommand {
}
}

const gitUri = GitUri.fromUri(uri, this.git);
const gitUri = await GitUri.fromUri(uri, this.git);

try {
const compare = await this.git.getVersionedFile(commit.uri.fsPath, commit.repoPath, commit.sha);
Expand Down
2 changes: 1 addition & 1 deletion src/commands/showBlameHistory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class ShowBlameHistoryCommand extends EditorCommand {
position = editor.document.validateRange(new Range(0, 0, 0, 1000000)).start;
}

const gitUri = GitUri.fromUri(uri, this.git);
const gitUri = await GitUri.fromUri(uri, this.git);

try {
const locations = await this.git.getBlameLocations(gitUri.fsPath, range, gitUri.sha, gitUri.repoPath, sha, line);
Expand Down
2 changes: 1 addition & 1 deletion src/commands/showFileHistory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export class ShowFileHistoryCommand extends EditorCommand {
position = editor.document.validateRange(new Range(0, 0, 0, 1000000)).start;
}

const gitUri = GitUri.fromUri(uri, this.git);
const gitUri = await GitUri.fromUri(uri, this.git);

try {
const locations = await this.git.getLogLocations(gitUri.fsPath, gitUri.sha, gitUri.repoPath, sha, line);
Expand Down
2 changes: 1 addition & 1 deletion src/commands/showQuickCommitDetails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export class ShowQuickCommitDetailsCommand extends ActiveEditorCommand {
uri = editor.document.uri;
}

const gitUri = GitUri.fromUri(uri, this.git);
const gitUri = await GitUri.fromUri(uri, this.git);

let repoPath = gitUri.repoPath;

Expand Down
2 changes: 1 addition & 1 deletion src/commands/showQuickFileHistory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export class ShowQuickFileHistoryCommand extends ActiveEditorCommand {
return commands.executeCommand(Commands.ShowQuickRepoHistory);
}

const gitUri = GitUri.fromUri(uri, this.git);
const gitUri = await GitUri.fromUri(uri, this.git);

if (maxCount == null) {
maxCount = this.git.config.advanced.maxQuickHistory;
Expand Down
2 changes: 1 addition & 1 deletion src/commands/showQuickRepoHistory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class ShowQuickRepoHistoryCommand extends ActiveEditorCommand {
try {
let repoPath: string;
if (uri instanceof Uri) {
const gitUri = GitUri.fromUri(uri, this.git);
const gitUri = await GitUri.fromUri(uri, this.git);
repoPath = gitUri.repoPath;

if (!repoPath) {
Expand Down
2 changes: 1 addition & 1 deletion src/commands/showQuickRepoStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export class ShowQuickRepoStatusCommand extends ActiveEditorCommand {
try {
let repoPath: string;
if (uri instanceof Uri) {
const gitUri = GitUri.fromUri(uri, this.git);
const gitUri = await GitUri.fromUri(uri, this.git);
repoPath = gitUri.repoPath;

if (!repoPath) {
Expand Down
5 changes: 3 additions & 2 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ export const BuiltInCommands = {
ToggleRenderWhitespace: 'editor.action.toggleRenderWhitespace' as BuiltInCommands
};

export type DocumentSchemes = 'file' | 'gitlens-git';
export type DocumentSchemes = 'file' | 'git' | 'gitlens-git';
export const DocumentSchemes = {
File: 'file' as DocumentSchemes,
Git: 'gitlens-git' as DocumentSchemes
Git: 'git' as DocumentSchemes,
GitLensGit: 'gitlens-git' as DocumentSchemes
};

export type WorkspaceState = 'repoPath';
Expand Down
16 changes: 11 additions & 5 deletions src/git/gitUri.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
'use strict';
import { Iterables } from '../system';
import { Uri } from 'vscode';
import { DocumentSchemes } from '../constants';
import { Git, GitProvider } from '../gitProvider';
Expand All @@ -22,7 +23,7 @@ export class GitUri extends Uri {
base._fragment = uri.fragment;

this.offset = 0;
if (uri.scheme === DocumentSchemes.Git) {
if (uri.scheme === DocumentSchemes.GitLensGit) {
const data = GitProvider.fromGitContentUri(uri);
base._fsPath = data.originalFileName || data.fileName;

Expand Down Expand Up @@ -52,12 +53,17 @@ export class GitUri extends Uri {
return Uri.file(this.sha ? this.path : this.fsPath);
}

static fromUri(uri: Uri, git?: GitProvider) {
static async fromUri(uri: Uri, git: GitProvider) {
if (uri instanceof GitUri) return uri;

if (git) {
const gitUri = git.getGitUriForFile(uri.fsPath);
if (gitUri) return gitUri;
const gitUri = git.getGitUriForFile(uri.fsPath);
if (gitUri) return gitUri;

// If this is a git uri, assume it is showing the most recent commit
if (uri.scheme === 'git' && uri.query === '~') {
const log = await git.getLogForFile(uri.fsPath, undefined, undefined, undefined, 1);
const commit = log && Iterables.first(log.commits.values());
if (commit) return new GitUri(uri, commit);
}

return new GitUri(uri);
Expand Down
2 changes: 1 addition & 1 deletion src/gitCodeLensProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export default class GitCodeLensProvider implements CodeLensProvider {

if (languageLocations.location === CodeLensLocation.None) return lenses;

const gitUri = GitUri.fromUri(document.uri, this.git);
const gitUri = await GitUri.fromUri(document.uri, this.git);

const blamePromise = this.git.getBlameForFile(gitUri.fsPath, gitUri.sha, gitUri.repoPath);
let blame: IGitBlame;
Expand Down
2 changes: 1 addition & 1 deletion src/gitContentProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import * as path from 'path';

export class GitContentProvider implements TextDocumentContentProvider {

static scheme = DocumentSchemes.Git;
static scheme = DocumentSchemes.GitLensGit;

constructor(context: ExtensionContext, private git: GitProvider) { }

Expand Down
12 changes: 9 additions & 3 deletions src/gitProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,12 @@ export class GitProvider extends Disposable {
return Git.getVersionedFileText(fileName, repoPath, sha);
}

isEditorBlameable(editor: TextEditor): boolean {
return (editor.viewColumn !== undefined ||
editor.document.uri.scheme === DocumentSchemes.Git ||
this.hasGitUriForFile(editor));
}

toggleCodeLens(editor: TextEditor) {
if (this.config.codeLens.visibility !== CodeLensVisibility.OnDemand ||
(!this.config.codeLens.recentChange.enabled && !this.config.codeLens.authors.enabled)) return;
Expand All @@ -632,7 +638,7 @@ export class GitProvider extends Disposable {
}

static fromGitContentUri(uri: Uri): IGitUriData {
if (uri.scheme !== DocumentSchemes.Git) throw new Error(`fromGitUri(uri=${uri}) invalid scheme`);
if (uri.scheme !== DocumentSchemes.GitLensGit) throw new Error(`fromGitUri(uri=${uri}) invalid scheme`);
return GitProvider._fromGitContentUri<IGitUriData>(uri);
}

Expand All @@ -658,11 +664,11 @@ export class GitProvider extends Disposable {
}

const extension = path.extname(fileName);
return Uri.parse(`${DocumentSchemes.Git}:${path.basename(fileName, extension)}:${data.sha}${extension}?${JSON.stringify(data)}`);
return Uri.parse(`${DocumentSchemes.GitLensGit}:${path.basename(fileName, extension)}:${data.sha}${extension}?${JSON.stringify(data)}`);
}

static toReferenceGitContentUri(commit: GitCommit, index: number, commitCount: number, originalFileName?: string, decoration?: string): Uri {
return GitProvider._toReferenceGitContentUri(commit, DocumentSchemes.Git, commitCount, GitProvider._toGitUriData(commit, index, originalFileName, decoration));
return GitProvider._toReferenceGitContentUri(commit, DocumentSchemes.GitLensGit, commitCount, GitProvider._toGitUriData(commit, index, originalFileName, decoration));
}

private static _toReferenceGitContentUri(commit: GitCommit, scheme: DocumentSchemes, commitCount: number, data: IGitUriData) {
Expand Down
2 changes: 1 addition & 1 deletion src/gitRevisionCodeLensProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export class GitDiffWithPreviousCodeLens extends CodeLens {

export class GitRevisionCodeLensProvider implements CodeLensProvider {

static selector: DocumentSelector = { scheme: DocumentSchemes.Git };
static selector: DocumentSelector = { scheme: DocumentSchemes.GitLensGit };

constructor(context: ExtensionContext, private git: GitProvider) { }

Expand Down
2 changes: 1 addition & 1 deletion src/quickPicks/gitQuickPicks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export class CommitWithFileStatusQuickPickItem extends OpenFileCommandQuickPickI
});

this.fileName = fileName;
this.gitUri = GitUri.fromUri(Uri.file(path.resolve(commit.repoPath, fileName)));
this.gitUri = new GitUri(Uri.file(path.resolve(commit.repoPath, fileName)));
this.sha = commit.sha;
this.status = status;
}
Expand Down

0 comments on commit 4da21c3

Please sign in to comment.