mirror of
https://github.com/ckaczor/vscode-gitlens.git
synced 2026-01-16 09:35:40 -05:00
Fixes #59 - Updates command context to opened file state
Removes insiders restriction from Open in Remote commands
This commit is contained in:
84
package.json
84
package.json
@@ -517,47 +517,47 @@
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffWithBranch",
|
||||
"when": "editorTextFocus && gitlens:enabled"
|
||||
"when": "editorTextFocus && gitlens:isTracked"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffWithNext",
|
||||
"when": "editorTextFocus && gitlens:enabled"
|
||||
"when": "editorTextFocus && gitlens:isTracked"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffWithPrevious",
|
||||
"when": "editorTextFocus && gitlens:enabled"
|
||||
"when": "editorTextFocus && gitlens:isTracked"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffLineWithPrevious",
|
||||
"when": "editorTextFocus && gitlens:enabled && gitlens:isBlameable"
|
||||
"when": "editorTextFocus && gitlens:isBlameable"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffWithWorking",
|
||||
"when": "editorTextFocus && gitlens:enabled"
|
||||
"when": "editorTextFocus && gitlens:isTracked"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffLineWithWorking",
|
||||
"when": "editorTextFocus && gitlens:enabled && gitlens:isBlameable"
|
||||
"when": "editorTextFocus && gitlens:isBlameable"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.showBlame",
|
||||
"when": "editorTextFocus && gitlens:enabled && gitlens:isBlameable"
|
||||
"when": "editorTextFocus && gitlens:isBlameable"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.toggleBlame",
|
||||
"when": "editorTextFocus && gitlens:enabled && gitlens:isBlameable"
|
||||
"when": "editorTextFocus && gitlens:isBlameable"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.toggleCodeLens",
|
||||
"when": "editorTextFocus && gitlens:enabled && gitlens:canToggleCodeLens"
|
||||
"when": "editorTextFocus && gitlens:isTracked && gitlens:canToggleCodeLens"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.showBlameHistory",
|
||||
"when": "editorTextFocus && gitlens:enabled && gitlens:isBlameable"
|
||||
"when": "editorTextFocus && gitlens:isBlameable"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.showFileHistory",
|
||||
"when": "editorTextFocus && gitlens:enabled"
|
||||
"when": "editorTextFocus && gitlens:isTracked"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.showLastQuickPick",
|
||||
@@ -565,15 +565,15 @@
|
||||
},
|
||||
{
|
||||
"command": "gitlens.showQuickCommitDetails",
|
||||
"when": "gitlens:enabled && gitlens:isBlameable"
|
||||
"when": "gitlens:isBlameable"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.showQuickCommitFileDetails",
|
||||
"when": "gitlens:enabled && gitlens:isBlameable"
|
||||
"when": "gitlens:isBlameable"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.showQuickFileHistory",
|
||||
"when": "editorTextFocus && gitlens:enabled"
|
||||
"when": "editorTextFocus && gitlens:isTracked"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.showQuickBranchHistory",
|
||||
@@ -593,11 +593,11 @@
|
||||
},
|
||||
{
|
||||
"command": "gitlens.copyShaToClipboard",
|
||||
"when": "editorTextFocus && gitlens:enabled && gitlens:isBlameable"
|
||||
"when": "editorTextFocus && gitlens:isBlameable"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.copyMessageToClipboard",
|
||||
"when": "editorTextFocus && gitlens:enabled && gitlens:isBlameable"
|
||||
"when": "editorTextFocus && gitlens:isBlameable"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.closeUnchangedFiles",
|
||||
@@ -609,11 +609,11 @@
|
||||
},
|
||||
{
|
||||
"command": "gitlens.openCommitInRemote",
|
||||
"when": "editorTextFocus && gitlens:enabled && gitlens:hasRemotes && gitlens:isBlameable"
|
||||
"when": "editorTextFocus && gitlens:isBlameable && gitlens:hasRemotes"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.openFileInRemote",
|
||||
"when": "editorTextFocus && gitlens:enabled && gitlens:hasRemotes"
|
||||
"when": "editorTextFocus && gitlens:isTracked && gitlens:hasRemotes"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.stashApply",
|
||||
@@ -642,29 +642,29 @@
|
||||
},
|
||||
{
|
||||
"command": "gitlens.openFileInRemote",
|
||||
"when": "gitlens:enabled && gitlens:hasRemotes",
|
||||
"when": "gitlens:enabled",
|
||||
"group": "1_gitlens_1@2"
|
||||
}
|
||||
],
|
||||
"editor/title": [
|
||||
{
|
||||
"command": "gitlens.toggleBlame",
|
||||
"when": "gitlens:enabled && gitlens:isBlameable",
|
||||
"when": "gitlens:isBlameable",
|
||||
"group": "navigation@100"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffWithPrevious",
|
||||
"when": "editorTextFocus && gitlens:enabled && config.gitlens.menus.diff.enabled",
|
||||
"when": "editorTextFocus && gitlens:isTracked && config.gitlens.menus.diff.enabled",
|
||||
"group": "2_gitlens"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffWithWorking",
|
||||
"when": "editorTextFocus && gitlens:enabled && config.gitlens.menus.diff.enabled",
|
||||
"when": "editorTextFocus && gitlens:isTracked && config.gitlens.menus.diff.enabled",
|
||||
"group": "2_gitlens"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.showQuickFileHistory",
|
||||
"when": "editorFocus && gitlens:enabled",
|
||||
"when": "editorFocus && gitlens:isTracked",
|
||||
"group": "2_gitlens_1"
|
||||
},
|
||||
{
|
||||
@@ -696,64 +696,64 @@
|
||||
},
|
||||
{
|
||||
"command": "gitlens.toggleBlame",
|
||||
"when": "gitlens:enabled && gitlens:isBlameable",
|
||||
"when": "gitlens:enabled",
|
||||
"group": "1_gitlens_1@2"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.openFileInRemote",
|
||||
"when": "gitlens:enabled && gitlens:hasRemotes",
|
||||
"when": "gitlens:enabled",
|
||||
"group": "1_gitlens_1@3"
|
||||
}
|
||||
],
|
||||
"editor/context": [
|
||||
{
|
||||
"command": "gitlens.diffLineWithPrevious",
|
||||
"when": "editorTextFocus && gitlens:enabled && gitlens:isBlameable && config.gitlens.menus.diff.enabled",
|
||||
"when": "editorTextFocus && gitlens:isBlameable && config.gitlens.menus.diff.enabled",
|
||||
"group": "1_gitlens@1"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffLineWithWorking",
|
||||
"when": "editorTextFocus && gitlens:enabled && gitlens:isBlameable && config.gitlens.menus.diff.enabled",
|
||||
"when": "editorTextFocus && gitlens:isBlameable && config.gitlens.menus.diff.enabled",
|
||||
"group": "1_gitlens@2"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.showQuickCommitFileDetails",
|
||||
"when": "editorTextFocus && gitlens:enabled && gitlens:isBlameable",
|
||||
"when": "editorTextFocus && gitlens:isBlameable",
|
||||
"group": "1_gitlens@3"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffWithPrevious",
|
||||
"when": "editorTextFocus && gitlens:enabled && config.gitlens.menus.diff.enabled",
|
||||
"when": "editorTextFocus && gitlens:isTracked && config.gitlens.menus.diff.enabled",
|
||||
"group": "1_gitlens_1@1"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffWithWorking",
|
||||
"when": "editorTextFocus && gitlens:enabled && config.gitlens.menus.diff.enabled",
|
||||
"when": "editorTextFocus && gitlens:isTracked && config.gitlens.menus.diff.enabled",
|
||||
"group": "1_gitlens_1@2"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.showQuickFileHistory",
|
||||
"when": "gitlens:enabled",
|
||||
"when": "gitlens:isTracked",
|
||||
"group": "2_gitlens@1"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.toggleBlame",
|
||||
"when": "editorTextFocus && gitlens:enabled && gitlens:isBlameable",
|
||||
"when": "editorTextFocus && gitlens:isBlameable",
|
||||
"group": "2_gitlens@2"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.openFileInRemote",
|
||||
"when": "editorTextFocus && gitlens:enabled && gitlens:hasRemotes",
|
||||
"when": "editorTextFocus && gitlens:isTracked && gitlens:hasRemotes",
|
||||
"group": "2_gitlens@3"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.copyShaToClipboard",
|
||||
"when": "editorTextFocus && gitlens:enabled && gitlens:isBlameable",
|
||||
"when": "editorTextFocus && gitlens:isBlameable",
|
||||
"group": "9_gitlens@1"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.copyMessageToClipboard",
|
||||
"when": "editorTextFocus && gitlens:enabled && gitlens:isBlameable",
|
||||
"when": "editorTextFocus && gitlens:isBlameable",
|
||||
"group": "9_gitlens@2"
|
||||
}
|
||||
]
|
||||
@@ -783,13 +783,13 @@
|
||||
"command": "gitlens.toggleBlame",
|
||||
"key": "alt+b",
|
||||
"mac": "alt+b",
|
||||
"when": "editorTextFocus && gitlens:enabled"
|
||||
"when": "editorTextFocus && gitlens:isBlameable"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.toggleCodeLens",
|
||||
"key": "alt+shift+b",
|
||||
"mac": "alt+shift+b",
|
||||
"when": "editorTextFocus && gitlens:enabled && gitlens:canToggleCodeLens"
|
||||
"when": "editorTextFocus && gitlens:isTracked && gitlens:canToggleCodeLens"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.showLastQuickPick",
|
||||
@@ -825,31 +825,31 @@
|
||||
"command": "gitlens.diffWithNext",
|
||||
"key": "alt+.",
|
||||
"mac": "alt+.",
|
||||
"when": "editorTextFocus && gitlens:enabled"
|
||||
"when": "editorTextFocus && gitlens:isTracked"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffLineWithPrevious",
|
||||
"key": "shift+alt+,",
|
||||
"mac": "shift+alt+,",
|
||||
"when": "editorTextFocus && gitlens:enabled"
|
||||
"when": "editorTextFocus && gitlens:isBlameable"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffWithPrevious",
|
||||
"key": "alt+,",
|
||||
"mac": "alt+,",
|
||||
"when": "editorTextFocus && gitlens:enabled"
|
||||
"when": "editorTextFocus && gitlens:isTracked"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffLineWithWorking",
|
||||
"key": "alt+w",
|
||||
"mac": "alt+w",
|
||||
"when": "editorTextFocus && gitlens:enabled"
|
||||
"when": "editorTextFocus && gitlens:isBlameable"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffWithWorking",
|
||||
"key": "shift+alt+w",
|
||||
"mac": "shift+alt+w",
|
||||
"when": "editorTextFocus && gitlens:enabled"
|
||||
"when": "editorTextFocus && gitlens:isTracked"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
'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';
|
||||
import { IBlameConfig, IConfig, StatusBarCommand } from './configuration';
|
||||
import { DocumentSchemes } from './constants';
|
||||
import { GitCommit, GitService, GitUri, IGitBlame, IGitCommitLine } from './gitService';
|
||||
import { BlameabilityChangeEvent, GitCommit, GitContextTracker, GitService, GitUri, IGitBlame, IGitCommitLine } from './gitService';
|
||||
import * as moment from 'moment';
|
||||
|
||||
const activeLineDecoration: TextEditorDecorationType = window.createTextEditorDecorationType({
|
||||
@@ -30,7 +29,7 @@ export class BlameActiveLineController extends Disposable {
|
||||
private _uri: GitUri;
|
||||
private _useCaching: boolean;
|
||||
|
||||
constructor(context: ExtensionContext, private git: GitService, private blameabilityTracker: BlameabilityTracker, private annotationController: BlameAnnotationController) {
|
||||
constructor(context: ExtensionContext, private git: GitService, private gitContextTracker: GitContextTracker, private annotationController: BlameAnnotationController) {
|
||||
super(() => this.dispose());
|
||||
|
||||
this._updateBlameDebounced = Functions.debounce(this._updateBlame, 50);
|
||||
@@ -95,7 +94,7 @@ export class BlameActiveLineController extends Disposable {
|
||||
|
||||
subscriptions.push(window.onDidChangeActiveTextEditor(this._onActiveTextEditorChanged, this));
|
||||
subscriptions.push(window.onDidChangeTextEditorSelection(this._onTextEditorSelectionChanged, this));
|
||||
subscriptions.push(this.blameabilityTracker.onDidChange(this._onBlameabilityChanged, this));
|
||||
subscriptions.push(this.gitContextTracker.onDidBlameabilityChange(this._onBlameabilityChanged, this));
|
||||
|
||||
this._activeEditorLineDisposable = Disposable.from(...subscriptions);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
'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';
|
||||
import { GitService, GitUri } from './gitService';
|
||||
import { BlameabilityChangeEvent, GitService, GitUri, GitContextTracker } from './gitService';
|
||||
import { Logger } from './logger';
|
||||
import { WhitespaceController } from './whitespaceController';
|
||||
|
||||
@@ -34,7 +33,7 @@ export class BlameAnnotationController extends Disposable {
|
||||
private _disposable: Disposable;
|
||||
private _whitespaceController: WhitespaceController | undefined;
|
||||
|
||||
constructor(private context: ExtensionContext, private git: GitService, private blameabilityTracker: BlameabilityTracker) {
|
||||
constructor(private context: ExtensionContext, private git: GitService, private gitContextTracker: GitContextTracker) {
|
||||
super(() => this.dispose());
|
||||
|
||||
this._onConfigurationChanged();
|
||||
@@ -177,7 +176,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));
|
||||
subscriptions.push(this.gitContextTracker.onDidBlameabilityChange(this._onBlameabilityChanged, this));
|
||||
|
||||
this._blameAnnotationsDisposable = Disposable.from(...subscriptions);
|
||||
}
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
'use strict';
|
||||
import { Disposable, Event, EventEmitter, TextDocument, TextDocumentChangeEvent, TextEditor, window, workspace } from 'vscode';
|
||||
import { CommandContext, setCommandContext } from './commands';
|
||||
import { TextDocumentComparer } from './comparers';
|
||||
import { GitService } from './gitService';
|
||||
|
||||
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: GitService) {
|
||||
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;
|
||||
|
||||
// Can't unsubscribe here because undo doesn't trigger any other event
|
||||
//this._unsubscribeToDocumentChanges();
|
||||
//this.updateBlameability(false);
|
||||
|
||||
// We have to defer because isDirty is not reliable inside this event
|
||||
setTimeout(() => this.updateBlameability(!e.document.isDirty), 1);
|
||||
}
|
||||
|
||||
private _onTextDocumentSaved(e: TextDocument) {
|
||||
if (!TextDocumentComparer.equals(this._editor && this._editor.document, e)) return;
|
||||
|
||||
// Don't need to resubscribe as we aren't unsubscribing on document changes anymore
|
||||
//this._subscribeToDocumentChanges();
|
||||
this.updateBlameability(!e.isDirty);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
setCommandContext(CommandContext.IsBlameable, blameable);
|
||||
this._onDidChange.fire({
|
||||
blameable: blameable,
|
||||
editor: this._editor
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -46,12 +46,14 @@ export const Commands = {
|
||||
ToggleCodeLens: 'gitlens.toggleCodeLens' as Commands
|
||||
};
|
||||
|
||||
export type CommandContext = 'gitlens:canToggleCodeLens' | 'gitlens:enabled' | 'gitlens:hasRemotes' | 'gitlens:isBlameable' | 'gitlens:key';
|
||||
export type CommandContext = 'gitlens:canToggleCodeLens' | 'gitlens:enabled' | 'gitlens:hasRemotes' | 'gitlens:isBlameable' | 'gitlens:isRepository' | 'gitlens:isTracked' | 'gitlens:key';
|
||||
export const CommandContext = {
|
||||
CanToggleCodeLens: 'gitlens:canToggleCodeLens' as CommandContext,
|
||||
Enabled: 'gitlens:enabled' as CommandContext,
|
||||
HasRemotes: 'gitlens:hasRemotes' as CommandContext,
|
||||
IsBlameable: 'gitlens:isBlameable' as CommandContext,
|
||||
IsRepository: 'gitlens:isRepository' as CommandContext,
|
||||
IsTracked: 'gitlens:isTracked' as CommandContext,
|
||||
Key: 'gitlens:key' as CommandContext
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
'use strict';
|
||||
import { Objects } from './system';
|
||||
import { commands, Disposable, ExtensionContext, extensions, languages, TextEditor, Uri, window, workspace } from 'vscode';
|
||||
import { BlameabilityTracker } from './blameabilityTracker';
|
||||
import { commands, ExtensionContext, extensions, languages, Uri, window, workspace } from 'vscode';
|
||||
import { BlameActiveLineController } from './blameActiveLineController';
|
||||
import { BlameAnnotationController } from './blameAnnotationController';
|
||||
import { configureCssCharacters } from './blameAnnotationFormatter';
|
||||
@@ -20,7 +19,7 @@ import { Keyboard } from './commands';
|
||||
import { IConfig } from './configuration';
|
||||
import { ApplicationInsightsKey, BuiltInCommands, ExtensionId, WorkspaceState } from './constants';
|
||||
import { GitContentProvider } from './gitContentProvider';
|
||||
import { Git, GitService } from './gitService';
|
||||
import { Git, GitContextTracker, GitService } from './gitService';
|
||||
import { GitRevisionCodeLensProvider } from './gitRevisionCodeLensProvider';
|
||||
import { Logger } from './logger';
|
||||
import { Telemetry } from './telemetry';
|
||||
@@ -69,19 +68,17 @@ export async function activate(context: ExtensionContext) {
|
||||
const git = new GitService(context, repoPath);
|
||||
context.subscriptions.push(git);
|
||||
|
||||
setCommandsContext(context, git);
|
||||
|
||||
const blameabilityTracker = new BlameabilityTracker(git);
|
||||
context.subscriptions.push(blameabilityTracker);
|
||||
const gitContextTracker = new GitContextTracker(git);
|
||||
context.subscriptions.push(gitContextTracker);
|
||||
|
||||
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, blameabilityTracker);
|
||||
const annotationController = new BlameAnnotationController(context, git, gitContextTracker);
|
||||
context.subscriptions.push(annotationController);
|
||||
|
||||
const activeLineController = new BlameActiveLineController(context, git, blameabilityTracker, annotationController);
|
||||
const activeLineController = new BlameActiveLineController(context, git, gitContextTracker, annotationController);
|
||||
context.subscriptions.push(activeLineController);
|
||||
|
||||
context.subscriptions.push(new Keyboard());
|
||||
@@ -155,54 +152,4 @@ async function notifyOnUnsupportedGitVersion(context: ExtensionContext, version:
|
||||
context.globalState.update(WorkspaceState.SuppressGitVersionWarning, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let savedGitEnabled: boolean;
|
||||
let savedInsiders: boolean;
|
||||
let insidersDisposable: Disposable;
|
||||
|
||||
async function setCommandsContext(context: ExtensionContext, git: GitService): Promise<void> {
|
||||
onCommandsContextConfigurationChanged(git);
|
||||
context.subscriptions.push(workspace.onDidChangeConfiguration(() => onCommandsContextConfigurationChanged(git), this));
|
||||
}
|
||||
|
||||
async function onCommandsContextConfigurationChanged(git: GitService) {
|
||||
const gitEnabled = workspace.getConfiguration('git').get<boolean>('enabled');
|
||||
if (gitEnabled !== savedGitEnabled) {
|
||||
savedGitEnabled = gitEnabled;
|
||||
setCommandContext(CommandContext.Enabled, gitEnabled);
|
||||
}
|
||||
|
||||
const insiders = workspace.getConfiguration('gitlens').get<boolean>('insiders');
|
||||
if (insiders !== savedInsiders) {
|
||||
savedInsiders = insiders;
|
||||
|
||||
insidersDisposable && insidersDisposable.dispose();
|
||||
if (insiders) {
|
||||
insidersDisposable = window.onDidChangeActiveTextEditor(e => onActiveTextEditorChanged(e, git));
|
||||
onActiveTextEditorChanged(window.activeTextEditor, git);
|
||||
}
|
||||
else {
|
||||
insidersDisposable = undefined;
|
||||
setCommandContext(CommandContext.HasRemotes, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function onActiveTextEditorChanged(editor: TextEditor, git: GitService) {
|
||||
try {
|
||||
let hasRemotes = false;
|
||||
if (editor) {
|
||||
const repoPath = await git.getRepoPathFromUri(editor.document.uri);
|
||||
if (repoPath) {
|
||||
const remotes = await git.getRemotes(repoPath);
|
||||
hasRemotes = remotes.length !== 0;
|
||||
}
|
||||
}
|
||||
|
||||
setCommandContext(CommandContext.HasRemotes, hasRemotes);
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'Extension.onActiveTextEditorChanged');
|
||||
}
|
||||
}
|
||||
@@ -235,6 +235,15 @@ export class Git {
|
||||
return gitCommand(root, ...params);
|
||||
}
|
||||
|
||||
static async ls_files(repoPath: string, fileName: string): Promise<string> {
|
||||
try {
|
||||
return await gitCommand(repoPath, 'ls-files', fileName);
|
||||
}
|
||||
catch (ex) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
static remote(repoPath: string): Promise<string> {
|
||||
return gitCommand(repoPath, 'remote', '-v');
|
||||
}
|
||||
|
||||
163
src/git/gitContextTracker.ts
Normal file
163
src/git/gitContextTracker.ts
Normal file
@@ -0,0 +1,163 @@
|
||||
'use strict';
|
||||
import { Disposable, Event, EventEmitter, TextDocument, TextDocumentChangeEvent, TextEditor, window, workspace } from 'vscode';
|
||||
import { CommandContext, setCommandContext } from '../commands';
|
||||
import { TextDocumentComparer } from '../comparers';
|
||||
import { GitService, GitUri } from '../gitService';
|
||||
import { Logger } from '../logger';
|
||||
|
||||
export interface BlameabilityChangeEvent {
|
||||
blameable: boolean;
|
||||
editor: TextEditor;
|
||||
}
|
||||
|
||||
export class GitContextTracker extends Disposable {
|
||||
|
||||
private _onDidBlameabilityChange = new EventEmitter<BlameabilityChangeEvent>();
|
||||
get onDidBlameabilityChange(): Event<BlameabilityChangeEvent> {
|
||||
return this._onDidBlameabilityChange.event;
|
||||
}
|
||||
|
||||
private _disposable: Disposable;
|
||||
private _documentChangeDisposable: Disposable;
|
||||
private _editor: TextEditor;
|
||||
private _gitEnabled: boolean;
|
||||
private _isBlameable: boolean;
|
||||
|
||||
constructor(private git: GitService) {
|
||||
super(() => this.dispose());
|
||||
|
||||
const subscriptions: Disposable[] = [];
|
||||
|
||||
subscriptions.push(window.onDidChangeActiveTextEditor(this._onActiveTextEditorChanged, this));
|
||||
subscriptions.push(workspace.onDidChangeConfiguration(this._onConfigurationChanged, this));
|
||||
subscriptions.push(workspace.onDidSaveTextDocument(this._onTextDocumentSaved, this));
|
||||
subscriptions.push(this.git.onDidBlameFail(this._onBlameFailed, this));
|
||||
|
||||
this._disposable = Disposable.from(...subscriptions);
|
||||
|
||||
setCommandContext(CommandContext.IsRepository, !!this.git.repoPath);
|
||||
|
||||
this._onConfigurationChanged();
|
||||
this._onActiveTextEditorChanged(window.activeTextEditor);
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this._disposable && this._disposable.dispose();
|
||||
this._documentChangeDisposable && this._documentChangeDisposable.dispose();
|
||||
}
|
||||
|
||||
_onConfigurationChanged() {
|
||||
const gitEnabled = workspace.getConfiguration('git').get<boolean>('enabled');
|
||||
if (this._gitEnabled !== gitEnabled) {
|
||||
this._gitEnabled = gitEnabled;
|
||||
setCommandContext(CommandContext.Enabled, gitEnabled);
|
||||
this._onActiveTextEditorChanged(window.activeTextEditor);
|
||||
}
|
||||
}
|
||||
|
||||
private _onActiveTextEditorChanged(editor: TextEditor) {
|
||||
this._editor = editor;
|
||||
this._updateContext(this._gitEnabled && editor);
|
||||
this._subscribeToDocumentChanges();
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
// Can't unsubscribe here because undo doesn't trigger any other event
|
||||
//this._unsubscribeToDocumentChanges();
|
||||
//this.updateBlameability(false);
|
||||
|
||||
// We have to defer because isDirty is not reliable inside this event
|
||||
setTimeout(() => this._updateBlameability(!e.document.isDirty), 1);
|
||||
}
|
||||
|
||||
private _onTextDocumentSaved(e: TextDocument) {
|
||||
if (!TextDocumentComparer.equals(this._editor && this._editor.document, e)) return;
|
||||
|
||||
// Don't need to resubscribe as we aren't unsubscribing on document changes anymore
|
||||
//this._subscribeToDocumentChanges();
|
||||
this._updateBlameability(!e.isDirty);
|
||||
}
|
||||
|
||||
private _subscribeToDocumentChanges() {
|
||||
this._unsubscribeToDocumentChanges();
|
||||
this._documentChangeDisposable = workspace.onDidChangeTextDocument(this._onTextDocumentChanged, this);
|
||||
}
|
||||
|
||||
private _unsubscribeToDocumentChanges() {
|
||||
this._documentChangeDisposable && this._documentChangeDisposable.dispose();
|
||||
this._documentChangeDisposable = undefined;
|
||||
}
|
||||
|
||||
private async _updateContext(editor: TextEditor) {
|
||||
try {
|
||||
const gitUri = editor && await GitUri.fromUri(editor.document.uri, this.git);
|
||||
|
||||
await Promise.all([
|
||||
this._updateEditorContext(gitUri, editor),
|
||||
this._updateContextHasRemotes(gitUri)
|
||||
]);
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'GitEditorTracker._updateContext');
|
||||
}
|
||||
}
|
||||
|
||||
private async _updateContextHasRemotes(uri: GitUri | undefined) {
|
||||
try {
|
||||
let hasRemotes = false;
|
||||
if (uri) {
|
||||
const repoPath = uri.repoPath || this.git.repoPath;
|
||||
if (repoPath) {
|
||||
const remotes = await this.git.getRemotes(repoPath);
|
||||
hasRemotes = remotes.length !== 0;
|
||||
}
|
||||
}
|
||||
|
||||
setCommandContext(CommandContext.HasRemotes, hasRemotes);
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'GitEditorTracker._updateContextHasRemotes');
|
||||
}
|
||||
}
|
||||
|
||||
private async _updateEditorContext(uri: GitUri | undefined, editor: TextEditor | undefined) {
|
||||
try {
|
||||
const tracked = uri && await this.git.isTracked(uri);
|
||||
setCommandContext(CommandContext.IsTracked, tracked);
|
||||
|
||||
let blameable = tracked && editor && editor.document && !editor.document.isDirty;
|
||||
if (blameable) {
|
||||
blameable = await this.git.getBlameability(uri);
|
||||
}
|
||||
|
||||
this._updateBlameability(blameable, true);
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'GitEditorTracker._updateEditorContext');
|
||||
}
|
||||
}
|
||||
|
||||
private _updateBlameability(blameable: boolean, force: boolean = false) {
|
||||
if (!force && this._isBlameable === blameable) return;
|
||||
|
||||
try {
|
||||
setCommandContext(CommandContext.IsBlameable, blameable);
|
||||
this._onDidBlameabilityChange.fire({
|
||||
blameable: blameable,
|
||||
editor: this._editor
|
||||
});
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'GitEditorTracker._updateBlameability');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,9 +13,9 @@ import * as ignore from 'ignore';
|
||||
import * as moment from 'moment';
|
||||
import * as path from 'path';
|
||||
|
||||
export { getGitStatusIcon } from './git/git';
|
||||
export { Git, GitUri };
|
||||
export { GitUri };
|
||||
export * from './git/git';
|
||||
export * from './git/gitContextTracker';
|
||||
|
||||
class UriCacheEntry {
|
||||
|
||||
@@ -296,12 +296,14 @@ export class GitService extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
public getBlameability(fileName: string): boolean {
|
||||
if (!this.UseGitCaching) return true;
|
||||
public async getBlameability(uri: GitUri): Promise<boolean> {
|
||||
if (!this.UseGitCaching) return await this.isTracked(uri);
|
||||
|
||||
const cacheKey = this.getCacheEntryKey(fileName);
|
||||
const cacheKey = this.getCacheEntryKey(uri.fsPath);
|
||||
const entry = this._gitCache.get(cacheKey);
|
||||
return !(entry && entry.hasErrors);
|
||||
if (!entry) return await this.isTracked(uri);
|
||||
|
||||
return !entry.hasErrors;
|
||||
}
|
||||
|
||||
async getBlameForFile(uri: GitUri): Promise<IGitBlame | undefined> {
|
||||
@@ -752,6 +754,13 @@ export class GitService extends Disposable {
|
||||
return !!status;
|
||||
}
|
||||
|
||||
async isTracked(uri: GitUri): Promise<boolean> {
|
||||
Logger.log(`isFileUncommitted('${uri.repoPath}', '${uri.fsPath}')`);
|
||||
|
||||
const result = await Git.ls_files(uri.repoPath, uri.fsPath);
|
||||
return !!result;
|
||||
}
|
||||
|
||||
openDirectoryDiff(repoPath: string, sha1: string, sha2?: string) {
|
||||
Logger.log(`openDirectoryDiff('${repoPath}', ${sha1}, ${sha2})`);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user