mirror of
https://github.com/ckaczor/vscode-gitlens.git
synced 2026-01-14 01:25:43 -05:00
Changes behaviors when file has unsaved changes:
- Status bar blame information will hide - CodeLens change to a `Cannot determine...` message and become unclickable - Many menu choices and commands will hide Fixes #36 - Blame information is invalid when a file has unsaved changes Fixed #38 - Toggle Blame Annotation button shows even when it isn't valid Preps v2.9.0
This commit is contained in:
3
.vscode/tasks.json
vendored
3
.vscode/tasks.json
vendored
@@ -8,8 +8,7 @@
|
||||
|
||||
// A task runner that calls a custom npm script that compiles the extension.
|
||||
{
|
||||
"version": "0.1.0",
|
||||
"_runner": "terminal",
|
||||
"version": "2.0.0",
|
||||
"command": "npm",
|
||||
"args": ["run"],
|
||||
"isShellCommand": true,
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
## Release Notes
|
||||
|
||||
### 2.9.0
|
||||
- To accomodate the realization that blame information is invalid when a file has unsaved changes, the following behavior changes have been made
|
||||
- Status bar blame information will hide
|
||||
- CodeLens change to a `Cannot determine...` message and become unclickable
|
||||
- Many menu choices and commands will hide
|
||||
- Fixes [#38](https://github.com/eamodio/vscode-gitlens/issues/38) - Toggle Blame Annotation button shows even when it isn't valid
|
||||
- Fixes [#36](https://github.com/eamodio/vscode-gitlens/issues/36) - Blame information is invalid when a file has unsaved changes
|
||||
|
||||
### 2.8.2
|
||||
- Adds `gitlens.blame.annotation.dateFormat` to specify how absolute commit dates will be shown in the blame annotations
|
||||
- Adds `gitlens.statusBar.date` to specify whether and how the commit date will be shown in the blame status bar
|
||||
|
||||
61
package.json
61
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gitlens",
|
||||
"version": "2.8.2",
|
||||
"version": "2.9.0",
|
||||
"author": {
|
||||
"name": "Eric Amodio",
|
||||
"email": "eamodio@gmail.com"
|
||||
@@ -444,7 +444,7 @@
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffLineWithPrevious",
|
||||
"when": "gitlens:enabled"
|
||||
"when": "gitlens:enabled && gitlens:isBlameable"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffWithWorking",
|
||||
@@ -452,15 +452,15 @@
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffLineWithWorking",
|
||||
"when": "gitlens:enabled"
|
||||
"when": "gitlens:enabled && gitlens:isBlameable"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.showBlame",
|
||||
"when": "gitlens:enabled"
|
||||
"when": "gitlens:enabled && gitlens:isBlameable"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.toggleBlame",
|
||||
"when": "gitlens:enabled"
|
||||
"when": "gitlens:enabled && gitlens:isBlameable"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.toggleCodeLens",
|
||||
@@ -468,7 +468,7 @@
|
||||
},
|
||||
{
|
||||
"command": "gitlens.showBlameHistory",
|
||||
"when": "gitlens:enabled"
|
||||
"when": "gitlens:enabled && gitlens:isBlameable"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.showFileHistory",
|
||||
@@ -476,7 +476,7 @@
|
||||
},
|
||||
{
|
||||
"command": "gitlens.showQuickCommitDetails",
|
||||
"when": "gitlens:enabled"
|
||||
"when": "gitlens:enabled && gitlens:isBlameable"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.showQuickFileHistory",
|
||||
@@ -492,11 +492,11 @@
|
||||
},
|
||||
{
|
||||
"command": "gitlens.copyShaToClipboard",
|
||||
"when": "gitlens:enabled"
|
||||
"when": "gitlens:enabled && gitlens:isBlameable"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.copyMessageToClipboard",
|
||||
"when": "gitlens:enabled"
|
||||
"when": "gitlens:enabled && gitlens:isBlameable"
|
||||
}
|
||||
],
|
||||
"explorer/context": [
|
||||
@@ -507,46 +507,51 @@
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffWithPrevious",
|
||||
"when": "config.gitlens.menus.diff.enabled && gitlens:enabled",
|
||||
"when": "gitlens:enabled && config.gitlens.menus.diff.enabled",
|
||||
"group": "gitlens_diff"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffWithWorking",
|
||||
"when": "config.gitlens.menus.diff.enabled && gitlens:enabled",
|
||||
"when": "gitlens:enabled && config.gitlens.menus.diff.enabled",
|
||||
"group": "gitlens_diff"
|
||||
}
|
||||
],
|
||||
"editor/title": [
|
||||
{
|
||||
"command": "gitlens.toggleBlame",
|
||||
"when": "gitlens:enabled",
|
||||
"when": "gitlens:enabled && gitlens:isBlameable",
|
||||
"group": "navigation@100"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.showQuickFileHistory",
|
||||
"when": "gitlens:enabled",
|
||||
"group": "1_gitlens@1"
|
||||
"when": "editorFocus && gitlens:enabled",
|
||||
"group": "gitlens"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.showQuickRepoHistory",
|
||||
"when": "!editorFocus && gitlens:enabled",
|
||||
"group": "gitlens"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.showQuickRepoStatus",
|
||||
"when": "gitlens:enabled",
|
||||
"group": "1_gitlens@2"
|
||||
"group": "gitlens"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffWithPrevious",
|
||||
"when": "config.gitlens.menus.diff.enabled && gitlens:enabled",
|
||||
"group": "1_gitlens_diff"
|
||||
"when": "editorTextFocus && gitlens:enabled && config.gitlens.menus.diff.enabled",
|
||||
"group": "gitlens_diff"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffWithWorking",
|
||||
"when": "config.gitlens.menus.diff.enabled && gitlens:enabled",
|
||||
"group": "1_gitlens_diff"
|
||||
"when": "editorTextFocus && gitlens:enabled && config.gitlens.menus.diff.enabled",
|
||||
"group": "gitlens_diff"
|
||||
}
|
||||
],
|
||||
"editor/title/context": [
|
||||
{
|
||||
"command": "gitlens.toggleBlame",
|
||||
"when": "gitlens:enabled",
|
||||
"when": "gitlens:enabled && gitlens:isBlameable",
|
||||
"group": "gitlens@1"
|
||||
},
|
||||
{
|
||||
@@ -558,32 +563,32 @@
|
||||
"editor/context": [
|
||||
{
|
||||
"command": "gitlens.diffLineWithPrevious",
|
||||
"when": "editorTextFocus && config.gitlens.menus.diff.enabled && gitlens:enabled",
|
||||
"when": "editorTextFocus && gitlens:enabled && gitlens:isBlameable && && config.gitlens.menus.diff.enabled",
|
||||
"group": "1_gitlens@1"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffLineWithWorking",
|
||||
"when": "editorTextFocus && config.gitlens.menus.diff.enabled && gitlens:enabled",
|
||||
"when": "editorTextFocus && gitlens:enabled && gitlens:isBlameable && config.gitlens.menus.diff.enabled",
|
||||
"group": "1_gitlens@2"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.showQuickCommitDetails",
|
||||
"when": "editorTextFocus && gitlens:enabled",
|
||||
"when": "editorTextFocus && gitlens:enabled && gitlens:isBlameable",
|
||||
"group": "1_gitlens@3"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffWithPrevious",
|
||||
"when": "editorTextFocus && config.gitlens.menus.diff.enabled && gitlens:enabled",
|
||||
"when": "editorTextFocus && gitlens:enabled && config.gitlens.menus.diff.enabled",
|
||||
"group": "1_gitlens-file@1"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffWithWorking",
|
||||
"when": "editorTextFocus && config.gitlens.menus.diff.enabled && gitlens:enabled",
|
||||
"when": "editorTextFocus && gitlens:enabled && config.gitlens.menus.diff.enabled",
|
||||
"group": "1_gitlens-file@2"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.toggleBlame",
|
||||
"when": "editorTextFocus && gitlens:enabled",
|
||||
"when": "editorTextFocus && gitlens:enabled && gitlens:isBlameable",
|
||||
"group": "2_gitlens@1"
|
||||
},
|
||||
{
|
||||
@@ -594,12 +599,12 @@
|
||||
},
|
||||
{
|
||||
"command": "gitlens.copyShaToClipboard",
|
||||
"when": "editorTextFocus && gitlens:enabled",
|
||||
"when": "editorTextFocus && gitlens:enabled && gitlens:isBlameable",
|
||||
"group": "9_gitlens@1"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.copyMessageToClipboard",
|
||||
"when": "editorTextFocus && gitlens:enabled",
|
||||
"when": "editorTextFocus && gitlens:enabled && gitlens:isBlameable",
|
||||
"group": "9_gitlens@2"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use strict';
|
||||
import { Functions, Objects } from './system';
|
||||
import { DecorationOptions, DecorationInstanceRenderOptions, DecorationRenderOptions, Disposable, ExtensionContext, Range, StatusBarAlignment, StatusBarItem, TextEditor, TextEditorDecorationType, TextEditorSelectionChangeEvent, window, workspace } from 'vscode';
|
||||
import { BlameabilityChangeEvent, BlameabilityTracker } from './blameabilityTracker';
|
||||
import { BlameAnnotationController } from './blameAnnotationController';
|
||||
import { BlameAnnotationFormat, BlameAnnotationFormatter } from './blameAnnotationFormatter';
|
||||
import { TextEditorComparer } from './comparers';
|
||||
@@ -19,17 +20,17 @@ export class BlameActiveLineController extends Disposable {
|
||||
|
||||
private _activeEditorLineDisposable: Disposable | undefined;
|
||||
private _blame: Promise<IGitBlame> | undefined;
|
||||
private _blameable: boolean;
|
||||
private _config: IConfig;
|
||||
private _currentLine: number = -1;
|
||||
private _disposable: Disposable;
|
||||
private _editor: TextEditor | undefined;
|
||||
private _editorIsDirty: boolean;
|
||||
private _statusBarItem: StatusBarItem | undefined;
|
||||
private _updateBlameDebounced: (line: number, editor: TextEditor) => Promise<void>;
|
||||
private _uri: GitUri;
|
||||
private _useCaching: boolean;
|
||||
|
||||
constructor(context: ExtensionContext, private git: GitProvider, private annotationController: BlameAnnotationController) {
|
||||
constructor(context: ExtensionContext, private git: GitProvider, private blameabilityTracker: BlameabilityTracker, private annotationController: BlameAnnotationController) {
|
||||
super(() => this.dispose());
|
||||
|
||||
this._updateBlameDebounced = Functions.debounce(this._updateBlame, 50);
|
||||
@@ -93,8 +94,8 @@ export class BlameActiveLineController extends Disposable {
|
||||
const subscriptions: Disposable[] = [];
|
||||
|
||||
subscriptions.push(window.onDidChangeActiveTextEditor(this._onActiveTextEditorChanged, this));
|
||||
subscriptions.push(window.onDidChangeTextEditorSelection(this._onEditorSelectionChanged, this));
|
||||
subscriptions.push(workspace.onDidChangeTextDocument(this._onDocumentChanged, this));
|
||||
subscriptions.push(window.onDidChangeTextEditorSelection(this._onTextEditorSelectionChanged, this));
|
||||
subscriptions.push(this.blameabilityTracker.onDidChange(this._onBlameabilityChanged, this));
|
||||
|
||||
this._activeEditorLineDisposable = Disposable.from(...subscriptions);
|
||||
}
|
||||
@@ -106,6 +107,54 @@ export class BlameActiveLineController extends Disposable {
|
||||
this._onActiveTextEditorChanged(window.activeTextEditor);
|
||||
}
|
||||
|
||||
private _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))) {
|
||||
this.clear(editor);
|
||||
|
||||
this._editor = undefined;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this._blameable = editor && editor.document && !editor.document.isDirty;
|
||||
this._editor = editor;
|
||||
this._uri = 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) {
|
||||
this._blame = this.git.getBlameForFile(this._uri.fsPath, this._uri.sha, this._uri.repoPath);
|
||||
}
|
||||
else {
|
||||
this._blame = undefined;
|
||||
}
|
||||
|
||||
this._updateBlame(editor.selection.active.line, editor);
|
||||
}
|
||||
|
||||
private _onBlameabilityChanged(e: BlameabilityChangeEvent) {
|
||||
this._blameable = e.blameable;
|
||||
if (!e.blameable || !this._editor) {
|
||||
this.clear(e.editor);
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure this is for the editor we are tracking
|
||||
if (!TextEditorComparer.equals(this._editor, e.editor)) return;
|
||||
|
||||
const line = this._editor.selection.active.line;
|
||||
if (line === this._currentLine) return;
|
||||
this._currentLine = line;
|
||||
|
||||
this._updateBlame(this._editor.selection.active.line, this._editor);
|
||||
}
|
||||
|
||||
private _onBlameAnnotationToggled() {
|
||||
this._onActiveTextEditorChanged(window.activeTextEditor);
|
||||
}
|
||||
@@ -115,39 +164,9 @@ export class BlameActiveLineController extends Disposable {
|
||||
this._onActiveTextEditorChanged(window.activeTextEditor);
|
||||
}
|
||||
|
||||
private _onActiveTextEditorChanged(e: TextEditor) {
|
||||
this._currentLine = -1;
|
||||
|
||||
const previousEditor = this._editor;
|
||||
previousEditor && previousEditor.setDecorations(activeLineDecoration, []);
|
||||
|
||||
if (!e || !e.document || (e.document.isUntitled && e.document.uri.scheme !== DocumentSchemes.Git) ||
|
||||
(e.document.uri.scheme !== DocumentSchemes.File && e.document.uri.scheme !== DocumentSchemes.Git) ||
|
||||
(e.viewColumn === undefined && !this.git.hasGitUriForFile(e))) {
|
||||
this.clear(e);
|
||||
|
||||
this._editor = undefined;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this._editor = e;
|
||||
this._uri = GitUri.fromUri(e.document.uri, this.git);
|
||||
const maxLines = this._config.advanced.caching.statusBar.maxLines;
|
||||
this._useCaching = this._config.advanced.caching.enabled && (maxLines <= 0 || e.document.lineCount <= maxLines);
|
||||
if (this._useCaching) {
|
||||
this._blame = this.git.getBlameForFile(this._uri.fsPath, this._uri.sha, this._uri.repoPath);
|
||||
}
|
||||
else {
|
||||
this._blame = undefined;
|
||||
}
|
||||
|
||||
this._updateBlame(e.selection.active.line, e);
|
||||
}
|
||||
|
||||
private _onEditorSelectionChanged(e: TextEditorSelectionChangeEvent): void {
|
||||
private _onTextEditorSelectionChanged(e: TextEditorSelectionChangeEvent): void {
|
||||
// Make sure this is for the editor we are tracking
|
||||
if (!TextEditorComparer.equals(e.textEditor, this._editor)) return;
|
||||
if (!this._blameable || !TextEditorComparer.equals(this._editor, e.textEditor)) return;
|
||||
|
||||
const line = e.selections[0].active.line;
|
||||
if (line === this._currentLine) return;
|
||||
@@ -156,24 +175,13 @@ export class BlameActiveLineController extends Disposable {
|
||||
this._updateBlameDebounced(line, e.textEditor);
|
||||
}
|
||||
|
||||
private _onDocumentChanged(e: TextDocumentChangeEvent) {
|
||||
// Make sure this is for the editor we are tracking
|
||||
if (!this._editor || !TextDocumentComparer.equals(e.document, this._editor.document)) return;
|
||||
|
||||
const line = this._editor.selections[0].active.line;
|
||||
if (line === this._currentLine && this._editorIsDirty === this._editor.document.isDirty) return;
|
||||
this._currentLine = line;
|
||||
this._editorIsDirty = this._editor.document.isDirty;
|
||||
|
||||
this._updateBlame(this._editor.selections[0].active.line, this._editor);
|
||||
}
|
||||
|
||||
private async _updateBlame(line: number, editor: TextEditor) {
|
||||
line = line - this._uri.offset;
|
||||
|
||||
let commitLine: IGitCommitLine;
|
||||
let commit: GitCommit;
|
||||
if (line >= 0) {
|
||||
let commitLine: IGitCommitLine;
|
||||
// Since blame information isn't valid when there are unsaved changes -- don't show any status
|
||||
if (this._blameable && line >= 0) {
|
||||
if (this._useCaching) {
|
||||
const blame = this._blame && await this._blame;
|
||||
if (!blame || !blame.lines.length) {
|
||||
@@ -202,6 +210,10 @@ export class BlameActiveLineController extends Disposable {
|
||||
|
||||
clear(editor: TextEditor, previousEditor?: TextEditor) {
|
||||
editor && editor.setDecorations(activeLineDecoration, []);
|
||||
// I have no idea why the decorators sometimes don't get removed, but if they don't try again with a tiny delay
|
||||
if (editor) {
|
||||
setTimeout(() => editor.setDecorations(activeLineDecoration, []), 1);
|
||||
}
|
||||
|
||||
this._statusBarItem && this._statusBarItem.hide();
|
||||
}
|
||||
@@ -258,20 +270,7 @@ export class BlameActiveLineController extends Disposable {
|
||||
}
|
||||
|
||||
if (this._config.blame.annotation.activeLine !== 'off') {
|
||||
let activeLine = this._config.blame.annotation.activeLine;
|
||||
|
||||
// Because the inline annotations can be noisy -- only show them if the document isn't dirty
|
||||
if (editor && editor.document && editor.document.isDirty) {
|
||||
editor.setDecorations(activeLineDecoration, []);
|
||||
switch (activeLine) {
|
||||
case 'both':
|
||||
activeLine = 'hover';
|
||||
break;
|
||||
case 'inline':
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const activeLine = this._config.blame.annotation.activeLine;
|
||||
const offset = this._uri.offset;
|
||||
|
||||
const config = {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use strict';
|
||||
import { Functions } from './system';
|
||||
import { DecorationRenderOptions, Disposable, Event, EventEmitter, ExtensionContext, OverviewRulerLane, TextDocument, TextEditor, TextEditorDecorationType, TextEditorViewColumnChangeEvent, window, workspace } from 'vscode';
|
||||
import { BlameabilityChangeEvent, BlameabilityTracker } from './blameabilityTracker';
|
||||
import { BlameAnnotationProvider } from './blameAnnotationProvider';
|
||||
import { TextDocumentComparer, TextEditorComparer } from './comparers';
|
||||
import { IBlameConfig } from './configuration';
|
||||
@@ -8,16 +9,17 @@ import { GitProvider } from './gitProvider';
|
||||
import { Logger } from './logger';
|
||||
import { WhitespaceController } from './whitespaceController';
|
||||
|
||||
export const blameDecoration: TextEditorDecorationType = window.createTextEditorDecorationType({
|
||||
before: {
|
||||
margin: '0 1.75em 0 0'
|
||||
},
|
||||
after: {
|
||||
margin: '0 0 0 4em'
|
||||
}
|
||||
} as DecorationRenderOptions);
|
||||
|
||||
export let highlightDecoration: TextEditorDecorationType;
|
||||
export const BlameDecorations = {
|
||||
annotation: window.createTextEditorDecorationType({
|
||||
before: {
|
||||
margin: '0 1.75em 0 0'
|
||||
},
|
||||
after: {
|
||||
margin: '0 0 0 4em'
|
||||
}
|
||||
} as DecorationRenderOptions),
|
||||
highlight: undefined as TextEditorDecorationType
|
||||
};
|
||||
|
||||
export class BlameAnnotationController extends Disposable {
|
||||
|
||||
@@ -32,7 +34,7 @@ export class BlameAnnotationController extends Disposable {
|
||||
private _disposable: Disposable;
|
||||
private _whitespaceController: WhitespaceController | undefined;
|
||||
|
||||
constructor(private context: ExtensionContext, private git: GitProvider) {
|
||||
constructor(private context: ExtensionContext, private git: GitProvider, private blameabilityTracker: BlameabilityTracker) {
|
||||
super(() => this.dispose());
|
||||
|
||||
this._onConfigurationChanged();
|
||||
@@ -47,6 +49,9 @@ export class BlameAnnotationController extends Disposable {
|
||||
dispose() {
|
||||
this._annotationProviders.forEach(async (p, i) => await this.clear(i));
|
||||
|
||||
BlameDecorations.annotation && BlameDecorations.annotation.dispose();
|
||||
BlameDecorations.highlight && BlameDecorations.highlight.dispose();
|
||||
|
||||
this._blameAnnotationsDisposable && this._blameAnnotationsDisposable.dispose();
|
||||
this._whitespaceController && this._whitespaceController.dispose();
|
||||
this._disposable && this._disposable.dispose();
|
||||
@@ -71,15 +76,11 @@ export class BlameAnnotationController extends Disposable {
|
||||
const config = workspace.getConfiguration('gitlens').get<IBlameConfig>('blame');
|
||||
|
||||
if (config.annotation.highlight !== (this._config && this._config.annotation.highlight)) {
|
||||
highlightDecoration && highlightDecoration.dispose();
|
||||
BlameDecorations.highlight && BlameDecorations.highlight.dispose();
|
||||
|
||||
switch (config.annotation.highlight) {
|
||||
case 'none':
|
||||
highlightDecoration = undefined;
|
||||
break;
|
||||
|
||||
case 'gutter':
|
||||
highlightDecoration = window.createTextEditorDecorationType({
|
||||
BlameDecorations.highlight = window.createTextEditorDecorationType({
|
||||
dark: {
|
||||
gutterIconPath: this.context.asAbsolutePath('images/blame-dark.svg'),
|
||||
overviewRulerColor: 'rgba(255, 255, 255, 0.75)'
|
||||
@@ -94,7 +95,7 @@ export class BlameAnnotationController extends Disposable {
|
||||
break;
|
||||
|
||||
case 'line':
|
||||
highlightDecoration = window.createTextEditorDecorationType({
|
||||
BlameDecorations.highlight = window.createTextEditorDecorationType({
|
||||
dark: {
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.15)',
|
||||
overviewRulerColor: 'rgba(255, 255, 255, 0.75)'
|
||||
@@ -109,7 +110,7 @@ export class BlameAnnotationController extends Disposable {
|
||||
break;
|
||||
|
||||
case 'both':
|
||||
highlightDecoration = window.createTextEditorDecorationType({
|
||||
BlameDecorations.highlight = window.createTextEditorDecorationType({
|
||||
dark: {
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.15)',
|
||||
gutterIconPath: this.context.asAbsolutePath('images/blame-dark.svg'),
|
||||
@@ -125,6 +126,10 @@ export class BlameAnnotationController extends Disposable {
|
||||
isWholeLine: true
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
BlameDecorations.highlight = undefined;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,6 +177,7 @@ export class BlameAnnotationController extends Disposable {
|
||||
subscriptions.push(window.onDidChangeVisibleTextEditors(Functions.debounce(this._onVisibleTextEditorsChanged, 100), this));
|
||||
subscriptions.push(window.onDidChangeTextEditorViewColumn(this._onTextEditorViewColumnChanged, this));
|
||||
subscriptions.push(workspace.onDidCloseTextDocument(this._onTextDocumentClosed, this));
|
||||
subscriptions.push(this.blameabilityTracker.onDidChange(this._onBlameabilityChanged, this));
|
||||
|
||||
this._blameAnnotationsDisposable = Disposable.from(...subscriptions);
|
||||
}
|
||||
@@ -202,6 +208,17 @@ export class BlameAnnotationController extends Disposable {
|
||||
return false;
|
||||
}
|
||||
|
||||
private _onBlameabilityChanged(e: BlameabilityChangeEvent) {
|
||||
if (e.blameable || !e.editor) return;
|
||||
|
||||
for (const [key, p] of this._annotationProviders) {
|
||||
if (!TextDocumentComparer.equals(p.document, e.editor.document)) continue;
|
||||
|
||||
Logger.log('BlameabilityChanged:', `Clear blame annotations for column ${key}`);
|
||||
this.clear(key);
|
||||
}
|
||||
}
|
||||
|
||||
private _onTextDocumentClosed(e: TextDocument) {
|
||||
for (const [key, p] of this._annotationProviders) {
|
||||
if (!TextDocumentComparer.equals(p.document, e)) continue;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { Iterables } from './system';
|
||||
import { DecorationInstanceRenderOptions, DecorationOptions, Disposable, ExtensionContext, Range, TextDocument, TextEditor, TextEditorSelectionChangeEvent, window, workspace } from 'vscode';
|
||||
import { BlameAnnotationFormat, BlameAnnotationFormatter, cssIndent, defaultShaLength, defaultAuthorLength } from './blameAnnotationFormatter';
|
||||
import { blameDecoration, highlightDecoration } from './blameAnnotationController';
|
||||
import { BlameDecorations } from './blameAnnotationController';
|
||||
import { TextDocumentComparer } from './comparers';
|
||||
import { BlameAnnotationStyle, IBlameConfig } from './configuration';
|
||||
import { GitProvider, GitUri, IGitBlame } from './gitProvider';
|
||||
@@ -36,8 +36,15 @@ export class BlameAnnotationProvider extends Disposable {
|
||||
|
||||
async dispose() {
|
||||
if (this.editor) {
|
||||
this.editor.setDecorations(blameDecoration, []);
|
||||
highlightDecoration && this.editor.setDecorations(highlightDecoration, []);
|
||||
try {
|
||||
this.editor.setDecorations(BlameDecorations.annotation, []);
|
||||
BlameDecorations.highlight && this.editor.setDecorations(BlameDecorations.highlight, []);
|
||||
// I have no idea why the decorators sometimes don't get removed, but if they don't try again with a tiny delay
|
||||
if (BlameDecorations.highlight) {
|
||||
setTimeout(() => this.editor.setDecorations(BlameDecorations.highlight, []), 1);
|
||||
}
|
||||
}
|
||||
catch (ex) { }
|
||||
}
|
||||
|
||||
// HACK: Until https://github.com/Microsoft/vscode/issues/11485 is fixed -- restore whitespace
|
||||
@@ -80,7 +87,7 @@ export class BlameAnnotationProvider extends Disposable {
|
||||
}
|
||||
|
||||
if (blameDecorationOptions) {
|
||||
this.editor.setDecorations(blameDecoration, blameDecorationOptions);
|
||||
this.editor.setDecorations(BlameDecorations.annotation, blameDecorationOptions);
|
||||
}
|
||||
|
||||
this._setSelection(blame, shaOrLine);
|
||||
@@ -95,7 +102,7 @@ export class BlameAnnotationProvider extends Disposable {
|
||||
}
|
||||
|
||||
private _setSelection(blame: IGitBlame, shaOrLine?: string | number) {
|
||||
if (!highlightDecoration) return;
|
||||
if (!BlameDecorations.highlight) return;
|
||||
|
||||
const offset = this._uri.offset;
|
||||
|
||||
@@ -115,7 +122,7 @@ export class BlameAnnotationProvider extends Disposable {
|
||||
}
|
||||
|
||||
if (!sha) {
|
||||
this.editor.setDecorations(highlightDecoration, []);
|
||||
this.editor.setDecorations(BlameDecorations.highlight, []);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -123,7 +130,7 @@ export class BlameAnnotationProvider extends Disposable {
|
||||
.filter(l => l.sha === sha)
|
||||
.map(l => this.editor.document.validateRange(new Range(l.line + offset, 0, l.line + offset, 1000000)));
|
||||
|
||||
this.editor.setDecorations(highlightDecoration, highlightDecorationRanges);
|
||||
this.editor.setDecorations(BlameDecorations.highlight, highlightDecorationRanges);
|
||||
}
|
||||
|
||||
private _getCompactGutterDecorations(blame: IGitBlame): DecorationOptions[] {
|
||||
|
||||
95
src/blameabilityTracker.ts
Normal file
95
src/blameabilityTracker.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
'use strict';
|
||||
import { commands, Disposable, Event, EventEmitter, TextDocument, TextDocumentChangeEvent, TextEditor, window, workspace } from 'vscode';
|
||||
import { TextDocumentComparer } from './comparers';
|
||||
import { BuiltInCommands } from './constants';
|
||||
import { GitProvider } from './gitProvider';
|
||||
|
||||
export interface BlameabilityChangeEvent {
|
||||
blameable: boolean;
|
||||
editor: TextEditor;
|
||||
}
|
||||
|
||||
export class BlameabilityTracker extends Disposable {
|
||||
|
||||
private _onDidChange = new EventEmitter<BlameabilityChangeEvent>();
|
||||
get onDidChange(): Event<BlameabilityChangeEvent> {
|
||||
return this._onDidChange.event;
|
||||
}
|
||||
|
||||
private _disposable: Disposable;
|
||||
private _documentChangeDisposable: Disposable;
|
||||
private _editor: TextEditor;
|
||||
private _isBlameable: boolean;
|
||||
|
||||
constructor(private git: GitProvider) {
|
||||
super(() => this.dispose());
|
||||
|
||||
const subscriptions: Disposable[] = [];
|
||||
|
||||
subscriptions.push(window.onDidChangeActiveTextEditor(this._onActiveTextEditorChanged, this));
|
||||
subscriptions.push(workspace.onDidSaveTextDocument(this._onTextDocumentSaved, this));
|
||||
subscriptions.push(this.git.onDidBlameFail(this._onBlameFailed, this));
|
||||
|
||||
this._disposable = Disposable.from(...subscriptions);
|
||||
|
||||
this._onActiveTextEditorChanged(window.activeTextEditor);
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this._disposable && this._disposable.dispose();
|
||||
this._documentChangeDisposable && this._documentChangeDisposable.dispose();
|
||||
}
|
||||
|
||||
private _onActiveTextEditorChanged(editor: TextEditor) {
|
||||
this._editor = editor;
|
||||
let blameable = editor && editor.document && !editor.document.isDirty;
|
||||
|
||||
if (blameable) {
|
||||
blameable = this.git.getBlameability(editor.document.fileName);
|
||||
}
|
||||
|
||||
this._subscribeToDocumentChanges();
|
||||
this.updateBlameability(blameable, true);
|
||||
}
|
||||
|
||||
private _onBlameFailed(key: string) {
|
||||
const fileName = this._editor && this._editor.document && this._editor.document.fileName;
|
||||
if (!fileName || key !== this.git.getCacheEntryKey(fileName)) return;
|
||||
|
||||
this.updateBlameability(false);
|
||||
}
|
||||
|
||||
private _onTextDocumentChanged(e: TextDocumentChangeEvent) {
|
||||
if (!TextDocumentComparer.equals(this._editor && this._editor.document, e && e.document)) return;
|
||||
|
||||
this._unsubscribeToDocumentChanges();
|
||||
this.updateBlameability(false);
|
||||
}
|
||||
|
||||
private _onTextDocumentSaved(e: TextDocument) {
|
||||
if (!TextDocumentComparer.equals(this._editor && this._editor.document, e)) return;
|
||||
|
||||
this._subscribeToDocumentChanges();
|
||||
this.updateBlameability(true);
|
||||
}
|
||||
|
||||
private _subscribeToDocumentChanges() {
|
||||
this._unsubscribeToDocumentChanges();
|
||||
this._documentChangeDisposable = workspace.onDidChangeTextDocument(this._onTextDocumentChanged, this);
|
||||
}
|
||||
|
||||
private _unsubscribeToDocumentChanges() {
|
||||
this._documentChangeDisposable && this._documentChangeDisposable.dispose();
|
||||
this._documentChangeDisposable = undefined;
|
||||
}
|
||||
|
||||
private updateBlameability(blameable: boolean, force: boolean = false) {
|
||||
if (!force && this._isBlameable === blameable) return;
|
||||
|
||||
commands.executeCommand(BuiltInCommands.SetContext, 'gitlens:isBlameable', blameable);
|
||||
this._onDidChange.fire({
|
||||
blameable: blameable,
|
||||
editor: this._editor
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,9 @@ export class CopyMessageToClipboardCommand extends ActiveEditorCommand {
|
||||
|
||||
if (!message) {
|
||||
if (!sha) {
|
||||
const line = editor.selection.active.line;
|
||||
if (editor && editor.document && editor.document.isDirty) return undefined;
|
||||
|
||||
const line = (editor && editor.selection.active.line) || gitUri.offset;
|
||||
const blameline = line - gitUri.offset;
|
||||
if (blameline < 0) return undefined;
|
||||
|
||||
|
||||
@@ -31,7 +31,9 @@ export class CopyShaToClipboardCommand extends ActiveEditorCommand {
|
||||
const gitUri = GitUri.fromUri(uri, this.git);
|
||||
|
||||
if (!sha) {
|
||||
const line = editor.selection.active.line;
|
||||
if (editor && editor.document && editor.document.isDirty) return undefined;
|
||||
|
||||
const line = (editor && editor.selection.active.line) || gitUri.offset;
|
||||
const blameline = line - gitUri.offset;
|
||||
if (blameline < 0) return undefined;
|
||||
|
||||
|
||||
@@ -20,10 +20,12 @@ export class DiffLineWithPreviousCommand extends ActiveEditorCommand {
|
||||
uri = editor.document.uri;
|
||||
}
|
||||
|
||||
line = line ||(editor && editor.selection.active.line) || 0;
|
||||
let gitUri = GitUri.fromUri(uri, this.git);
|
||||
const gitUri = GitUri.fromUri(uri, this.git);
|
||||
line = line || (editor && editor.selection.active.line) || gitUri.offset;
|
||||
|
||||
if (!commit || GitProvider.isUncommitted(commit.sha)) {
|
||||
if (editor && editor.document && editor.document.isDirty) return undefined;
|
||||
|
||||
const blameline = line - gitUri.offset;
|
||||
if (blameline < 0) return undefined;
|
||||
|
||||
|
||||
@@ -18,10 +18,12 @@ export class DiffLineWithWorkingCommand extends ActiveEditorCommand {
|
||||
uri = editor.document.uri;
|
||||
}
|
||||
|
||||
line = line || (editor && editor.selection.active.line) || 0;
|
||||
const gitUri = GitUri.fromUri(uri, this.git);
|
||||
line = line || (editor && editor.selection.active.line) || gitUri.offset;
|
||||
|
||||
if (!commit || GitProvider.isUncommitted(commit.sha)) {
|
||||
const gitUri = GitUri.fromUri(uri, this.git);
|
||||
if (editor && editor.document && editor.document.isDirty) return undefined;
|
||||
|
||||
const blameline = line - gitUri.offset;
|
||||
if (blameline < 0) return undefined;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
'use strict';
|
||||
import { commands, ExtensionContext, languages, window, workspace } from 'vscode';
|
||||
import { BlameabilityTracker } from './blameabilityTracker';
|
||||
import { BlameActiveLineController } from './blameActiveLineController';
|
||||
import { BlameAnnotationController } from './blameAnnotationController';
|
||||
import { configureCssCharacters } from './blameAnnotationFormatter';
|
||||
@@ -63,14 +64,17 @@ export async function activate(context: ExtensionContext) {
|
||||
const git = new GitProvider(context);
|
||||
context.subscriptions.push(git);
|
||||
|
||||
const blameabilityTracker = new BlameabilityTracker(git);
|
||||
context.subscriptions.push(blameabilityTracker);
|
||||
|
||||
context.subscriptions.push(workspace.registerTextDocumentContentProvider(GitContentProvider.scheme, new GitContentProvider(context, git)));
|
||||
|
||||
context.subscriptions.push(languages.registerCodeLensProvider(GitRevisionCodeLensProvider.selector, new GitRevisionCodeLensProvider(context, git)));
|
||||
|
||||
const annotationController = new BlameAnnotationController(context, git);
|
||||
const annotationController = new BlameAnnotationController(context, git, blameabilityTracker);
|
||||
context.subscriptions.push(annotationController);
|
||||
|
||||
const activeLineController = new BlameActiveLineController(context, git, annotationController);
|
||||
const activeLineController = new BlameActiveLineController(context, git, blameabilityTracker, annotationController);
|
||||
context.subscriptions.push(activeLineController);
|
||||
|
||||
context.subscriptions.push(new Keyboard(context));
|
||||
|
||||
@@ -40,6 +40,7 @@ export default class GitCodeLensProvider implements CodeLensProvider {
|
||||
static selector: DocumentSelector = { scheme: DocumentSchemes.File };
|
||||
|
||||
private _config: IConfig;
|
||||
private _documentIsDirty: boolean;
|
||||
|
||||
constructor(context: ExtensionContext, private git: GitProvider) {
|
||||
this._config = workspace.getConfiguration('').get<IConfig>('gitlens');
|
||||
@@ -53,6 +54,8 @@ export default class GitCodeLensProvider implements CodeLensProvider {
|
||||
}
|
||||
|
||||
async provideCodeLenses(document: TextDocument, token: CancellationToken): Promise<CodeLens[]> {
|
||||
this._documentIsDirty = document.isDirty;
|
||||
|
||||
let languageLocations = this._config.codeLens.languageLocations.find(_ => _.language.toLowerCase() === document.languageId);
|
||||
if (languageLocations == null) {
|
||||
languageLocations = {
|
||||
@@ -93,7 +96,7 @@ export default class GitCodeLensProvider implements CodeLensProvider {
|
||||
if (!lenses.find(l => l.range.start.line === 0 && l.range.end.line === 0)) {
|
||||
const blameRange = document.validateRange(new Range(0, 1000000, 1000000, 1000000));
|
||||
let blameForRangeFn: () => IGitBlameLines;
|
||||
if (this._config.codeLens.recentChange.enabled) {
|
||||
if (this._documentIsDirty || this._config.codeLens.recentChange.enabled) {
|
||||
blameForRangeFn = Functions.once(() => this.git.getBlameForRangeSync(blame, gitUri.fsPath, blameRange, gitUri.sha, gitUri.repoPath));
|
||||
lenses.push(new GitRecentChangeCodeLens(blameForRangeFn, gitUri, SymbolKind.File, blameRange, true, new Range(0, 0, 0, blameRange.start.character)));
|
||||
}
|
||||
@@ -101,7 +104,9 @@ export default class GitCodeLensProvider implements CodeLensProvider {
|
||||
if (!blameForRangeFn) {
|
||||
blameForRangeFn = Functions.once(() => this.git.getBlameForRangeSync(blame, gitUri.fsPath, blameRange, gitUri.sha, gitUri.repoPath));
|
||||
}
|
||||
lenses.push(new GitAuthorsCodeLens(blameForRangeFn, gitUri, SymbolKind.File, blameRange, true, new Range(0, 1, 0, blameRange.start.character)));
|
||||
if (!this._documentIsDirty) {
|
||||
lenses.push(new GitAuthorsCodeLens(blameForRangeFn, gitUri, SymbolKind.File, blameRange, true, new Range(0, 1, 0, blameRange.start.character)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -158,7 +163,7 @@ export default class GitCodeLensProvider implements CodeLensProvider {
|
||||
}
|
||||
|
||||
let blameForRangeFn: () => IGitBlameLines;
|
||||
if (this._config.codeLens.recentChange.enabled) {
|
||||
if (this._documentIsDirty || this._config.codeLens.recentChange.enabled) {
|
||||
blameForRangeFn = Functions.once(() => this.git.getBlameForRangeSync(blame, gitUri.fsPath, symbol.location.range, gitUri.sha, gitUri.repoPath));
|
||||
lenses.push(new GitRecentChangeCodeLens(blameForRangeFn, gitUri, symbol.kind, symbol.location.range, false, line.range.with(new Position(line.range.start.line, startChar))));
|
||||
startChar++;
|
||||
@@ -188,7 +193,9 @@ export default class GitCodeLensProvider implements CodeLensProvider {
|
||||
if (!blameForRangeFn) {
|
||||
blameForRangeFn = Functions.once(() => this.git.getBlameForRangeSync(blame, gitUri.fsPath, symbol.location.range, gitUri.sha, gitUri.repoPath));
|
||||
}
|
||||
lenses.push(new GitAuthorsCodeLens(blameForRangeFn, gitUri, symbol.kind, symbol.location.range, false, line.range.with(new Position(line.range.start.line, startChar))));
|
||||
if (!this._documentIsDirty) {
|
||||
lenses.push(new GitAuthorsCodeLens(blameForRangeFn, gitUri, symbol.kind, symbol.location.range, false, line.range.with(new Position(line.range.start.line, startChar))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -200,10 +207,30 @@ export default class GitCodeLensProvider implements CodeLensProvider {
|
||||
}
|
||||
|
||||
_resolveGitRecentChangeCodeLens(lens: GitRecentChangeCodeLens, token: CancellationToken): CodeLens {
|
||||
// Since blame information isn't valid when there are unsaved changes -- update the lenses appropriately
|
||||
let title: string;
|
||||
if (this._documentIsDirty) {
|
||||
if (this._config.codeLens.recentChange.enabled && this._config.codeLens.authors.enabled) {
|
||||
title = 'Cannot determine recent change or authors (unsaved changes)';
|
||||
}
|
||||
else if (this._config.codeLens.recentChange.enabled) {
|
||||
title = 'Cannot determine recent change (unsaved changes)';
|
||||
}
|
||||
else {
|
||||
title = 'Cannot determine authors (unsaved changes)';
|
||||
}
|
||||
|
||||
lens.command = {
|
||||
title: title,
|
||||
command: undefined
|
||||
};
|
||||
return lens;
|
||||
}
|
||||
|
||||
const blame = lens.getBlame();
|
||||
|
||||
const recentCommit = Iterables.first(blame.commits.values());
|
||||
let title = `${recentCommit.author}, ${moment(recentCommit.date).fromNow()}`;
|
||||
title = `${recentCommit.author}, ${moment(recentCommit.date).fromNow()}`;
|
||||
if (this._config.advanced.debug && this._config.advanced.output.level === OutputLevel.Verbose) {
|
||||
title += ` [${recentCommit.sha}, Symbol(${SymbolKind[lens.symbolKind]}), Lines(${lens.blameRange.start.line + 1}-${lens.blameRange.end.line + 1})]`;
|
||||
}
|
||||
@@ -223,7 +250,7 @@ export default class GitCodeLensProvider implements CodeLensProvider {
|
||||
_resolveGitAuthorsCodeLens(lens: GitAuthorsCodeLens, token: CancellationToken): CodeLens {
|
||||
const blame = lens.getBlame();
|
||||
const count = blame.authors.size;
|
||||
const title = `${count} ${count > 1 ? 'authors' : 'author'} (${Iterables.first(blame.authors.values()).name}${count > 1 ? ' and others' : ''})`;
|
||||
let title = `${count} ${count > 1 ? 'authors' : 'author'} (${Iterables.first(blame.authors.values()).name}${count > 1 ? ' and others' : ''})`;
|
||||
|
||||
switch (this._config.codeLens.authors.command) {
|
||||
case CodeLensCommand.BlameAnnotate: return this._applyBlameAnnotateCommand<GitAuthorsCodeLens>(title, lens, blame);
|
||||
|
||||
@@ -52,6 +52,11 @@ export class GitProvider extends Disposable {
|
||||
return this._onDidChangeGitCacheEmitter.event;
|
||||
}
|
||||
|
||||
private _onDidBlameFailEmitter = new EventEmitter<string>();
|
||||
get onDidBlameFail(): Event<string> {
|
||||
return this._onDidBlameFailEmitter.event;
|
||||
}
|
||||
|
||||
private _gitCache: Map<string, GitCacheEntry> | undefined;
|
||||
private _cacheDisposable: Disposable | undefined;
|
||||
private _repoPath: string;
|
||||
@@ -100,6 +105,12 @@ export class GitProvider extends Disposable {
|
||||
this._uriCache = undefined;
|
||||
}
|
||||
|
||||
public getBlameability(fileName: string): boolean {
|
||||
const cacheKey = this.getCacheEntryKey(Git.normalizePath(fileName));
|
||||
const entry = this._gitCache.get(cacheKey);
|
||||
return !(entry && entry.hasErrors);
|
||||
}
|
||||
|
||||
public get UseUriCaching() {
|
||||
return !!this._uriCache;
|
||||
}
|
||||
@@ -189,7 +200,7 @@ export class GitProvider extends Disposable {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
private _getCacheEntryKey(fileName: string) {
|
||||
getCacheEntryKey(fileName: string) {
|
||||
return fileName.toLowerCase();
|
||||
}
|
||||
|
||||
@@ -206,7 +217,7 @@ export class GitProvider extends Disposable {
|
||||
|
||||
const fileName = Git.normalizePath(document.fileName);
|
||||
|
||||
const cacheKey = this._getCacheEntryKey(fileName);
|
||||
const cacheKey = this.getCacheEntryKey(fileName);
|
||||
|
||||
if (reason === RemoveCacheReason.DocumentSaved) {
|
||||
// Don't remove broken blame on save (since otherwise we'll have to run the broken blame again)
|
||||
@@ -240,7 +251,7 @@ export class GitProvider extends Disposable {
|
||||
fileName = fileNameOrEditor.document.uri.fsPath;
|
||||
}
|
||||
|
||||
const cacheKey = this._getCacheEntryKey(fileName);
|
||||
const cacheKey = this.getCacheEntryKey(fileName);
|
||||
return this._uriCache.has(cacheKey);
|
||||
}
|
||||
|
||||
@@ -271,7 +282,7 @@ export class GitProvider extends Disposable {
|
||||
getGitUriForFile(fileName: string) {
|
||||
if (!this.UseUriCaching) return undefined;
|
||||
|
||||
const cacheKey = this._getCacheEntryKey(fileName);
|
||||
const cacheKey = this.getCacheEntryKey(fileName);
|
||||
const entry = this._uriCache.get(cacheKey);
|
||||
return entry && entry.uri;
|
||||
}
|
||||
@@ -294,7 +305,7 @@ export class GitProvider extends Disposable {
|
||||
let cacheKey: string | undefined;
|
||||
let entry: GitCacheEntry | undefined;
|
||||
if (useCaching) {
|
||||
cacheKey = this._getCacheEntryKey(fileName);
|
||||
cacheKey = this.getCacheEntryKey(fileName);
|
||||
entry = this._gitCache.get(cacheKey);
|
||||
|
||||
if (entry !== undefined && entry.blame !== undefined) return entry.blame.item;
|
||||
@@ -306,6 +317,9 @@ export class GitProvider extends Disposable {
|
||||
const promise = this._gitignore.then(ignore => {
|
||||
if (ignore && !ignore.filter([fileName]).length) {
|
||||
Logger.log(`Skipping blame; '${fileName}' is gitignored`);
|
||||
if (cacheKey) {
|
||||
this._onDidBlameFailEmitter.fire(cacheKey);
|
||||
}
|
||||
return GitProvider.EmptyPromise as Promise<IGitBlame>;
|
||||
}
|
||||
|
||||
@@ -323,6 +337,7 @@ export class GitProvider extends Disposable {
|
||||
errorMessage: msg
|
||||
} as ICachedBlame;
|
||||
|
||||
this._onDidBlameFailEmitter.fire(cacheKey);
|
||||
this._gitCache.set(cacheKey, entry);
|
||||
return GitProvider.EmptyPromise as Promise<IGitBlame>;
|
||||
}
|
||||
@@ -485,7 +500,7 @@ export class GitProvider extends Disposable {
|
||||
let cacheKey: string;
|
||||
let entry: GitCacheEntry;
|
||||
if (useCaching) {
|
||||
cacheKey = this._getCacheEntryKey(fileName);
|
||||
cacheKey = this.getCacheEntryKey(fileName);
|
||||
entry = this._gitCache.get(cacheKey);
|
||||
|
||||
if (entry !== undefined && entry.log !== undefined) return entry.log.item;
|
||||
@@ -583,7 +598,7 @@ export class GitProvider extends Disposable {
|
||||
|
||||
const file = await Git.getVersionedFile(fileName, repoPath, sha);
|
||||
if (this.UseUriCaching) {
|
||||
const cacheKey = this._getCacheEntryKey(file);
|
||||
const cacheKey = this.getCacheEntryKey(file);
|
||||
const entry = new UriCacheEntry(new GitUri(Uri.file(fileName), { sha, repoPath, fileName }));
|
||||
this._uriCache.set(cacheKey, entry);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user