Browse Source

Reworks container usage

main
Eric Amodio 3 years ago
parent
commit
5dee2e97b0
165 changed files with 1401 additions and 1105 deletions
  1. +4
    -4
      src/annotations/annotations.ts
  2. +2
    -2
      src/annotations/autolinks.ts
  3. +12
    -11
      src/annotations/blameAnnotationProvider.ts
  4. +21
    -15
      src/annotations/fileAnnotationController.ts
  5. +7
    -7
      src/annotations/gutterBlameAnnotationProvider.ts
  6. +18
    -14
      src/annotations/gutterChangesAnnotationProvider.ts
  7. +4
    -3
      src/annotations/gutterHeatmapBlameAnnotationProvider.ts
  8. +22
    -18
      src/annotations/lineAnnotationController.ts
  9. +5
    -5
      src/api/actionRunners.ts
  10. +7
    -2
      src/api/api.ts
  11. +6
    -6
      src/avatars.ts
  12. +14
    -8
      src/codelens/codeLensController.ts
  13. +24
    -29
      src/codelens/codeLensProvider.ts
  14. +1
    -1
      src/commands/addAuthors.ts
  15. +1
    -1
      src/commands/browseRepoAtRevision.ts
  16. +1
    -1
      src/commands/closeUnchangedFiles.ts
  17. +1
    -1
      src/commands/closeView.ts
  18. +2
    -2
      src/commands/common.ts
  19. +2
    -2
      src/commands/compareWith.ts
  20. +1
    -1
      src/commands/copyCurrentBranch.ts
  21. +9
    -5
      src/commands/copyMessageToClipboard.ts
  22. +9
    -5
      src/commands/copyShaToClipboard.ts
  23. +1
    -1
      src/commands/createPullRequestOnRemote.ts
  24. +1
    -1
      src/commands/diffLineWithPrevious.ts
  25. +3
    -3
      src/commands/diffLineWithWorking.ts
  26. +9
    -5
      src/commands/diffWith.ts
  27. +1
    -1
      src/commands/diffWithNext.ts
  28. +1
    -1
      src/commands/diffWithPrevious.ts
  29. +2
    -2
      src/commands/diffWithRevision.ts
  30. +1
    -1
      src/commands/diffWithRevisionFrom.ts
  31. +8
    -3
      src/commands/diffWithWorking.ts
  32. +8
    -6
      src/commands/externalDiff.ts
  33. +1
    -1
      src/commands/git/branch.ts
  34. +2
    -2
      src/commands/git/cherry-pick.ts
  35. +2
    -2
      src/commands/git/coauthors.ts
  36. +2
    -2
      src/commands/git/fetch.ts
  37. +4
    -4
      src/commands/git/log.ts
  38. +3
    -3
      src/commands/git/merge.ts
  39. +2
    -2
      src/commands/git/pull.ts
  40. +3
    -3
      src/commands/git/push.ts
  41. +4
    -4
      src/commands/git/rebase.ts
  42. +2
    -2
      src/commands/git/reset.ts
  43. +2
    -2
      src/commands/git/revert.ts
  44. +5
    -5
      src/commands/git/search.ts
  45. +5
    -2
      src/commands/git/show.ts
  46. +5
    -5
      src/commands/git/stash.ts
  47. +1
    -1
      src/commands/git/status.ts
  48. +2
    -2
      src/commands/git/switch.ts
  49. +1
    -1
      src/commands/git/tag.ts
  50. +35
    -31
      src/commands/gitCommands.actions.ts
  51. +6
    -6
      src/commands/gitCommands.ts
  52. +2
    -2
      src/commands/inviteToLiveShare.ts
  53. +1
    -1
      src/commands/openAssociatedPullRequestOnRemote.ts
  54. +1
    -1
      src/commands/openChangedFiles.ts
  55. +2
    -2
      src/commands/openCommitOnRemote.ts
  56. +5
    -3
      src/commands/openFileAtRevision.ts
  57. +2
    -2
      src/commands/openFileFromRemote.ts
  58. +9
    -5
      src/commands/openFileOnRemote.ts
  59. +2
    -2
      src/commands/openOnRemote.ts
  60. +2
    -2
      src/commands/openPullRequestOnRemote.ts
  61. +1
    -1
      src/commands/openRevisionFile.ts
  62. +4
    -2
      src/commands/openWorkingFile.ts
  63. +8
    -6
      src/commands/quickCommand.buttons.ts
  64. +52
    -26
      src/commands/quickCommand.steps.ts
  65. +1
    -1
      src/commands/quickCommand.ts
  66. +2
    -2
      src/commands/rebaseEditor.ts
  67. +7
    -7
      src/commands/remoteProviders.ts
  68. +12
    -3
      src/commands/repositories.ts
  69. +1
    -1
      src/commands/searchCommits.ts
  70. +2
    -2
      src/commands/showCommitsInView.ts
  71. +1
    -1
      src/commands/showQuickBranchHistory.ts
  72. +2
    -2
      src/commands/showQuickCommit.ts
  73. +5
    -3
      src/commands/showQuickCommitFile.ts
  74. +1
    -1
      src/commands/showQuickFileHistory.ts
  75. +11
    -11
      src/commands/showView.ts
  76. +4
    -4
      src/commands/stashSave.ts
  77. +16
    -8
      src/commands/switchMode.ts
  78. +1
    -1
      src/commands/toggleCodeLens.ts
  79. +2
    -2
      src/commands/toggleFileAnnotations.ts
  80. +1
    -1
      src/commands/toggleLineBlame.ts
  81. +155
    -118
      src/container.ts
  82. +33
    -37
      src/extension.ts
  83. +22
    -15
      src/git/formatters/commitFormatter.ts
  84. +4
    -4
      src/git/fsProvider.ts
  85. +7
    -3
      src/git/git.ts
  86. +72
    -77
      src/git/gitService.ts
  87. +5
    -5
      src/git/gitUri.ts
  88. +6
    -6
      src/git/models/branch.ts
  89. +4
    -4
      src/git/models/commit.ts
  90. +1
    -1
      src/git/models/models.ts
  91. +7
    -4
      src/git/models/remote.ts
  92. +36
    -30
      src/git/models/repository.ts
  93. +1
    -1
      src/git/models/stashCommit.ts
  94. +1
    -1
      src/git/models/status.ts
  95. +6
    -6
      src/git/remotes/github.ts
  96. +8
    -8
      src/git/remotes/provider.ts
  97. +12
    -12
      src/hovers/hovers.ts
  98. +34
    -28
      src/hovers/lineHoverController.ts
  99. +27
    -23
      src/partners.ts
  100. +1
    -1
      src/quickpicks/commitPicker.ts

+ 4
- 4
src/annotations/annotations.ts View File

@ -63,14 +63,14 @@ export async function getHeatmapColors() {
if (heatmapColors == null) { if (heatmapColors == null) {
let colors; let colors;
if ( if (
Container.config.heatmap.coldColor === defaultHeatmapColdColor &&
Container.config.heatmap.hotColor === defaultHeatmapHotColor
Container.instance.config.heatmap.coldColor === defaultHeatmapColdColor &&
Container.instance.config.heatmap.hotColor === defaultHeatmapHotColor
) { ) {
colors = defaultHeatmapColors; colors = defaultHeatmapColors;
} else { } else {
const chroma = (await import(/* webpackChunkName: "heatmap-chroma" */ 'chroma-js')).default; const chroma = (await import(/* webpackChunkName: "heatmap-chroma" */ 'chroma-js')).default;
colors = chroma colors = chroma
.scale([Container.config.heatmap.hotColor, Container.config.heatmap.coldColor])
.scale([Container.instance.config.heatmap.hotColor, Container.instance.config.heatmap.coldColor])
.mode('lrgb') .mode('lrgb')
.classes(20) .classes(20)
.colors(20); .colors(20);
@ -110,7 +110,7 @@ export class Annotations {
) { ) {
const [r, g, b, a] = this.getHeatmapColor(date, heatmap); const [r, g, b, a] = this.getHeatmapColor(date, heatmap);
const { locations } = Container.config.heatmap;
const { locations } = Container.instance.config.heatmap;
const gutter = locations.includes(HeatmapLocations.Gutter); const gutter = locations.includes(HeatmapLocations.Gutter);
const overview = locations.includes(HeatmapLocations.Overview); const overview = locations.includes(HeatmapLocations.Overview);

+ 2
- 2
src/annotations/autolinks.ts View File

@ -31,7 +31,7 @@ export class Autolinks implements Disposable {
protected _disposable: Disposable | undefined; protected _disposable: Disposable | undefined;
private _references: CacheableAutolinkReference[] = []; private _references: CacheableAutolinkReference[] = [];
constructor() {
constructor(private readonly container: Container) {
this._disposable = Disposable.from(configuration.onDidChange(this.onConfigurationChanged, this)); this._disposable = Disposable.from(configuration.onDidChange(this.onConfigurationChanged, this));
this.onConfigurationChanged(); this.onConfigurationChanged();
@ -43,7 +43,7 @@ export class Autolinks implements Disposable {
private onConfigurationChanged(e?: ConfigurationChangeEvent) { private onConfigurationChanged(e?: ConfigurationChangeEvent) {
if (configuration.changed(e, 'autolinks')) { if (configuration.changed(e, 'autolinks')) {
this._references = Container.config.autolinks ?? [];
this._references = this.container.config.autolinks ?? [];
} }
} }

+ 12
- 11
src/annotations/blameAnnotationProvider.ts View File

@ -18,12 +18,13 @@ export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase
annotationType: FileAnnotationType, annotationType: FileAnnotationType,
editor: TextEditor, editor: TextEditor,
trackedDocument: TrackedDocument<GitDocumentState>, trackedDocument: TrackedDocument<GitDocumentState>,
protected readonly container: Container,
) { ) {
super(annotationType, editor, trackedDocument); super(annotationType, editor, trackedDocument);
this.blame = editor.document.isDirty this.blame = editor.document.isDirty
? Container.git.getBlameForFileContents(this.trackedDocument.uri, editor.document.getText())
: Container.git.getBlameForFile(this.trackedDocument.uri);
? this.container.git.getBlameForFileContents(this.trackedDocument.uri, editor.document.getText())
: this.container.git.getBlameForFile(this.trackedDocument.uri);
if (editor.document.isDirty) { if (editor.document.isDirty) {
trackedDocument.setForceDirtyStateChangeOnNextDocumentChange(); trackedDocument.setForceDirtyStateChangeOnNextDocumentChange();
@ -69,7 +70,7 @@ export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase
dates.sort((a, b) => a.getTime() - b.getTime()); dates.sort((a, b) => a.getTime() - b.getTime());
const coldThresholdDate = new Date(); const coldThresholdDate = new Date();
coldThresholdDate.setDate(coldThresholdDate.getDate() - (Container.config.heatmap.ageThreshold || 90));
coldThresholdDate.setDate(coldThresholdDate.getDate() - (this.container.config.heatmap.ageThreshold || 90));
const coldThresholdTimestamp = coldThresholdDate.getTime(); const coldThresholdTimestamp = coldThresholdDate.getTime();
const hotDates: Date[] = []; const hotDates: Date[] = [];
@ -122,8 +123,8 @@ export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase
registerHoverProviders(providers: { details: boolean; changes: boolean }) { registerHoverProviders(providers: { details: boolean; changes: boolean }) {
if ( if (
!Container.config.hovers.enabled ||
!Container.config.hovers.annotations.enabled ||
!this.container.config.hovers.enabled ||
!this.container.config.hovers.annotations.enabled ||
(!providers.details && !providers.changes) (!providers.details && !providers.changes)
) { ) {
return; return;
@ -144,7 +145,7 @@ export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase
position: Position, position: Position,
_token: CancellationToken, _token: CancellationToken,
): Promise<Hover | undefined> { ): Promise<Hover | undefined> {
if (Container.config.hovers.annotations.over !== 'line' && position.character !== 0) return undefined;
if (this.container.config.hovers.annotations.over !== 'line' && position.character !== 0) return undefined;
if (this.document.uri.toString() !== document.uri.toString()) return undefined; if (this.document.uri.toString() !== document.uri.toString()) return undefined;
@ -175,7 +176,7 @@ export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase
// Get the full commit message -- since blame only returns the summary // Get the full commit message -- since blame only returns the summary
let logCommit: GitCommit | undefined = undefined; let logCommit: GitCommit | undefined = undefined;
if (!commit.isUncommitted) { if (!commit.isUncommitted) {
logCommit = await Container.git.getCommitForFile(commit.repoPath, commit.uri.fsPath, {
logCommit = await this.container.git.getCommitForFile(commit.repoPath, commit.uri.fsPath, {
ref: commit.sha, ref: commit.sha,
}); });
if (logCommit != null) { if (logCommit != null) {
@ -194,12 +195,12 @@ export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase
logCommit ?? commit, logCommit ?? commit,
await GitUri.fromUri(document.uri), await GitUri.fromUri(document.uri),
editorLine, editorLine,
Container.config.hovers.detailsMarkdownFormat,
Container.config.defaultDateFormat,
this.container.config.hovers.detailsMarkdownFormat,
this.container.config.defaultDateFormat,
{ {
autolinks: Container.config.hovers.autolinks.enabled,
autolinks: this.container.config.hovers.autolinks.enabled,
pullRequests: { pullRequests: {
enabled: Container.config.hovers.pullRequests.enabled,
enabled: this.container.config.hovers.pullRequests.enabled,
}, },
}, },
); );

+ 21
- 15
src/annotations/fileAnnotationController.ts View File

@ -79,11 +79,13 @@ export class FileAnnotationController implements Disposable {
private readonly _toggleModes: Map<FileAnnotationType, AnnotationsToggleMode>; private readonly _toggleModes: Map<FileAnnotationType, AnnotationsToggleMode>;
private _windowAnnotationType?: FileAnnotationType | undefined = undefined; private _windowAnnotationType?: FileAnnotationType | undefined = undefined;
constructor() {
this._disposable = Disposable.from(configuration.onDidChange(this.onConfigurationChanged, this));
constructor(private readonly container: Container) {
this._disposable = Disposable.from(
container.onReady(this.onReady, this),
configuration.onDidChange(this.onConfigurationChanged, this),
);
this._toggleModes = new Map<FileAnnotationType, AnnotationsToggleMode>(); this._toggleModes = new Map<FileAnnotationType, AnnotationsToggleMode>();
this.onConfigurationChanged();
} }
dispose() { dispose() {
@ -99,8 +101,12 @@ export class FileAnnotationController implements Disposable {
this._disposable?.dispose(); this._disposable?.dispose();
} }
private onReady(): void {
this.onConfigurationChanged();
}
private onConfigurationChanged(e?: ConfigurationChangeEvent) { private onConfigurationChanged(e?: ConfigurationChangeEvent) {
const cfg = Container.config;
const cfg = this.container.config;
if (configuration.changed(e, 'blame.highlight')) { if (configuration.changed(e, 'blame.highlight')) {
Decorations.gutterBlameHighlight?.dispose(); Decorations.gutterBlameHighlight?.dispose();
@ -274,7 +280,7 @@ export class FileAnnotationController implements Disposable {
} }
private onTextDocumentClosed(document: TextDocument) { private onTextDocumentClosed(document: TextDocument) {
if (!Container.git.isTrackable(document.uri)) return;
if (!this.container.git.isTrackable(document.uri)) return;
for (const [key, p] of this._annotationProviders) { for (const [key, p] of this._annotationProviders) {
if (p.document !== document) continue; if (p.document !== document) continue;
@ -340,7 +346,7 @@ export class FileAnnotationController implements Disposable {
const provider = this.getProvider(editor); const provider = this.getProvider(editor);
if (provider == null) return undefined; if (provider == null) return undefined;
const trackedDocument = await Container.tracker.get(editor!.document);
const trackedDocument = await this.container.tracker.get(editor!.document);
if (trackedDocument == null || !trackedDocument.isBlameable) return undefined; if (trackedDocument == null || !trackedDocument.isBlameable) return undefined;
return provider.annotationType; return provider.annotationType;
@ -385,7 +391,7 @@ export class FileAnnotationController implements Disposable {
if (editor == null) return false; // || editor.viewColumn == null) return false; if (editor == null) return false; // || editor.viewColumn == null) return false;
this._editor = editor; this._editor = editor;
const trackedDocument = await Container.tracker.getOrAdd(editor.document);
const trackedDocument = await this.container.tracker.getOrAdd(editor.document);
if (!trackedDocument.isBlameable) return false; if (!trackedDocument.isBlameable) return false;
const currentProvider = this.getProvider(editor); const currentProvider = this.getProvider(editor);
@ -433,7 +439,7 @@ export class FileAnnotationController implements Disposable {
on?: boolean, on?: boolean,
): Promise<boolean> { ): Promise<boolean> {
if (editor != null) { if (editor != null) {
const trackedDocument = await Container.tracker.getOrAdd(editor.document);
const trackedDocument = await this.container.tracker.getOrAdd(editor.document);
if ((type === FileAnnotationType.Changes && !trackedDocument.isTracked) || !trackedDocument.isBlameable) { if ((type === FileAnnotationType.Changes && !trackedDocument.isTracked) || !trackedDocument.isBlameable) {
return false; return false;
} }
@ -459,7 +465,7 @@ export class FileAnnotationController implements Disposable {
private async attachKeyboardHook() { private async attachKeyboardHook() {
// Allows pressing escape to exit the annotations // Allows pressing escape to exit the annotations
if (this._keyboardScope == null) { if (this._keyboardScope == null) {
this._keyboardScope = await Container.keyboard.beginScope({
this._keyboardScope = await this.container.keyboard.beginScope({
escape: { escape: {
onDidPressKey: async () => { onDidPressKey: async () => {
const e = this._editor; const e = this._editor;
@ -535,20 +541,20 @@ export class FileAnnotationController implements Disposable {
// Allows pressing escape to exit the annotations // Allows pressing escape to exit the annotations
await this.attachKeyboardHook(); await this.attachKeyboardHook();
const trackedDocument = await Container.tracker.getOrAdd(editor.document);
const trackedDocument = await this.container.tracker.getOrAdd(editor.document);
let provider: AnnotationProviderBase | undefined = undefined; let provider: AnnotationProviderBase | undefined = undefined;
switch (type) { switch (type) {
case FileAnnotationType.Blame: case FileAnnotationType.Blame:
provider = new GutterBlameAnnotationProvider(editor, trackedDocument);
provider = new GutterBlameAnnotationProvider(editor, trackedDocument, this.container);
break; break;
case FileAnnotationType.Changes: case FileAnnotationType.Changes:
provider = new GutterChangesAnnotationProvider(editor, trackedDocument);
provider = new GutterChangesAnnotationProvider(editor, trackedDocument, this.container);
break; break;
case FileAnnotationType.Heatmap: case FileAnnotationType.Heatmap:
provider = new GutterHeatmapBlameAnnotationProvider(editor, trackedDocument);
provider = new GutterHeatmapBlameAnnotationProvider(editor, trackedDocument, this.container);
break; break;
} }
if (provider == null || !(await provider.validate())) return undefined; if (provider == null || !(await provider.validate())) return undefined;
@ -565,8 +571,8 @@ export class FileAnnotationController implements Disposable {
window.onDidChangeTextEditorViewColumn(this.onTextEditorViewColumnChanged, this), window.onDidChangeTextEditorViewColumn(this.onTextEditorViewColumnChanged, this),
window.onDidChangeVisibleTextEditors(Functions.debounce(this.onVisibleTextEditorsChanged, 50), this), window.onDidChangeVisibleTextEditors(Functions.debounce(this.onVisibleTextEditorsChanged, 50), this),
workspace.onDidCloseTextDocument(this.onTextDocumentClosed, this), workspace.onDidCloseTextDocument(this.onTextDocumentClosed, this),
Container.tracker.onDidChangeBlameState(this.onBlameStateChanged, this),
Container.tracker.onDidChangeDirtyState(this.onDirtyStateChanged, this),
this.container.tracker.onDidChangeBlameState(this.onBlameStateChanged, this),
this.container.tracker.onDidChangeDirtyState(this.onDirtyStateChanged, this),
); );
} }

+ 7
- 7
src/annotations/gutterBlameAnnotationProvider.ts View File

@ -14,8 +14,8 @@ import { BlameAnnotationProviderBase } from './blameAnnotationProvider';
import { Decorations } from './fileAnnotationController'; import { Decorations } from './fileAnnotationController';
export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase { export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase {
constructor(editor: TextEditor, trackedDocument: TrackedDocument<GitDocumentState>) {
super(FileAnnotationType.Blame, editor, trackedDocument);
constructor(editor: TextEditor, trackedDocument: TrackedDocument<GitDocumentState>, container: Container) {
super(FileAnnotationType.Blame, editor, trackedDocument, container);
} }
override clear() { override clear() {
@ -39,7 +39,7 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase {
let start = process.hrtime(); let start = process.hrtime();
const cfg = Container.config.blame;
const cfg = this.container.config.blame;
// Precalculate the formatting options so we don't need to do it on each iteration // Precalculate the formatting options so we don't need to do it on each iteration
const tokenOptions = Strings.getTokensFromTemplate(cfg.format).reduce<{ const tokenOptions = Strings.getTokensFromTemplate(cfg.format).reduce<{
@ -51,17 +51,17 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase {
let getBranchAndTagTips; let getBranchAndTagTips;
if (CommitFormatter.has(cfg.format, 'tips')) { if (CommitFormatter.has(cfg.format, 'tips')) {
getBranchAndTagTips = await Container.git.getBranchesAndTagsTipsFn(blame.repoPath);
getBranchAndTagTips = await this.container.git.getBranchesAndTagsTipsFn(blame.repoPath);
} }
const options: CommitFormatOptions = { const options: CommitFormatOptions = {
dateFormat: cfg.dateFormat === null ? Container.config.defaultDateFormat : cfg.dateFormat,
dateFormat: cfg.dateFormat === null ? this.container.config.defaultDateFormat : cfg.dateFormat,
getBranchAndTagTips: getBranchAndTagTips, getBranchAndTagTips: getBranchAndTagTips,
tokenOptions: tokenOptions, tokenOptions: tokenOptions,
}; };
const avatars = cfg.avatars; const avatars = cfg.avatars;
const gravatarDefault = Container.config.defaultGravatarsStyle;
const gravatarDefault = this.container.config.defaultGravatarsStyle;
const separateLines = cfg.separateLines; const separateLines = cfg.separateLines;
const renderOptions = Annotations.gutterRenderOptions( const renderOptions = Annotations.gutterRenderOptions(
separateLines, separateLines,
@ -169,7 +169,7 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase {
Logger.log(cc, `${Strings.getDurationMilliseconds(start)} ms to apply all gutter blame annotations`); Logger.log(cc, `${Strings.getDurationMilliseconds(start)} ms to apply all gutter blame annotations`);
} }
this.registerHoverProviders(Container.config.hovers.annotations);
this.registerHoverProviders(this.container.config.hovers.annotations);
return true; return true;
} }

+ 18
- 14
src/annotations/gutterChangesAnnotationProvider.ts View File

@ -32,7 +32,11 @@ export class GutterChangesAnnotationProvider extends AnnotationProviderBase
private state: { commit: GitLogCommit | undefined; diffs: GitDiff[] } | undefined; private state: { commit: GitLogCommit | undefined; diffs: GitDiff[] } | undefined;
private hoverProviderDisposable: Disposable | undefined; private hoverProviderDisposable: Disposable | undefined;
constructor(editor: TextEditor, trackedDocument: TrackedDocument<GitDocumentState>) {
constructor(
editor: TextEditor,
trackedDocument: TrackedDocument<GitDocumentState>,
private readonly container: Container,
) {
super(FileAnnotationType.Changes, editor, trackedDocument); super(FileAnnotationType.Changes, editor, trackedDocument);
} }
@ -74,13 +78,13 @@ export class GutterChangesAnnotationProvider extends AnnotationProviderBase
let localChanges = ref1 == null && ref2 == null; let localChanges = ref1 == null && ref2 == null;
if (localChanges) { if (localChanges) {
let ref = await Container.git.getOldestUnpushedRefForFile(
let ref = await this.container.git.getOldestUnpushedRefForFile(
this.trackedDocument.uri.repoPath!, this.trackedDocument.uri.repoPath!,
this.trackedDocument.uri.fsPath, this.trackedDocument.uri.fsPath,
); );
if (ref != null) { if (ref != null) {
ref = `${ref}^`; ref = `${ref}^`;
commit = await Container.git.getCommitForFile(
commit = await this.container.git.getCommitForFile(
this.trackedDocument.uri.repoPath, this.trackedDocument.uri.repoPath,
this.trackedDocument.uri.fsPath, this.trackedDocument.uri.fsPath,
{ ref: ref }, { ref: ref },
@ -96,15 +100,15 @@ export class GutterChangesAnnotationProvider extends AnnotationProviderBase
localChanges = false; localChanges = false;
} }
} else { } else {
const status = await Container.git.getStatusForFile(
const status = await this.container.git.getStatusForFile(
this.trackedDocument.uri.repoPath!, this.trackedDocument.uri.repoPath!,
this.trackedDocument.uri.fsPath, this.trackedDocument.uri.fsPath,
); );
const commits = status?.toPsuedoCommits( const commits = status?.toPsuedoCommits(
await Container.git.getCurrentUser(this.trackedDocument.uri.repoPath!),
await this.container.git.getCurrentUser(this.trackedDocument.uri.repoPath!),
); );
if (commits?.length) { if (commits?.length) {
commit = await Container.git.getCommitForFile(
commit = await this.container.git.getCommitForFile(
this.trackedDocument.uri.repoPath, this.trackedDocument.uri.repoPath,
this.trackedDocument.uri.fsPath, this.trackedDocument.uri.fsPath,
); );
@ -118,7 +122,7 @@ export class GutterChangesAnnotationProvider extends AnnotationProviderBase
} }
if (!localChanges) { if (!localChanges) {
commit = await Container.git.getCommitForFile(
commit = await this.container.git.getCommitForFile(
this.trackedDocument.uri.repoPath, this.trackedDocument.uri.repoPath,
this.trackedDocument.uri.fsPath, this.trackedDocument.uri.fsPath,
{ {
@ -139,14 +143,14 @@ export class GutterChangesAnnotationProvider extends AnnotationProviderBase
await Promise.all( await Promise.all(
ref2 == null && this.editor.document.isDirty ref2 == null && this.editor.document.isDirty
? [ ? [
Container.git.getDiffForFileContents(
this.container.git.getDiffForFileContents(
this.trackedDocument.uri, this.trackedDocument.uri,
ref1!, ref1!,
this.editor.document.getText(), this.editor.document.getText(),
), ),
Container.git.getDiffForFile(this.trackedDocument.uri, ref1, ref2),
this.container.git.getDiffForFile(this.trackedDocument.uri, ref1, ref2),
] ]
: [Container.git.getDiffForFile(this.trackedDocument.uri, ref1, ref2)],
: [this.container.git.getDiffForFile(this.trackedDocument.uri, ref1, ref2)],
) )
).filter(<T>(d?: T): d is T => Boolean(d)); ).filter(<T>(d?: T): d is T => Boolean(d));
if (!diffs?.length) return false; if (!diffs?.length) return false;
@ -162,11 +166,11 @@ export class GutterChangesAnnotationProvider extends AnnotationProviderBase
const blame = const blame =
context?.sha != null && context?.only context?.sha != null && context?.only
? this.editor?.document.isDirty ? this.editor?.document.isDirty
? await Container.git.getBlameForFileContents(
? await this.container.git.getBlameForFileContents(
this.trackedDocument.uri, this.trackedDocument.uri,
this.editor.document.getText(), this.editor.document.getText(),
) )
: await Container.git.getBlameForFile(this.trackedDocument.uri)
: await this.container.git.getBlameForFile(this.trackedDocument.uri)
: undefined; : undefined;
let selection: Selection | undefined; let selection: Selection | undefined;
@ -279,7 +283,7 @@ export class GutterChangesAnnotationProvider extends AnnotationProviderBase
} }
registerHoverProvider() { registerHoverProvider() {
if (!Container.config.hovers.enabled || !Container.config.hovers.annotations.enabled) {
if (!this.container.config.hovers.enabled || !this.container.config.hovers.annotations.enabled) {
return; return;
} }
@ -294,7 +298,7 @@ export class GutterChangesAnnotationProvider extends AnnotationProviderBase
provideHover(document: TextDocument, position: Position, _token: CancellationToken): Hover | undefined { provideHover(document: TextDocument, position: Position, _token: CancellationToken): Hover | undefined {
if (this.state == null) return undefined; if (this.state == null) return undefined;
if (Container.config.hovers.annotations.over !== 'line' && position.character !== 0) return undefined;
if (this.container.config.hovers.annotations.over !== 'line' && position.character !== 0) return undefined;
const { commit, diffs } = this.state; const { commit, diffs } = this.state;

+ 4
- 3
src/annotations/gutterHeatmapBlameAnnotationProvider.ts View File

@ -1,6 +1,7 @@
'use strict'; 'use strict';
import { Range, TextEditor, TextEditorDecorationType } from 'vscode'; import { Range, TextEditor, TextEditorDecorationType } from 'vscode';
import { FileAnnotationType } from '../configuration'; import { FileAnnotationType } from '../configuration';
import { Container } from '../container';
import { GitBlameCommit } from '../git/git'; import { GitBlameCommit } from '../git/git';
import { Logger } from '../logger'; import { Logger } from '../logger';
import { log, Strings } from '../system'; import { log, Strings } from '../system';
@ -11,8 +12,8 @@ import { Annotations } from './annotations';
import { BlameAnnotationProviderBase } from './blameAnnotationProvider'; import { BlameAnnotationProviderBase } from './blameAnnotationProvider';
export class GutterHeatmapBlameAnnotationProvider extends BlameAnnotationProviderBase { export class GutterHeatmapBlameAnnotationProvider extends BlameAnnotationProviderBase {
constructor(editor: TextEditor, trackedDocument: TrackedDocument<GitDocumentState>) {
super(FileAnnotationType.Heatmap, editor, trackedDocument);
constructor(editor: TextEditor, trackedDocument: TrackedDocument<GitDocumentState>, container: Container) {
super(FileAnnotationType.Heatmap, editor, trackedDocument, container);
} }
@log() @log()
@ -58,7 +59,7 @@ export class GutterHeatmapBlameAnnotationProvider extends BlameAnnotationProvide
Logger.log(cc, `${Strings.getDurationMilliseconds(start)} ms to apply recent changes annotations`); Logger.log(cc, `${Strings.getDurationMilliseconds(start)} ms to apply recent changes annotations`);
} }
// this.registerHoverProviders(Container.config.hovers.annotations);
// this.registerHoverProviders(this.container.config.hovers.annotations);
return true; return true;
} }

+ 22
- 18
src/annotations/lineAnnotationController.ts View File

@ -34,27 +34,31 @@ export class LineAnnotationController implements Disposable {
private _editor: TextEditor | undefined; private _editor: TextEditor | undefined;
private _enabled: boolean = false; private _enabled: boolean = false;
constructor() {
constructor(private readonly container: Container) {
this._disposable = Disposable.from( this._disposable = Disposable.from(
container.onReady(this.onReady, this),
configuration.onDidChange(this.onConfigurationChanged, this), configuration.onDidChange(this.onConfigurationChanged, this),
Container.fileAnnotations.onDidToggleAnnotations(this.onFileAnnotationsToggled, this),
container.fileAnnotations.onDidToggleAnnotations(this.onFileAnnotationsToggled, this),
Authentication.onDidChange(() => void this.refresh(window.activeTextEditor)), Authentication.onDidChange(() => void this.refresh(window.activeTextEditor)),
); );
this.onConfigurationChanged();
} }
dispose() { dispose() {
this.clearAnnotations(this._editor); this.clearAnnotations(this._editor);
Container.lineTracker.stop(this);
this.container.lineTracker.stop(this);
this._disposable.dispose(); this._disposable.dispose();
} }
private onReady(): void {
this.onConfigurationChanged();
}
private onConfigurationChanged(e?: ConfigurationChangeEvent) { private onConfigurationChanged(e?: ConfigurationChangeEvent) {
if (!configuration.changed(e, 'currentLine')) return; if (!configuration.changed(e, 'currentLine')) return;
if (configuration.changed(e, 'currentLine.enabled')) { if (configuration.changed(e, 'currentLine.enabled')) {
if (Container.config.currentLine.enabled) {
if (this.container.config.currentLine.enabled) {
this._enabled = true; this._enabled = true;
this.resume(); this.resume();
} else { } else {
@ -152,7 +156,7 @@ export class LineAnnotationController implements Disposable {
) { ) {
if (lines.length === 0) return undefined; if (lines.length === 0) return undefined;
const remote = await Container.git.getRichRemoteProvider(repoPath);
const remote = await this.container.git.getRichRemoteProvider(repoPath);
if (remote?.provider == null) return undefined; if (remote?.provider == null) return undefined;
const refs = new Set<string>(); const refs = new Set<string>();
@ -166,7 +170,7 @@ export class LineAnnotationController implements Disposable {
const { provider } = remote; const { provider } = remote;
const prs = await Promises.raceAll( const prs = await Promises.raceAll(
refs.values(), refs.values(),
ref => Container.git.getPullRequestForCommit(ref, provider),
ref => this.container.git.getPullRequestForCommit(ref, provider),
timeout, timeout,
); );
if (prs.size === 0 || Iterables.every(prs.values(), pr => pr == null)) return undefined; if (prs.size === 0 || Iterables.every(prs.values(), pr => pr == null)) return undefined;
@ -180,7 +184,7 @@ export class LineAnnotationController implements Disposable {
const cc = Logger.getCorrelationContext(); const cc = Logger.getCorrelationContext();
const selections = Container.lineTracker.selections;
const selections = this.container.lineTracker.selections;
if (editor == null || selections == null || !isTextEditor(editor)) { if (editor == null || selections == null || !isTextEditor(editor)) {
if (cc != null) { if (cc != null) {
cc.exitDetails = ` ${GlyphChars.Dot} Skipped because there is no valid editor or no valid selections`; cc.exitDetails = ` ${GlyphChars.Dot} Skipped because there is no valid editor or no valid selections`;
@ -197,7 +201,7 @@ export class LineAnnotationController implements Disposable {
this._editor = editor; this._editor = editor;
} }
const cfg = Container.config.currentLine;
const cfg = this.container.config.currentLine;
if (this.suspended) { if (this.suspended) {
if (cc != null) { if (cc != null) {
cc.exitDetails = ` ${GlyphChars.Dot} Skipped because the controller is suspended`; cc.exitDetails = ` ${GlyphChars.Dot} Skipped because the controller is suspended`;
@ -207,7 +211,7 @@ export class LineAnnotationController implements Disposable {
return; return;
} }
const trackedDocument = await Container.tracker.getOrAdd(editor.document);
const trackedDocument = await this.container.tracker.getOrAdd(editor.document);
if (!trackedDocument.isBlameable && this.suspended) { if (!trackedDocument.isBlameable && this.suspended) {
if (cc != null) { if (cc != null) {
cc.exitDetails = ` ${GlyphChars.Dot} Skipped because the ${ cc.exitDetails = ` ${GlyphChars.Dot} Skipped because the ${
@ -222,7 +226,7 @@ export class LineAnnotationController implements Disposable {
} }
// Make sure the editor hasn't died since the await above and that we are still on the same line(s) // Make sure the editor hasn't died since the await above and that we are still on the same line(s)
if (editor.document == null || !Container.lineTracker.includes(selections)) {
if (editor.document == null || !this.container.lineTracker.includes(selections)) {
if (cc != null) { if (cc != null) {
cc.exitDetails = ` ${GlyphChars.Dot} Skipped because the ${ cc.exitDetails = ` ${GlyphChars.Dot} Skipped because the ${
editor.document == null editor.document == null
@ -243,7 +247,7 @@ export class LineAnnotationController implements Disposable {
const commitLines = [ const commitLines = [
...Iterables.filterMap<LineSelection, [number, GitBlameCommit]>(selections, selection => { ...Iterables.filterMap<LineSelection, [number, GitBlameCommit]>(selections, selection => {
const state = Container.lineTracker.getState(selection.active);
const state = this.container.lineTracker.getState(selection.active);
if (state?.commit == null) { if (state?.commit == null) {
Logger.debug(cc, `Line ${selection.active} returned no commit`); Logger.debug(cc, `Line ${selection.active} returned no commit`);
return undefined; return undefined;
@ -258,7 +262,7 @@ export class LineAnnotationController implements Disposable {
// TODO: Make this configurable? // TODO: Make this configurable?
const timeout = 100; const timeout = 100;
const [getBranchAndTagTips, prs] = await Promise.all([ const [getBranchAndTagTips, prs] = await Promise.all([
CommitFormatter.has(cfg.format, 'tips') ? Container.git.getBranchesAndTagsTipsFn(repoPath) : undefined,
CommitFormatter.has(cfg.format, 'tips') ? this.container.git.getBranchesAndTagsTipsFn(repoPath) : undefined,
repoPath != null && repoPath != null &&
cfg.pullRequests.enabled && cfg.pullRequests.enabled &&
CommitFormatter.has( CommitFormatter.has(
@ -293,7 +297,7 @@ export class LineAnnotationController implements Disposable {
// l, // l,
cfg.format, cfg.format,
{ {
dateFormat: cfg.dateFormat === null ? Container.config.defaultDateFormat : cfg.dateFormat,
dateFormat: cfg.dateFormat === null ? this.container.config.defaultDateFormat : cfg.dateFormat,
getBranchAndTagTips: getBranchAndTagTips, getBranchAndTagTips: getBranchAndTagTips,
pullRequestOrRemote: prs?.get(commit.ref), pullRequestOrRemote: prs?.get(commit.ref),
pullRequestPendingMessage: `PR ${GlyphChars.Ellipsis}`, pullRequestPendingMessage: `PR ${GlyphChars.Ellipsis}`,
@ -312,17 +316,17 @@ export class LineAnnotationController implements Disposable {
private setLineTracker(enabled: boolean) { private setLineTracker(enabled: boolean) {
if (enabled) { if (enabled) {
if (!Container.lineTracker.isSubscribed(this)) {
Container.lineTracker.start(
if (!this.container.lineTracker.isSubscribed(this)) {
this.container.lineTracker.start(
this, this,
Container.lineTracker.onDidChangeActiveLines(this.onActiveLinesChanged, this),
this.container.lineTracker.onDidChangeActiveLines(this.onActiveLinesChanged, this),
); );
} }
return; return;
} }
Container.lineTracker.stop(this);
this.container.lineTracker.stop(this);
} }
private async waitForAnyPendingPullRequests( private async waitForAnyPendingPullRequests(

+ 5
- 5
src/api/actionRunners.ts View File

@ -1,7 +1,7 @@
'use strict'; 'use strict';
import { commands, Disposable, Event, EventEmitter, QuickPickItem, window } from 'vscode'; import { commands, Disposable, Event, EventEmitter, QuickPickItem, window } from 'vscode';
import { Commands } from '../commands/common'; import { Commands } from '../commands/common';
import { configuration } from '../configuration';
import { Config, configuration } from '../configuration';
import { ContextKeys, setContext } from '../constants'; import { ContextKeys, setContext } from '../constants';
import { Container } from '../container'; import { Container } from '../container';
import { getQuickPickIgnoreFocusOut } from '../quickpicks'; import { getQuickPickIgnoreFocusOut } from '../quickpicks';
@ -128,7 +128,7 @@ export class ActionRunners implements Disposable {
private readonly _actionRunners = new Map<Actions, RegisteredActionRunner<any>[]>(); private readonly _actionRunners = new Map<Actions, RegisteredActionRunner<any>[]>();
private readonly _disposable: Disposable; private readonly _disposable: Disposable;
constructor() {
constructor(private readonly container: Container) {
const subscriptions: Disposable[] = [ const subscriptions: Disposable[] = [
configuration.onDidChange(e => { configuration.onDidChange(e => {
if (!configuration.changed(e, 'partners')) return; if (!configuration.changed(e, 'partners')) return;
@ -165,7 +165,7 @@ export class ActionRunners implements Disposable {
} }
get(action: Actions): RegisteredActionRunner[] | undefined { get(action: Actions): RegisteredActionRunner[] | undefined {
return filterOnlyEnabledRunners(this._actionRunners.get(action));
return filterOnlyEnabledRunners(this.container.config, this._actionRunners.get(action));
} }
has(action: Actions): boolean { has(action: Actions): boolean {
@ -337,10 +337,10 @@ export class ActionRunners implements Disposable {
} }
} }
function filterOnlyEnabledRunners(runners: RegisteredActionRunner[] | undefined) {
function filterOnlyEnabledRunners(config: Config, runners: RegisteredActionRunner[] | undefined) {
if (runners == null || runners.length === 0) return undefined; if (runners == null || runners.length === 0) return undefined;
const partners = Container.config.partners;
const partners = config.partners;
if (partners == null) return runners; if (partners == null) return runners;
return runners.filter( return runners.filter(

+ 7
- 2
src/api/api.ts View File

@ -12,6 +12,11 @@ const emptyDisposable = Object.freeze({
}); });
export class Api implements GitLensApi { export class Api implements GitLensApi {
readonly #container: Container;
constructor(container: Container) {
this.#container = container;
}
registerActionRunner<T extends ActionContext>(action: Action<T>, runner: ActionRunner): Disposable { registerActionRunner<T extends ActionContext>(action: Action<T>, runner: ActionRunner): Disposable {
if (runner.name === builtInActionRunnerName) { if (runner.name === builtInActionRunnerName) {
throw new Error(`Cannot use the reserved name '${builtInActionRunnerName}'`); throw new Error(`Cannot use the reserved name '${builtInActionRunnerName}'`);
@ -20,7 +25,7 @@ export class Api implements GitLensApi {
if ((action as string) === 'hover.commandHelp') { if ((action as string) === 'hover.commandHelp') {
action = 'hover.commands'; action = 'hover.commands';
} }
return Container.actionRunners.register(action, runner);
return this.#container.actionRunners.register(action, runner);
} }
// registerAutolinkProvider(provider: RemoteProvider): Disposable; // registerAutolinkProvider(provider: RemoteProvider): Disposable;
@ -39,7 +44,7 @@ export function preview() {
if (fn == null) throw new Error('Not supported'); if (fn == null) throw new Error('Not supported');
descriptor.value = function (this: any, ...args: any[]) { descriptor.value = function (this: any, ...args: any[]) {
if (Container.insiders || Logger.isDebugging) return fn!.apply(this, args);
if (Container.instance.insiders || Logger.isDebugging) return fn!.apply(this, args);
console.error('GitLens preview APIs are only available in the Insiders edition'); console.error('GitLens preview APIs are only available in the Insiders edition');
return emptyDisposable; return emptyDisposable;

+ 6
- 6
src/avatars.ts View File

@ -27,7 +27,7 @@ _onDidFetchAvatar.event(
), ),
] ]
: undefined; : undefined;
void Container.context.globalState.update(GlobalState.Avatars, avatars);
void Container.instance.context.globalState.update(GlobalState.Avatars, avatars);
}, 1000), }, 1000),
); );
@ -139,7 +139,7 @@ function createOrUpdateAvatar(
function ensureAvatarCache(cache: Map<string, Avatar> | undefined): asserts cache is Map<string, Avatar> { function ensureAvatarCache(cache: Map<string, Avatar> | undefined): asserts cache is Map<string, Avatar> {
if (cache == null) { if (cache == null) {
const avatars: [string, Avatar][] | undefined = Container.context.globalState
const avatars: [string, Avatar][] | undefined = Container.instance.context.globalState
.get<[string, SerializedAvatar][]>(GlobalState.Avatars) .get<[string, SerializedAvatar][]>(GlobalState.Avatars)
?.map<[string, Avatar]>(([key, avatar]) => [ ?.map<[string, Avatar]>(([key, avatar]) => [
key, key,
@ -184,13 +184,13 @@ async function getAvatarUriFromRemoteProvider(
try { try {
let account; let account;
if (Container.config.integrations.enabled) {
if (Container.instance.config.integrations.enabled) {
// if (typeof repoPathOrCommit === 'string') { // if (typeof repoPathOrCommit === 'string') {
// const remote = await Container.git.getRichRemoteProvider(repoPathOrCommit);
// const remote = await Container.instance.git.getRichRemoteProvider(repoPathOrCommit);
// account = await remote?.provider.getAccountForEmail(email, { avatarSize: size }); // account = await remote?.provider.getAccountForEmail(email, { avatarSize: size });
// } else { // } else {
if (typeof repoPathOrCommit !== 'string') { if (typeof repoPathOrCommit !== 'string') {
const remote = await Container.git.getRichRemoteProvider(repoPathOrCommit.repoPath);
const remote = await Container.instance.git.getRichRemoteProvider(repoPathOrCommit.repoPath);
account = await remote?.provider.getAccountForCommit(repoPathOrCommit.ref, { avatarSize: size }); account = await remote?.provider.getAccountForCommit(repoPathOrCommit.ref, { avatarSize: size });
} }
} }
@ -248,7 +248,7 @@ export function getPresenceDataUri(status: ContactPresenceStatus) {
export function resetAvatarCache(reset: 'all' | 'failed' | 'fallback') { export function resetAvatarCache(reset: 'all' | 'failed' | 'fallback') {
switch (reset) { switch (reset) {
case 'all': case 'all':
void Container.context.globalState.update(GlobalState.Avatars, undefined);
void Container.instance.context.globalState.update(GlobalState.Avatars, undefined);
avatarCache?.clear(); avatarCache?.clear();
avatarQueue.clear(); avatarQueue.clear();
break; break;

+ 14
- 8
src/codelens/codeLensController.ts View File

@ -17,9 +17,11 @@ export class GitCodeLensController implements Disposable {
private _provider: GitCodeLensProvider | undefined; private _provider: GitCodeLensProvider | undefined;
private _providerDisposable: Disposable | undefined; private _providerDisposable: Disposable | undefined;
constructor() {
this._disposable = Disposable.from(configuration.onDidChange(this.onConfigurationChanged, this));
this.onConfigurationChanged();
constructor(private readonly container: Container) {
this._disposable = Disposable.from(
container.onReady(this.onReady, this),
configuration.onDidChange(this.onConfigurationChanged, this),
);
} }
dispose() { dispose() {
@ -27,6 +29,10 @@ export class GitCodeLensController implements Disposable {
this._disposable?.dispose(); this._disposable?.dispose();
} }
private onReady(): void {
this.onConfigurationChanged();
}
private onConfigurationChanged(e?: ConfigurationChangeEvent) { private onConfigurationChanged(e?: ConfigurationChangeEvent) {
if ( if (
configuration.changed(e, 'codeLens') || configuration.changed(e, 'codeLens') ||
@ -38,7 +44,7 @@ export class GitCodeLensController implements Disposable {
Logger.log('CodeLens config changed; resetting CodeLens provider'); Logger.log('CodeLens config changed; resetting CodeLens provider');
} }
const cfg = Container.config.codeLens;
const cfg = this.container.config.codeLens;
if (cfg.enabled && (cfg.recentChange.enabled || cfg.authors.enabled)) { if (cfg.enabled && (cfg.recentChange.enabled || cfg.authors.enabled)) {
this.ensureProvider(); this.ensureProvider();
} else { } else {
@ -62,7 +68,7 @@ export class GitCodeLensController implements Disposable {
private onDirtyIdleTriggered(e: DocumentDirtyIdleTriggerEvent<GitDocumentState>) { private onDirtyIdleTriggered(e: DocumentDirtyIdleTriggerEvent<GitDocumentState>) {
if (this._provider === undefined || !e.document.isBlameable) return; if (this._provider === undefined || !e.document.isBlameable) return;
const maxLines = Container.config.advanced.blame.sizeThresholdAfterEdit;
const maxLines = this.container.config.advanced.blame.sizeThresholdAfterEdit;
if (maxLines > 0 && e.document.lineCount > maxLines) return; if (maxLines > 0 && e.document.lineCount > maxLines) return;
Logger.log('Dirty idle triggered; resetting CodeLens provider'); Logger.log('Dirty idle triggered; resetting CodeLens provider');
@ -92,11 +98,11 @@ export class GitCodeLensController implements Disposable {
this._providerDisposable?.dispose(); this._providerDisposable?.dispose();
this._provider = new GitCodeLensProvider(Container.context, Container.git, Container.tracker);
this._provider = new GitCodeLensProvider(this.container);
this._providerDisposable = Disposable.from( this._providerDisposable = Disposable.from(
languages.registerCodeLensProvider(GitCodeLensProvider.selector, this._provider), languages.registerCodeLensProvider(GitCodeLensProvider.selector, this._provider),
Container.tracker.onDidChangeBlameState(this.onBlameStateChanged, this),
Container.tracker.onDidTriggerDirtyIdle(this.onDirtyIdleTriggered, this),
this.container.tracker.onDidChangeBlameState(this.onBlameStateChanged, this),
this.container.tracker.onDidTriggerDirtyIdle(this.onDirtyIdleTriggered, this),
); );
} }
} }

+ 24
- 29
src/codelens/codeLensProvider.ts View File

@ -9,7 +9,6 @@ import {
DocumentSymbol, DocumentSymbol,
Event, Event,
EventEmitter, EventEmitter,
ExtensionContext,
Location, Location,
Position, Position,
Range, Range,
@ -40,11 +39,9 @@ import {
import { BuiltInCommands, DocumentSchemes } from '../constants'; import { BuiltInCommands, DocumentSchemes } from '../constants';
import { Container } from '../container'; import { Container } from '../container';
import { GitBlame, GitBlameLines, GitCommit, RemoteResourceType } from '../git/git'; import { GitBlame, GitBlameLines, GitCommit, RemoteResourceType } from '../git/git';
import { GitService } from '../git/gitService';
import { GitUri } from '../git/gitUri'; import { GitUri } from '../git/gitUri';
import { Logger } from '../logger'; import { Logger } from '../logger';
import { Functions, Iterables } from '../system'; import { Functions, Iterables } from '../system';
import { DocumentTracker, GitDocumentState } from '../trackers/gitDocumentTracker';
export class GitRecentChangeCodeLens extends CodeLens { export class GitRecentChangeCodeLens extends CodeLens {
constructor( constructor(
@ -86,11 +83,6 @@ export class GitAuthorsCodeLens extends CodeLens {
} }
export class GitCodeLensProvider implements CodeLensProvider { export class GitCodeLensProvider implements CodeLensProvider {
private _onDidChangeCodeLenses = new EventEmitter<void>();
get onDidChangeCodeLenses(): Event<void> {
return this._onDidChangeCodeLenses.event;
}
static selector: DocumentSelector = [ static selector: DocumentSelector = [
{ scheme: DocumentSchemes.File }, { scheme: DocumentSchemes.File },
{ scheme: DocumentSchemes.Git }, { scheme: DocumentSchemes.Git },
@ -99,25 +91,26 @@ export class GitCodeLensProvider implements CodeLensProvider {
{ scheme: DocumentSchemes.Vsls }, { scheme: DocumentSchemes.Vsls },
]; ];
constructor(
_context: ExtensionContext,
private readonly _git: GitService,
private readonly _tracker: DocumentTracker<GitDocumentState>,
) {}
private _onDidChangeCodeLenses = new EventEmitter<void>();
get onDidChangeCodeLenses(): Event<void> {
return this._onDidChangeCodeLenses.event;
}
constructor(private readonly container: Container) {}
reset(_reason?: 'idle' | 'saved') { reset(_reason?: 'idle' | 'saved') {
this._onDidChangeCodeLenses.fire(); this._onDidChangeCodeLenses.fire();
} }
async provideCodeLenses(document: TextDocument, token: CancellationToken): Promise<CodeLens[]> { async provideCodeLenses(document: TextDocument, token: CancellationToken): Promise<CodeLens[]> {
const trackedDocument = await this._tracker.getOrAdd(document);
const trackedDocument = await this.container.tracker.getOrAdd(document);
if (!trackedDocument.isBlameable) return []; if (!trackedDocument.isBlameable) return [];
let dirty = false; let dirty = false;
if (document.isDirty) { if (document.isDirty) {
// Only allow dirty blames if we are idle // Only allow dirty blames if we are idle
if (trackedDocument.isDirtyIdle) { if (trackedDocument.isDirtyIdle) {
const maxLines = Container.config.advanced.blame.sizeThresholdAfterEdit;
const maxLines = this.container.config.advanced.blame.sizeThresholdAfterEdit;
if (maxLines > 0 && document.lineCount > maxLines) { if (maxLines > 0 && document.lineCount > maxLines) {
dirty = true; dirty = true;
} }
@ -157,13 +150,13 @@ export class GitCodeLensProvider implements CodeLensProvider {
if (languageScope.scopes.length === 1 && languageScope.scopes.includes(CodeLensScopes.Document)) { if (languageScope.scopes.length === 1 && languageScope.scopes.includes(CodeLensScopes.Document)) {
blame = document.isDirty blame = document.isDirty
? await this._git.getBlameForFileContents(gitUri, document.getText())
: await this._git.getBlameForFile(gitUri);
? await this.container.git.getBlameForFileContents(gitUri, document.getText())
: await this.container.git.getBlameForFile(gitUri);
} else { } else {
[blame, symbols] = await Promise.all([ [blame, symbols] = await Promise.all([
document.isDirty document.isDirty
? this._git.getBlameForFileContents(gitUri, document.getText())
: this._git.getBlameForFile(gitUri),
? this.container.git.getBlameForFileContents(gitUri, document.getText())
: this.container.git.getBlameForFile(gitUri),
commands.executeCommand(BuiltInCommands.ExecuteDocumentSymbolProvider, document.uri) as Promise< commands.executeCommand(BuiltInCommands.ExecuteDocumentSymbolProvider, document.uri) as Promise<
SymbolInformation[] SymbolInformation[]
>, >,
@ -217,7 +210,7 @@ export class GitCodeLensProvider implements CodeLensProvider {
if (dirty || cfg.recentChange.enabled) { if (dirty || cfg.recentChange.enabled) {
if (!dirty) { if (!dirty) {
blameForRangeFn = Functions.once(() => blameForRangeFn = Functions.once(() =>
this._git.getBlameForRangeSync(blame!, gitUri, blameRange),
this.container.git.getBlameForRangeSync(blame!, gitUri, blameRange),
); );
} }
@ -244,7 +237,7 @@ export class GitCodeLensProvider implements CodeLensProvider {
if (!dirty && cfg.authors.enabled) { if (!dirty && cfg.authors.enabled) {
if (blameForRangeFn === undefined) { if (blameForRangeFn === undefined) {
blameForRangeFn = Functions.once(() => blameForRangeFn = Functions.once(() =>
this._git.getBlameForRangeSync(blame!, gitUri, blameRange),
this.container.git.getBlameForRangeSync(blame!, gitUri, blameRange),
); );
} }
@ -404,7 +397,9 @@ export class GitCodeLensProvider implements CodeLensProvider {
let blameForRangeFn: (() => GitBlameLines | undefined) | undefined; let blameForRangeFn: (() => GitBlameLines | undefined) | undefined;
if (dirty || cfg.recentChange.enabled) { if (dirty || cfg.recentChange.enabled) {
if (!dirty) { if (!dirty) {
blameForRangeFn = Functions.once(() => this._git.getBlameForRangeSync(blame!, gitUri!, blameRange));
blameForRangeFn = Functions.once(() =>
this.container.git.getBlameForRangeSync(blame!, gitUri!, blameRange),
);
} }
lenses.push( lenses.push(
new GitRecentChangeCodeLens( new GitRecentChangeCodeLens(
@ -446,7 +441,7 @@ export class GitCodeLensProvider implements CodeLensProvider {
if (multiline && !dirty) { if (multiline && !dirty) {
if (blameForRangeFn === undefined) { if (blameForRangeFn === undefined) {
blameForRangeFn = Functions.once(() => blameForRangeFn = Functions.once(() =>
this._git.getBlameForRangeSync(blame!, gitUri!, blameRange),
this.container.git.getBlameForRangeSync(blame!, gitUri!, blameRange),
); );
} }
lenses.push( lenses.push(
@ -496,7 +491,7 @@ export class GitCodeLensProvider implements CodeLensProvider {
const recentCommit: GitCommit = Iterables.first(blame.commits.values()); const recentCommit: GitCommit = Iterables.first(blame.commits.values());
// TODO@eamodio This is FAR too expensive, but this accounts for commits that delete lines -- is there another way? // TODO@eamodio This is FAR too expensive, but this accounts for commits that delete lines -- is there another way?
// if (lens.uri != null) { // if (lens.uri != null) {
// const commit = await this._git.getCommitForFile(lens.uri.repoPath, lens.uri.fsPath, {
// const commit = await this.container.git.getCommitForFile(lens.uri.repoPath, lens.uri.fsPath, {
// range: lens.blameRange, // range: lens.blameRange,
// }); // });
// if ( // if (
@ -509,7 +504,7 @@ export class GitCodeLensProvider implements CodeLensProvider {
// } // }
let title = `${recentCommit.author}, ${recentCommit.formattedDate}`; let title = `${recentCommit.author}, ${recentCommit.formattedDate}`;
if (Container.config.debug) {
if (this.container.config.debug) {
title += ` [${lens.languageId}: ${SymbolKind[lens.symbol.kind]}(${lens.range.start.character}-${ title += ` [${lens.languageId}: ${SymbolKind[lens.symbol.kind]}(${lens.range.start.character}-${
lens.range.end.character lens.range.end.character
}${ }${
@ -580,7 +575,7 @@ export class GitCodeLensProvider implements CodeLensProvider {
const author = Iterables.first(blame.authors.values()).name; const author = Iterables.first(blame.authors.values()).name;
let title = `${count} ${count > 1 ? 'authors' : 'author'} (${author}${count > 1 ? ' and others' : ''})`; let title = `${count} ${count > 1 ? 'authors' : 'author'} (${author}${count > 1 ? ' and others' : ''})`;
if (Container.config.debug) {
if (this.container.config.debug) {
title += ` [${lens.languageId}: ${SymbolKind[lens.symbol.kind]}(${lens.range.start.character}-${ title += ` [${lens.languageId}: ${SymbolKind[lens.symbol.kind]}(${lens.range.start.character}-${
lens.range.end.character lens.range.end.character
}${ }${
@ -871,10 +866,10 @@ export class GitCodeLensProvider implements CodeLensProvider {
private getDirtyTitle(cfg: CodeLensConfig) { private getDirtyTitle(cfg: CodeLensConfig) {
if (cfg.recentChange.enabled && cfg.authors.enabled) { if (cfg.recentChange.enabled && cfg.authors.enabled) {
return Container.config.strings.codeLens.unsavedChanges.recentChangeAndAuthors;
return this.container.config.strings.codeLens.unsavedChanges.recentChangeAndAuthors;
} }
if (cfg.recentChange.enabled) return Container.config.strings.codeLens.unsavedChanges.recentChangeOnly;
return Container.config.strings.codeLens.unsavedChanges.authorsOnly;
if (cfg.recentChange.enabled) return this.container.config.strings.codeLens.unsavedChanges.recentChangeOnly;
return this.container.config.strings.codeLens.unsavedChanges.authorsOnly;
} }
} }

+ 1
- 1
src/commands/addAuthors.ts View File

@ -13,7 +13,7 @@ export class AddAuthorsCommand extends Command {
async execute(sourceControl: SourceControl) { async execute(sourceControl: SourceControl) {
let repo; let repo;
if (sourceControl?.rootUri != null) { if (sourceControl?.rootUri != null) {
repo = await Container.git.getRepository(sourceControl.rootUri);
repo = await Container.instance.git.getRepository(sourceControl.rootUri);
} }
return executeGitCommand({ return executeGitCommand({

+ 1
- 1
src/commands/browseRepoAtRevision.ts View File

@ -66,7 +66,7 @@ export class BrowseRepoAtRevisionCommand extends ActiveEditorCommand {
if (gitUri.sha == null) return; if (gitUri.sha == null) return;
const sha = args?.before const sha = args?.before
? await Container.git.resolveReference(gitUri.repoPath!, `${gitUri.sha}^`)
? await Container.instance.git.resolveReference(gitUri.repoPath!, `${gitUri.sha}^`)
: gitUri.sha; : gitUri.sha;
uri = toGitLensFSUri(sha, gitUri.repoPath!); uri = toGitLensFSUri(sha, gitUri.repoPath!);
gitUri = GitUri.fromRevisionUri(uri); gitUri = GitUri.fromRevisionUri(uri);

+ 1
- 1
src/commands/closeUnchangedFiles.ts View File

@ -28,7 +28,7 @@ export class CloseUnchangedFilesCommand extends Command {
const repoPath = await getRepoPathOrPrompt('Close All Unchanged Files'); const repoPath = await getRepoPathOrPrompt('Close All Unchanged Files');
if (!repoPath) return; if (!repoPath) return;
const status = await Container.git.getStatusForRepo(repoPath);
const status = await Container.instance.git.getStatusForRepo(repoPath);
if (status == null) { if (status == null) {
void window.showWarningMessage('Unable to close unchanged files'); void window.showWarningMessage('Unable to close unchanged files');

+ 1
- 1
src/commands/closeView.ts View File

@ -16,7 +16,7 @@ export class CloseViewCommand extends Command {
async execute(command: Commands) { async execute(command: Commands) {
switch (command) { switch (command) {
case Commands.CloseWelcomeView: case Commands.CloseWelcomeView:
await Container.context.globalState.update(SyncedState.WelcomeViewVisible, false);
await Container.instance.context.globalState.update(SyncedState.WelcomeViewVisible, false);
await setContext(ContextKeys.ViewsWelcomeVisible, false); await setContext(ContextKeys.ViewsWelcomeVisible, false);
break; break;
} }

+ 2
- 2
src/commands/common.ts View File

@ -230,7 +230,7 @@ export function getCommandUri(uri?: Uri, editor?: TextEditor): Uri | undefined {
} }
export async function getRepoPathOrActiveOrPrompt(uri: Uri | undefined, editor: TextEditor | undefined, title: string) { export async function getRepoPathOrActiveOrPrompt(uri: Uri | undefined, editor: TextEditor | undefined, title: string) {
const repoPath = await Container.git.getRepoPathOrActive(uri, editor);
const repoPath = await Container.instance.git.getRepoPathOrActive(uri, editor);
if (repoPath) return repoPath; if (repoPath) return repoPath;
const pick = await RepositoryPicker.show(title); const pick = await RepositoryPicker.show(title);
@ -243,7 +243,7 @@ export async function getRepoPathOrActiveOrPrompt(uri: Uri | undefined, editor:
} }
export async function getRepoPathOrPrompt(title: string, uri?: Uri) { export async function getRepoPathOrPrompt(title: string, uri?: Uri) {
const repoPath = await Container.git.getRepoPath(uri);
const repoPath = await Container.instance.git.getRepoPath(uri);
if (repoPath) return repoPath; if (repoPath) return repoPath;
const pick = await RepositoryPicker.show(title); const pick = await RepositoryPicker.show(title);

+ 2
- 2
src/commands/compareWith.ts View File

@ -76,9 +76,9 @@ export class CompareWithCommand extends ActiveEditorCommand {
if (!repoPath) return; if (!repoPath) return;
if (args.ref1 != null && args.ref2 != null) { if (args.ref1 != null && args.ref2 != null) {
void (await Container.searchAndCompareView.compare(repoPath, args.ref1, args.ref2));
void (await Container.instance.searchAndCompareView.compare(repoPath, args.ref1, args.ref2));
} else { } else {
Container.searchAndCompareView.selectForCompare(repoPath, args.ref1, { prompt: true });
Container.instance.searchAndCompareView.selectForCompare(repoPath, args.ref1, { prompt: true });
} }
} catch (ex) { } catch (ex) {
Logger.error(ex, 'CompareWithCommmand'); Logger.error(ex, 'CompareWithCommmand');

+ 1
- 1
src/commands/copyCurrentBranch.ts View File

@ -20,7 +20,7 @@ export class CopyCurrentBranchCommand extends ActiveEditorCommand {
if (!repoPath) return; if (!repoPath) return;
try { try {
const branch = await Container.git.getBranch(repoPath);
const branch = await Container.instance.git.getBranch(repoPath);
if (branch?.name) { if (branch?.name) {
await env.clipboard.writeText(branch.name); await env.clipboard.writeText(branch.name);
} }

+ 9
- 5
src/commands/copyMessageToClipboard.ts View File

@ -53,10 +53,10 @@ export class CopyMessageToClipboardCommand extends ActiveEditorCommand {
let repoPath; let repoPath;
// If we don't have an editor then get the message of the last commit to the branch // If we don't have an editor then get the message of the last commit to the branch
if (uri == null) { if (uri == null) {
repoPath = await Container.git.getActiveRepoPath(editor);
repoPath = await Container.instance.git.getActiveRepoPath(editor);
if (!repoPath) return; if (!repoPath) return;
const log = await Container.git.getLog(repoPath, { limit: 1 });
const log = await Container.instance.git.getLog(repoPath, { limit: 1 });
if (log == null) return; if (log == null) return;
args.message = Iterables.first(log.commits.values()).message; args.message = Iterables.first(log.commits.values()).message;
@ -70,8 +70,12 @@ export class CopyMessageToClipboardCommand extends ActiveEditorCommand {
try { try {
const blame = editor?.document.isDirty const blame = editor?.document.isDirty
? await Container.git.getBlameForLineContents(gitUri, blameline, editor.document.getText())
: await Container.git.getBlameForLine(gitUri, blameline);
? await Container.instance.git.getBlameForLineContents(
gitUri,
blameline,
editor.document.getText(),
)
: await Container.instance.git.getBlameForLine(gitUri, blameline);
if (blame == null) return; if (blame == null) return;
if (blame.commit.isUncommitted) return; if (blame.commit.isUncommitted) return;
@ -89,7 +93,7 @@ export class CopyMessageToClipboardCommand extends ActiveEditorCommand {
} }
// Get the full commit message -- since blame only returns the summary // Get the full commit message -- since blame only returns the summary
const commit = await Container.git.getCommit(repoPath!, args.sha);
const commit = await Container.instance.git.getCommit(repoPath!, args.sha);
if (commit == null) return; if (commit == null) return;
args.message = commit.message; args.message = commit.message;

+ 9
- 5
src/commands/copyShaToClipboard.ts View File

@ -29,7 +29,7 @@ export class CopyShaToClipboardCommand extends ActiveEditorCommand {
protected override preExecute(context: CommandContext, args?: CopyShaToClipboardCommandArgs) { protected override preExecute(context: CommandContext, args?: CopyShaToClipboardCommandArgs) {
if (isCommandContextViewNodeHasCommit(context)) { if (isCommandContextViewNodeHasCommit(context)) {
args = { ...args }; args = { ...args };
args.sha = Container.config.advanced.abbreviateShaOnCopy
args.sha = Container.instance.config.advanced.abbreviateShaOnCopy
? context.node.commit.shortSha ? context.node.commit.shortSha
: context.node.commit.sha; : context.node.commit.sha;
return this.execute(context.editor, context.node.commit.uri, args); return this.execute(context.editor, context.node.commit.uri, args);
@ -53,10 +53,10 @@ export class CopyShaToClipboardCommand extends ActiveEditorCommand {
try { try {
// If we don't have an editor then get the sha of the last commit to the branch // If we don't have an editor then get the sha of the last commit to the branch
if (uri == null) { if (uri == null) {
const repoPath = await Container.git.getActiveRepoPath(editor);
const repoPath = await Container.instance.git.getActiveRepoPath(editor);
if (!repoPath) return; if (!repoPath) return;
const log = await Container.git.getLog(repoPath, { limit: 1 });
const log = await Container.instance.git.getLog(repoPath, { limit: 1 });
if (log == null) return; if (log == null) return;
args.sha = Iterables.first(log.commits.values()).sha; args.sha = Iterables.first(log.commits.values()).sha;
@ -67,8 +67,12 @@ export class CopyShaToClipboardCommand extends ActiveEditorCommand {
try { try {
const gitUri = await GitUri.fromUri(uri); const gitUri = await GitUri.fromUri(uri);
const blame = editor?.document.isDirty const blame = editor?.document.isDirty
? await Container.git.getBlameForLineContents(gitUri, blameline, editor.document.getText())
: await Container.git.getBlameForLine(gitUri, blameline);
? await Container.instance.git.getBlameForLineContents(
gitUri,
blameline,
editor.document.getText(),
)
: await Container.instance.git.getBlameForLine(gitUri, blameline);
if (blame == null) return; if (blame == null) return;
args.sha = blame.commit.sha; args.sha = blame.commit.sha;

+ 1
- 1
src/commands/createPullRequestOnRemote.ts View File

@ -22,7 +22,7 @@ export class CreatePullRequestOnRemoteCommand extends Command {
async execute(args?: CreatePullRequestOnRemoteCommandArgs) { async execute(args?: CreatePullRequestOnRemoteCommandArgs) {
if (args?.repoPath == null) return; if (args?.repoPath == null) return;
const repo = await Container.git.getRepository(args.repoPath);
const repo = await Container.instance.git.getRepository(args.repoPath);
if (repo == null) return; if (repo == null) return;
const compareRemote = await repo.getRemote(args.remote); const compareRemote = await repo.getRemote(args.remote);

+ 1
- 1
src/commands/diffLineWithPrevious.ts View File

@ -33,7 +33,7 @@ export class DiffLineWithPreviousCommand extends ActiveEditorCommand {
const gitUri = args.commit != null ? GitUri.fromCommit(args.commit) : await GitUri.fromUri(uri); const gitUri = args.commit != null ? GitUri.fromCommit(args.commit) : await GitUri.fromUri(uri);
try { try {
const diffUris = await Container.git.getPreviousLineDiffUris(
const diffUris = await Container.instance.git.getPreviousLineDiffUris(
gitUri.repoPath!, gitUri.repoPath!,
gitUri, gitUri,
args.line, args.line,

+ 3
- 3
src/commands/diffLineWithWorking.ts View File

@ -38,8 +38,8 @@ export class DiffLineWithWorkingCommand extends ActiveEditorCommand {
try { try {
const blame = editor?.document.isDirty const blame = editor?.document.isDirty
? await Container.git.getBlameForLineContents(gitUri, blameline, editor.document.getText())
: await Container.git.getBlameForLine(gitUri, blameline);
? await Container.instance.git.getBlameForLineContents(gitUri, blameline, editor.document.getText())
: await Container.instance.git.getBlameForLine(gitUri, blameline);
if (blame == null) { if (blame == null) {
void Messages.showFileNotUnderSourceControlWarningMessage('Unable to open compare'); void Messages.showFileNotUnderSourceControlWarningMessage('Unable to open compare');
@ -50,7 +50,7 @@ export class DiffLineWithWorkingCommand extends ActiveEditorCommand {
// If the line is uncommitted, change the previous commit // If the line is uncommitted, change the previous commit
if (args.commit.isUncommitted) { if (args.commit.isUncommitted) {
const status = await Container.git.getStatusForFile(gitUri.repoPath!, gitUri.fsPath);
const status = await Container.instance.git.getStatusForFile(gitUri.repoPath!, gitUri.fsPath);
args.commit = args.commit.with({ args.commit = args.commit.with({
sha: status?.indexStatus != null ? GitRevision.uncommittedStaged : args.commit.previousSha!, sha: status?.indexStatus != null ? GitRevision.uncommittedStaged : args.commit.previousSha!,
fileName: args.commit.previousFileName!, fileName: args.commit.previousFileName!,

+ 9
- 5
src/commands/diffWith.ts View File

@ -88,8 +88,12 @@ export class DiffWithCommand extends Command {
let rhsSha = args.rhs.sha; let rhsSha = args.rhs.sha;
[args.lhs.sha, args.rhs.sha] = await Promise.all([ [args.lhs.sha, args.rhs.sha] = await Promise.all([
await Container.git.resolveReference(args.repoPath, args.lhs.sha, args.lhs.uri, { timeout: 100 }),
await Container.git.resolveReference(args.repoPath, args.rhs.sha, args.rhs.uri, { timeout: 100 }),
await Container.instance.git.resolveReference(args.repoPath, args.lhs.sha, args.lhs.uri, {
timeout: 100,
}),
await Container.instance.git.resolveReference(args.repoPath, args.rhs.sha, args.rhs.uri, {
timeout: 100,
}),
]); ]);
if (args.lhs.sha !== GitRevision.deletedOrMissing) { if (args.lhs.sha !== GitRevision.deletedOrMissing) {
@ -98,7 +102,7 @@ export class DiffWithCommand extends Command {
if (args.rhs.sha && args.rhs.sha !== GitRevision.deletedOrMissing) { if (args.rhs.sha && args.rhs.sha !== GitRevision.deletedOrMissing) {
// Ensure that the file still exists in this commit // Ensure that the file still exists in this commit
const status = await Container.git.getFileStatusForCommit(
const status = await Container.instance.git.getFileStatusForCommit(
args.repoPath, args.repoPath,
args.rhs.uri.fsPath, args.rhs.uri.fsPath,
args.rhs.sha, args.rhs.sha,
@ -115,8 +119,8 @@ export class DiffWithCommand extends Command {
} }
const [lhs, rhs] = await Promise.all([ const [lhs, rhs] = await Promise.all([
Container.git.getVersionedUri(args.repoPath, args.lhs.uri.fsPath, args.lhs.sha),
Container.git.getVersionedUri(args.repoPath, args.rhs.uri.fsPath, args.rhs.sha),
Container.instance.git.getVersionedUri(args.repoPath, args.lhs.uri.fsPath, args.lhs.sha),
Container.instance.git.getVersionedUri(args.repoPath, args.rhs.uri.fsPath, args.rhs.sha),
]); ]);
let rhsSuffix = GitRevision.shorten(rhsSha, { strings: { uncommitted: 'Working Tree' } }); let rhsSuffix = GitRevision.shorten(rhsSha, { strings: { uncommitted: 'Working Tree' } });

+ 1
- 1
src/commands/diffWithNext.ts View File

@ -42,7 +42,7 @@ export class DiffWithNextCommand extends ActiveEditorCommand {
const gitUri = args.commit != null ? GitUri.fromCommit(args.commit) : await GitUri.fromUri(uri); const gitUri = args.commit != null ? GitUri.fromCommit(args.commit) : await GitUri.fromUri(uri);
try { try {
const diffUris = await Container.git.getNextDiffUris(
const diffUris = await Container.instance.git.getNextDiffUris(
gitUri.repoPath!, gitUri.repoPath!,
gitUri, gitUri,
gitUri.sha, gitUri.sha,

+ 1
- 1
src/commands/diffWithPrevious.ts View File

@ -83,7 +83,7 @@ export class DiffWithPreviousCommand extends ActiveEditorCommand {
// } // }
try { try {
const diffUris = await Container.git.getPreviousDiffUris(
const diffUris = await Container.instance.git.getPreviousDiffUris(
gitUri.repoPath!, gitUri.repoPath!,
gitUri, gitUri,
gitUri.sha, gitUri.sha,

+ 2
- 2
src/commands/diffWithRevision.ts View File

@ -34,13 +34,13 @@ export class DiffWithRevisionCommand extends ActiveEditorCommand {
} }
try { try {
const log = Container.git
const log = Container.instance.git
.getLogForFile(gitUri.repoPath, gitUri.fsPath) .getLogForFile(gitUri.repoPath, gitUri.fsPath)
.then( .then(
log => log =>
log ?? log ??
(gitUri.sha (gitUri.sha
? Container.git.getLogForFile(gitUri.repoPath, gitUri.fsPath, { ref: gitUri.sha })
? Container.instance.git.getLogForFile(gitUri.repoPath, gitUri.fsPath, { ref: gitUri.sha })
: undefined), : undefined),
); );

+ 1
- 1
src/commands/diffWithRevisionFrom.ts View File

@ -57,7 +57,7 @@ export class DiffWithRevisionFromCommand extends ActiveEditorCommand {
let renamedTitle: string | undefined; let renamedTitle: string | undefined;
// Check to see if this file has been renamed // Check to see if this file has been renamed
const files = await Container.git.getDiffStatus(gitUri.repoPath, 'HEAD', ref, { filters: ['R', 'C'] });
const files = await Container.instance.git.getDiffStatus(gitUri.repoPath, 'HEAD', ref, { filters: ['R', 'C'] });
if (files != null) { if (files != null) {
const fileName = Strings.normalizePath(paths.relative(gitUri.repoPath, gitUri.fsPath)); const fileName = Strings.normalizePath(paths.relative(gitUri.repoPath, gitUri.fsPath));
const rename = files.find(s => s.fileName === fileName); const rename = files.find(s => s.fileName === fileName);

+ 8
- 3
src/commands/diffWithWorking.ts View File

@ -38,7 +38,12 @@ export class DiffWithWorkingCommand extends ActiveEditorCommand {
if (args.inDiffRightEditor) { if (args.inDiffRightEditor) {
try { try {
const diffUris = await Container.git.getPreviousDiffUris(gitUri.repoPath!, gitUri, gitUri.sha, 0);
const diffUris = await Container.instance.git.getPreviousDiffUris(
gitUri.repoPath!,
gitUri,
gitUri.sha,
0,
);
gitUri = diffUris?.previous ?? gitUri; gitUri = diffUris?.previous ?? gitUri;
} catch (ex) { } catch (ex) {
Logger.error( Logger.error(
@ -66,7 +71,7 @@ export class DiffWithWorkingCommand extends ActiveEditorCommand {
// If we are a fake "staged" sha, check the status // If we are a fake "staged" sha, check the status
if (gitUri.isUncommittedStaged) { if (gitUri.isUncommittedStaged) {
const status = await Container.git.getStatusForFile(gitUri.repoPath!, gitUri.fsPath);
const status = await Container.instance.git.getStatusForFile(gitUri.repoPath!, gitUri.fsPath);
if (status?.indexStatus != null) { if (status?.indexStatus != null) {
void (await executeCommand<DiffWithCommandArgs>(Commands.DiffWith, { void (await executeCommand<DiffWithCommandArgs>(Commands.DiffWith, {
repoPath: gitUri.repoPath, repoPath: gitUri.repoPath,
@ -88,7 +93,7 @@ export class DiffWithWorkingCommand extends ActiveEditorCommand {
uri = gitUri.toFileUri(); uri = gitUri.toFileUri();
const workingUri = await Container.git.getWorkingUri(gitUri.repoPath!, uri);
const workingUri = await Container.instance.git.getWorkingUri(gitUri.repoPath!, uri);
if (workingUri == null) { if (workingUri == null) {
void window.showWarningMessage('Unable to open compare. File has been deleted from the working tree'); void window.showWarningMessage('Unable to open compare. File has been deleted from the working tree');

+ 8
- 6
src/commands/externalDiff.ts View File

@ -122,7 +122,7 @@ export class ExternalDiffCommand extends Command {
const repoPath = await getRepoPathOrPrompt('Open All Changes (difftool)'); const repoPath = await getRepoPathOrPrompt('Open All Changes (difftool)');
if (!repoPath) return undefined; if (!repoPath) return undefined;
const status = await Container.git.getStatusForRepo(repoPath);
const status = await Container.instance.git.getStatusForRepo(repoPath);
if (status == null) { if (status == null) {
return window.showInformationMessage("The repository doesn't have any changes"); return window.showInformationMessage("The repository doesn't have any changes");
} }
@ -158,11 +158,11 @@ export class ExternalDiffCommand extends Command {
const editor = window.activeTextEditor; const editor = window.activeTextEditor;
if (editor == null) return; if (editor == null) return;
repoPath = await Container.git.getRepoPathOrActive(undefined, editor);
repoPath = await Container.instance.git.getRepoPathOrActive(undefined, editor);
if (!repoPath) return; if (!repoPath) return;
const uri = editor.document.uri; const uri = editor.document.uri;
const status = await Container.git.getStatusForFile(repoPath, uri.fsPath);
const status = await Container.instance.git.getStatusForFile(repoPath, uri.fsPath);
if (status == null) { if (status == null) {
void window.showInformationMessage("The current file doesn't have any changes"); void window.showInformationMessage("The current file doesn't have any changes");
@ -178,11 +178,13 @@ export class ExternalDiffCommand extends Command {
args.files.push({ uri: status.uri, staged: false }); args.files.push({ uri: status.uri, staged: false });
} }
} else { } else {
repoPath = await Container.git.getRepoPath(args.files[0].uri.fsPath);
repoPath = await Container.instance.git.getRepoPath(args.files[0].uri.fsPath);
if (!repoPath) return; if (!repoPath) return;
} }
const tool = Container.config.advanced.externalDiffTool || (await Container.git.getDiffTool(repoPath));
const tool =
Container.instance.config.advanced.externalDiffTool ||
(await Container.instance.git.getDiffTool(repoPath));
if (!tool) { if (!tool) {
const viewDocs = 'View Git Docs'; const viewDocs = 'View Git Docs';
const result = await window.showWarningMessage( const result = await window.showWarningMessage(
@ -199,7 +201,7 @@ export class ExternalDiffCommand extends Command {
} }
for (const file of args.files) { for (const file of args.files) {
void Container.git.openDiffTool(repoPath, file.uri, {
void Container.instance.git.openDiffTool(repoPath, file.uri, {
ref1: file.ref1, ref1: file.ref1,
ref2: file.ref2, ref2: file.ref2,
staged: file.staged, staged: file.staged,

+ 1
- 1
src/commands/git/branch.ts View File

@ -148,7 +148,7 @@ export class BranchGitCommand extends QuickCommand {
protected async *steps(state: PartialStepState<State>): StepGenerator { protected async *steps(state: PartialStepState<State>): StepGenerator {
const context: Context = { const context: Context = {
repos: [...(await Container.git.getOrderedRepositories())],
repos: [...(await Container.instance.git.getOrderedRepositories())],
showTags: false, showTags: false,
title: this.title, title: this.title,
}; };

+ 2
- 2
src/commands/git/cherry-pick.ts View File

@ -80,7 +80,7 @@ export class CherryPickGitCommand extends QuickCommand {
protected async *steps(state: PartialStepState<State>): StepGenerator { protected async *steps(state: PartialStepState<State>): StepGenerator {
const context: Context = { const context: Context = {
repos: [...(await Container.git.getOrderedRepositories())],
repos: [...(await Container.instance.git.getOrderedRepositories())],
cache: new Map<string, Promise<GitLog | undefined>>(), cache: new Map<string, Promise<GitLog | undefined>>(),
destination: undefined!, destination: undefined!,
selectedBranchOrTag: undefined, selectedBranchOrTag: undefined,
@ -162,7 +162,7 @@ export class CherryPickGitCommand extends QuickCommand {
let log = context.cache.get(ref); let log = context.cache.get(ref);
if (log == null) { if (log == null) {
log = Container.git.getLog(state.repo.path, { ref: ref, merges: false });
log = Container.instance.git.getLog(state.repo.path, { ref: ref, merges: false });
context.cache.set(ref, log); context.cache.set(ref, log);
} }

+ 2
- 2
src/commands/git/coauthors.ts View File

@ -93,7 +93,7 @@ export class CoAuthorsGitCommand extends QuickCommand {
protected async *steps(state: PartialStepState<State>): StepGenerator { protected async *steps(state: PartialStepState<State>): StepGenerator {
const context: Context = { const context: Context = {
repos: [...(await Container.git.getOrderedRepositories())],
repos: [...(await Container.instance.git.getOrderedRepositories())],
activeRepo: undefined, activeRepo: undefined,
title: this.title, title: this.title,
}; };
@ -106,7 +106,7 @@ export class CoAuthorsGitCommand extends QuickCommand {
); );
// Ensure that the active repo is known to the built-in git // Ensure that the active repo is known to the built-in git
context.activeRepo = await Container.git.getActiveRepository();
context.activeRepo = await Container.instance.git.getActiveRepository();
if ( if (
context.activeRepo != null && context.activeRepo != null &&
!gitApi.repositories.some(r => r.rootUri.fsPath === context.activeRepo!.path) !gitApi.repositories.some(r => r.rootUri.fsPath === context.activeRepo!.path)

+ 2
- 2
src/commands/git/fetch.ts View File

@ -59,7 +59,7 @@ export class FetchGitCommand extends QuickCommand {
return state.repos[0].fetch({ branch: state.reference }); return state.repos[0].fetch({ branch: state.reference });
} }
return Container.git.fetchAll(state.repos, {
return Container.instance.git.fetchAll(state.repos, {
all: state.flags.includes('--all'), all: state.flags.includes('--all'),
prune: state.flags.includes('--prune'), prune: state.flags.includes('--prune'),
}); });
@ -67,7 +67,7 @@ export class FetchGitCommand extends QuickCommand {
protected async *steps(state: PartialStepState<State>): StepGenerator { protected async *steps(state: PartialStepState<State>): StepGenerator {
const context: Context = { const context: Context = {
repos: [...(await Container.git.getOrderedRepositories())],
repos: [...(await Container.instance.git.getOrderedRepositories())],
title: this.title, title: this.title,
}; };

+ 4
- 4
src/commands/git/log.ts View File

@ -76,7 +76,7 @@ export class LogGitCommand extends QuickCommand {
protected async *steps(state: PartialStepState<State>): StepGenerator { protected async *steps(state: PartialStepState<State>): StepGenerator {
const context: Context = { const context: Context = {
repos: [...(await Container.git.getOrderedRepositories())],
repos: [...(await Container.instance.git.getOrderedRepositories())],
cache: new Map<string, Promise<GitLog | undefined>>(), cache: new Map<string, Promise<GitLog | undefined>>(),
selectedBranchOrTag: undefined, selectedBranchOrTag: undefined,
title: this.title, title: this.title,
@ -152,8 +152,8 @@ export class LogGitCommand extends QuickCommand {
if (log == null) { if (log == null) {
log = log =
state.fileName != null state.fileName != null
? Container.git.getLogForFile(state.repo.path, state.fileName, { ref: ref })
: Container.git.getLog(state.repo.path, { ref: ref });
? Container.instance.git.getLogForFile(state.repo.path, state.fileName, { ref: ref })
: Container.instance.git.getLog(state.repo.path, { ref: ref });
context.cache.set(ref, log); context.cache.set(ref, log);
} }
@ -175,7 +175,7 @@ export class LogGitCommand extends QuickCommand {
} }
if (!(state.reference instanceof GitLogCommit) || state.reference.isFile) { if (!(state.reference instanceof GitLogCommit) || state.reference.isFile) {
state.reference = await Container.git.getCommit(state.repo.path, state.reference.ref);
state.reference = await Container.instance.git.getCommit(state.repo.path, state.reference.ref);
} }
const result = yield* GitCommandsCommand.getSteps( const result = yield* GitCommandsCommand.getSteps(

+ 3
- 3
src/commands/git/merge.ts View File

@ -76,7 +76,7 @@ export class MergeGitCommand extends QuickCommand {
protected async *steps(state: PartialStepState<State>): StepGenerator { protected async *steps(state: PartialStepState<State>): StepGenerator {
const context: Context = { const context: Context = {
repos: [...(await Container.git.getOrderedRepositories())],
repos: [...(await Container.instance.git.getOrderedRepositories())],
cache: new Map<string, Promise<GitLog | undefined>>(), cache: new Map<string, Promise<GitLog | undefined>>(),
destination: undefined!, destination: undefined!,
pickCommit: false, pickCommit: false,
@ -159,7 +159,7 @@ export class MergeGitCommand extends QuickCommand {
let log = context.cache.get(ref); let log = context.cache.get(ref);
if (log == null) { if (log == null) {
log = Container.git.getLog(state.repo.path, { ref: ref, merges: false });
log = Container.instance.git.getLog(state.repo.path, { ref: ref, merges: false });
context.cache.set(ref, log); context.cache.set(ref, log);
} }
@ -195,7 +195,7 @@ export class MergeGitCommand extends QuickCommand {
} }
private async *confirmStep(state: MergeStepState, context: Context): AsyncStepResultGenerator<Flags[]> { private async *confirmStep(state: MergeStepState, context: Context): AsyncStepResultGenerator<Flags[]> {
const aheadBehind = await Container.git.getAheadBehindCommitCount(state.repo.path, [
const aheadBehind = await Container.instance.git.getAheadBehindCommitCount(state.repo.path, [
GitRevision.createRange(context.destination.name, state.reference.name), GitRevision.createRange(context.destination.name, state.reference.name),
]); ]);
const count = aheadBehind != null ? aheadBehind.ahead + aheadBehind.behind : 0; const count = aheadBehind != null ? aheadBehind.ahead + aheadBehind.behind : 0;

+ 2
- 2
src/commands/git/pull.ts View File

@ -68,12 +68,12 @@ export class PullGitCommand extends QuickCommand {
} }
} }
return Container.git.pullAll(state.repos, { rebase: state.flags.includes('--rebase') });
return Container.instance.git.pullAll(state.repos, { rebase: state.flags.includes('--rebase') });
} }
protected async *steps(state: PartialStepState<State>): StepGenerator { protected async *steps(state: PartialStepState<State>): StepGenerator {
const context: Context = { const context: Context = {
repos: [...(await Container.git.getOrderedRepositories())],
repos: [...(await Container.instance.git.getOrderedRepositories())],
title: this.title, title: this.title,
}; };

+ 3
- 3
src/commands/git/push.ts View File

@ -64,14 +64,14 @@ export class PushGitCommand extends QuickCommand {
if (index !== -1) { if (index !== -1) {
if (!GitReference.isBranch(state.reference)) return Promise.resolve(); if (!GitReference.isBranch(state.reference)) return Promise.resolve();
return Container.git.pushAll(state.repos, {
return Container.instance.git.pushAll(state.repos, {
force: false, force: false,
publish: { remote: state.flags[index + 1] }, publish: { remote: state.flags[index + 1] },
reference: state.reference, reference: state.reference,
}); });
} }
return Container.git.pushAll(state.repos, {
return Container.instance.git.pushAll(state.repos, {
force: state.flags.includes('--force'), force: state.flags.includes('--force'),
reference: state.reference, reference: state.reference,
}); });
@ -79,7 +79,7 @@ export class PushGitCommand extends QuickCommand {
protected async *steps(state: PartialStepState<State>): StepGenerator { protected async *steps(state: PartialStepState<State>): StepGenerator {
const context: Context = { const context: Context = {
repos: [...(await Container.git.getOrderedRepositories())],
repos: [...(await Container.instance.git.getOrderedRepositories())],
title: this.title, title: this.title,
}; };

+ 4
- 4
src/commands/git/rebase.ts View File

@ -75,7 +75,7 @@ export class RebaseGitCommand extends QuickCommand {
async execute(state: RebaseStepState) { async execute(state: RebaseStepState) {
let configs: string[] | undefined; let configs: string[] | undefined;
if (state.flags.includes('--interactive')) { if (state.flags.includes('--interactive')) {
await Container.rebaseEditor.enableForNextUse();
await Container.instance.rebaseEditor.enableForNextUse();
let editor; let editor;
switch (env.appName) { switch (env.appName) {
@ -97,7 +97,7 @@ export class RebaseGitCommand extends QuickCommand {
protected async *steps(state: PartialStepState<State>): StepGenerator { protected async *steps(state: PartialStepState<State>): StepGenerator {
const context: Context = { const context: Context = {
repos: [...(await Container.git.getOrderedRepositories())],
repos: [...(await Container.instance.git.getOrderedRepositories())],
cache: new Map<string, Promise<GitLog | undefined>>(), cache: new Map<string, Promise<GitLog | undefined>>(),
destination: undefined!, destination: undefined!,
pickCommit: false, pickCommit: false,
@ -180,7 +180,7 @@ export class RebaseGitCommand extends QuickCommand {
let log = context.cache.get(ref); let log = context.cache.get(ref);
if (log == null) { if (log == null) {
log = Container.git.getLog(state.repo.path, { ref: ref, merges: false });
log = Container.instance.git.getLog(state.repo.path, { ref: ref, merges: false });
context.cache.set(ref, log); context.cache.set(ref, log);
} }
@ -216,7 +216,7 @@ export class RebaseGitCommand extends QuickCommand {
} }
private async *confirmStep(state: RebaseStepState, context: Context): AsyncStepResultGenerator<Flags[]> { private async *confirmStep(state: RebaseStepState, context: Context): AsyncStepResultGenerator<Flags[]> {
const aheadBehind = await Container.git.getAheadBehindCommitCount(state.repo.path, [
const aheadBehind = await Container.instance.git.getAheadBehindCommitCount(state.repo.path, [
state.reference.refType === 'revision' state.reference.refType === 'revision'
? GitRevision.createRange(state.reference.ref, context.destination.ref) ? GitRevision.createRange(state.reference.ref, context.destination.ref)
: GitRevision.createRange(context.destination.name, state.reference.name), : GitRevision.createRange(context.destination.name, state.reference.name),

+ 2
- 2
src/commands/git/reset.ts View File

@ -71,7 +71,7 @@ export class ResetGitCommand extends QuickCommand {
protected async *steps(state: PartialStepState<State>): StepGenerator { protected async *steps(state: PartialStepState<State>): StepGenerator {
const context: Context = { const context: Context = {
repos: [...(await Container.git.getOrderedRepositories())],
repos: [...(await Container.instance.git.getOrderedRepositories())],
cache: new Map<string, Promise<GitLog | undefined>>(), cache: new Map<string, Promise<GitLog | undefined>>(),
destination: undefined!, destination: undefined!,
title: this.title, title: this.title,
@ -118,7 +118,7 @@ export class ResetGitCommand extends QuickCommand {
let log = context.cache.get(ref); let log = context.cache.get(ref);
if (log == null) { if (log == null) {
log = Container.git.getLog(state.repo.path, { ref: ref, merges: false });
log = Container.instance.git.getLog(state.repo.path, { ref: ref, merges: false });
context.cache.set(ref, log); context.cache.set(ref, log);
} }

+ 2
- 2
src/commands/git/revert.ts View File

@ -73,7 +73,7 @@ export class RevertGitCommand extends QuickCommand {
protected async *steps(state: PartialStepState<State>): StepGenerator { protected async *steps(state: PartialStepState<State>): StepGenerator {
const context: Context = { const context: Context = {
repos: [...(await Container.git.getOrderedRepositories())],
repos: [...(await Container.instance.git.getOrderedRepositories())],
cache: new Map<string, Promise<GitLog | undefined>>(), cache: new Map<string, Promise<GitLog | undefined>>(),
destination: undefined!, destination: undefined!,
title: this.title, title: this.title,
@ -122,7 +122,7 @@ export class RevertGitCommand extends QuickCommand {
let log = context.cache.get(ref); let log = context.cache.get(ref);
if (log == null) { if (log == null) {
log = Container.git.getLog(state.repo.path, { ref: ref, merges: false });
log = Container.instance.git.getLog(state.repo.path, { ref: ref, merges: false });
context.cache.set(ref, log); context.cache.set(ref, log);
} }

+ 5
- 5
src/commands/git/search.ts View File

@ -91,14 +91,14 @@ export class SearchGitCommand extends QuickCommand {
protected async *steps(state: PartialStepState<State>): StepGenerator { protected async *steps(state: PartialStepState<State>): StepGenerator {
const context: Context = { const context: Context = {
repos: [...(await Container.git.getOrderedRepositories())],
repos: [...(await Container.instance.git.getOrderedRepositories())],
commit: undefined, commit: undefined,
resultsKey: undefined, resultsKey: undefined,
resultsPromise: undefined, resultsPromise: undefined,
title: this.title, title: this.title,
}; };
const cfg = Container.config.gitCommands.search;
const cfg = Container.instance.config.gitCommands.search;
if (state.matchAll == null) { if (state.matchAll == null) {
state.matchAll = cfg.matchAll; state.matchAll = cfg.matchAll;
} }
@ -166,7 +166,7 @@ export class SearchGitCommand extends QuickCommand {
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
if (state.showResultsInSideBar) { if (state.showResultsInSideBar) {
void Container.searchAndCompareView.search(
void Container.instance.searchAndCompareView.search(
state.repo.path, state.repo.path,
search, search,
{ {
@ -195,7 +195,7 @@ export class SearchGitCommand extends QuickCommand {
showInSideBarCommand: new ActionQuickPickItem( showInSideBarCommand: new ActionQuickPickItem(
'$(link-external) Show Results in Side Bar', '$(link-external) Show Results in Side Bar',
() => () =>
void Container.searchAndCompareView.search(
void Container.instance.searchAndCompareView.search(
repoPath, repoPath,
search, search,
{ {
@ -212,7 +212,7 @@ export class SearchGitCommand extends QuickCommand {
showInSideBarButton: { showInSideBarButton: {
button: QuickCommandButtons.ShowResultsInSideBar, button: QuickCommandButtons.ShowResultsInSideBar,
onDidClick: () => onDidClick: () =>
void Container.searchAndCompareView.search(
void Container.instance.searchAndCompareView.search(
repoPath, repoPath,
search, search,
{ {

+ 5
- 2
src/commands/git/show.ts View File

@ -76,7 +76,7 @@ export class ShowGitCommand extends QuickCommand {
protected async *steps(state: PartialStepState<State>): StepGenerator { protected async *steps(state: PartialStepState<State>): StepGenerator {
const context: Context = { const context: Context = {
repos: [...(await Container.git.getOrderedRepositories())],
repos: [...(await Container.instance.git.getOrderedRepositories())],
title: this.title, title: this.title,
}; };
@ -110,7 +110,10 @@ export class ShowGitCommand extends QuickCommand {
state.reference.isFile state.reference.isFile
) { ) {
if (state.reference != null && (!GitLogCommit.is(state.reference) || state.reference.isFile)) { if (state.reference != null && (!GitLogCommit.is(state.reference) || state.reference.isFile)) {
state.reference = await Container.git.getCommit(state.reference.repoPath, state.reference.ref);
state.reference = await Container.instance.git.getCommit(
state.reference.repoPath,
state.reference.ref,
);
} }
if (state.counter < 2 || state.reference == null) { if (state.counter < 2 || state.reference == null) {

+ 5
- 5
src/commands/git/stash.ts View File

@ -144,7 +144,7 @@ export class StashGitCommand extends QuickCommand {
protected async *steps(state: PartialStepState<State>): StepGenerator { protected async *steps(state: PartialStepState<State>): StepGenerator {
const context: Context = { const context: Context = {
repos: [...(await Container.git.getOrderedRepositories())],
repos: [...(await Container.instance.git.getOrderedRepositories())],
title: this.title, title: this.title,
}; };
@ -258,7 +258,7 @@ export class StashGitCommand extends QuickCommand {
while (this.canStepsContinue(state)) { while (this.canStepsContinue(state)) {
if (state.counter < 3 || state.reference == null) { if (state.counter < 3 || state.reference == null) {
const result: StepResult<GitStashReference> = yield* pickStashStep(state, context, { const result: StepResult<GitStashReference> = yield* pickStashStep(state, context, {
stash: await Container.git.getStash(state.repo.path),
stash: await Container.instance.git.getStash(state.repo.path),
placeholder: (context, stash) => placeholder: (context, stash) =>
stash == null stash == null
? `No stashes found in ${state.repo.formattedName}` ? `No stashes found in ${state.repo.formattedName}`
@ -374,7 +374,7 @@ export class StashGitCommand extends QuickCommand {
while (this.canStepsContinue(state)) { while (this.canStepsContinue(state)) {
if (state.counter < 3 || state.reference == null) { if (state.counter < 3 || state.reference == null) {
const result: StepResult<GitStashReference> = yield* pickStashStep(state, context, { const result: StepResult<GitStashReference> = yield* pickStashStep(state, context, {
stash: await Container.git.getStash(state.repo.path),
stash: await Container.instance.git.getStash(state.repo.path),
placeholder: (context, stash) => placeholder: (context, stash) =>
stash == null ? `No stashes found in ${state.repo.formattedName}` : 'Choose a stash to delete', stash == null ? `No stashes found in ${state.repo.formattedName}` : 'Choose a stash to delete',
picked: state.reference?.ref, picked: state.reference?.ref,
@ -435,7 +435,7 @@ export class StashGitCommand extends QuickCommand {
while (this.canStepsContinue(state)) { while (this.canStepsContinue(state)) {
if (state.counter < 3 || state.reference == null) { if (state.counter < 3 || state.reference == null) {
const result: StepResult<GitStashCommit> = yield* pickStashStep(state, context, { const result: StepResult<GitStashCommit> = yield* pickStashStep(state, context, {
stash: await Container.git.getStash(state.repo.path),
stash: await Container.instance.git.getStash(state.repo.path),
placeholder: (context, stash) => placeholder: (context, stash) =>
stash == null ? `No stashes found in ${state.repo.formattedName}` : 'Choose a stash', stash == null ? `No stashes found in ${state.repo.formattedName}` : 'Choose a stash',
picked: state.reference?.ref, picked: state.reference?.ref,
@ -447,7 +447,7 @@ export class StashGitCommand extends QuickCommand {
} }
// if (!(state.reference instanceof GitStashCommit)) { // if (!(state.reference instanceof GitStashCommit)) {
// state.reference = await Container.git.getCommit(state.repo.path, state.reference.ref);
// state.reference = await Container.instance.git.getCommit(state.repo.path, state.reference.ref);
// } // }
const result = yield* GitCommandsCommand.getSteps( const result = yield* GitCommandsCommand.getSteps(

+ 1
- 1
src/commands/git/status.ts View File

@ -55,7 +55,7 @@ export class StatusGitCommand extends QuickCommand {
protected async *steps(state: PartialStepState<State>): StepGenerator { protected async *steps(state: PartialStepState<State>): StepGenerator {
const context: Context = { const context: Context = {
repos: [...(await Container.git.getOrderedRepositories())],
repos: [...(await Container.instance.git.getOrderedRepositories())],
status: undefined!, status: undefined!,
title: this.title, title: this.title,
}; };

+ 2
- 2
src/commands/git/switch.ts View File

@ -88,7 +88,7 @@ export class SwitchGitCommand extends QuickCommand {
protected async *steps(state: PartialStepState<State>): StepGenerator { protected async *steps(state: PartialStepState<State>): StepGenerator {
const context: Context = { const context: Context = {
repos: [...(await Container.git.getOrderedRepositories())],
repos: [...(await Container.instance.git.getOrderedRepositories())],
showTags: false, showTags: false,
title: this.title, title: this.title,
}; };
@ -146,7 +146,7 @@ export class SwitchGitCommand extends QuickCommand {
if (GitReference.isBranch(state.reference) && state.reference.remote) { if (GitReference.isBranch(state.reference) && state.reference.remote) {
context.title = `Create Branch and ${this.title}`; context.title = `Create Branch and ${this.title}`;
const branches = await Container.git.getBranches(state.reference.repoPath, {
const branches = await Container.instance.git.getBranches(state.reference.repoPath, {
filter: b => b.upstream?.name === state.reference!.name, filter: b => b.upstream?.name === state.reference!.name,
sort: { orderBy: BranchSorting.DateDesc }, sort: { orderBy: BranchSorting.DateDesc },
}); });

+ 1
- 1
src/commands/git/tag.ts View File

@ -127,7 +127,7 @@ export class TagGitCommand extends QuickCommand {
protected async *steps(state: PartialStepState<State>): StepGenerator { protected async *steps(state: PartialStepState<State>): StepGenerator {
const context: Context = { const context: Context = {
repos: [...(await Container.git.getOrderedRepositories())],
repos: [...(await Container.instance.git.getOrderedRepositories())],
showTags: false, showTags: false,
title: this.title, title: this.title,
}; };

+ 35
- 31
src/commands/gitCommands.actions.ts View File

@ -35,7 +35,7 @@ export async function executeGitCommand(args: GitCommandsCommandArgs): Promise
} }
async function ensureRepo(repo: string | Repository): Promise<Repository> { async function ensureRepo(repo: string | Repository): Promise<Repository> {
return typeof repo === 'string' ? (await Container.git.getRepository(repo))! : repo;
return typeof repo === 'string' ? (await Container.instance.git.getRepository(repo))! : repo;
} }
export namespace GitActions { export namespace GitActions {
@ -152,17 +152,17 @@ export namespace GitActions {
) { ) {
if ( if (
!configuration.get(`views.${branch.remote ? 'remotes' : 'branches'}.reveal` as const) || !configuration.get(`views.${branch.remote ? 'remotes' : 'branches'}.reveal` as const) ||
(Container.repositoriesView.visible &&
!(branch.remote ? Container.remotesView.visible : Container.branchesView.visible))
(Container.instance.repositoriesView.visible &&
!(branch.remote ? Container.instance.remotesView.visible : Container.instance.branchesView.visible))
) { ) {
return Container.repositoriesView.revealBranch(branch, options);
return Container.instance.repositoriesView.revealBranch(branch, options);
} }
let node; let node;
if (branch.remote) { if (branch.remote) {
node = await Container.remotesView.revealBranch(branch, options);
node = await Container.instance.remotesView.revealBranch(branch, options);
} else { } else {
node = await Container.branchesView.revealBranch(branch, options);
node = await Container.instance.branchesView.revealBranch(branch, options);
} }
return node; return node;
@ -177,7 +177,7 @@ export namespace GitActions {
) { ) {
// Open the working file to ensure undo will work // Open the working file to ensure undo will work
void (await GitActions.Commit.openFile(file, ref1, { preserveFocus: true, preview: false })); void (await GitActions.Commit.openFile(file, ref1, { preserveFocus: true, preview: false }));
void (await Container.git.applyChangesToWorkingFile(
void (await Container.instance.git.applyChangesToWorkingFile(
GitUri.fromFile(file, ref1.repoPath, ref1.ref), GitUri.fromFile(file, ref1.repoPath, ref1.ref),
ref1.ref, ref1.ref,
ref2?.ref, ref2?.ref,
@ -193,7 +193,7 @@ export namespace GitActions {
if (GitLogCommit.is(ref)) { if (GitLogCommit.is(ref)) {
message = ref.message; message = ref.message;
} else { } else {
const commit = await Container.git.getCommit(ref.repoPath, ref.ref);
const commit = await Container.instance.git.getCommit(ref.repoPath, ref.ref);
if (commit == null) return; if (commit == null) return;
message = commit.message; message = commit.message;
@ -399,7 +399,7 @@ export namespace GitActions {
file = f; file = f;
} }
return Container.git.openDiffTool(
return Container.instance.git.openDiffTool(
commitOrRef.repoPath, commitOrRef.repoPath,
GitUri.fromFile(file, file.repoPath ?? commitOrRef.repoPath), GitUri.fromFile(file, file.repoPath ?? commitOrRef.repoPath),
{ {
@ -461,7 +461,7 @@ export namespace GitActions {
ref2: string | undefined, ref2: string | undefined,
tool?: string, tool?: string,
): Promise<void> { ): Promise<void> {
return Container.git.openDirectoryCompare(repoPath, ref, ref2, tool);
return Container.instance.git.openDirectoryCompare(repoPath, ref, ref2, tool);
} }
export async function openDirectoryCompareWithPrevious( export async function openDirectoryCompareWithPrevious(
@ -558,7 +558,9 @@ export namespace GitActions {
const editor = await findOrOpenEditor(uri, opts); const editor = await findOrOpenEditor(uri, opts);
if (annotationType != null && editor != null) { if (annotationType != null && editor != null) {
void (await Container.fileAnnotations.show(editor, annotationType, { selection: { line: line } }));
void (await Container.instance.fileAnnotations.show(editor, annotationType, {
selection: { line: line },
}));
} }
} }
@ -589,7 +591,9 @@ export namespace GitActions {
const uris: Uri[] = ( const uris: Uri[] = (
await Promise.all( await Promise.all(
files.map(file => Container.git.getWorkingUri(repoPath!, GitUri.fromFile(file, repoPath!, ref))),
files.map(file =>
Container.instance.git.getWorkingUri(repoPath!, GitUri.fromFile(file, repoPath!, ref)),
),
) )
).filter(<T>(u?: T): u is T => Boolean(u)); ).filter(<T>(u?: T): u is T => Boolean(u));
findOrOpenEditors(uris); findOrOpenEditors(uris);
@ -633,7 +637,7 @@ export namespace GitActions {
} }
export async function restoreFile(file: string | GitFile, ref: GitRevisionReference) { export async function restoreFile(file: string | GitFile, ref: GitRevisionReference) {
void (await Container.git.checkout(ref.repoPath, ref.ref, {
void (await Container.instance.git.checkout(ref.repoPath, ref.ref, {
fileName: typeof file === 'string' ? file : file.fileName, fileName: typeof file === 'string' ? file : file.fileName,
})); }));
} }
@ -648,20 +652,20 @@ export namespace GitActions {
) { ) {
if ( if (
!configuration.get('views.commits.reveal') || !configuration.get('views.commits.reveal') ||
(Container.repositoriesView.visible && !Container.commitsView.visible)
(Container.instance.repositoriesView.visible && !Container.instance.commitsView.visible)
) { ) {
return Container.repositoriesView.revealCommit(commit, options);
return Container.instance.repositoriesView.revealCommit(commit, options);
} }
// TODO@eamodio stop duplicate notifications // TODO@eamodio stop duplicate notifications
let node = await Container.commitsView.revealCommit(commit, options);
let node = await Container.instance.commitsView.revealCommit(commit, options);
if (node != null) return node; if (node != null) return node;
node = await Container.branchesView.revealCommit(commit, options);
node = await Container.instance.branchesView.revealCommit(commit, options);
if (node != null) return node; if (node != null) return node;
node = await Container.remotesView.revealCommit(commit, options);
node = await Container.instance.remotesView.revealCommit(commit, options);
if (node != null) return node; if (node != null) return node;
return undefined; return undefined;
@ -711,12 +715,12 @@ export namespace GitActions {
) { ) {
if ( if (
!configuration.get('views.tags.reveal') || !configuration.get('views.tags.reveal') ||
(Container.repositoriesView.visible && !Container.tagsView.visible)
(Container.instance.repositoriesView.visible && !Container.instance.tagsView.visible)
) { ) {
return Container.repositoriesView.revealTag(tag, options);
return Container.instance.repositoriesView.revealTag(tag, options);
} }
const node = await Container.tagsView.revealTag(tag, options);
const node = await Container.instance.tagsView.revealTag(tag, options);
return node; return node;
} }
} }
@ -724,7 +728,7 @@ export namespace GitActions {
export namespace Remote { export namespace Remote {
export async function add(repo?: string | Repository) { export async function add(repo?: string | Repository) {
if (repo == null) { if (repo == null) {
repo = Container.git.getHighlanderRepoPath();
repo = Container.instance.git.getHighlanderRepoPath();
if (repo == null) { if (repo == null) {
const pick = await RepositoryPicker.show(undefined, 'Choose a repository to add a remote to'); const pick = await RepositoryPicker.show(undefined, 'Choose a repository to add a remote to');
@ -750,7 +754,7 @@ export namespace GitActions {
if (url == null || url.length === 0) return undefined; if (url == null || url.length === 0) return undefined;
repo = await ensureRepo(repo); repo = await ensureRepo(repo);
void (await Container.git.addRemote(repo.path, name, url));
void (await Container.instance.git.addRemote(repo.path, name, url));
void (await repo.fetch({ remote: name })); void (await repo.fetch({ remote: name }));
return name; return name;
@ -758,7 +762,7 @@ export namespace GitActions {
export async function fetch(repo: string | Repository, remote: string) { export async function fetch(repo: string | Repository, remote: string) {
if (typeof repo === 'string') { if (typeof repo === 'string') {
const r = await Container.git.getRepository(repo);
const r = await Container.instance.git.getRepository(repo);
if (r == null) return; if (r == null) return;
repo = r; repo = r;
@ -768,7 +772,7 @@ export namespace GitActions {
} }
export async function prune(repo: string | Repository, remote: string) { export async function prune(repo: string | Repository, remote: string) {
void (await Container.git.pruneRemote(typeof repo === 'string' ? repo : repo.path, remote));
void (await Container.instance.git.pruneRemote(typeof repo === 'string' ? repo : repo.path, remote));
} }
export async function reveal( export async function reveal(
@ -781,12 +785,12 @@ export namespace GitActions {
) { ) {
// if ( // if (
// configuration.get('views.repositories.enabled') && // configuration.get('views.repositories.enabled') &&
// (Container.repositoriesView.visible || !Container.remotesView.visible)
// (Container.instance.repositoriesView.visible || !Container.instance.remotesView.visible)
// ) { // ) {
// return Container.repositoriesView.revealRemote(remote, options);
// return Container.instance.repositoriesView.revealRemote(remote, options);
// } // }
const node = await Container.remotesView.revealRemote(remote, options);
const node = await Container.instance.remotesView.revealRemote(remote, options);
return node; return node;
} }
} }
@ -836,12 +840,12 @@ export namespace GitActions {
) { ) {
if ( if (
!configuration.get('views.stashes.reveal') || !configuration.get('views.stashes.reveal') ||
(Container.repositoriesView.visible && !Container.stashesView.visible)
(Container.instance.repositoriesView.visible && !Container.instance.stashesView.visible)
) { ) {
return Container.repositoriesView.revealStash(stash, options);
return Container.instance.repositoriesView.revealStash(stash, options);
} }
const node = await Container.stashesView.revealStash(stash, options);
const node = await Container.instance.stashesView.revealStash(stash, options);
return node; return node;
} }
} }

+ 6
- 6
src/commands/gitCommands.ts View File

@ -310,7 +310,7 @@ export class GitCommandsCommand extends Command {
} }
} }
const scope = Container.keyboard.createScope(mapping);
const scope = Container.instance.keyboard.createScope(mapping);
void scope.start(); void scope.start();
disposables.push( disposables.push(
@ -460,7 +460,7 @@ export class GitCommandsCommand extends Command {
} }
} }
const scope = Container.keyboard.createScope(mapping);
const scope = Container.instance.keyboard.createScope(mapping);
void scope.start(); void scope.start();
let overrideItems = false; let overrideItems = false;
@ -767,8 +767,8 @@ class PickCommandStep implements QuickPickStep {
new TagGitCommand(args?.command === 'tag' ? args : undefined), new TagGitCommand(args?.command === 'tag' ? args : undefined),
]; ];
if (Container.config.gitCommands.sortBy === GitCommandSorting.Usage) {
const usage = Container.context.workspaceState.get<Usage>(WorkspaceState.GitCommandPaletteUsage);
if (Container.instance.config.gitCommands.sortBy === GitCommandSorting.Usage) {
const usage = Container.instance.context.workspaceState.get<Usage>(WorkspaceState.GitCommandPaletteUsage);
if (usage != null) { if (usage != null) {
this.items.sort((a, b) => (usage[b.key] ?? 0) - (usage[a.key] ?? 0)); this.items.sort((a, b) => (usage[b.key] ?? 0) - (usage[a.key] ?? 0));
} }
@ -808,12 +808,12 @@ class PickCommandStep implements QuickPickStep {
} }
private async updateCommandUsage(id: string, timestamp: number) { private async updateCommandUsage(id: string, timestamp: number) {
let usage = Container.context.workspaceState.get<Usage>(WorkspaceState.GitCommandPaletteUsage);
let usage = Container.instance.context.workspaceState.get<Usage>(WorkspaceState.GitCommandPaletteUsage);
if (usage === undefined) { if (usage === undefined) {
usage = Object.create(null) as Usage; usage = Object.create(null) as Usage;
} }
usage[id] = timestamp; usage[id] = timestamp;
await Container.context.workspaceState.update(WorkspaceState.GitCommandPaletteUsage, usage);
await Container.instance.context.workspaceState.update(WorkspaceState.GitCommandPaletteUsage, usage);
} }
} }

+ 2
- 2
src/commands/inviteToLiveShare.ts View File

@ -32,12 +32,12 @@ export class InviteToLiveShareCommand extends Command {
async execute(args?: InviteToLiveShareCommandArgs) { async execute(args?: InviteToLiveShareCommandArgs) {
if (args?.email) { if (args?.email) {
const contact = await Container.vsls.getContact(args.email);
const contact = await Container.instance.vsls.getContact(args.email);
if (contact != null) { if (contact != null) {
return contact.invite(); return contact.invite();
} }
} }
return Container.vsls.startSession();
return Container.instance.vsls.startSession();
} }
} }

+ 1
- 1
src/commands/openAssociatedPullRequestOnRemote.ts View File

@ -24,7 +24,7 @@ export class OpenAssociatedPullRequestOnRemoteCommand extends ActiveEditorComman
if (blameline < 0) return; if (blameline < 0) return;
try { try {
const blame = await Container.git.getBlameForLine(gitUri, blameline);
const blame = await Container.instance.git.getBlameForLine(gitUri, blameline);
if (blame == null) return; if (blame == null) return;
await executeCommand<OpenPullRequestOnRemoteCommandArgs>(Commands.OpenPullRequestOnRemote, { await executeCommand<OpenPullRequestOnRemoteCommandArgs>(Commands.OpenPullRequestOnRemote, {

+ 1
- 1
src/commands/openChangedFiles.ts View File

@ -24,7 +24,7 @@ export class OpenChangedFilesCommand extends Command {
const repoPath = await getRepoPathOrPrompt('Open All Changed Files'); const repoPath = await getRepoPathOrPrompt('Open All Changed Files');
if (!repoPath) return; if (!repoPath) return;
const status = await Container.git.getStatusForRepo(repoPath);
const status = await Container.instance.git.getStatusForRepo(repoPath);
if (status == null) { if (status == null) {
void window.showWarningMessage('Unable to open changed files'); void window.showWarningMessage('Unable to open changed files');

+ 2
- 2
src/commands/openCommitOnRemote.ts View File

@ -72,8 +72,8 @@ export class OpenCommitOnRemoteCommand extends ActiveEditorCommand {
if (blameline < 0) return; if (blameline < 0) return;
const blame = editor?.document.isDirty const blame = editor?.document.isDirty
? await Container.git.getBlameForLineContents(gitUri, blameline, editor.document.getText())
: await Container.git.getBlameForLine(gitUri, blameline);
? await Container.instance.git.getBlameForLineContents(gitUri, blameline, editor.document.getText())
: await Container.instance.git.getBlameForLine(gitUri, blameline);
if (blame == null) { if (blame == null) {
void Messages.showFileNotUnderSourceControlWarningMessage( void Messages.showFileNotUnderSourceControlWarningMessage(
'Unable to open commit on remote provider', 'Unable to open commit on remote provider',

+ 5
- 3
src/commands/openFileAtRevision.ts View File

@ -57,7 +57,7 @@ export class OpenFileAtRevisionCommand extends ActiveEditorCommand {
if (blameline >= 0) { if (blameline >= 0) {
try { try {
const gitUri = await GitUri.fromUri(context.editor.document.uri); const gitUri = await GitUri.fromUri(context.editor.document.uri);
const blame = await Container.git.getBlameForLine(gitUri, blameline);
const blame = await Container.instance.git.getBlameForLine(gitUri, blameline);
if (blame != null && !blame.commit.isUncommitted && blame.commit.previousSha != null) { if (blame != null && !blame.commit.isUncommitted && blame.commit.previousSha != null) {
args.revisionUri = GitUri.toRevisionUri(GitUri.fromCommit(blame.commit, true)); args.revisionUri = GitUri.toRevisionUri(GitUri.fromCommit(blame.commit, true));
} }
@ -82,13 +82,15 @@ export class OpenFileAtRevisionCommand extends ActiveEditorCommand {
try { try {
if (args.revisionUri == null) { if (args.revisionUri == null) {
const log = Container.git
const log = Container.instance.git
.getLogForFile(gitUri.repoPath, gitUri.fsPath) .getLogForFile(gitUri.repoPath, gitUri.fsPath)
.then( .then(
log => log =>
log ?? log ??
(gitUri.sha (gitUri.sha
? Container.git.getLogForFile(gitUri.repoPath, gitUri.fsPath, { ref: gitUri.sha })
? Container.instance.git.getLogForFile(gitUri.repoPath, gitUri.fsPath, {
ref: gitUri.sha,
})
: undefined), : undefined),
); );

+ 2
- 2
src/commands/openFileFromRemote.ts View File

@ -25,9 +25,9 @@ export class OpenFileFromRemoteCommand extends Command {
}); });
if (url == null || url.length === 0) return; if (url == null || url.length === 0) return;
let local = await Container.git.getLocalInfoFromRemoteUri(Uri.parse(url));
let local = await Container.instance.git.getLocalInfoFromRemoteUri(Uri.parse(url));
if (local == null) { if (local == null) {
local = await Container.git.getLocalInfoFromRemoteUri(Uri.parse(url), { validate: false });
local = await Container.instance.git.getLocalInfoFromRemoteUri(Uri.parse(url), { validate: false });
if (local == null) { if (local == null) {
void window.showWarningMessage('Unable to parse the provided remote url.'); void window.showWarningMessage('Unable to parse the provided remote url.');

+ 9
- 5
src/commands/openFileOnRemote.ts View File

@ -83,9 +83,13 @@ export class OpenFileOnRemoteCommand extends ActiveEditorCommand {
const gitUri = await GitUri.fromUri(uri); const gitUri = await GitUri.fromUri(uri);
if (gitUri.repoPath) { if (gitUri.repoPath) {
if (gitUri.sha == null) { if (gitUri.sha == null) {
const commit = await Container.git.getCommitForFile(gitUri.repoPath, gitUri.fsPath, {
firstIfNotFound: true,
});
const commit = await Container.instance.git.getCommitForFile(
gitUri.repoPath,
gitUri.fsPath,
{
firstIfNotFound: true,
},
);
if (commit != null) { if (commit != null) {
args.sha = commit.sha; args.sha = commit.sha;
@ -115,7 +119,7 @@ export class OpenFileOnRemoteCommand extends ActiveEditorCommand {
args = { range: true, ...args }; args = { range: true, ...args };
try { try {
let remotes = await Container.git.getRemotes(gitUri.repoPath);
let remotes = await Container.instance.git.getRemotes(gitUri.repoPath);
const range = const range =
args.range && editor != null && UriComparer.equals(editor.document.uri, uri) args.range && editor != null && UriComparer.equals(editor.document.uri, uri)
? new Range( ? new Range(
@ -143,7 +147,7 @@ export class OpenFileOnRemoteCommand extends ActiveEditorCommand {
if ((args.sha == null && args.branchOrTag == null) || args.pickBranchOrTag) { if ((args.sha == null && args.branchOrTag == null) || args.pickBranchOrTag) {
let branch; let branch;
if (!args.pickBranchOrTag) { if (!args.pickBranchOrTag) {
branch = await Container.git.getBranch(gitUri.repoPath);
branch = await Container.instance.git.getBranch(gitUri.repoPath);
} }
if (branch?.upstream == null) { if (branch?.upstream == null) {

+ 2
- 2
src/commands/openOnRemote.ts View File

@ -33,7 +33,7 @@ export class OpenOnRemoteCommand extends Command {
async execute(args?: OpenOnRemoteCommandArgs) { async execute(args?: OpenOnRemoteCommandArgs) {
if (args?.resource == null) return; if (args?.resource == null) return;
let remotes = 'remotes' in args ? args.remotes : await Container.git.getRemotes(args.repoPath);
let remotes = 'remotes' in args ? args.remotes : await Container.instance.git.getRemotes(args.repoPath);
if (args.remote != null) { if (args.remote != null) {
const filtered = remotes.filter(r => r.name === args.remote); const filtered = remotes.filter(r => r.name === args.remote);
@ -60,7 +60,7 @@ export class OpenOnRemoteCommand extends Command {
const file = commit?.files.find(f => f.fileName === fileName); const file = commit?.files.find(f => f.fileName === fileName);
if (file?.status === 'D') { if (file?.status === 'D') {
// Resolve to the previous commit to that file // Resolve to the previous commit to that file
args.resource.sha = await Container.git.resolveReference(
args.resource.sha = await Container.instance.git.resolveReference(
commit.repoPath, commit.repoPath,
`${commit.sha}^`, `${commit.sha}^`,
fileName, fileName,

+ 2
- 2
src/commands/openPullRequestOnRemote.ts View File

@ -33,10 +33,10 @@ export class OpenPullRequestOnRemoteCommand extends Command {
if (args?.pr == null) { if (args?.pr == null) {
if (args?.repoPath == null || args?.ref == null) return; if (args?.repoPath == null || args?.ref == null) return;
const remote = await Container.git.getRichRemoteProvider(args.repoPath);
const remote = await Container.instance.git.getRichRemoteProvider(args.repoPath);
if (remote?.provider == null) return; if (remote?.provider == null) return;
const pr = await Container.git.getPullRequestForCommit(args.ref, remote.provider);
const pr = await Container.instance.git.getPullRequestForCommit(args.ref, remote.provider);
if (pr == null) return; if (pr == null) return;
args = { ...args }; args = { ...args };

+ 1
- 1
src/commands/openRevisionFile.ts View File

@ -36,7 +36,7 @@ export class OpenRevisionFileCommand extends ActiveEditorCommand {
try { try {
if (args.revisionUri == null) { if (args.revisionUri == null) {
if (gitUri?.sha) { if (gitUri?.sha) {
const commit = await Container.git.getCommit(gitUri.repoPath!, gitUri.sha);
const commit = await Container.instance.git.getCommit(gitUri.repoPath!, gitUri.sha);
args.revisionUri = args.revisionUri =
commit != null && commit.status === 'D' commit != null && commit.status === 'D'

+ 4
- 2
src/commands/openWorkingFile.ts View File

@ -36,7 +36,7 @@ export class OpenWorkingFileCommand extends ActiveEditorCommand {
args.uri = await GitUri.fromUri(uri); args.uri = await GitUri.fromUri(uri);
if (GitUri.is(args.uri) && args.uri.sha) { if (GitUri.is(args.uri) && args.uri.sha) {
const workingUri = await Container.git.getWorkingUri(args.uri.repoPath!, args.uri);
const workingUri = await Container.instance.git.getWorkingUri(args.uri.repoPath!, args.uri);
if (workingUri === undefined) { if (workingUri === undefined) {
void window.showWarningMessage( void window.showWarningMessage(
'Unable to open working file. File could not be found in the working tree', 'Unable to open working file. File could not be found in the working tree',
@ -58,7 +58,9 @@ export class OpenWorkingFileCommand extends ActiveEditorCommand {
const e = await findOrOpenEditor(args.uri, { ...args.showOptions, throwOnError: true }); const e = await findOrOpenEditor(args.uri, { ...args.showOptions, throwOnError: true });
if (args.annotationType === undefined) return; if (args.annotationType === undefined) return;
void (await Container.fileAnnotations.show(e, args.annotationType, { selection: { line: args.line } }));
void (await Container.instance.fileAnnotations.show(e, args.annotationType, {
selection: { line: args.line },
}));
} catch (ex) { } catch (ex) {
Logger.error(ex, 'OpenWorkingFileCommand'); Logger.error(ex, 'OpenWorkingFileCommand');
void Messages.showGenericErrorMessage('Unable to open working file'); void Messages.showGenericErrorMessage('Unable to open working file');

+ 8
- 6
src/commands/quickCommand.buttons.ts View File

@ -20,8 +20,8 @@ export class ToggleQuickInputButton implements QuickInputButton {
const icon = this.getToggledState().icon; const icon = this.getToggledState().icon;
return typeof icon === 'string' return typeof icon === 'string'
? { ? {
dark: Uri.file(Container.context.asAbsolutePath(`images/dark/${icon}.svg`)),
light: Uri.file(Container.context.asAbsolutePath(`images/light/${icon}.svg`)),
dark: Uri.file(Container.instance.context.asAbsolutePath(`images/dark/${icon}.svg`)),
light: Uri.file(Container.instance.context.asAbsolutePath(`images/light/${icon}.svg`)),
} }
: icon; : icon;
} }
@ -133,15 +133,17 @@ export namespace QuickCommandButtons {
on: { on: {
tooltip: 'Will confirm', tooltip: 'Will confirm',
icon: { icon: {
dark: Uri.file(Container.context.asAbsolutePath('images/dark/icon-check.svg')),
light: Uri.file(Container.context.asAbsolutePath('images/light/icon-check.svg')),
dark: Uri.file(Container.instance.context.asAbsolutePath('images/dark/icon-check.svg')),
light: Uri.file(Container.instance.context.asAbsolutePath('images/light/icon-check.svg')),
}, },
}, },
off: { off: {
tooltip: 'Skips confirm', tooltip: 'Skips confirm',
icon: { icon: {
dark: Uri.file(Container.context.asAbsolutePath('images/dark/icon-no-check.svg')),
light: Uri.file(Container.context.asAbsolutePath('images/light/icon-no-check.svg')),
dark: Uri.file(Container.instance.context.asAbsolutePath('images/dark/icon-no-check.svg')),
light: Uri.file(
Container.instance.context.asAbsolutePath('images/light/icon-no-check.svg'),
),
}, },
}, },
}), }),

+ 52
- 26
src/commands/quickCommand.steps.ts View File

@ -315,7 +315,7 @@ export function getValidateGitReferenceFn(
return true; return true;
} }
if (!(await Container.git.validateReference(repos.path, value))) {
if (!(await Container.instance.git.validateReference(repos.path, value))) {
if (inRefMode) { if (inRefMode) {
quickpick.items = [ quickpick.items = [
DirectiveQuickPickItem.create(Directive.Back, true, { DirectiveQuickPickItem.create(Directive.Back, true, {
@ -330,7 +330,7 @@ export function getValidateGitReferenceFn(
if (!inRefMode) { if (!inRefMode) {
if ( if (
await Container.git.hasBranchesAndOrTags(repos.path, {
await Container.instance.git.hasBranchesAndOrTags(repos.path, {
filter: { branches: b => b.name.includes(value), tags: t => t.name.includes(value) }, filter: { branches: b => b.name.includes(value), tags: t => t.name.includes(value) },
}) })
) { ) {
@ -338,7 +338,7 @@ export function getValidateGitReferenceFn(
} }
} }
const commit = await Container.git.getCommit(repos.path, value);
const commit = await Container.instance.git.getCommit(repos.path, value);
quickpick.items = [ quickpick.items = [
CommitQuickPickItem.create(commit!, true, { CommitQuickPickItem.create(commit!, true, {
alwaysShow: true, alwaysShow: true,
@ -370,8 +370,21 @@ export async function* inputBranchNameStep<
value = value.trim(); value = value.trim();
if (value.length === 0) return [false, 'Please enter a valid branch name']; if (value.length === 0) return [false, 'Please enter a valid branch name'];
const valid = await Container.git.validateBranchOrTagName(value);
return [valid, valid ? undefined : `'${value}' isn't a valid branch name`];
if ('repo' in state) {
const valid = await Container.instance.git.validateBranchOrTagName(state.repo.path, value);
return [valid, valid ? undefined : `'${value}' isn't a valid branch name`];
}
let valid = true;
for (const repo of state.repos) {
valid = await Container.instance.git.validateBranchOrTagName(repo.path, value);
if (!valid) {
return [false, `'${value}' isn't a valid branch name`];
}
}
return [true, undefined];
}, },
}); });
@ -405,8 +418,21 @@ export async function* inputTagNameStep<
value = value.trim(); value = value.trim();
if (value.length === 0) return [false, 'Please enter a valid tag name']; if (value.length === 0) return [false, 'Please enter a valid tag name'];
const valid = await Container.git.validateBranchOrTagName(value);
return [valid, valid ? undefined : `'${value}' isn't a valid tag name`];
if ('repo' in state) {
const valid = await Container.instance.git.validateBranchOrTagName(state.repo.path, value);
return [valid, valid ? undefined : `'${value}' isn't a valid tag name`];
}
let valid = true;
for (const repo of state.repos) {
valid = await Container.instance.git.validateBranchOrTagName(repo.path, value);
if (!valid) {
return [false, `'${value}' isn't a valid branch name`];
}
}
return [true, undefined];
}, },
}); });
@ -830,7 +856,7 @@ export async function* pickCommitStep<
break; break;
case QuickCommandButtons.SearchInSideBar: case QuickCommandButtons.SearchInSideBar:
void Container.searchAndCompareView.search(
void Container.instance.searchAndCompareView.search(
state.repo.path, state.repo.path,
{ pattern: SearchPattern.fromCommit(item.item.ref) }, { pattern: SearchPattern.fromCommit(item.item.ref) },
{ {
@ -874,7 +900,7 @@ export async function* pickCommitStep<
}); });
} else { } else {
const commit = items[0].item; const commit = items[0].item;
await Container.searchAndCompareView.search(
await Container.instance.searchAndCompareView.search(
commit.repoPath, commit.repoPath,
{ pattern: SearchPattern.fromCommit(commit) }, { pattern: SearchPattern.fromCommit(commit) },
{ {
@ -974,7 +1000,7 @@ export function* pickCommitsStep<
break; break;
case QuickCommandButtons.SearchInSideBar: case QuickCommandButtons.SearchInSideBar:
void Container.searchAndCompareView.search(
void Container.instance.searchAndCompareView.search(
state.repo.path, state.repo.path,
{ pattern: SearchPattern.fromCommit(item.ref) }, { pattern: SearchPattern.fromCommit(item.ref) },
{ {
@ -1003,7 +1029,7 @@ export function* pickCommitsStep<
}); });
} else { } else {
const commit = quickpick.activeItems[0].item; const commit = quickpick.activeItems[0].item;
await Container.searchAndCompareView.search(
await Container.instance.searchAndCompareView.search(
commit.repoPath, commit.repoPath,
{ pattern: SearchPattern.fromCommit(commit) }, { pattern: SearchPattern.fromCommit(commit) },
{ {
@ -1038,7 +1064,7 @@ export async function* pickContributorsStep<
multiselect: true, multiselect: true,
placeholder: placeholder, placeholder: placeholder,
matchOnDescription: true, matchOnDescription: true,
items: (await Container.git.getContributors(state.repo.path)).map(c =>
items: (await Container.instance.git.getContributors(state.repo.path)).map(c =>
ContributorQuickPickItem.create(c, message?.includes(c.toCoauthor())), ContributorQuickPickItem.create(c, message?.includes(c.toCoauthor())),
), ),
}); });
@ -1051,10 +1077,10 @@ export async function* pickRepositoryStep<
Context extends { repos: Repository[]; title: string }, Context extends { repos: Repository[]; title: string },
>(state: State, context: Context, placeholder: string = 'Choose a repository'): AsyncStepResultGenerator<Repository> { >(state: State, context: Context, placeholder: string = 'Choose a repository'): AsyncStepResultGenerator<Repository> {
if (typeof state.repo === 'string') { if (typeof state.repo === 'string') {
state.repo = await Container.git.getRepository(state.repo);
state.repo = await Container.instance.git.getRepository(state.repo);
if (state.repo != null) return state.repo; if (state.repo != null) return state.repo;
} }
const active = state.repo ?? (await Container.git.getActiveRepository());
const active = state.repo ?? (await Container.instance.git.getActiveRepository());
const step = QuickCommand.createPickStep<RepositoryQuickPickItem>({ const step = QuickCommand.createPickStep<RepositoryQuickPickItem>({
title: context.title, title: context.title,
@ -1074,7 +1100,7 @@ export async function* pickRepositoryStep<
), ),
onDidClickItemButton: (quickpick, button, { item }) => { onDidClickItemButton: (quickpick, button, { item }) => {
if (button === QuickCommandButtons.RevealInSideBar) { if (button === QuickCommandButtons.RevealInSideBar) {
void Container.repositoriesView.revealRepository(item.path, {
void Container.instance.repositoriesView.revealRepository(item.path, {
select: true, select: true,
expand: true, expand: true,
}); });
@ -1084,7 +1110,7 @@ export async function* pickRepositoryStep<
onDidPressKey: quickpick => { onDidPressKey: quickpick => {
if (quickpick.activeItems.length === 0) return; if (quickpick.activeItems.length === 0) return;
void Container.repositoriesView.revealRepository(quickpick.activeItems[0].item.path, {
void Container.instance.repositoriesView.revealRepository(quickpick.activeItems[0].item.path, {
select: true, select: true,
focus: false, focus: false,
expand: true, expand: true,
@ -1116,7 +1142,7 @@ export async function* pickRepositoriesStep<
actives = state.repos; actives = state.repos;
} }
} else { } else {
const active = await Container.git.getActiveRepository();
const active = await Container.instance.git.getActiveRepository();
actives = active != null ? [active] : []; actives = active != null ? [active] : [];
} }
@ -1143,7 +1169,7 @@ export async function* pickRepositoriesStep<
), ),
onDidClickItemButton: (quickpick, button, { item }) => { onDidClickItemButton: (quickpick, button, { item }) => {
if (button === QuickCommandButtons.RevealInSideBar) { if (button === QuickCommandButtons.RevealInSideBar) {
void Container.repositoriesView.revealRepository(item.path, {
void Container.instance.repositoriesView.revealRepository(item.path, {
select: true, select: true,
expand: true, expand: true,
}); });
@ -1153,7 +1179,7 @@ export async function* pickRepositoriesStep<
onDidPressKey: quickpick => { onDidPressKey: quickpick => {
if (quickpick.activeItems.length === 0) return; if (quickpick.activeItems.length === 0) return;
void Container.repositoriesView.revealRepository(quickpick.activeItems[0].item.path, {
void Container.instance.repositoriesView.revealRepository(quickpick.activeItems[0].item.path, {
select: true, select: true,
focus: false, focus: false,
expand: true, expand: true,
@ -1312,7 +1338,7 @@ export async function* showCommitOrStashStep<
: [QuickCommandButtons.RevealInSideBar, QuickCommandButtons.SearchInSideBar], : [QuickCommandButtons.RevealInSideBar, QuickCommandButtons.SearchInSideBar],
onDidClickButton: (quickpick, button) => { onDidClickButton: (quickpick, button) => {
if (button === QuickCommandButtons.SearchInSideBar) { if (button === QuickCommandButtons.SearchInSideBar) {
void Container.searchAndCompareView.search(
void Container.instance.searchAndCompareView.search(
state.repo.path, state.repo.path,
{ pattern: SearchPattern.fromCommit(state.reference.ref) }, { pattern: SearchPattern.fromCommit(state.reference.ref) },
{ {
@ -1360,7 +1386,7 @@ async function getShowCommitOrStashStepItems<
>(state: State) { >(state: State) {
const items: CommandQuickPickItem[] = [new CommitFilesQuickPickItem(state.reference)]; const items: CommandQuickPickItem[] = [new CommitFilesQuickPickItem(state.reference)];
const branch = await Container.git.getBranch(state.repo.path);
const branch = await Container.instance.git.getBranch(state.repo.path);
let remotes: GitRemote<RemoteProvider>[] | undefined; let remotes: GitRemote<RemoteProvider>[] | undefined;
let isStash = false; let isStash = false;
@ -1389,7 +1415,7 @@ async function getShowCommitOrStashStepItems<
}), }),
); );
} else { } else {
remotes = await Container.git.getRemotes(state.repo.path, { sort: true });
remotes = await Container.instance.git.getRemotes(state.repo.path, { sort: true });
items.push( items.push(
new RevealInSideBarQuickPickItem(state.reference), new RevealInSideBarQuickPickItem(state.reference),
@ -1398,7 +1424,7 @@ async function getShowCommitOrStashStepItems<
if ( if (
branch != null && branch != null &&
(await Container.git.branchContainsCommit(state.repo.path, branch.name, state.reference.ref))
(await Container.instance.git.branchContainsCommit(state.repo.path, branch.name, state.reference.ref))
) { ) {
items.push( items.push(
new GitCommandQuickPickItem('Revert Commit...', { new GitCommandQuickPickItem('Revert Commit...', {
@ -1567,7 +1593,7 @@ export function* showCommitOrStashFilesStep<
additionalButtons: [QuickCommandButtons.RevealInSideBar, QuickCommandButtons.SearchInSideBar], additionalButtons: [QuickCommandButtons.RevealInSideBar, QuickCommandButtons.SearchInSideBar],
onDidClickButton: (quickpick, button) => { onDidClickButton: (quickpick, button) => {
if (button === QuickCommandButtons.SearchInSideBar) { if (button === QuickCommandButtons.SearchInSideBar) {
void Container.searchAndCompareView.search(
void Container.instance.searchAndCompareView.search(
state.repo.path, state.repo.path,
{ pattern: SearchPattern.fromCommit(state.reference.ref) }, { pattern: SearchPattern.fromCommit(state.reference.ref) },
{ {
@ -1639,7 +1665,7 @@ export async function* showCommitOrStashFileStep<
additionalButtons: [QuickCommandButtons.RevealInSideBar, QuickCommandButtons.SearchInSideBar], additionalButtons: [QuickCommandButtons.RevealInSideBar, QuickCommandButtons.SearchInSideBar],
onDidClickButton: (quickpick, button) => { onDidClickButton: (quickpick, button) => {
if (button === QuickCommandButtons.SearchInSideBar) { if (button === QuickCommandButtons.SearchInSideBar) {
void Container.searchAndCompareView.search(
void Container.instance.searchAndCompareView.search(
state.repo.path, state.repo.path,
{ pattern: SearchPattern.fromCommit(state.reference.ref) }, { pattern: SearchPattern.fromCommit(state.reference.ref) },
{ {
@ -1704,7 +1730,7 @@ async function getShowCommitOrStashFileStepItems<
items.push(new RevealInSideBarQuickPickItem(state.reference)); items.push(new RevealInSideBarQuickPickItem(state.reference));
} else { } else {
remotes = await Container.git.getRemotes(state.repo.path, { sort: true });
remotes = await Container.instance.git.getRemotes(state.repo.path, { sort: true });
items.push( items.push(
new RevealInSideBarQuickPickItem(state.reference), new RevealInSideBarQuickPickItem(state.reference),

+ 1
- 1
src/commands/quickCommand.ts View File

@ -147,7 +147,7 @@ export abstract class QuickCommand implements QuickPickItem {
return override != null return override != null
? override ? override
: !Container.config.gitCommands.skipConfirmations.includes(this.skipConfirmKey);
: !Container.instance.config.gitCommands.skipConfirmations.includes(this.skipConfirmKey);
} }
isMatch(key: string) { isMatch(key: string) {

+ 2
- 2
src/commands/rebaseEditor.ts View File

@ -9,7 +9,7 @@ export class DisableRebaseEditorCommand extends Command {
} }
execute() { execute() {
return Container.rebaseEditor.setEnabled(false);
return Container.instance.rebaseEditor.setEnabled(false);
} }
} }
@ -20,6 +20,6 @@ export class EnableRebaseEditorCommand extends Command {
} }
execute() { execute() {
return Container.rebaseEditor.setEnabled(true);
return Container.instance.rebaseEditor.setEnabled(true);
} }
} }

+ 7
- 7
src/commands/remoteProviders.ts View File

@ -47,7 +47,7 @@ export class ConnectRemoteProviderCommand extends Command {
if (args?.repoPath == null) { if (args?.repoPath == null) {
const repos = new Map<Repository, GitRemote<RichRemoteProvider>>(); const repos = new Map<Repository, GitRemote<RichRemoteProvider>>();
for (const repo of await Container.git.getOrderedRepositories()) {
for (const repo of await Container.instance.git.getOrderedRepositories()) {
const remote = await repo.getRichRemote(); const remote = await repo.getRichRemote();
if (remote?.provider != null && !(await remote.provider.isConnected())) { if (remote?.provider != null && !(await remote.provider.isConnected())) {
repos.set(repo, remote); repos.set(repo, remote);
@ -73,18 +73,18 @@ export class ConnectRemoteProviderCommand extends Command {
} else if (args?.remote == null) { } else if (args?.remote == null) {
repoPath = args.repoPath; repoPath = args.repoPath;
remote = await Container.git.getRichRemoteProvider(repoPath, { includeDisconnected: true });
remote = await Container.instance.git.getRichRemoteProvider(repoPath, { includeDisconnected: true });
if (remote == null) return false; if (remote == null) return false;
} else { } else {
repoPath = args.repoPath; repoPath = args.repoPath;
remotes = await Container.git.getRemotes(repoPath);
remotes = await Container.instance.git.getRemotes(repoPath);
remote = remotes.find(r => r.id === args.remote) as GitRemote<RichRemoteProvider> | undefined; remote = remotes.find(r => r.id === args.remote) as GitRemote<RichRemoteProvider> | undefined;
if (!remote?.provider.hasApi()) return false; if (!remote?.provider.hasApi()) return false;
} }
const connected = await remote.provider.connect(); const connected = await remote.provider.connect();
if (connected && !(remotes ?? (await Container.git.getRemotes(repoPath))).some(r => r.default)) {
if (connected && !(remotes ?? (await Container.instance.git.getRemotes(repoPath))).some(r => r.default)) {
await remote.setAsDefault(true); await remote.setAsDefault(true);
} }
return connected; return connected;
@ -135,7 +135,7 @@ export class DisconnectRemoteProviderCommand extends Command {
if (args?.repoPath == null) { if (args?.repoPath == null) {
const repos = new Map<Repository, GitRemote<RichRemoteProvider>>(); const repos = new Map<Repository, GitRemote<RichRemoteProvider>>();
for (const repo of await Container.git.getOrderedRepositories()) {
for (const repo of await Container.instance.git.getOrderedRepositories()) {
const remote = await repo.getRichRemote(true); const remote = await repo.getRichRemote(true);
if (remote != null) { if (remote != null) {
repos.set(repo, remote); repos.set(repo, remote);
@ -161,12 +161,12 @@ export class DisconnectRemoteProviderCommand extends Command {
} else if (args?.remote == null) { } else if (args?.remote == null) {
repoPath = args.repoPath; repoPath = args.repoPath;
remote = await Container.git.getRichRemoteProvider(repoPath, { includeDisconnected: false });
remote = await Container.instance.git.getRichRemoteProvider(repoPath, { includeDisconnected: false });
if (remote == null) return undefined; if (remote == null) return undefined;
} else { } else {
repoPath = args.repoPath; repoPath = args.repoPath;
remote = (await Container.git.getRemotes(repoPath)).find(r => r.id === args.remote) as
remote = (await Container.instance.git.getRemotes(repoPath)).find(r => r.id === args.remote) as
| GitRemote<RichRemoteProvider> | GitRemote<RichRemoteProvider>
| undefined; | undefined;
if (!remote?.provider.hasApi()) return undefined; if (!remote?.provider.hasApi()) return undefined;

+ 12
- 3
src/commands/repositories.ts View File

@ -10,7 +10,10 @@ export class FetchRepositoriesCommand extends Command {
} }
async execute() { async execute() {
return executeGitCommand({ command: 'fetch', state: { repos: await Container.git.getOrderedRepositories() } });
return executeGitCommand({
command: 'fetch',
state: { repos: await Container.instance.git.getOrderedRepositories() },
});
} }
} }
@ -21,7 +24,10 @@ export class PullRepositoriesCommand extends Command {
} }
async execute() { async execute() {
return executeGitCommand({ command: 'pull', state: { repos: await Container.git.getOrderedRepositories() } });
return executeGitCommand({
command: 'pull',
state: { repos: await Container.instance.git.getOrderedRepositories() },
});
} }
} }
@ -32,6 +38,9 @@ export class PushRepositoriesCommand extends Command {
} }
async execute() { async execute() {
return executeGitCommand({ command: 'push', state: { repos: await Container.git.getOrderedRepositories() } });
return executeGitCommand({
command: 'push',
state: { repos: await Container.instance.git.getOrderedRepositories() },
});
} }
} }

+ 1
- 1
src/commands/searchCommits.ts View File

@ -50,7 +50,7 @@ export class SearchCommitsCommand extends Command {
repo: args?.repoPath, repo: args?.repoPath,
...args?.search, ...args?.search,
showResultsInSideBar: showResultsInSideBar:
Container.config.gitCommands.search.showResultsInSideBar ?? args?.showResultsInSideBar,
Container.instance.config.gitCommands.search.showResultsInSideBar ?? args?.showResultsInSideBar,
}, },
})); }));
} }

+ 2
- 2
src/commands/showCommitsInView.ts View File

@ -35,12 +35,12 @@ export class ShowCommitsInViewCommand extends ActiveEditorCommand {
try { try {
// Check for any uncommitted changes in the range // Check for any uncommitted changes in the range
const blame = editor.document.isDirty const blame = editor.document.isDirty
? await Container.git.getBlameForRangeContents(
? await Container.instance.git.getBlameForRangeContents(
gitUri, gitUri,
editor.selection, editor.selection,
editor.document.getText(), editor.document.getText(),
) )
: await Container.git.getBlameForRange(gitUri, editor.selection);
: await Container.instance.git.getBlameForRange(gitUri, editor.selection);
if (blame === undefined) { if (blame === undefined) {
return Messages.showFileNotUnderSourceControlWarningMessage('Unable to find commits'); return Messages.showFileNotUnderSourceControlWarningMessage('Unable to find commits');
} }

+ 1
- 1
src/commands/showQuickBranchHistory.ts View File

@ -32,7 +32,7 @@ export class ShowQuickBranchHistoryCommand extends ActiveEditorCachedCommand {
const gitUri = uri != null ? await GitUri.fromUri(uri) : undefined; const gitUri = uri != null ? await GitUri.fromUri(uri) : undefined;
const repoPath = args?.repoPath ?? gitUri?.repoPath ?? Container.git.getHighlanderRepoPath();
const repoPath = args?.repoPath ?? gitUri?.repoPath ?? Container.instance.git.getHighlanderRepoPath();
let ref: GitReference | 'HEAD' | undefined; let ref: GitReference | 'HEAD' | undefined;
if (repoPath != null) { if (repoPath != null) {
if (args?.branch != null) { if (args?.branch != null) {

+ 2
- 2
src/commands/showQuickCommit.ts View File

@ -89,7 +89,7 @@ export class ShowQuickCommitCommand extends ActiveEditorCachedCommand {
if (blameline < 0) return; if (blameline < 0) return;
try { try {
const blame = await Container.git.getBlameForLine(gitUri, blameline);
const blame = await Container.instance.git.getBlameForLine(gitUri, blameline);
if (blame == null) { if (blame == null) {
void Messages.showFileNotUnderSourceControlWarningMessage('Unable to show commit'); void Messages.showFileNotUnderSourceControlWarningMessage('Unable to show commit');
@ -126,7 +126,7 @@ export class ShowQuickCommitCommand extends ActiveEditorCachedCommand {
} }
if (args.repoLog == null) { if (args.repoLog == null) {
args.commit = await Container.git.getCommit(repoPath!, args.sha);
args.commit = await Container.instance.git.getCommit(repoPath!, args.sha);
} }
} }

+ 5
- 3
src/commands/showQuickCommitFile.ts View File

@ -78,7 +78,7 @@ export class ShowQuickCommitFileCommand extends ActiveEditorCachedCommand {
if (blameline < 0) return; if (blameline < 0) return;
try { try {
const blame = await Container.git.getBlameForLine(gitUri, blameline);
const blame = await Container.instance.git.getBlameForLine(gitUri, blameline);
if (blame == null) { if (blame == null) {
void Messages.showFileNotUnderSourceControlWarningMessage('Unable to show commit file details'); void Messages.showFileNotUnderSourceControlWarningMessage('Unable to show commit file details');
@ -115,7 +115,9 @@ export class ShowQuickCommitFileCommand extends ActiveEditorCachedCommand {
if (args.fileLog === undefined) { if (args.fileLog === undefined) {
const repoPath = args.commit === undefined ? gitUri.repoPath : args.commit.repoPath; const repoPath = args.commit === undefined ? gitUri.repoPath : args.commit.repoPath;
args.commit = await Container.git.getCommitForFile(repoPath, gitUri.fsPath, { ref: args.sha });
args.commit = await Container.instance.git.getCommitForFile(repoPath, gitUri.fsPath, {
ref: args.sha,
});
if (args.commit === undefined) { if (args.commit === undefined) {
void Messages.showCommitNotFoundWarningMessage('Unable to show commit file details'); void Messages.showCommitNotFoundWarningMessage('Unable to show commit file details');
@ -134,7 +136,7 @@ export class ShowQuickCommitFileCommand extends ActiveEditorCachedCommand {
const fileName = args.commit.fileName; const fileName = args.commit.fileName;
if (args.commit instanceof GitBlameCommit) { if (args.commit instanceof GitBlameCommit) {
args.commit = (await Container.git.getCommit(args.commit.repoPath, args.commit.ref))!;
args.commit = (await Container.instance.git.getCommit(args.commit.repoPath, args.commit.ref))!;
} }
void (await executeGitCommand({ void (await executeGitCommand({

+ 1
- 1
src/commands/showQuickFileHistory.ts View File

@ -50,7 +50,7 @@ export class ShowQuickFileHistoryCommand extends ActiveEditorCachedCommand {
const gitUri = await GitUri.fromUri(uri); const gitUri = await GitUri.fromUri(uri);
if (args?.showInSideBar) { if (args?.showInSideBar) {
await Container.fileHistoryView.showHistoryForUri(gitUri);
await Container.instance.fileHistoryView.showHistoryForUri(gitUri);
return; return;
} }

+ 11
- 11
src/commands/showView.ts View File

@ -29,28 +29,28 @@ export class ShowViewCommand extends Command {
async execute(command: Commands) { async execute(command: Commands) {
switch (command) { switch (command) {
case Commands.ShowBranchesView: case Commands.ShowBranchesView:
return Container.branchesView.show();
return Container.instance.branchesView.show();
case Commands.ShowCommitsView: case Commands.ShowCommitsView:
return Container.commitsView.show();
return Container.instance.commitsView.show();
case Commands.ShowContributorsView: case Commands.ShowContributorsView:
return Container.contributorsView.show();
return Container.instance.contributorsView.show();
case Commands.ShowFileHistoryView: case Commands.ShowFileHistoryView:
return Container.fileHistoryView.show();
return Container.instance.fileHistoryView.show();
case Commands.ShowLineHistoryView: case Commands.ShowLineHistoryView:
return Container.lineHistoryView.show();
return Container.instance.lineHistoryView.show();
case Commands.ShowRemotesView: case Commands.ShowRemotesView:
return Container.remotesView.show();
return Container.instance.remotesView.show();
case Commands.ShowRepositoriesView: case Commands.ShowRepositoriesView:
return Container.repositoriesView.show();
return Container.instance.repositoriesView.show();
case Commands.ShowSearchAndCompareView: case Commands.ShowSearchAndCompareView:
return Container.searchAndCompareView.show();
return Container.instance.searchAndCompareView.show();
case Commands.ShowStashesView: case Commands.ShowStashesView:
return Container.stashesView.show();
return Container.instance.stashesView.show();
case Commands.ShowTagsView: case Commands.ShowTagsView:
return Container.tagsView.show();
return Container.instance.tagsView.show();
case Commands.ShowWelcomeView: case Commands.ShowWelcomeView:
await setContext(ContextKeys.ViewsWelcomeVisible, true); await setContext(ContextKeys.ViewsWelcomeVisible, true);
void Container.context.globalState.update(SyncedState.WelcomeViewVisible, true);
void Container.instance.context.globalState.update(SyncedState.WelcomeViewVisible, true);
void (await commands.executeCommand('gitlens.views.welcome.focus')); void (await commands.executeCommand('gitlens.views.welcome.focus'));
} }

+ 4
- 4
src/commands/stashSave.ts View File

@ -46,9 +46,9 @@ export class StashSaveCommand extends Command {
} else if (context.type === 'scm-states') { } else if (context.type === 'scm-states') {
args = { ...args }; args = { ...args };
args.uris = context.scmResourceStates.map(s => s.resourceUri); args.uris = context.scmResourceStates.map(s => s.resourceUri);
args.repoPath = await Container.git.getRepoPath(args.uris[0].fsPath);
args.repoPath = await Container.instance.git.getRepoPath(args.uris[0].fsPath);
const status = await Container.git.getStatusForRepo(args.repoPath);
const status = await Container.instance.git.getStatusForRepo(args.repoPath);
if (status?.computeWorkingTreeStatus().staged) { if (status?.computeWorkingTreeStatus().staged) {
if (!context.scmResourceStates.some(s => (s as any).resourceGroupType === ResourceGroupType.Index)) { if (!context.scmResourceStates.some(s => (s as any).resourceGroupType === ResourceGroupType.Index)) {
args.keepStaged = true; args.keepStaged = true;
@ -60,9 +60,9 @@ export class StashSaveCommand extends Command {
(a, b) => a.concat(b.resourceStates.map(s => s.resourceUri)), (a, b) => a.concat(b.resourceStates.map(s => s.resourceUri)),
[], [],
); );
args.repoPath = await Container.git.getRepoPath(args.uris[0].fsPath);
args.repoPath = await Container.instance.git.getRepoPath(args.uris[0].fsPath);
const status = await Container.git.getStatusForRepo(args.repoPath);
const status = await Container.instance.git.getStatusForRepo(args.repoPath);
if (status?.computeWorkingTreeStatus().staged) { if (status?.computeWorkingTreeStatus().staged) {
if (!context.scmResourceGroups.some(g => g.id === 'index')) { if (!context.scmResourceGroups.some(g => g.id === 'index')) {
args.keepStaged = true; args.keepStaged = true;

+ 16
- 8
src/commands/switchMode.ts View File

@ -24,16 +24,17 @@ export class SwitchModeCommand extends Command {
cc.exitDetails = ` \u2014 mode=${pick.key ?? ''}`; cc.exitDetails = ` \u2014 mode=${pick.key ?? ''}`;
} }
const active = Container.config.mode.active;
const active = Container.instance.config.mode.active;
if (active === pick.key) return; if (active === pick.key) return;
// Check if we have applied any annotations and clear them if we won't be applying them again // Check if we have applied any annotations and clear them if we won't be applying them again
if (active != null && active.length !== 0) { if (active != null && active.length !== 0) {
const activeAnnotations = Container.config.modes?.[active].annotations;
const activeAnnotations = Container.instance.config.modes?.[active].annotations;
if (activeAnnotations != null) { if (activeAnnotations != null) {
const newAnnotations = pick.key != null ? Container.config.modes?.[pick.key].annotations : undefined;
const newAnnotations =
pick.key != null ? Container.instance.config.modes?.[pick.key].annotations : undefined;
if (activeAnnotations !== newAnnotations) { if (activeAnnotations !== newAnnotations) {
await Container.fileAnnotations.clearAll();
await Container.instance.fileAnnotations.clearAll();
} }
} }
} }
@ -50,9 +51,14 @@ export class ToggleReviewModeCommand extends Command {
@log({ args: false, singleLine: true, timed: false }) @log({ args: false, singleLine: true, timed: false })
async execute() { async execute() {
if (Container.config.modes == null || !Object.keys(Container.config.modes).includes('review')) return;
if (
Container.instance.config.modes == null ||
!Object.keys(Container.instance.config.modes).includes('review')
) {
return;
}
const mode = Container.config.mode.active === 'review' ? undefined : 'review';
const mode = Container.instance.config.mode.active === 'review' ? undefined : 'review';
await configuration.update('mode.active', mode, ConfigurationTarget.Global); await configuration.update('mode.active', mode, ConfigurationTarget.Global);
} }
} }
@ -65,9 +71,11 @@ export class ToggleZenModeCommand extends Command {
@log({ args: false, singleLine: true, timed: false }) @log({ args: false, singleLine: true, timed: false })
async execute() { async execute() {
if (Container.config.modes == null || !Object.keys(Container.config.modes).includes('zen')) return;
if (Container.instance.config.modes == null || !Object.keys(Container.instance.config.modes).includes('zen')) {
return;
}
const mode = Container.config.mode.active === 'zen' ? undefined : 'zen';
const mode = Container.instance.config.mode.active === 'zen' ? undefined : 'zen';
await configuration.update('mode.active', mode, ConfigurationTarget.Global); await configuration.update('mode.active', mode, ConfigurationTarget.Global);
} }
} }

+ 1
- 1
src/commands/toggleCodeLens.ts View File

@ -9,6 +9,6 @@ export class ToggleCodeLensCommand extends Command {
} }
execute() { execute() {
return Container.codeLens.toggleCodeLens();
return Container.instance.codeLens.toggleCodeLens();
} }
} }

+ 2
- 2
src/commands/toggleFileAnnotations.ts View File

@ -28,7 +28,7 @@ export class ClearFileAnnotationsCommand extends EditorCommand {
} }
try { try {
void (await Container.fileAnnotations.clear(editor));
void (await Container.instance.fileAnnotations.clear(editor));
} catch (ex) { } catch (ex) {
Logger.error(ex, 'ClearFileAnnotationsCommand'); Logger.error(ex, 'ClearFileAnnotationsCommand');
void Messages.showGenericErrorMessage('Unable to clear file annotations'); void Messages.showGenericErrorMessage('Unable to clear file annotations');
@ -123,7 +123,7 @@ async function toggleFileAnnotations
try { try {
args = { type: FileAnnotationType.Blame, ...(args as any) }; args = { type: FileAnnotationType.Blame, ...(args as any) };
void (await Container.fileAnnotations.toggle(
void (await Container.instance.fileAnnotations.toggle(
editor, editor,
args.type, args.type,
{ {

+ 1
- 1
src/commands/toggleLineBlame.ts View File

@ -11,7 +11,7 @@ export class ToggleLineBlameCommand extends ActiveEditorCommand {
async execute(editor: TextEditor, _uri?: Uri): Promise<void> { async execute(editor: TextEditor, _uri?: Uri): Promise<void> {
try { try {
void (await Container.lineAnnotations.toggle(editor));
void (await Container.instance.lineAnnotations.toggle(editor));
} catch (ex) { } catch (ex) {
Logger.error(ex, 'ToggleLineBlameCommand'); Logger.error(ex, 'ToggleLineBlameCommand');
void window.showErrorMessage( void window.showErrorMessage(

+ 155
- 118
src/container.ts View File

@ -1,5 +1,5 @@
'use strict'; 'use strict';
import { commands, ConfigurationChangeEvent, ConfigurationScope, ExtensionContext } from 'vscode';
import { commands, ConfigurationChangeEvent, ConfigurationScope, Event, EventEmitter, ExtensionContext } from 'vscode';
import { Autolinks } from './annotations/autolinks'; import { Autolinks } from './annotations/autolinks';
import { FileAnnotationController } from './annotations/fileAnnotationController'; import { FileAnnotationController } from './annotations/fileAnnotationController';
import { LineAnnotationController } from './annotations/lineAnnotationController'; import { LineAnnotationController } from './annotations/lineAnnotationController';
@ -42,53 +42,81 @@ import { SettingsWebview } from './webviews/settingsWebview';
import { WelcomeWebview } from './webviews/welcomeWebview'; import { WelcomeWebview } from './webviews/welcomeWebview';
export class Container { export class Container {
private static _configsAffectedByMode: string[] | undefined;
private static _applyModeConfigurationTransformBound:
static #instance: Container | undefined;
static #proxy = new Proxy<Container>({} as Container, {
get: function (target, prop) {
// In case anyone has cached this instance
if (Container.#instance != null) return (Container.#instance as any)[prop];
// Allow access to config before we are initialized
if (prop === 'config') return configuration.get();
// debugger;
throw new Error('Container is not initialized');
},
});
static create(context: ExtensionContext, cfg: Config) {
if (Container.#instance != null) throw new Error('Container is already initialized');
Container.#instance = new Container(context, cfg);
return Container.#instance;
}
static get instance(): Container {
return Container.#instance ?? Container.#proxy;
}
private _onReady: EventEmitter<void> = new EventEmitter<void>();
get onReady(): Event<void> {
return this._onReady.event;
}
private _configsAffectedByMode: string[] | undefined;
private _applyModeConfigurationTransformBound:
| ((e: ConfigurationChangeEvent) => ConfigurationChangeEvent) | ((e: ConfigurationChangeEvent) => ConfigurationChangeEvent)
| undefined; | undefined;
private static _terminalLinks: GitTerminalLinkProvider | undefined;
private _terminalLinks: GitTerminalLinkProvider | undefined;
static initialize(context: ExtensionContext, config: Config) {
private constructor(context: ExtensionContext, config: Config) {
this._context = context; this._context = context;
this._config = Container.applyMode(config);
this._config = this.applyMode(config);
context.subscriptions.push(configuration.onWillChange(this.onConfigurationChanging, this));
context.subscriptions.push((this._actionRunners = new ActionRunners()));
context.subscriptions.push((this._lineTracker = new GitLineTracker()));
context.subscriptions.push((this._tracker = new GitDocumentTracker()));
context.subscriptions.push((this._vsls = new VslsController()));
context.subscriptions.push((this._git = new GitService(this)));
context.subscriptions.push(new GitFileSystemProvider(this));
context.subscriptions.push((this._git = new GitService()));
context.subscriptions.push((this._actionRunners = new ActionRunners(this)));
context.subscriptions.push((this._tracker = new GitDocumentTracker(this)));
context.subscriptions.push((this._lineTracker = new GitLineTracker(this)));
context.subscriptions.push((this._keyboard = new Keyboard()));
context.subscriptions.push((this._vsls = new VslsController(this)));
context.subscriptions.push(new ViewFileDecorationProvider());
context.subscriptions.push((this._fileAnnotationController = new FileAnnotationController(this)));
context.subscriptions.push((this._lineAnnotationController = new LineAnnotationController(this)));
context.subscriptions.push((this._lineHoverController = new LineHoverController(this)));
context.subscriptions.push((this._statusBarController = new StatusBarController(this)));
context.subscriptions.push((this._codeLensController = new GitCodeLensController(this)));
// Since there is a bit of a chicken & egg problem with the DocumentTracker and the GitService, initialize the tracker once the GitService is loaded
this._tracker.initialize();
context.subscriptions.push((this._settingsWebview = new SettingsWebview(this)));
context.subscriptions.push((this._welcomeWebview = new WelcomeWebview(this)));
context.subscriptions.push((this._rebaseEditor = new RebaseEditorProvider(this)));
context.subscriptions.push((this._fileAnnotationController = new FileAnnotationController()));
context.subscriptions.push((this._lineAnnotationController = new LineAnnotationController()));
context.subscriptions.push((this._lineHoverController = new LineHoverController()));
context.subscriptions.push((this._statusBarController = new StatusBarController()));
context.subscriptions.push((this._codeLensController = new GitCodeLensController()));
context.subscriptions.push((this._keyboard = new Keyboard()));
context.subscriptions.push((this._settingsWebview = new SettingsWebview()));
context.subscriptions.push((this._welcomeWebview = new WelcomeWebview()));
context.subscriptions.push((this._repositoriesView = new RepositoriesView()));
context.subscriptions.push((this._commitsView = new CommitsView()));
context.subscriptions.push((this._fileHistoryView = new FileHistoryView()));
context.subscriptions.push((this._lineHistoryView = new LineHistoryView()));
context.subscriptions.push((this._branchesView = new BranchesView()));
context.subscriptions.push((this._remotesView = new RemotesView()));
context.subscriptions.push((this._stashesView = new StashesView()));
context.subscriptions.push((this._tagsView = new TagsView()));
context.subscriptions.push((this._contributorsView = new ContributorsView()));
context.subscriptions.push((this._searchAndCompareView = new SearchAndCompareView()));
context.subscriptions.push((this._rebaseEditor = new RebaseEditorProvider()));
context.subscriptions.push(new ViewFileDecorationProvider());
context.subscriptions.push((this._repositoriesView = new RepositoriesView(this)));
context.subscriptions.push((this._commitsView = new CommitsView(this)));
context.subscriptions.push((this._fileHistoryView = new FileHistoryView(this)));
context.subscriptions.push((this._lineHistoryView = new LineHistoryView(this)));
context.subscriptions.push((this._branchesView = new BranchesView(this)));
context.subscriptions.push((this._remotesView = new RemotesView(this)));
context.subscriptions.push((this._stashesView = new StashesView(this)));
context.subscriptions.push((this._tagsView = new TagsView(this)));
context.subscriptions.push((this._contributorsView = new ContributorsView(this)));
context.subscriptions.push((this._searchAndCompareView = new SearchAndCompareView(this)));
if (config.terminalLinks.enabled) { if (config.terminalLinks.enabled) {
context.subscriptions.push((this._terminalLinks = new GitTerminalLinkProvider()));
context.subscriptions.push((this._terminalLinks = new GitTerminalLinkProvider(this)));
} }
context.subscriptions.push( context.subscriptions.push(
@ -96,18 +124,22 @@ export class Container {
if (!configuration.changed(e, 'terminalLinks.enabled')) return; if (!configuration.changed(e, 'terminalLinks.enabled')) return;
this._terminalLinks?.dispose(); this._terminalLinks?.dispose();
if (Container.config.terminalLinks.enabled) {
context.subscriptions.push((this._terminalLinks = new GitTerminalLinkProvider()));
if (this.config.terminalLinks.enabled) {
context.subscriptions.push((this._terminalLinks = new GitTerminalLinkProvider(this)));
} }
}), }),
); );
}
context.subscriptions.push(new GitFileSystemProvider());
private _ready: boolean = false;
ready() {
if (this._ready) throw new Error('Container is already ready');
context.subscriptions.push(configuration.onWillChange(this.onConfigurationChanging, this));
this._ready = true;
this._onReady.fire();
} }
private static onConfigurationChanging(e: ConfigurationWillChangeEvent) {
private onConfigurationChanging(e: ConfigurationWillChangeEvent) {
this._config = undefined; this._config = undefined;
if (configuration.changed(e.change, 'outputLevel')) { if (configuration.changed(e.change, 'outputLevel')) {
@ -126,90 +158,90 @@ export class Container {
} }
} }
private static _actionRunners: ActionRunners;
static get actionRunners() {
private _actionRunners: ActionRunners;
get actionRunners() {
if (this._actionRunners == null) { if (this._actionRunners == null) {
this._context.subscriptions.push((this._actionRunners = new ActionRunners()));
this._context.subscriptions.push((this._actionRunners = new ActionRunners(this)));
} }
return this._actionRunners; return this._actionRunners;
} }
private static _autolinks: Autolinks;
static get autolinks() {
private _autolinks: Autolinks | undefined;
get autolinks() {
if (this._autolinks == null) { if (this._autolinks == null) {
this._context.subscriptions.push((this._autolinks = new Autolinks()));
this._context.subscriptions.push((this._autolinks = new Autolinks(this)));
} }
return this._autolinks; return this._autolinks;
} }
private static _codeLensController: GitCodeLensController;
static get codeLens() {
private _codeLensController: GitCodeLensController;
get codeLens() {
return this._codeLensController; return this._codeLensController;
} }
private static _branchesView: BranchesView | undefined;
static get branchesView() {
private _branchesView: BranchesView | undefined;
get branchesView() {
if (this._branchesView == null) { if (this._branchesView == null) {
this._context.subscriptions.push((this._branchesView = new BranchesView()));
this._context.subscriptions.push((this._branchesView = new BranchesView(this)));
} }
return this._branchesView; return this._branchesView;
} }
private static _commitsView: CommitsView | undefined;
static get commitsView() {
private _commitsView: CommitsView | undefined;
get commitsView() {
if (this._commitsView == null) { if (this._commitsView == null) {
this._context.subscriptions.push((this._commitsView = new CommitsView()));
this._context.subscriptions.push((this._commitsView = new CommitsView(this)));
} }
return this._commitsView; return this._commitsView;
} }
private static _config: Config | undefined;
static get config() {
private _config: Config | undefined;
get config() {
if (this._config == null) { if (this._config == null) {
this._config = Container.applyMode(configuration.get());
this._config = this.applyMode(configuration.get());
} }
return this._config; return this._config;
} }
private static _context: ExtensionContext;
static get context() {
private _context: ExtensionContext;
get context() {
return this._context; return this._context;
} }
private static _contributorsView: ContributorsView | undefined;
static get contributorsView() {
private _contributorsView: ContributorsView | undefined;
get contributorsView() {
if (this._contributorsView == null) { if (this._contributorsView == null) {
this._context.subscriptions.push((this._contributorsView = new ContributorsView()));
this._context.subscriptions.push((this._contributorsView = new ContributorsView(this)));
} }
return this._contributorsView; return this._contributorsView;
} }
private static _fileAnnotationController: FileAnnotationController;
static get fileAnnotations() {
private _fileAnnotationController: FileAnnotationController;
get fileAnnotations() {
return this._fileAnnotationController; return this._fileAnnotationController;
} }
private static _fileHistoryView: FileHistoryView | undefined;
static get fileHistoryView() {
private _fileHistoryView: FileHistoryView | undefined;
get fileHistoryView() {
if (this._fileHistoryView == null) { if (this._fileHistoryView == null) {
this._context.subscriptions.push((this._fileHistoryView = new FileHistoryView()));
this._context.subscriptions.push((this._fileHistoryView = new FileHistoryView(this)));
} }
return this._fileHistoryView; return this._fileHistoryView;
} }
private static _git: GitService;
static get git() {
private _git: GitService;
get git() {
return this._git; return this._git;
} }
private static _github: Promise<import('./github/github').GitHubApi | undefined> | undefined;
static get github() {
private _github: Promise<import('./github/github').GitHubApi | undefined> | undefined;
get github() {
if (this._github == null) { if (this._github == null) {
this._github = this._loadGitHubApi(); this._github = this._loadGitHubApi();
} }
@ -217,7 +249,7 @@ export class Container {
return this._github; return this._github;
} }
private static async _loadGitHubApi() {
private async _loadGitHubApi() {
try { try {
return new (await import(/* webpackChunkName: "github" */ './github/github')).GitHubApi(); return new (await import(/* webpackChunkName: "github" */ './github/github')).GitHubApi();
} catch (ex) { } catch (ex) {
@ -227,127 +259,132 @@ export class Container {
} }
@memoize() @memoize()
static get insiders() {
get insiders() {
return this._context.extension.id.endsWith('-insiders'); return this._context.extension.id.endsWith('-insiders');
} }
private static _keyboard: Keyboard;
static get keyboard() {
private _keyboard: Keyboard;
get keyboard() {
return this._keyboard; return this._keyboard;
} }
private static _lineAnnotationController: LineAnnotationController;
static get lineAnnotations() {
private _lineAnnotationController: LineAnnotationController;
get lineAnnotations() {
return this._lineAnnotationController; return this._lineAnnotationController;
} }
private static _lineHistoryView: LineHistoryView | undefined;
static get lineHistoryView() {
private _lineHistoryView: LineHistoryView | undefined;
get lineHistoryView() {
if (this._lineHistoryView == null) { if (this._lineHistoryView == null) {
this._context.subscriptions.push((this._lineHistoryView = new LineHistoryView()));
this._context.subscriptions.push((this._lineHistoryView = new LineHistoryView(this)));
} }
return this._lineHistoryView; return this._lineHistoryView;
} }
private static _lineHoverController: LineHoverController;
static get lineHovers() {
private _lineHoverController: LineHoverController;
get lineHovers() {
return this._lineHoverController; return this._lineHoverController;
} }
private static _lineTracker: GitLineTracker;
static get lineTracker() {
private _lineTracker: GitLineTracker;
get lineTracker() {
return this._lineTracker; return this._lineTracker;
} }
private static _rebaseEditor: RebaseEditorProvider | undefined;
static get rebaseEditor() {
private _rebaseEditor: RebaseEditorProvider | undefined;
get rebaseEditor() {
if (this._rebaseEditor == null) { if (this._rebaseEditor == null) {
this._context.subscriptions.push((this._rebaseEditor = new RebaseEditorProvider()));
this._context.subscriptions.push((this._rebaseEditor = new RebaseEditorProvider(this)));
} }
return this._rebaseEditor; return this._rebaseEditor;
} }
private static _remotesView: RemotesView | undefined;
static get remotesView() {
private _remotesView: RemotesView | undefined;
get remotesView() {
if (this._remotesView == null) { if (this._remotesView == null) {
this._context.subscriptions.push((this._remotesView = new RemotesView()));
this._context.subscriptions.push((this._remotesView = new RemotesView(this)));
} }
return this._remotesView; return this._remotesView;
} }
private static _repositoriesView: RepositoriesView | undefined;
static get repositoriesView(): RepositoriesView {
private _repositoriesView: RepositoriesView | undefined;
get repositoriesView(): RepositoriesView {
if (this._repositoriesView == null) { if (this._repositoriesView == null) {
this._context.subscriptions.push((this._repositoriesView = new RepositoriesView()));
this._context.subscriptions.push((this._repositoriesView = new RepositoriesView(this)));
} }
return this._repositoriesView; return this._repositoriesView;
} }
private static _searchAndCompareView: SearchAndCompareView | undefined;
static get searchAndCompareView() {
private _searchAndCompareView: SearchAndCompareView | undefined;
get searchAndCompareView() {
if (this._searchAndCompareView == null) { if (this._searchAndCompareView == null) {
this._context.subscriptions.push((this._searchAndCompareView = new SearchAndCompareView()));
this._context.subscriptions.push((this._searchAndCompareView = new SearchAndCompareView(this)));
} }
return this._searchAndCompareView; return this._searchAndCompareView;
} }
private static _settingsWebview: SettingsWebview;
static get settingsWebview() {
private _settingsWebview: SettingsWebview;
get settingsWebview() {
return this._settingsWebview; return this._settingsWebview;
} }
private static _stashesView: StashesView | undefined;
static get stashesView() {
private _stashesView: StashesView | undefined;
get stashesView() {
if (this._stashesView == null) { if (this._stashesView == null) {
this._context.subscriptions.push((this._stashesView = new StashesView()));
this._context.subscriptions.push((this._stashesView = new StashesView(this)));
} }
return this._stashesView; return this._stashesView;
} }
private static _statusBarController: StatusBarController;
static get statusBar() {
private _statusBarController: StatusBarController;
get statusBar() {
return this._statusBarController; return this._statusBarController;
} }
private static _tagsView: TagsView | undefined;
static get tagsView() {
private _tagsView: TagsView | undefined;
get tagsView() {
if (this._tagsView == null) { if (this._tagsView == null) {
this._context.subscriptions.push((this._tagsView = new TagsView()));
this._context.subscriptions.push((this._tagsView = new TagsView(this)));
} }
return this._tagsView; return this._tagsView;
} }
private static _tracker: GitDocumentTracker;
static get tracker() {
private _tracker: GitDocumentTracker;
get tracker() {
return this._tracker; return this._tracker;
} }
private static _viewCommands: ViewCommands | undefined;
static get viewCommands() {
@memoize()
get version(): string {
return this.context.extension.packageJSON.version;
}
private _viewCommands: ViewCommands | undefined;
get viewCommands() {
if (this._viewCommands == null) { if (this._viewCommands == null) {
this._viewCommands = new ViewCommands();
this._viewCommands = new ViewCommands(this);
} }
return this._viewCommands; return this._viewCommands;
} }
private static _vsls: VslsController;
static get vsls() {
private _vsls: VslsController;
get vsls() {
return this._vsls; return this._vsls;
} }
private static _welcomeWebview: WelcomeWebview;
static get welcomeWebview() {
private _welcomeWebview: WelcomeWebview;
get welcomeWebview() {
return this._welcomeWebview; return this._welcomeWebview;
} }
private static applyMode(config: Config) {
private applyMode(config: Config) {
if (!config.mode.active) return config; if (!config.mode.active) return config;
const mode = config.modes?.[config.mode.active]; const mode = config.modes?.[config.mode.active];
@ -399,7 +436,7 @@ export class Container {
return config; return config;
} }
private static applyModeConfigurationTransform(e: ConfigurationChangeEvent): ConfigurationChangeEvent {
private applyModeConfigurationTransform(e: ConfigurationChangeEvent): ConfigurationChangeEvent {
if (this._configsAffectedByMode == null) { if (this._configsAffectedByMode == null) {
this._configsAffectedByMode = [ this._configsAffectedByMode = [
`gitlens.${configuration.name('mode')}`, `gitlens.${configuration.name('mode')}`,

+ 33
- 37
src/extension.ts View File

@ -17,13 +17,9 @@ import { registerPartnerActionRunners } from './partners';
import { Strings, Versions } from './system'; import { Strings, Versions } from './system';
import { ViewNode } from './views/nodes'; import { ViewNode } from './views/nodes';
let _context: ExtensionContext | undefined;
export async function activate(context: ExtensionContext): Promise<GitLensApi | undefined> { export async function activate(context: ExtensionContext): Promise<GitLensApi | undefined> {
const start = process.hrtime(); const start = process.hrtime();
_context = context;
if (context.extension.id === 'eamodio.gitlens-insiders') { if (context.extension.id === 'eamodio.gitlens-insiders') {
// Ensure that stable isn't also installed // Ensure that stable isn't also installed
const stable = extensions.getExtension('eamodio.gitlens'); const stable = extensions.getExtension('eamodio.gitlens');
@ -47,7 +43,7 @@ export async function activate(context: ExtensionContext): Promise
); );
} }
setKeysForSync();
setKeysForSync(context);
Logger.configure(context, configuration.get('outputLevel'), o => { Logger.configure(context, configuration.get('outputLevel'), o => {
if (GitUri.is(o)) { if (GitUri.is(o)) {
@ -112,13 +108,13 @@ export async function activate(context: ExtensionContext): Promise
} }
Configuration.configure(context); Configuration.configure(context);
const cfg = configuration.get(); const cfg = configuration.get();
// await migrateSettings(context, previousVersion); // await migrateSettings(context, previousVersion);
try { try {
await GitService.initialize();
// Try to use the same git as the built-in vscode git extension
const gitApi = await GitService.getBuiltInGitApi();
await Git.setOrFindGitPath(gitApi?.git.path ?? configuration.getAny<string | string[]>('git.path'));
} catch (ex) { } catch (ex) {
Logger.error(ex, `GitLens (v${gitlensVersion}) activate`); Logger.error(ex, `GitLens (v${gitlensVersion}) activate`);
void setEnabled(false); void setEnabled(false);
@ -137,16 +133,16 @@ export async function activate(context: ExtensionContext): Promise
return undefined; return undefined;
} }
Container.initialize(context, cfg);
const container = Container.create(context, cfg);
// Signal that the container is now ready
container.ready();
registerCommands(context); registerCommands(context);
registerBuiltInActionRunners(context);
registerBuiltInActionRunners(container);
registerPartnerActionRunners(context); registerPartnerActionRunners(context);
const gitVersion = Git.getGitVersion();
notifyOnUnsupportedGitVersion(gitVersion);
void showWelcomeOrWhatsNew(context, gitlensVersion, previousVersion);
notifyOnUnsupportedGitVersion(Git.getGitVersion());
void showWelcomeOrWhatsNew(container, gitlensVersion, previousVersion);
void context.globalState.update(GlobalState.Version, gitlensVersion); void context.globalState.update(GlobalState.Version, gitlensVersion);
@ -171,7 +167,7 @@ export async function activate(context: ExtensionContext): Promise
} ${Strings.getDurationMilliseconds(start)} ms`, } ${Strings.getDurationMilliseconds(start)} ms`,
); );
const api = new Api();
const api = new Api(container);
return api; return api;
} }
@ -196,20 +192,20 @@ export async function setEnabled(enabled: boolean): Promise {
await Promise.all([setContext(ContextKeys.Enabled, enabled), setContext(ContextKeys.Disabled, !enabled)]); await Promise.all([setContext(ContextKeys.Enabled, enabled), setContext(ContextKeys.Disabled, !enabled)]);
} }
export function setKeysForSync(...keys: (SyncedState | string)[]) {
return _context?.globalState?.setKeysForSync([...keys, SyncedState.Version, SyncedState.WelcomeViewVisible]);
function setKeysForSync(context: ExtensionContext, ...keys: (SyncedState | string)[]) {
return context.globalState?.setKeysForSync([...keys, SyncedState.Version, SyncedState.WelcomeViewVisible]);
} }
export function notifyOnUnsupportedGitVersion(version: string) {
function notifyOnUnsupportedGitVersion(version: string) {
if (GitService.compareGitVersion('2.7.2') !== -1) return; if (GitService.compareGitVersion('2.7.2') !== -1) return;
// If git is less than v2.7.2 // If git is less than v2.7.2
void Messages.showGitVersionUnsupportedErrorMessage(version, '2.7.2'); void Messages.showGitVersionUnsupportedErrorMessage(version, '2.7.2');
} }
function registerBuiltInActionRunners(context: ExtensionContext): void {
context.subscriptions.push(
Container.actionRunners.registerBuiltIn<CreatePullRequestActionContext>('createPullRequest', {
function registerBuiltInActionRunners(container: Container): void {
container.context.subscriptions.push(
container.actionRunners.registerBuiltIn<CreatePullRequestActionContext>('createPullRequest', {
label: ctx => `Create Pull Request on ${ctx.remote?.provider?.name ?? 'Remote'}`, label: ctx => `Create Pull Request on ${ctx.remote?.provider?.name ?? 'Remote'}`,
run: async ctx => { run: async ctx => {
if (ctx.type !== 'createPullRequest') return; if (ctx.type !== 'createPullRequest') return;
@ -226,7 +222,7 @@ function registerBuiltInActionRunners(context: ExtensionContext): void {
})); }));
}, },
}), }),
Container.actionRunners.registerBuiltIn<OpenPullRequestActionContext>('openPullRequest', {
container.actionRunners.registerBuiltIn<OpenPullRequestActionContext>('openPullRequest', {
label: ctx => `Open Pull Request on ${ctx.provider?.name ?? 'Remote'}`, label: ctx => `Open Pull Request on ${ctx.provider?.name ?? 'Remote'}`,
run: async ctx => { run: async ctx => {
if (ctx.type !== 'openPullRequest') return; if (ctx.type !== 'openPullRequest') return;
@ -239,31 +235,31 @@ function registerBuiltInActionRunners(context: ExtensionContext): void {
); );
} }
async function showWelcomeOrWhatsNew(context: ExtensionContext, version: string, previousVersion: string | undefined) {
async function showWelcomeOrWhatsNew(container: Container, version: string, previousVersion: string | undefined) {
if (previousVersion == null) { if (previousVersion == null) {
Logger.log(`GitLens first-time install; window.focused=${window.state.focused}`); Logger.log(`GitLens first-time install; window.focused=${window.state.focused}`);
if (Container.config.showWelcomeOnInstall === false) return;
if (container.config.showWelcomeOnInstall === false) return;
if (window.state.focused) { if (window.state.focused) {
await context.globalState.update(GlobalState.PendingWelcomeOnFocus, undefined);
await container.context.globalState.update(GlobalState.PendingWelcomeOnFocus, undefined);
await commands.executeCommand(Commands.ShowWelcomePage); await commands.executeCommand(Commands.ShowWelcomePage);
} else { } else {
// Save pending on window getting focus // Save pending on window getting focus
await context.globalState.update(GlobalState.PendingWelcomeOnFocus, true);
await container.context.globalState.update(GlobalState.PendingWelcomeOnFocus, true);
const disposable = window.onDidChangeWindowState(e => { const disposable = window.onDidChangeWindowState(e => {
if (!e.focused) return; if (!e.focused) return;
disposable.dispose(); disposable.dispose();
// If the window is now focused and we are pending the welcome, clear the pending state and show the welcome // If the window is now focused and we are pending the welcome, clear the pending state and show the welcome
if (context.globalState.get(GlobalState.PendingWelcomeOnFocus) === true) {
void context.globalState.update(GlobalState.PendingWelcomeOnFocus, undefined);
if (Container.config.showWelcomeOnInstall) {
if (container.context.globalState.get(GlobalState.PendingWelcomeOnFocus) === true) {
void container.context.globalState.update(GlobalState.PendingWelcomeOnFocus, undefined);
if (container.config.showWelcomeOnInstall) {
void commands.executeCommand(Commands.ShowWelcomePage); void commands.executeCommand(Commands.ShowWelcomePage);
} }
} }
}); });
context.subscriptions.push(disposable);
container.context.subscriptions.push(disposable);
} }
return; return;
@ -284,27 +280,27 @@ async function showWelcomeOrWhatsNew(context: ExtensionContext, version: string,
return; return;
} }
if (major !== prevMajor && Container.config.showWhatsNewAfterUpgrades) {
if (major !== prevMajor && container.config.showWhatsNewAfterUpgrades) {
if (window.state.focused) { if (window.state.focused) {
await context.globalState.update(GlobalState.PendingWhatsNewOnFocus, undefined);
await container.context.globalState.update(GlobalState.PendingWhatsNewOnFocus, undefined);
await Messages.showWhatsNewMessage(version); await Messages.showWhatsNewMessage(version);
} else { } else {
// Save pending on window getting focus // Save pending on window getting focus
await context.globalState.update(GlobalState.PendingWhatsNewOnFocus, true);
await container.context.globalState.update(GlobalState.PendingWhatsNewOnFocus, true);
const disposable = window.onDidChangeWindowState(e => { const disposable = window.onDidChangeWindowState(e => {
if (!e.focused) return; if (!e.focused) return;
disposable.dispose(); disposable.dispose();
// If the window is now focused and we are pending the what's new, clear the pending state and show the what's new // If the window is now focused and we are pending the what's new, clear the pending state and show the what's new
if (context.globalState.get(GlobalState.PendingWhatsNewOnFocus) === true) {
void context.globalState.update(GlobalState.PendingWhatsNewOnFocus, undefined);
if (Container.config.showWhatsNewAfterUpgrades) {
if (container.context.globalState.get(GlobalState.PendingWhatsNewOnFocus) === true) {
void container.context.globalState.update(GlobalState.PendingWhatsNewOnFocus, undefined);
if (container.config.showWhatsNewAfterUpgrades) {
void Messages.showWhatsNewMessage(version); void Messages.showWhatsNewMessage(version);
} }
} }
}); });
context.subscriptions.push(disposable);
container.context.subscriptions.push(disposable);
} }
} }
} }

+ 22
- 15
src/git/formatters/commitFormatter.ts View File

@ -136,7 +136,8 @@ export class CommitFormatter extends Formatter {
} }
private get _pullRequestDateOrAgo() { private get _pullRequestDateOrAgo() {
const dateStyle = this._options.dateStyle != null ? this._options.dateStyle : Container.config.defaultDateStyle;
const dateStyle =
this._options.dateStyle != null ? this._options.dateStyle : Container.instance.config.defaultDateStyle;
return dateStyle === DateStyle.Absolute ? this._pullRequestDate : this._pullRequestDateAgo; return dateStyle === DateStyle.Absolute ? this._pullRequestDate : this._pullRequestDateAgo;
} }
@ -145,7 +146,8 @@ export class CommitFormatter extends Formatter {
} }
get agoOrDate(): string { get agoOrDate(): string {
const dateStyle = this._options.dateStyle != null ? this._options.dateStyle : Container.config.defaultDateStyle;
const dateStyle =
this._options.dateStyle != null ? this._options.dateStyle : Container.instance.config.defaultDateStyle;
return this._padOrTruncate( return this._padOrTruncate(
dateStyle === DateStyle.Absolute ? this._date : this._dateAgo, dateStyle === DateStyle.Absolute ? this._date : this._dateAgo,
this._options.tokenOptions.agoOrDate, this._options.tokenOptions.agoOrDate,
@ -153,7 +155,8 @@ export class CommitFormatter extends Formatter {
} }
get agoOrDateShort(): string { get agoOrDateShort(): string {
const dateStyle = this._options.dateStyle != null ? this._options.dateStyle : Container.config.defaultDateStyle;
const dateStyle =
this._options.dateStyle != null ? this._options.dateStyle : Container.instance.config.defaultDateStyle;
return this._padOrTruncate( return this._padOrTruncate(
dateStyle === DateStyle.Absolute ? this._date : this._dateAgoShort, dateStyle === DateStyle.Absolute ? this._date : this._dateAgoShort,
this._options.tokenOptions.agoOrDateShort, this._options.tokenOptions.agoOrDateShort,
@ -174,7 +177,8 @@ export class CommitFormatter extends Formatter {
} }
get authorAgoOrDate(): string { get authorAgoOrDate(): string {
const dateStyle = this._options.dateStyle != null ? this._options.dateStyle : Container.config.defaultDateStyle;
const dateStyle =
this._options.dateStyle != null ? this._options.dateStyle : Container.instance.config.defaultDateStyle;
return this._padOrTruncate( return this._padOrTruncate(
dateStyle === DateStyle.Absolute ? this._authorDate : this._authorDateAgo, dateStyle === DateStyle.Absolute ? this._authorDate : this._authorDateAgo,
this._options.tokenOptions.authorAgoOrDate, this._options.tokenOptions.authorAgoOrDate,
@ -182,7 +186,8 @@ export class CommitFormatter extends Formatter {
} }
get authorAgoOrDateShort(): string { get authorAgoOrDateShort(): string {
const dateStyle = this._options.dateStyle != null ? this._options.dateStyle : Container.config.defaultDateStyle;
const dateStyle =
this._options.dateStyle != null ? this._options.dateStyle : Container.instance.config.defaultDateStyle;
return this._padOrTruncate( return this._padOrTruncate(
dateStyle === DateStyle.Absolute ? this._authorDate : this._authorDateAgoShort, dateStyle === DateStyle.Absolute ? this._authorDate : this._authorDateAgoShort,
this._options.tokenOptions.authorAgoOrDateShort, this._options.tokenOptions.authorAgoOrDateShort,
@ -205,7 +210,7 @@ export class CommitFormatter extends Formatter {
} }
get avatar(): string | Promise<string> { get avatar(): string | Promise<string> {
if (!this._options.markdown || !Container.config.hovers.avatars) {
if (!this._options.markdown || !Container.instance.config.hovers.avatars) {
return this._padOrTruncate(emptyStr, this._options.tokenOptions.avatar); return this._padOrTruncate(emptyStr, this._options.tokenOptions.avatar);
} }
@ -228,9 +233,9 @@ export class CommitFormatter extends Formatter {
} }
private async _getAvatarMarkdown(title: string, size?: number) { private async _getAvatarMarkdown(title: string, size?: number) {
size = size ?? Container.config.hovers.avatarSize;
size = size ?? Container.instance.config.hovers.avatarSize;
const avatarPromise = this._item.getAvatarUri({ const avatarPromise = this._item.getAvatarUri({
defaultStyle: Container.config.defaultGravatarsStyle,
defaultStyle: Container.instance.config.defaultGravatarsStyle,
size: size, size: size,
}); });
return this._padOrTruncate( return this._padOrTruncate(
@ -350,13 +355,13 @@ export class CommitFormatter extends Formatter {
provider: { id: pr.provider.id, name: pr.provider.name, domain: pr.provider.domain }, provider: { id: pr.provider.id, name: pr.provider.name, domain: pr.provider.domain },
pullRequest: { id: pr.id, url: pr.url }, pullRequest: { id: pr.id, url: pr.url },
})} "Open Pull Request \\#${pr.id}${ })} "Open Pull Request \\#${pr.id}${
Container.actionRunners.count('openPullRequest') == 1 ? ` on ${pr.provider.name}` : '...'
Container.instance.actionRunners.count('openPullRequest') == 1 ? ` on ${pr.provider.name}` : '...'
}\n${GlyphChars.Dash.repeat(2)}\n${Strings.escapeMarkdown(pr.title).replace(/"/g, '\\"')}\n${ }\n${GlyphChars.Dash.repeat(2)}\n${Strings.escapeMarkdown(pr.title).replace(/"/g, '\\"')}\n${
pr.state pr.state
}, ${pr.formatDateFromNow()}")`; }, ${pr.formatDateFromNow()}")`;
} else if (pr instanceof Promises.CancellationError) { } else if (pr instanceof Promises.CancellationError) {
commands += `${separator}[$(git-pull-request) PR $(loading~spin)](command:${Commands.RefreshHover} "Searching for a Pull Request (if any) that introduced this commit...")`; commands += `${separator}[$(git-pull-request) PR $(loading~spin)](command:${Commands.RefreshHover} "Searching for a Pull Request (if any) that introduced this commit...")`;
} else if (pr.provider != null && Container.config.integrations.enabled) {
} else if (pr.provider != null && Container.instance.config.integrations.enabled) {
commands += `${separator}[$(plug) Connect to ${pr.provider.name}${ commands += `${separator}[$(plug) Connect to ${pr.provider.name}${
GlyphChars.Ellipsis GlyphChars.Ellipsis
}](${ConnectRemoteProviderCommand.getMarkdownCommandArgs(pr)} "Connect to ${ }](${ConnectRemoteProviderCommand.getMarkdownCommandArgs(pr)} "Connect to ${
@ -365,7 +370,7 @@ export class CommitFormatter extends Formatter {
} }
} }
if (Container.actionRunners.count('hover.commands') > 0) {
if (Container.instance.actionRunners.count('hover.commands') > 0) {
commands += `${separator}[$(organization) Team${GlyphChars.SpaceThinnest}${ commands += `${separator}[$(organization) Team${GlyphChars.SpaceThinnest}${
GlyphChars.Ellipsis GlyphChars.Ellipsis
}](${getMarkdownActionCommand<HoverCommandsActionContext>('hover.commands', { }](${getMarkdownActionCommand<HoverCommandsActionContext>('hover.commands', {
@ -400,7 +405,8 @@ export class CommitFormatter extends Formatter {
} }
get committerAgoOrDate(): string { get committerAgoOrDate(): string {
const dateStyle = this._options.dateStyle != null ? this._options.dateStyle : Container.config.defaultDateStyle;
const dateStyle =
this._options.dateStyle != null ? this._options.dateStyle : Container.instance.config.defaultDateStyle;
return this._padOrTruncate( return this._padOrTruncate(
dateStyle === DateStyle.Absolute ? this._committerDate : this._committerDateAgo, dateStyle === DateStyle.Absolute ? this._committerDate : this._committerDateAgo,
this._options.tokenOptions.committerAgoOrDate, this._options.tokenOptions.committerAgoOrDate,
@ -408,7 +414,8 @@ export class CommitFormatter extends Formatter {
} }
get committerAgoOrDateShort(): string { get committerAgoOrDateShort(): string {
const dateStyle = this._options.dateStyle != null ? this._options.dateStyle : Container.config.defaultDateStyle;
const dateStyle =
this._options.dateStyle != null ? this._options.dateStyle : Container.instance.config.defaultDateStyle;
return this._padOrTruncate( return this._padOrTruncate(
dateStyle === DateStyle.Absolute ? this._committerDate : this._committerDateAgoShort, dateStyle === DateStyle.Absolute ? this._committerDate : this._committerDateAgoShort,
this._options.tokenOptions.committerAgoOrDateShort, this._options.tokenOptions.committerAgoOrDateShort,
@ -477,7 +484,7 @@ export class CommitFormatter extends Formatter {
message = this._padOrTruncate(message, this._options.tokenOptions.message); message = this._padOrTruncate(message, this._options.tokenOptions.message);
if (this._options.messageAutolinks) { if (this._options.messageAutolinks) {
message = Container.autolinks.linkify(
message = Container.instance.autolinks.linkify(
this._options.markdown ? Strings.escapeMarkdown(message, { quoted: true }) : message, this._options.markdown ? Strings.escapeMarkdown(message, { quoted: true }) : message,
this._options.markdown ?? false, this._options.markdown ?? false,
this._options.remotes, this._options.remotes,
@ -507,7 +514,7 @@ export class CommitFormatter extends Formatter {
provider: { id: pr.provider.id, name: pr.provider.name, domain: pr.provider.domain }, provider: { id: pr.provider.id, name: pr.provider.name, domain: pr.provider.domain },
pullRequest: { id: pr.id, url: pr.url }, pullRequest: { id: pr.id, url: pr.url },
})} "Open Pull Request \\#${pr.id}${ })} "Open Pull Request \\#${pr.id}${
Container.actionRunners.count('openPullRequest') == 1 ? ` on ${pr.provider.name}` : '...'
Container.instance.actionRunners.count('openPullRequest') == 1 ? ` on ${pr.provider.name}` : '...'
}\n${GlyphChars.Dash.repeat(2)}\n${Strings.escapeMarkdown(pr.title).replace(/"/g, '\\"')}\n${ }\n${GlyphChars.Dash.repeat(2)}\n${Strings.escapeMarkdown(pr.title).replace(/"/g, '\\"')}\n${
pr.state pr.state
}, ${pr.formatDateFromNow()}")`; }, ${pr.formatDateFromNow()}")`;

+ 4
- 4
src/git/fsProvider.ts View File

@ -33,7 +33,7 @@ export class GitFileSystemProvider implements FileSystemProvider, Disposable {
private readonly _disposable: Disposable; private readonly _disposable: Disposable;
private readonly _searchTreeMap = new Map<string, Promise<TernarySearchTree<string, GitTree>>>(); private readonly _searchTreeMap = new Map<string, Promise<TernarySearchTree<string, GitTree>>>();
constructor() {
constructor(private readonly container: Container) {
this._disposable = Disposable.from( this._disposable = Disposable.from(
workspace.registerFileSystemProvider(DocumentSchemes.GitLens, this, { workspace.registerFileSystemProvider(DocumentSchemes.GitLens, this, {
isCaseSensitive: true, isCaseSensitive: true,
@ -83,7 +83,7 @@ export class GitFileSystemProvider implements FileSystemProvider, Disposable {
if (ref === GitRevision.deletedOrMissing) return emptyArray; if (ref === GitRevision.deletedOrMissing) return emptyArray;
const buffer = await Container.git.getVersionedFileBuffer(repoPath, path, ref);
const buffer = await this.container.git.getVersionedFileBuffer(repoPath, path, ref);
if (buffer === undefined) return emptyArray; if (buffer === undefined) return emptyArray;
return buffer; return buffer;
@ -125,7 +125,7 @@ export class GitFileSystemProvider implements FileSystemProvider, Disposable {
}; };
} }
treeItem = await Container.git.getTreeFileForRevision(repoPath, path, ref);
treeItem = await this.container.git.getTreeFileForRevision(repoPath, path, ref);
} }
if (treeItem === undefined) { if (treeItem === undefined) {
@ -154,7 +154,7 @@ export class GitFileSystemProvider implements FileSystemProvider, Disposable {
private async createSearchTree(ref: string, repoPath: string) { private async createSearchTree(ref: string, repoPath: string) {
const searchTree = TernarySearchTree.forPaths<GitTree>(); const searchTree = TernarySearchTree.forPaths<GitTree>();
const trees = await Container.git.getTreeForRevision(repoPath, ref);
const trees = await this.container.git.getTreeForRevision(repoPath, ref);
// Add a fake root folder so that searches will work // Add a fake root folder so that searches will work
searchTree.set('~', { commitSha: '', path: '~', size: 0, type: 'tree' }); searchTree.set('~', { commitSha: '', path: '~', size: 0, type: 'tree' });

+ 7
- 3
src/git/git.ts View File

@ -75,9 +75,9 @@ export interface GitCommandOptions extends RunOptions
const pendingCommands = new Map<string, Promise<string | Buffer>>(); const pendingCommands = new Map<string, Promise<string | Buffer>>();
export async function git<TOut extends string | Buffer>(options: GitCommandOptions, ...args: any[]): Promise<TOut> { export async function git<TOut extends string | Buffer>(options: GitCommandOptions, ...args: any[]): Promise<TOut> {
if (Container.vsls.isMaybeGuest) {
if (Container.instance.vsls.isMaybeGuest) {
if (options.local !== true) { if (options.local !== true) {
const guest = await Container.vsls.guest();
const guest = await Container.instance.vsls.guest();
if (guest !== undefined) { if (guest !== undefined) {
return guest.git<TOut>(options, ...args); return guest.git<TOut>(options, ...args);
} }
@ -1396,7 +1396,11 @@ export namespace Git {
return git<string>({ cwd: repoPath, errors: GitErrorHandling.Ignore }, 'show-ref', '--tags'); return git<string>({ cwd: repoPath, errors: GitErrorHandling.Ignore }, 'show-ref', '--tags');
} }
export function stash__apply(repoPath: string, stashName: string, deleteAfter: boolean) {
export function stash__apply(
repoPath: string,
stashName: string,
deleteAfter: boolean,
): Promise<string | undefined> {
if (!stashName) return Promise.resolve(undefined); if (!stashName) return Promise.resolve(undefined);
return git<string>({ cwd: repoPath }, 'stash', deleteAfter ? 'pop' : 'apply', stashName); return git<string>({ cwd: repoPath }, 'stash', deleteAfter ? 'pop' : 'apply', stashName);
} }

+ 72
- 77
src/git/gitService.ts View File

@ -137,6 +137,7 @@ export class GitService implements Disposable {
private readonly _disposable: Disposable; private readonly _disposable: Disposable;
private readonly _repositoryTree: TernarySearchTree<string, Repository>; private readonly _repositoryTree: TernarySearchTree<string, Repository>;
private _repositoriesLoadingPromise: Promise<void> | undefined; private _repositoriesLoadingPromise: Promise<void> | undefined;
private _repositoriesLoadingPromiseResolver: (() => void) | undefined;
private readonly _branchesCache = new Map<string, Promise<GitBranch[]>>(); private readonly _branchesCache = new Map<string, Promise<GitBranch[]>>();
private readonly _contributorsCache = new Map<string, Promise<GitContributor[]>>(); private readonly _contributorsCache = new Map<string, Promise<GitContributor[]>>();
@ -148,10 +149,11 @@ export class GitService implements Disposable {
private readonly _trackedCache = new Map<string, boolean | Promise<boolean>>(); private readonly _trackedCache = new Map<string, boolean | Promise<boolean>>();
private readonly _userMapCache = new Map<string, GitUser | null>(); private readonly _userMapCache = new Map<string, GitUser | null>();
constructor() {
constructor(private readonly container: Container) {
this._repositoryTree = TernarySearchTree.forPaths(); this._repositoryTree = TernarySearchTree.forPaths();
this._disposable = Disposable.from( this._disposable = Disposable.from(
container.onReady(this.onReady, this),
window.onDidChangeWindowState(this.onWindowStateChanged, this), window.onDidChangeWindowState(this.onWindowStateChanged, this),
workspace.onDidChangeWorkspaceFolders(this.onWorkspaceFoldersChanged, this), workspace.onDidChangeWorkspaceFolders(this.onWorkspaceFoldersChanged, this),
configuration.onDidChange(this.onConfigurationChanged, this), configuration.onDidChange(this.onConfigurationChanged, this),
@ -163,9 +165,10 @@ export class GitService implements Disposable {
void this.updateContext(this._repositoryTree); void this.updateContext(this._repositoryTree);
}), }),
); );
this.onConfigurationChanged();
this._repositoriesLoadingPromise = this.onWorkspaceFoldersChanged();
this._repositoriesLoadingPromise = new Promise(resolve => (this._repositoriesLoadingPromiseResolver = resolve));
this.onConfigurationChanged();
} }
dispose() { dispose() {
@ -174,24 +177,16 @@ export class GitService implements Disposable {
this._disposable.dispose(); this._disposable.dispose();
} }
@log()
static async initialize(): Promise<void> {
// Try to use the same git as the built-in vscode git extension
let gitPath;
const gitApi = await GitService.getBuiltInGitApi();
if (gitApi != null) {
gitPath = gitApi.git.path;
}
await Git.setOrFindGitPath(gitPath ?? configuration.getAny<string | string[]>('git.path'));
private onReady() {
this.onWorkspaceFoldersChanged().finally(() => this._repositoriesLoadingPromiseResolver!());
} }
get readonly() { get readonly() {
return Container.vsls.readonly;
return this.container.vsls.readonly;
} }
get useCaching() { get useCaching() {
return Container.config.advanced.caching.enabled;
return this.container.config.advanced.caching.enabled;
} }
private onAnyRepositoryChanged(repo: Repository, e: RepositoryChangeEvent) { private onAnyRepositoryChanged(repo: Repository, e: RepositoryChangeEvent) {
@ -287,8 +282,8 @@ export class GitService implements Disposable {
if (scheme !== DocumentSchemes.File && scheme !== DocumentSchemes.Vsls) continue; if (scheme !== DocumentSchemes.File && scheme !== DocumentSchemes.Vsls) continue;
if (scheme === DocumentSchemes.Vsls) { if (scheme === DocumentSchemes.Vsls) {
if (Container.vsls.isMaybeGuest) {
const guest = await Container.vsls.guest();
if (this.container.vsls.isMaybeGuest) {
const guest = await this.container.vsls.guest();
if (guest != null) { if (guest != null) {
const repositories = await guest.getRepositoriesInFolder( const repositories = await guest.getRepositoriesInFolder(
f, f,
@ -859,7 +854,7 @@ export class GitService implements Disposable {
let repoPath; let repoPath;
if (editor != null) { if (editor != null) {
const doc = await Container.tracker.getOrAdd(editor.document.uri);
const doc = await this.container.tracker.getOrAdd(editor.document.uri);
if (doc != null) { if (doc != null) {
repoPath = doc.uri.repoPath; repoPath = doc.uri.repoPath;
} }
@ -888,7 +883,7 @@ export class GitService implements Disposable {
key += `:${uri.sha}`; key += `:${uri.sha}`;
} }
const doc = await Container.tracker.getOrAdd(uri);
const doc = await this.container.tracker.getOrAdd(uri);
if (this.useCaching) { if (this.useCaching) {
if (doc.state != null) { if (doc.state != null) {
const cachedBlame = doc.state.get<CachedBlame>(key); const cachedBlame = doc.state.get<CachedBlame>(key);
@ -934,8 +929,8 @@ export class GitService implements Disposable {
try { try {
const data = await Git.blame(root, file, uri.sha, { const data = await Git.blame(root, file, uri.sha, {
args: Container.config.advanced.blame.customArguments,
ignoreWhitespace: Container.config.blame.ignoreWhitespace,
args: this.container.config.advanced.blame.customArguments,
ignoreWhitespace: this.container.config.blame.ignoreWhitespace,
}); });
const blame = GitBlameParser.parse(data, root, file, await this.getCurrentUser(root)); const blame = GitBlameParser.parse(data, root, file, await this.getCurrentUser(root));
return blame; return blame;
@ -970,7 +965,7 @@ export class GitService implements Disposable {
const key = `blame:${Strings.sha1(contents)}`; const key = `blame:${Strings.sha1(contents)}`;
const doc = await Container.tracker.getOrAdd(uri);
const doc = await this.container.tracker.getOrAdd(uri);
if (this.useCaching) { if (this.useCaching) {
if (doc.state != null) { if (doc.state != null) {
const cachedBlame = doc.state.get<CachedBlame>(key); const cachedBlame = doc.state.get<CachedBlame>(key);
@ -1017,9 +1012,9 @@ export class GitService implements Disposable {
try { try {
const data = await Git.blame__contents(root, file, contents, { const data = await Git.blame__contents(root, file, contents, {
args: Container.config.advanced.blame.customArguments,
args: this.container.config.advanced.blame.customArguments,
correlationKey: `:${key}`, correlationKey: `:${key}`,
ignoreWhitespace: Container.config.blame.ignoreWhitespace,
ignoreWhitespace: this.container.config.blame.ignoreWhitespace,
}); });
const blame = GitBlameParser.parse(data, root, file, await this.getCurrentUser(root)); const blame = GitBlameParser.parse(data, root, file, await this.getCurrentUser(root));
return blame; return blame;
@ -1075,8 +1070,8 @@ export class GitService implements Disposable {
try { try {
const data = await Git.blame(uri.repoPath, fileName, uri.sha, { const data = await Git.blame(uri.repoPath, fileName, uri.sha, {
args: Container.config.advanced.blame.customArguments,
ignoreWhitespace: Container.config.blame.ignoreWhitespace,
args: this.container.config.advanced.blame.customArguments,
ignoreWhitespace: this.container.config.blame.ignoreWhitespace,
startLine: lineToBlame, startLine: lineToBlame,
endLine: lineToBlame, endLine: lineToBlame,
}); });
@ -1130,8 +1125,8 @@ export class GitService implements Disposable {
try { try {
const data = await Git.blame__contents(uri.repoPath, fileName, contents, { const data = await Git.blame__contents(uri.repoPath, fileName, contents, {
args: Container.config.advanced.blame.customArguments,
ignoreWhitespace: Container.config.blame.ignoreWhitespace,
args: this.container.config.advanced.blame.customArguments,
ignoreWhitespace: this.container.config.blame.ignoreWhitespace,
startLine: lineToBlame, startLine: lineToBlame,
endLine: lineToBlame, endLine: lineToBlame,
}); });
@ -1227,14 +1222,14 @@ export class GitService implements Disposable {
let [branch] = await this.getBranches(repoPath, { filter: b => b.current }); let [branch] = await this.getBranches(repoPath, { filter: b => b.current });
if (branch != null) return branch; if (branch != null) return branch;
const data = await Git.rev_parse__currentBranch(repoPath, Container.config.advanced.commitOrdering);
const data = await Git.rev_parse__currentBranch(repoPath, this.container.config.advanced.commitOrdering);
if (data == null) return undefined; if (data == null) return undefined;
const [name, upstream] = data[0].split('\n'); const [name, upstream] = data[0].split('\n');
if (GitBranch.isDetached(name)) { if (GitBranch.isDetached(name)) {
const [rebaseStatus, committerDate] = await Promise.all([ const [rebaseStatus, committerDate] = await Promise.all([
this.getRebaseStatus(repoPath), this.getRebaseStatus(repoPath),
Git.log__recent_committerdate(repoPath, Container.config.advanced.commitOrdering),
Git.log__recent_committerdate(repoPath, this.container.config.advanced.commitOrdering),
]); ]);
branch = new GitBranch( branch = new GitBranch(
@ -1316,13 +1311,13 @@ export class GitService implements Disposable {
const data = await Git.rev_parse__currentBranch( const data = await Git.rev_parse__currentBranch(
repoPath!, repoPath!,
Container.config.advanced.commitOrdering,
this.container.config.advanced.commitOrdering,
); );
if (data != null) { if (data != null) {
const [name, upstream] = data[0].split('\n'); const [name, upstream] = data[0].split('\n');
const [rebaseStatus, committerDate] = await Promise.all([ const [rebaseStatus, committerDate] = await Promise.all([
GitBranch.isDetached(name) ? this.getRebaseStatus(repoPath!) : undefined, GitBranch.isDetached(name) ? this.getRebaseStatus(repoPath!) : undefined,
Git.log__recent_committerdate(repoPath!, Container.config.advanced.commitOrdering),
Git.log__recent_committerdate(repoPath!, this.container.config.advanced.commitOrdering),
]); ]);
current = new GitBranch( current = new GitBranch(
@ -1537,7 +1532,7 @@ export class GitService implements Disposable {
async getOldestUnpushedRefForFile(repoPath: string, fileName: string): Promise<string | undefined> { async getOldestUnpushedRefForFile(repoPath: string, fileName: string): Promise<string | undefined> {
const data = await Git.log__file(repoPath, fileName, '@{push}..', { const data = await Git.log__file(repoPath, fileName, '@{push}..', {
format: 'refs', format: 'refs',
ordering: Container.config.advanced.commitOrdering,
ordering: this.container.config.advanced.commitOrdering,
renames: true, renames: true,
}); });
if (data == null || data.length === 0) return undefined; if (data == null || data.length === 0) return undefined;
@ -1690,7 +1685,7 @@ export class GitService implements Disposable {
key += `:${ref2}`; key += `:${ref2}`;
} }
const doc = await Container.tracker.getOrAdd(uri);
const doc = await this.container.tracker.getOrAdd(uri);
if (this.useCaching) { if (this.useCaching) {
if (doc.state != null) { if (doc.state != null) {
const cachedDiff = doc.state.get<CachedDiff>(key); const cachedDiff = doc.state.get<CachedDiff>(key);
@ -1748,7 +1743,7 @@ export class GitService implements Disposable {
// let data; // let data;
// if (ref2 == null && ref1 != null && !GitRevision.isUncommittedStaged(ref1)) { // if (ref2 == null && ref1 != null && !GitRevision.isUncommittedStaged(ref1)) {
// data = await Git.show__diff(root, file, ref1, originalFileName, { // data = await Git.show__diff(root, file, ref1, originalFileName, {
// similarityThreshold: Container.config.advanced.similarityThreshold,
// similarityThreshold: this.container.config.advanced.similarityThreshold,
// }); // });
// } else { // } else {
const data = await Git.diff(root, file, ref1, ref2, { const data = await Git.diff(root, file, ref1, ref2, {
@ -1756,7 +1751,7 @@ export class GitService implements Disposable {
filters: ['M'], filters: ['M'],
linesOfContext: 0, linesOfContext: 0,
renames: true, renames: true,
similarityThreshold: Container.config.advanced.similarityThreshold,
similarityThreshold: this.container.config.advanced.similarityThreshold,
}); });
// } // }
@ -1796,7 +1791,7 @@ export class GitService implements Disposable {
const key = `diff:${Strings.sha1(contents)}`; const key = `diff:${Strings.sha1(contents)}`;
const doc = await Container.tracker.getOrAdd(uri);
const doc = await this.container.tracker.getOrAdd(uri);
if (this.useCaching) { if (this.useCaching) {
if (doc.state != null) { if (doc.state != null) {
const cachedDiff = doc.state.get<CachedDiff>(key); const cachedDiff = doc.state.get<CachedDiff>(key);
@ -1854,7 +1849,7 @@ export class GitService implements Disposable {
const data = await Git.diff__contents(root, file, ref, contents, { const data = await Git.diff__contents(root, file, ref, contents, {
...options, ...options,
filters: ['M'], filters: ['M'],
similarityThreshold: Container.config.advanced.similarityThreshold,
similarityThreshold: this.container.config.advanced.similarityThreshold,
}); });
const diff = GitDiffParser.parse(data); const diff = GitDiffParser.parse(data);
@ -1909,7 +1904,7 @@ export class GitService implements Disposable {
): Promise<GitFile[] | undefined> { ): Promise<GitFile[] | undefined> {
try { try {
const data = await Git.diff__name_status(repoPath, ref1, ref2, { const data = await Git.diff__name_status(repoPath, ref1, ref2, {
similarityThreshold: Container.config.advanced.similarityThreshold,
similarityThreshold: this.container.config.advanced.similarityThreshold,
...options, ...options,
}); });
const files = GitDiffParser.parseNameStatus(data, repoPath); const files = GitDiffParser.parseNameStatus(data, repoPath);
@ -1949,15 +1944,15 @@ export class GitService implements Disposable {
since?: string; since?: string;
} = {}, } = {},
): Promise<GitLog | undefined> { ): Promise<GitLog | undefined> {
const limit = options.limit ?? Container.config.advanced.maxListItems ?? 0;
const limit = options.limit ?? this.container.config.advanced.maxListItems ?? 0;
try { try {
const data = await Git.log(repoPath, ref, { const data = await Git.log(repoPath, ref, {
...options, ...options,
limit: limit, limit: limit,
merges: options.merges == null ? true : options.merges, merges: options.merges == null ? true : options.merges,
ordering: options.ordering ?? Container.config.advanced.commitOrdering,
similarityThreshold: Container.config.advanced.similarityThreshold,
ordering: options.ordering ?? this.container.config.advanced.commitOrdering,
similarityThreshold: this.container.config.advanced.similarityThreshold,
}); });
const log = GitLogParser.parse( const log = GitLogParser.parse(
data, data,
@ -2001,7 +1996,7 @@ export class GitService implements Disposable {
since?: string; since?: string;
} = {}, } = {},
): Promise<Set<string> | undefined> { ): Promise<Set<string> | undefined> {
const limit = options.limit ?? Container.config.advanced.maxListItems ?? 0;
const limit = options.limit ?? this.container.config.advanced.maxListItems ?? 0;
try { try {
const data = await Git.log(repoPath, ref, { const data = await Git.log(repoPath, ref, {
@ -2010,9 +2005,9 @@ export class GitService implements Disposable {
limit: limit, limit: limit,
merges: options.merges == null ? true : options.merges, merges: options.merges == null ? true : options.merges,
reverse: options.reverse, reverse: options.reverse,
similarityThreshold: Container.config.advanced.similarityThreshold,
similarityThreshold: this.container.config.advanced.similarityThreshold,
since: options.since, since: options.since,
ordering: options.ordering ?? Container.config.advanced.commitOrdering,
ordering: options.ordering ?? this.container.config.advanced.commitOrdering,
}); });
const commits = GitLogParser.parseRefsOnly(data); const commits = GitLogParser.parseRefsOnly(data);
return new Set(commits); return new Set(commits);
@ -2040,7 +2035,7 @@ export class GitService implements Disposable {
return log; return log;
} }
moreLimit = moreLimit ?? Container.config.advanced.maxSearchItems ?? 0;
moreLimit = moreLimit ?? this.container.config.advanced.maxSearchItems ?? 0;
// If the log is for a range, then just get everything prior + more // If the log is for a range, then just get everything prior + more
if (GitRevision.isRange(log.sha)) { if (GitRevision.isRange(log.sha)) {
@ -2102,8 +2097,8 @@ export class GitService implements Disposable {
search = { matchAll: false, matchCase: false, matchRegex: true, ...search }; search = { matchAll: false, matchCase: false, matchRegex: true, ...search };
try { try {
const limit = options.limit ?? Container.config.advanced.maxSearchItems ?? 0;
const similarityThreshold = Container.config.advanced.similarityThreshold;
const limit = options.limit ?? this.container.config.advanced.maxSearchItems ?? 0;
const similarityThreshold = this.container.config.advanced.similarityThreshold;
const operations = SearchPattern.parseSearchOperations(search.pattern); const operations = SearchPattern.parseSearchOperations(search.pattern);
@ -2175,7 +2170,7 @@ export class GitService implements Disposable {
} }
const data = await Git.log__search(repoPath, args, { const data = await Git.log__search(repoPath, args, {
ordering: Container.config.advanced.commitOrdering,
ordering: this.container.config.advanced.commitOrdering,
...options, ...options,
limit: limit, limit: limit,
useShow: useShow, useShow: useShow,
@ -2212,7 +2207,7 @@ export class GitService implements Disposable {
options: { limit?: number; ordering?: string | null }, options: { limit?: number; ordering?: string | null },
): (limit: number | undefined) => Promise<GitLog> { ): (limit: number | undefined) => Promise<GitLog> {
return async (limit: number | undefined) => { return async (limit: number | undefined) => {
limit = limit ?? Container.config.advanced.maxSearchItems ?? 0;
limit = limit ?? this.container.config.advanced.maxSearchItems ?? 0;
const moreLog = await this.getLogForSearch(log.repoPath, search, { const moreLog = await this.getLogForSearch(log.repoPath, search, {
...options, ...options,
@ -2279,7 +2274,7 @@ export class GitService implements Disposable {
options = { reverse: false, ...options }; options = { reverse: false, ...options };
if (options.renames == null) { if (options.renames == null) {
options.renames = Container.config.advanced.fileHistoryFollowsRenames;
options.renames = this.container.config.advanced.fileHistoryFollowsRenames;
} }
let key = 'log'; let key = 'log';
@ -2288,13 +2283,13 @@ export class GitService implements Disposable {
} }
if (options.all == null) { if (options.all == null) {
options.all = Container.config.advanced.fileHistoryShowAllBranches;
options.all = this.container.config.advanced.fileHistoryShowAllBranches;
} }
if (options.all) { if (options.all) {
key += ':all'; key += ':all';
} }
options.limit = options.limit == null ? Container.config.advanced.maxListItems || 0 : options.limit;
options.limit = options.limit == null ? this.container.config.advanced.maxListItems || 0 : options.limit;
if (options.limit) { if (options.limit) {
key += `:n${options.limit}`; key += `:n${options.limit}`;
} }
@ -2315,7 +2310,7 @@ export class GitService implements Disposable {
key += `:skip${options.skip}`; key += `:skip${options.skip}`;
} }
const doc = await Container.tracker.getOrAdd(GitUri.fromFile(fileName, repoPath!, options.ref));
const doc = await this.container.tracker.getOrAdd(GitUri.fromFile(fileName, repoPath!, options.ref));
if (this.useCaching && options.range == null) { if (this.useCaching && options.range == null) {
if (doc.state != null) { if (doc.state != null) {
const cachedLog = doc.state.get<CachedLog>(key); const cachedLog = doc.state.get<CachedLog>(key);
@ -2437,7 +2432,7 @@ export class GitService implements Disposable {
} }
const data = await Git.log__file(root, file, ref, { const data = await Git.log__file(root, file, ref, {
ordering: Container.config.advanced.commitOrdering,
ordering: this.container.config.advanced.commitOrdering,
...options, ...options,
firstParent: options.renames, firstParent: options.renames,
startLine: range == null ? undefined : range.start.line + 1, startLine: range == null ? undefined : range.start.line + 1,
@ -2506,7 +2501,7 @@ export class GitService implements Disposable {
return log; return log;
} }
moreLimit = moreLimit ?? Container.config.advanced.maxSearchItems ?? 0;
moreLimit = moreLimit ?? this.container.config.advanced.maxSearchItems ?? 0;
const ref = Iterables.last(log.commits.values())?.ref; const ref = Iterables.last(log.commits.values())?.ref;
const moreLog = await this.getLogForFile(log.repoPath, fileName, { const moreLog = await this.getLogForFile(log.repoPath, fileName, {
@ -2768,7 +2763,7 @@ export class GitService implements Disposable {
filters: filters, filters: filters,
format: 'simple', format: 'simple',
limit: skip + 1, limit: skip + 1,
ordering: Container.config.advanced.commitOrdering,
ordering: this.container.config.advanced.commitOrdering,
reverse: true, reverse: true,
// startLine: editorLine != null ? editorLine + 1 : undefined, // startLine: editorLine != null ? editorLine + 1 : undefined,
}); });
@ -2781,7 +2776,7 @@ export class GitService implements Disposable {
filters: ['R', 'C'], filters: ['R', 'C'],
format: 'simple', format: 'simple',
limit: 1, limit: 1,
ordering: Container.config.advanced.commitOrdering,
ordering: this.container.config.advanced.commitOrdering,
// startLine: editorLine != null ? editorLine + 1 : undefined // startLine: editorLine != null ? editorLine + 1 : undefined
}); });
if (data == null || data.length === 0) { if (data == null || data.length === 0) {
@ -3020,7 +3015,7 @@ export class GitService implements Disposable {
firstParent: firstParent, firstParent: firstParent,
format: 'simple', format: 'simple',
limit: skip + 2, limit: skip + 2,
ordering: Container.config.advanced.commitOrdering,
ordering: this.container.config.advanced.commitOrdering,
startLine: editorLine != null ? editorLine + 1 : undefined, startLine: editorLine != null ? editorLine + 1 : undefined,
}); });
} catch (ex) { } catch (ex) {
@ -3035,7 +3030,7 @@ export class GitService implements Disposable {
} }
ref = await Git.log__file_recent(repoPath, fileName, { ref = await Git.log__file_recent(repoPath, fileName, {
ordering: Container.config.advanced.commitOrdering,
ordering: this.container.config.advanced.commitOrdering,
}); });
return GitUri.fromFile(fileName, repoPath, ref ?? GitRevision.deletedOrMissing); return GitUri.fromFile(fileName, repoPath, ref ?? GitRevision.deletedOrMissing);
} }
@ -3175,11 +3170,11 @@ export class GitService implements Disposable {
): Promise<GitReflog | undefined> { ): Promise<GitReflog | undefined> {
const cc = Logger.getCorrelationContext(); const cc = Logger.getCorrelationContext();
limit = limit ?? Container.config.advanced.maxListItems ?? 0;
limit = limit ?? this.container.config.advanced.maxListItems ?? 0;
try { try {
// Pass a much larger limit to reflog, because we aggregate the data and we won't know how many lines we'll need // Pass a much larger limit to reflog, because we aggregate the data and we won't know how many lines we'll need
const data = await Git.reflog(repoPath, { const data = await Git.reflog(repoPath, {
ordering: Container.config.advanced.commitOrdering,
ordering: this.container.config.advanced.commitOrdering,
...options, ...options,
limit: limit * 100, limit: limit * 100,
}); });
@ -3202,7 +3197,7 @@ export class GitService implements Disposable {
options: { all?: boolean; branch?: string; limit?: number; ordering?: string | null; skip?: number }, options: { all?: boolean; branch?: string; limit?: number; ordering?: string | null; skip?: number },
): (limit: number) => Promise<GitReflog> { ): (limit: number) => Promise<GitReflog> {
return async (limit: number | undefined) => { return async (limit: number | undefined) => {
limit = limit ?? Container.config.advanced.maxSearchItems ?? 0;
limit = limit ?? this.container.config.advanced.maxSearchItems ?? 0;
const moreLog = await this.getIncomingActivity(reflog.repoPath, { const moreLog = await this.getIncomingActivity(reflog.repoPath, {
...options, ...options,
@ -3512,7 +3507,7 @@ export class GitService implements Disposable {
@gate(() => '') @gate(() => '')
private async ensureProperWorkspaceCasing(repoPath: string, filePath: string) { private async ensureProperWorkspaceCasing(repoPath: string, filePath: string) {
if (Container.config.advanced.messages.suppressImproperWorkspaceCasingWarning) return;
if (this.container.config.advanced.messages.suppressImproperWorkspaceCasingWarning) return;
filePath = filePath.replace(/\\/g, '/'); filePath = filePath.replace(/\\/g, '/');
@ -3633,7 +3628,7 @@ export class GitService implements Disposable {
): Repository | undefined { ): Repository | undefined {
let repo = repositoryTree.findSubstr(path); let repo = repositoryTree.findSubstr(path);
// If we can't find the repo and we are a guest, check if we are a "root" workspace // If we can't find the repo and we are a guest, check if we are a "root" workspace
if (repo == null && isVslsScheme !== false && Container.vsls.isMaybeGuest) {
if (repo == null && isVslsScheme !== false && this.container.vsls.isMaybeGuest) {
if (!vslsUriPrefixRegex.test(path)) { if (!vslsUriPrefixRegex.test(path)) {
path = Strings.normalizePath(path); path = Strings.normalizePath(path);
const vslsPath = `/~0${path.startsWith(slash) ? path : `/${path}`}`; const vslsPath = `/~0${path.startsWith(slash) ? path : `/${path}`}`;
@ -3670,7 +3665,7 @@ export class GitService implements Disposable {
let stash = this.useCaching ? this._stashesCache.get(repoPath) : undefined; let stash = this.useCaching ? this._stashesCache.get(repoPath) : undefined;
if (stash === undefined) { if (stash === undefined) {
const data = await Git.stash__list(repoPath, { const data = await Git.stash__list(repoPath, {
similarityThreshold: Container.config.advanced.similarityThreshold,
similarityThreshold: this.container.config.advanced.similarityThreshold,
}); });
stash = GitStashParser.parse(data, repoPath); stash = GitStashParser.parse(data, repoPath);
@ -3691,7 +3686,7 @@ export class GitService implements Disposable {
const porcelainVersion = Git.validateVersion(2, 11) ? 2 : 1; const porcelainVersion = Git.validateVersion(2, 11) ? 2 : 1;
const data = await Git.status__file(repoPath, fileName, porcelainVersion, { const data = await Git.status__file(repoPath, fileName, porcelainVersion, {
similarityThreshold: Container.config.advanced.similarityThreshold,
similarityThreshold: this.container.config.advanced.similarityThreshold,
}); });
const status = GitStatusParser.parse(data, repoPath, porcelainVersion); const status = GitStatusParser.parse(data, repoPath, porcelainVersion);
if (status == null || !status.files.length) return undefined; if (status == null || !status.files.length) return undefined;
@ -3704,7 +3699,7 @@ export class GitService implements Disposable {
const porcelainVersion = Git.validateVersion(2, 11) ? 2 : 1; const porcelainVersion = Git.validateVersion(2, 11) ? 2 : 1;
const data = await Git.status__file(repoPath, path, porcelainVersion, { const data = await Git.status__file(repoPath, path, porcelainVersion, {
similarityThreshold: Container.config.advanced.similarityThreshold,
similarityThreshold: this.container.config.advanced.similarityThreshold,
}); });
const status = GitStatusParser.parse(data, repoPath, porcelainVersion); const status = GitStatusParser.parse(data, repoPath, porcelainVersion);
if (status == null || !status.files.length) return []; if (status == null || !status.files.length) return [];
@ -3719,7 +3714,7 @@ export class GitService implements Disposable {
const porcelainVersion = Git.validateVersion(2, 11) ? 2 : 1; const porcelainVersion = Git.validateVersion(2, 11) ? 2 : 1;
const data = await Git.status(repoPath, porcelainVersion, { const data = await Git.status(repoPath, porcelainVersion, {
similarityThreshold: Container.config.advanced.similarityThreshold,
similarityThreshold: this.container.config.advanced.similarityThreshold,
}); });
const status = GitStatusParser.parse(data, repoPath, porcelainVersion); const status = GitStatusParser.parse(data, repoPath, porcelainVersion);
@ -3857,8 +3852,8 @@ export class GitService implements Disposable {
// TODO: Add caching // TODO: Add caching
// Get the most recent commit for this file name // Get the most recent commit for this file name
ref = await Git.log__file_recent(repoPath, fileName, { ref = await Git.log__file_recent(repoPath, fileName, {
ordering: Container.config.advanced.commitOrdering,
similarityThreshold: Container.config.advanced.similarityThreshold,
ordering: this.container.config.advanced.commitOrdering,
similarityThreshold: this.container.config.advanced.similarityThreshold,
}); });
if (ref == null) return undefined; if (ref == null) return undefined;
@ -3867,7 +3862,7 @@ export class GitService implements Disposable {
filters: ['R', 'C', 'D'], filters: ['R', 'C', 'D'],
format: 'simple', format: 'simple',
limit: 1, limit: 1,
ordering: Container.config.advanced.commitOrdering,
ordering: this.container.config.advanced.commitOrdering,
}); });
if (data == null || data.length === 0) break; if (data == null || data.length === 0) break;
@ -3937,7 +3932,7 @@ export class GitService implements Disposable {
editor = editor ?? window.activeTextEditor; editor = editor ?? window.activeTextEditor;
if (editor == null) return false; if (editor == null) return false;
const doc = await Container.tracker.getOrAdd(editor.document.uri);
const doc = await this.container.tracker.getOrAdd(editor.document.uri);
return repoPath === doc?.uri.repoPath; return repoPath === doc?.uri.repoPath;
} }
@ -4053,7 +4048,7 @@ export class GitService implements Disposable {
if (!options.tool) { if (!options.tool) {
const cc = Logger.getCorrelationContext(); const cc = Logger.getCorrelationContext();
options.tool = Container.config.advanced.externalDiffTool || (await this.getDiffTool(repoPath));
options.tool = this.container.config.advanced.externalDiffTool || (await this.getDiffTool(repoPath));
if (options.tool == null) throw new Error('No diff tool found'); if (options.tool == null) throw new Error('No diff tool found');
Logger.log(cc, `Using tool=${options.tool}`); Logger.log(cc, `Using tool=${options.tool}`);
@ -4089,7 +4084,7 @@ export class GitService implements Disposable {
if (!tool) { if (!tool) {
const cc = Logger.getCorrelationContext(); const cc = Logger.getCorrelationContext();
tool = Container.config.advanced.externalDirectoryDiffTool || (await this.getDiffTool(repoPath));
tool = this.container.config.advanced.externalDirectoryDiffTool || (await this.getDiffTool(repoPath));
if (tool == null) throw new Error('No diff tool found'); if (tool == null) throw new Error('No diff tool found');
Logger.log(cc, `Using tool=${tool}`); Logger.log(cc, `Using tool=${tool}`);
@ -4154,7 +4149,7 @@ export class GitService implements Disposable {
repoPath, repoPath,
blob, blob,
ref, ref,
Container.config.advanced.commitOrdering,
this.container.config.advanced.commitOrdering,
fileName, fileName,
); );
if (options?.timeout != null) { if (options?.timeout != null) {
@ -4165,7 +4160,7 @@ export class GitService implements Disposable {
} }
@log() @log()
validateBranchOrTagName(ref: string, repoPath?: string): Promise<boolean> {
validateBranchOrTagName(repoPath: string, ref: string): Promise<boolean> {
return Git.check_ref_format(ref, repoPath); return Git.check_ref_format(ref, repoPath);
} }

+ 5
- 5
src/git/gitUri.ts View File

@ -215,7 +215,7 @@ export class GitUri extends (Uri as any as UriEx) {
static file(path: string, useVslsScheme?: boolean) { static file(path: string, useVslsScheme?: boolean) {
const uri = Uri.file(path); const uri = Uri.file(path);
if (Container.vsls.isMaybeGuest && useVslsScheme !== false) {
if (Container.instance.vsls.isMaybeGuest && useVslsScheme !== false) {
return uri.with({ scheme: DocumentSchemes.Vsls }); return uri.with({ scheme: DocumentSchemes.Vsls });
} }
@ -257,7 +257,7 @@ export class GitUri extends (Uri as any as UriEx) {
static async fromUri(uri: Uri): Promise<GitUri> { static async fromUri(uri: Uri): Promise<GitUri> {
if (GitUri.is(uri)) return uri; if (GitUri.is(uri)) return uri;
if (!Container.git.isTrackable(uri)) return new GitUri(uri);
if (!Container.instance.git.isTrackable(uri)) return new GitUri(uri);
if (uri.scheme === DocumentSchemes.GitLens) return new GitUri(uri); if (uri.scheme === DocumentSchemes.GitLens) return new GitUri(uri);
@ -266,7 +266,7 @@ export class GitUri extends (Uri as any as UriEx) {
try { try {
const data: { path: string; ref: string } = JSON.parse(uri.query); const data: { path: string; ref: string } = JSON.parse(uri.query);
const repoPath = await Container.git.getRepoPath(data.path);
const repoPath = await Container.instance.git.getRepoPath(data.path);
let ref; let ref;
switch (data.ref) { switch (data.ref) {
@ -309,7 +309,7 @@ export class GitUri extends (Uri as any as UriEx) {
if (repoPath.endsWith(data.fileName)) { if (repoPath.endsWith(data.fileName)) {
repoPath = repoPath.substr(0, repoPath.length - data.fileName.length - 1); repoPath = repoPath.substr(0, repoPath.length - data.fileName.length - 1);
} else { } else {
repoPath = (await Container.git.getRepoPath(uri.fsPath))!;
repoPath = (await Container.instance.git.getRepoPath(uri.fsPath))!;
} }
const commitish: GitCommitish = { const commitish: GitCommitish = {
@ -321,7 +321,7 @@ export class GitUri extends (Uri as any as UriEx) {
} catch {} } catch {}
} }
return new GitUri(uri, await Container.git.getRepoPath(uri));
return new GitUri(uri, await Container.instance.git.getRepoPath(uri));
} }
static getDirectory(fileName: string, relativeTo?: string): string { static getDirectory(fileName: string, relativeTo?: string): string {

+ 6
- 6
src/git/models/branch.ts View File

@ -180,7 +180,7 @@ export class GitBranch implements GitBranchReference {
const remote = await this.getRemote(); const remote = await this.getRemote();
if (remote == null) return undefined; if (remote == null) return undefined;
return Container.git.getPullRequestForBranch(this.getNameWithoutRemote(), remote, options);
return Container.instance.git.getPullRequestForBranch(this.getNameWithoutRemote(), remote, options);
} }
@memoize() @memoize()
@ -205,7 +205,7 @@ export class GitBranch implements GitBranchReference {
const remoteName = this.getRemoteName(); const remoteName = this.getRemoteName();
if (remoteName == null) return undefined; if (remoteName == null) return undefined;
const remotes = await Container.git.getRemotes(this.repoPath);
const remotes = await Container.instance.git.getRemotes(this.repoPath);
if (remotes.length === 0) return undefined; if (remotes.length === 0) return undefined;
return remotes.find(r => r.name === remoteName); return remotes.find(r => r.name === remoteName);
@ -231,7 +231,7 @@ export class GitBranch implements GitBranchReference {
return GitBranchStatus.UpToDate; return GitBranchStatus.UpToDate;
} }
const remotes = await Container.git.getRemotes(this.repoPath);
const remotes = await Container.instance.git.getRemotes(this.repoPath);
if (remotes.length > 0) return GitBranchStatus.Unpublished; if (remotes.length > 0) return GitBranchStatus.Unpublished;
return GitBranchStatus.Local; return GitBranchStatus.Local;
@ -250,16 +250,16 @@ export class GitBranch implements GitBranchReference {
} }
get starred() { get starred() {
const starred = Container.context.workspaceState.get<Starred>(WorkspaceState.StarredBranches);
const starred = Container.instance.context.workspaceState.get<Starred>(WorkspaceState.StarredBranches);
return starred !== undefined && starred[this.id] === true; return starred !== undefined && starred[this.id] === true;
} }
async star() { async star() {
await (await Container.git.getRepository(this.repoPath))?.star(this);
await (await Container.instance.git.getRepository(this.repoPath))?.star(this);
} }
async unstar() { async unstar() {
await (await Container.git.getRepository(this.repoPath))?.unstar(this);
await (await Container.instance.git.getRepository(this.repoPath))?.unstar(this);
} }
static formatDetached(sha: string): string { static formatDetached(sha: string): string {

+ 4
- 4
src/git/models/commit.ts View File

@ -148,10 +148,10 @@ export abstract class GitCommit implements GitRevisionReference {
@memoize() @memoize()
async getAssociatedPullRequest(options?: { timeout?: number }): Promise<PullRequest | undefined> { async getAssociatedPullRequest(options?: { timeout?: number }): Promise<PullRequest | undefined> {
const remote = await Container.git.getRichRemoteProvider(this.repoPath);
const remote = await Container.instance.git.getRichRemoteProvider(this.repoPath);
if (remote?.provider == null) return undefined; if (remote?.provider == null) return undefined;
return Container.git.getPullRequestForCommit(this.ref, remote, options);
return Container.instance.git.getPullRequestForCommit(this.ref, remote, options);
} }
@memoize<GitCommit['getPreviousLineDiffUris']>( @memoize<GitCommit['getPreviousLineDiffUris']>(
@ -160,14 +160,14 @@ export abstract class GitCommit implements GitRevisionReference {
getPreviousLineDiffUris(uri: Uri, editorLine: number, ref: string | undefined) { getPreviousLineDiffUris(uri: Uri, editorLine: number, ref: string | undefined) {
if (!this.isFile) return Promise.resolve(undefined); if (!this.isFile) return Promise.resolve(undefined);
return Container.git.getPreviousLineDiffUris(this.repoPath, uri, editorLine, ref);
return Container.instance.git.getPreviousLineDiffUris(this.repoPath, uri, editorLine, ref);
} }
@memoize() @memoize()
getWorkingUri(): Promise<Uri | undefined> { getWorkingUri(): Promise<Uri | undefined> {
if (!this.isFile) return Promise.resolve(undefined); if (!this.isFile) return Promise.resolve(undefined);
return Container.git.getWorkingUri(this.repoPath, this.uri);
return Container.instance.git.getWorkingUri(this.repoPath, this.uri);
} }
@memoize() @memoize()

+ 1
- 1
src/git/models/models.ts View File

@ -77,7 +77,7 @@ export namespace GitRevision {
if (!force && !isShaLike(ref)) return ref; if (!force && !isShaLike(ref)) return ref;
// Don't allow shas to be shortened to less than 5 characters // Don't allow shas to be shortened to less than 5 characters
const len = Math.max(5, Container.config.advanced.abbreviatedShaLength);
const len = Math.max(5, Container.instance.config.advanced.abbreviatedShaLength);
// If we have a suffix, append it // If we have a suffix, append it
const match = shaShortenRegex.exec(ref); const match = shaShortenRegex.exec(ref);

+ 7
- 4
src/git/models/remote.ts View File

@ -59,7 +59,7 @@ export class GitRemote
) {} ) {}
get default() { get default() {
const defaultRemote = Container.context.workspaceState.get<string>(WorkspaceState.DefaultRemote);
const defaultRemote = Container.instance.context.workspaceState.get<string>(WorkspaceState.DefaultRemote);
return this.id === defaultRemote; return this.id === defaultRemote;
} }
@ -79,12 +79,15 @@ export class GitRemote
} }
async setAsDefault(state: boolean = true, updateViews: boolean = true) { async setAsDefault(state: boolean = true, updateViews: boolean = true) {
void (await Container.context.workspaceState.update(WorkspaceState.DefaultRemote, state ? this.id : undefined));
void (await Container.instance.context.workspaceState.update(
WorkspaceState.DefaultRemote,
state ? this.id : undefined,
));
// TODO@eamodio this is UGLY // TODO@eamodio this is UGLY
if (updateViews) { if (updateViews) {
void (await Container.remotesView.refresh());
void (await Container.repositoriesView.refresh());
void (await Container.instance.remotesView.refresh());
void (await Container.instance.repositoriesView.refresh());
} }
} }
} }

+ 36
- 30
src/git/models/repository.ts View File

@ -157,14 +157,14 @@ export class Repository implements Disposable {
} }
if (short) { if (short) {
return formatter.format(Container.config.defaultDateShortFormat ?? 'MMM D, YYYY');
return formatter.format(Container.instance.config.defaultDateShortFormat ?? 'MMM D, YYYY');
} }
let format = let format =
Container.config.defaultDateFormat ??
`dddd, MMMM Do, YYYY [at] ${Container.config.defaultTimeFormat ?? 'h:mma'}`;
Container.instance.config.defaultDateFormat ??
`dddd, MMMM Do, YYYY [at] ${Container.instance.config.defaultTimeFormat ?? 'h:mma'}`;
if (!/[hHm]/.test(format)) { if (!/[hHm]/.test(format)) {
format += ` [at] ${Container.config.defaultTimeFormat ?? 'h:mma'}`;
format += ` [at] ${Container.instance.config.defaultTimeFormat ?? 'h:mma'}`;
} }
return formatter.format(format); return formatter.format(format);
} }
@ -298,6 +298,10 @@ export class Repository implements Disposable {
this._disposable.dispose(); this._disposable.dispose();
} }
get uri(): Uri {
return Uri.file(this.path);
}
private _supportsChangeEvents: boolean = true; private _supportsChangeEvents: boolean = true;
get supportsChangeEvents(): boolean { get supportsChangeEvents(): boolean {
return this._supportsChangeEvents; return this._supportsChangeEvents;
@ -524,7 +528,7 @@ export class Repository implements Disposable {
options: { all?: boolean; branch?: GitBranchReference; prune?: boolean; pull?: boolean; remote?: string } = {}, options: { all?: boolean; branch?: GitBranchReference; prune?: boolean; pull?: boolean; remote?: string } = {},
) { ) {
try { try {
void (await Container.git.fetch(this.path, options));
void (await Container.instance.git.fetch(this.path, options));
this.fireChange(RepositoryChange.Unknown); this.fireChange(RepositoryChange.Unknown);
} catch (ex) { } catch (ex) {
@ -540,7 +544,7 @@ export class Repository implements Disposable {
} }
if (this._branch == null || !this.supportsChangeEvents) { if (this._branch == null || !this.supportsChangeEvents) {
this._branch = Container.git.getBranch(this.path);
this._branch = Container.instance.git.getBranch(this.path);
} }
return this._branch; return this._branch;
} }
@ -551,7 +555,7 @@ export class Repository implements Disposable {
sort?: boolean | BranchSortOptions; sort?: boolean | BranchSortOptions;
} = {}, } = {},
): Promise<GitBranch[]> { ): Promise<GitBranch[]> {
return Container.git.getBranches(this.path, options);
return Container.instance.git.getBranches(this.path, options);
} }
getBranchesAndOrTags( getBranchesAndOrTags(
@ -561,19 +565,19 @@ export class Repository implements Disposable {
sort?: boolean | { branches?: BranchSortOptions; tags?: TagSortOptions }; sort?: boolean | { branches?: BranchSortOptions; tags?: TagSortOptions };
} = {}, } = {},
) { ) {
return Container.git.getBranchesAndOrTags(this.path, options);
return Container.instance.git.getBranchesAndOrTags(this.path, options);
} }
getChangedFilesCount(sha?: string): Promise<GitDiffShortStat | undefined> { getChangedFilesCount(sha?: string): Promise<GitDiffShortStat | undefined> {
return Container.git.getChangedFilesCount(this.path, sha);
return Container.instance.git.getChangedFilesCount(this.path, sha);
} }
getCommit(ref: string): Promise<GitLogCommit | undefined> { getCommit(ref: string): Promise<GitLogCommit | undefined> {
return Container.git.getCommit(this.path, ref);
return Container.instance.git.getCommit(this.path, ref);
} }
getContributors(options?: { all?: boolean; ref?: string; stats?: boolean }): Promise<GitContributor[]> { getContributors(options?: { all?: boolean; ref?: string; stats?: boolean }): Promise<GitContributor[]> {
return Container.git.getContributors(this.path, options);
return Container.instance.git.getContributors(this.path, options);
} }
private _lastFetched: number | undefined; private _lastFetched: number | undefined;
@ -581,7 +585,7 @@ export class Repository implements Disposable {
async getLastFetched(): Promise<number> { async getLastFetched(): Promise<number> {
if (this._lastFetched == null) { if (this._lastFetched == null) {
const hasRemotes = await this.hasRemotes(); const hasRemotes = await this.hasRemotes();
if (!hasRemotes || Container.vsls.isMaybeGuest) return 0;
if (!hasRemotes || Container.instance.vsls.isMaybeGuest) return 0;
} }
try { try {
@ -598,11 +602,11 @@ export class Repository implements Disposable {
} }
getMergeStatus(): Promise<GitMergeStatus | undefined> { getMergeStatus(): Promise<GitMergeStatus | undefined> {
return Container.git.getMergeStatus(this.path);
return Container.instance.git.getMergeStatus(this.path);
} }
getRebaseStatus(): Promise<GitRebaseStatus | undefined> { getRebaseStatus(): Promise<GitRebaseStatus | undefined> {
return Container.git.getRebaseStatus(this.path);
return Container.instance.git.getRebaseStatus(this.path);
} }
async getRemote(remote: string): Promise<GitRemote | undefined> { async getRemote(remote: string): Promise<GitRemote | undefined> {
@ -617,7 +621,7 @@ export class Repository implements Disposable {
} }
// Since we are caching the results, always sort // Since we are caching the results, always sort
this._remotes = Container.git.getRemotesCore(this.path, this._providers, { sort: true });
this._remotes = Container.instance.git.getRemotesCore(this.path, this._providers, { sort: true });
void this.subscribeToRemotes(this._remotes); void this.subscribeToRemotes(this._remotes);
} }
@ -625,7 +629,9 @@ export class Repository implements Disposable {
} }
async getRichRemote(connectedOnly: boolean = false): Promise<GitRemote<RichRemoteProvider> | undefined> { async getRichRemote(connectedOnly: boolean = false): Promise<GitRemote<RichRemoteProvider> | undefined> {
return Container.git.getRichRemoteProvider(await this.getRemotes(), { includeDisconnected: !connectedOnly });
return Container.instance.git.getRichRemoteProvider(await this.getRemotes(), {
includeDisconnected: !connectedOnly,
});
} }
private async subscribeToRemotes(remotes: Promise<GitRemote[]>) { private async subscribeToRemotes(remotes: Promise<GitRemote[]>) {
@ -642,15 +648,15 @@ export class Repository implements Disposable {
} }
getStash(): Promise<GitStash | undefined> { getStash(): Promise<GitStash | undefined> {
return Container.git.getStash(this.path);
return Container.instance.git.getStash(this.path);
} }
getStatus(): Promise<GitStatus | undefined> { getStatus(): Promise<GitStatus | undefined> {
return Container.git.getStatusForRepo(this.path);
return Container.instance.git.getStatusForRepo(this.path);
} }
getTags(options?: { filter?: (t: GitTag) => boolean; sort?: boolean | TagSortOptions }): Promise<GitTag[]> { getTags(options?: { filter?: (t: GitTag) => boolean; sort?: boolean | TagSortOptions }): Promise<GitTag[]> {
return Container.git.getTags(this.path, options);
return Container.instance.git.getTags(this.path, options);
} }
async hasRemotes(): Promise<boolean> { async hasRemotes(): Promise<boolean> {
@ -698,7 +704,7 @@ export class Repository implements Disposable {
this.path, this.path,
)); ));
} else if (configuration.getAny<boolean>(BuiltInGitConfiguration.FetchOnPull, Uri.file(this.path))) { } else if (configuration.getAny<boolean>(BuiltInGitConfiguration.FetchOnPull, Uri.file(this.path))) {
void (await Container.git.fetch(this.path));
void (await Container.instance.git.fetch(this.path));
} }
this.fireChange(RepositoryChange.Unknown); this.fireChange(RepositoryChange.Unknown);
@ -735,7 +741,7 @@ export class Repository implements Disposable {
} }
private async showCreatePullRequestPrompt(remoteName: string, branch: GitBranchReference) { private async showCreatePullRequestPrompt(remoteName: string, branch: GitBranchReference) {
if (!Container.actionRunners.count('createPullRequest')) return;
if (!Container.instance.actionRunners.count('createPullRequest')) return;
if (!(await Messages.showCreatePullRequestPrompt(branch.name))) return; if (!(await Messages.showCreatePullRequestPrompt(branch.name))) return;
const remote = await this.getRemote(remoteName); const remote = await this.getRemote(remoteName);
@ -871,11 +877,11 @@ export class Repository implements Disposable {
search: SearchPattern, search: SearchPattern,
options: { limit?: number; skip?: number } = {}, options: { limit?: number; skip?: number } = {},
): Promise<GitLog | undefined> { ): Promise<GitLog | undefined> {
return Container.git.getLogForSearch(this.path, search, options);
return Container.instance.git.getLogForSearch(this.path, search, options);
} }
get starred() { get starred() {
const starred = Container.context.workspaceState.get<Starred>(WorkspaceState.StarredRepositories);
const starred = Container.instance.context.workspaceState.get<Starred>(WorkspaceState.StarredRepositories);
return starred != null && starred[this.id] === true; return starred != null && starred[this.id] === true;
} }
@ -886,7 +892,7 @@ export class Repository implements Disposable {
@gate(() => '') @gate(() => '')
@log() @log()
async stashApply(stashName: string, options: { deleteAfter?: boolean } = {}) { async stashApply(stashName: string, options: { deleteAfter?: boolean } = {}) {
void (await Container.git.stashApply(this.path, stashName, options));
void (await Container.instance.git.stashApply(this.path, stashName, options));
this.fireChange(RepositoryChange.Stash); this.fireChange(RepositoryChange.Stash);
} }
@ -894,7 +900,7 @@ export class Repository implements Disposable {
@gate(() => '') @gate(() => '')
@log() @log()
async stashDelete(stashName: string, ref?: string) { async stashDelete(stashName: string, ref?: string) {
void (await Container.git.stashDelete(this.path, stashName, ref));
void (await Container.instance.git.stashDelete(this.path, stashName, ref));
this.fireChange(RepositoryChange.Stash); this.fireChange(RepositoryChange.Stash);
} }
@ -902,7 +908,7 @@ export class Repository implements Disposable {
@gate(() => '') @gate(() => '')
@log() @log()
async stashSave(message?: string, uris?: Uri[], options: { includeUntracked?: boolean; keepIndex?: boolean } = {}) { async stashSave(message?: string, uris?: Uri[], options: { includeUntracked?: boolean; keepIndex?: boolean } = {}) {
void (await Container.git.stashSave(this.path, message, uris, options));
void (await Container.instance.git.stashSave(this.path, message, uris, options));
this.fireChange(RepositoryChange.Stash); this.fireChange(RepositoryChange.Stash);
} }
@ -925,7 +931,7 @@ export class Repository implements Disposable {
private async switchCore(ref: string, options: { createBranch?: string } = {}) { private async switchCore(ref: string, options: { createBranch?: string } = {}) {
try { try {
void (await Container.git.checkout(this.path, ref, options));
void (await Container.instance.git.checkout(this.path, ref, options));
this.fireChange(RepositoryChange.Unknown); this.fireChange(RepositoryChange.Unknown);
} catch (ex) { } catch (ex) {
@ -954,7 +960,7 @@ export class Repository implements Disposable {
} }
private async updateStarredCore(key: WorkspaceState, id: string, star: boolean) { private async updateStarredCore(key: WorkspaceState, id: string, star: boolean) {
let starred = Container.context.workspaceState.get<Starred>(key);
let starred = Container.instance.context.workspaceState.get<Starred>(key);
if (starred === undefined) { if (starred === undefined) {
starred = Object.create(null) as Starred; starred = Object.create(null) as Starred;
} }
@ -965,7 +971,7 @@ export class Repository implements Disposable {
const { [id]: _, ...rest } = starred; const { [id]: _, ...rest } = starred;
starred = rest; starred = rest;
} }
await Container.context.workspaceState.update(key, starred);
await Container.instance.context.workspaceState.update(key, starred);
this.fireChange(RepositoryChange.Starred); this.fireChange(RepositoryChange.Starred);
} }
@ -1081,7 +1087,7 @@ export class Repository implements Disposable {
this._pendingFileSystemChange = undefined; this._pendingFileSystemChange = undefined;
const uris = await Container.git.excludeIgnoredUris(this.path, e.uris);
const uris = await Container.instance.git.excludeIgnoredUris(this.path, e.uris);
if (uris.length === 0) return; if (uris.length === 0) return;
if (uris.length !== e.uris.length) { if (uris.length !== e.uris.length) {

+ 1
- 1
src/git/models/stashCommit.ts View File

@ -58,7 +58,7 @@ export class GitStashCommit extends GitLogCommit {
// Check for any untracked files -- since git doesn't return them via `git stash list` :( // Check for any untracked files -- since git doesn't return them via `git stash list` :(
// See https://stackoverflow.com/questions/12681529/ // See https://stackoverflow.com/questions/12681529/
const commit = await Container.git.getCommit(this.repoPath, `${this.stashName}^3`);
const commit = await Container.instance.git.getCommit(this.repoPath, `${this.stashName}^3`);
if (commit != null && commit.files.length !== 0) { if (commit != null && commit.files.length !== 0) {
// Since these files are untracked -- make them look that way // Since these files are untracked -- make them look that way
const files = commit.files.map(s => ({ const files = commit.files.map(s => ({

+ 1
- 1
src/git/models/status.ts View File

@ -234,7 +234,7 @@ export class GitStatus {
async getRemote(): Promise<GitRemote | undefined> { async getRemote(): Promise<GitRemote | undefined> {
if (this.upstream == null) return undefined; if (this.upstream == null) return undefined;
const remotes = await Container.git.getRemotes(this.repoPath);
const remotes = await Container.instance.git.getRemotes(this.repoPath);
if (remotes.length === 0) return undefined; if (remotes.length === 0) return undefined;
const remoteName = GitBranch.getRemote(this.upstream); const remoteName = GitBranch.getRemote(this.upstream);

+ 6
- 6
src/git/remotes/github.ts View File

@ -188,7 +188,7 @@ export class GitHubRemote extends RichRemoteProvider {
}, },
): Promise<Account | undefined> { ): Promise<Account | undefined> {
const [owner, repo] = this.splitPath(); const [owner, repo] = this.splitPath();
return (await Container.github)?.getAccountForCommit(this, accessToken, owner, repo, ref, {
return (await Container.instance.github)?.getAccountForCommit(this, accessToken, owner, repo, ref, {
...options, ...options,
baseUrl: this.apiBaseUrl, baseUrl: this.apiBaseUrl,
}); });
@ -202,7 +202,7 @@ export class GitHubRemote extends RichRemoteProvider {
}, },
): Promise<Account | undefined> { ): Promise<Account | undefined> {
const [owner, repo] = this.splitPath(); const [owner, repo] = this.splitPath();
return (await Container.github)?.getAccountForEmail(this, accessToken, owner, repo, email, {
return (await Container.instance.github)?.getAccountForEmail(this, accessToken, owner, repo, email, {
...options, ...options,
baseUrl: this.apiBaseUrl, baseUrl: this.apiBaseUrl,
}); });
@ -212,7 +212,7 @@ export class GitHubRemote extends RichRemoteProvider {
accessToken, accessToken,
}: AuthenticationSession): Promise<DefaultBranch | undefined> { }: AuthenticationSession): Promise<DefaultBranch | undefined> {
const [owner, repo] = this.splitPath(); const [owner, repo] = this.splitPath();
return (await Container.github)?.getDefaultBranch(this, accessToken, owner, repo, {
return (await Container.instance.github)?.getDefaultBranch(this, accessToken, owner, repo, {
baseUrl: this.apiBaseUrl, baseUrl: this.apiBaseUrl,
}); });
} }
@ -221,7 +221,7 @@ export class GitHubRemote extends RichRemoteProvider {
id: string, id: string,
): Promise<IssueOrPullRequest | undefined> { ): Promise<IssueOrPullRequest | undefined> {
const [owner, repo] = this.splitPath(); const [owner, repo] = this.splitPath();
return (await Container.github)?.getIssueOrPullRequest(this, accessToken, owner, repo, Number(id), {
return (await Container.instance.github)?.getIssueOrPullRequest(this, accessToken, owner, repo, Number(id), {
baseUrl: this.apiBaseUrl, baseUrl: this.apiBaseUrl,
}); });
} }
@ -237,7 +237,7 @@ export class GitHubRemote extends RichRemoteProvider {
const [owner, repo] = this.splitPath(); const [owner, repo] = this.splitPath();
const { include, ...opts } = options ?? {}; const { include, ...opts } = options ?? {};
return (await Container.github)?.getPullRequestForBranch(this, accessToken, owner, repo, branch, {
return (await Container.instance.github)?.getPullRequestForBranch(this, accessToken, owner, repo, branch, {
...opts, ...opts,
include: include?.map(s => GitHubPullRequest.toState(s)), include: include?.map(s => GitHubPullRequest.toState(s)),
baseUrl: this.apiBaseUrl, baseUrl: this.apiBaseUrl,
@ -249,7 +249,7 @@ export class GitHubRemote extends RichRemoteProvider {
ref: string, ref: string,
): Promise<PullRequest | undefined> { ): Promise<PullRequest | undefined> {
const [owner, repo] = this.splitPath(); const [owner, repo] = this.splitPath();
return (await Container.github)?.getPullRequestForCommit(this, accessToken, owner, repo, ref, {
return (await Container.instance.github)?.getPullRequestForCommit(this, accessToken, owner, repo, ref, {
baseUrl: this.apiBaseUrl, baseUrl: this.apiBaseUrl,
}); });
} }

+ 8
- 8
src/git/remotes/provider.ts View File

@ -281,7 +281,7 @@ export abstract class RichRemoteProvider extends RemoteProvider {
constructor(domain: string, path: string, protocol?: string, name?: string, custom?: boolean) { constructor(domain: string, path: string, protocol?: string, name?: string, custom?: boolean) {
super(domain, path, protocol, name, custom); super(domain, path, protocol, name, custom);
Container.context.subscriptions.push(
Container.instance.context.subscriptions.push(
// TODO@eamodio revisit how connections are linked or not // TODO@eamodio revisit how connections are linked or not
Authentication.onDidChange(e => { Authentication.onDidChange(e => {
if (e.key !== this.key) return; if (e.key !== this.key) return;
@ -346,7 +346,7 @@ export abstract class RichRemoteProvider extends RemoteProvider {
this._session = null; this._session = null;
if (disconnected) { if (disconnected) {
void Container.context.workspaceState.update(this.connectedKey, false);
void Container.instance.context.workspaceState.update(this.connectedKey, false);
this._onDidChange.fire(); this._onDidChange.fire();
if (!silent) { if (!silent) {
@ -570,11 +570,11 @@ export abstract class RichRemoteProvider extends RemoteProvider {
private async ensureSession(createIfNeeded: boolean): Promise<AuthenticationSession | undefined> { private async ensureSession(createIfNeeded: boolean): Promise<AuthenticationSession | undefined> {
if (this._session != null) return this._session; if (this._session != null) return this._session;
if (!Container.config.integrations.enabled) return undefined;
if (!Container.instance.config.integrations.enabled) return undefined;
if (createIfNeeded) { if (createIfNeeded) {
await Container.context.workspaceState.update(this.connectedKey, undefined);
} else if (Container.context.workspaceState.get<boolean>(this.connectedKey) === false) {
await Container.instance.context.workspaceState.update(this.connectedKey, undefined);
} else if (Container.instance.context.workspaceState.get<boolean>(this.connectedKey) === false) {
return undefined; return undefined;
} }
@ -584,7 +584,7 @@ export abstract class RichRemoteProvider extends RemoteProvider {
createIfNone: createIfNeeded, createIfNone: createIfNeeded,
}); });
} catch (ex) { } catch (ex) {
await Container.context.workspaceState.update(this.connectedKey, undefined);
await Container.instance.context.workspaceState.update(this.connectedKey, undefined);
if (ex instanceof Error && ex.message.includes('User did not consent')) { if (ex instanceof Error && ex.message.includes('User did not consent')) {
return undefined; return undefined;
@ -594,14 +594,14 @@ export abstract class RichRemoteProvider extends RemoteProvider {
} }
if (session === undefined && !createIfNeeded) { if (session === undefined && !createIfNeeded) {
await Container.context.workspaceState.update(this.connectedKey, undefined);
await Container.instance.context.workspaceState.update(this.connectedKey, undefined);
} }
this._session = session ?? null; this._session = session ?? null;
this.invalidClientExceptionCount = 0; this.invalidClientExceptionCount = 0;
if (session != null) { if (session != null) {
await Container.context.workspaceState.update(this.connectedKey, true);
await Container.instance.context.workspaceState.update(this.connectedKey, true);
this._onDidChange.fire(); this._onDidChange.fire();
_onDidChangeAuthentication.fire({ reason: 'connected', key: this.key }); _onDidChangeAuthentication.fire({ reason: 'connected', key: this.key });

+ 12
- 12
src/hovers/hovers.ts View File

@ -50,11 +50,11 @@ export namespace Hovers {
editorLine = commitLine.line - 1; editorLine = commitLine.line - 1;
// TODO: Doesn't work with dirty files -- pass in editor? or contents? // TODO: Doesn't work with dirty files -- pass in editor? or contents?
hunkLine = await Container.git.getDiffForLine(uri, editorLine, ref, documentRef, originalFileName);
hunkLine = await Container.instance.git.getDiffForLine(uri, editorLine, ref, documentRef, originalFileName);
// If we didn't find a diff & ref is undefined (meaning uncommitted), check for a staged diff // If we didn't find a diff & ref is undefined (meaning uncommitted), check for a staged diff
if (hunkLine == null && ref == null) { if (hunkLine == null && ref == null) {
hunkLine = await Container.git.getDiffForLine(
hunkLine = await Container.instance.git.getDiffForLine(
uri, uri,
editorLine, editorLine,
undefined, undefined,
@ -200,7 +200,7 @@ export namespace Hovers {
dateFormat = 'MMMM Do, YYYY h:mma'; dateFormat = 'MMMM Do, YYYY h:mma';
} }
const remotes = await Container.git.getRemotes(commit.repoPath, { sort: true });
const remotes = await Container.instance.git.getRemotes(commit.repoPath, { sort: true });
const [previousLineDiffUris, autolinkedIssuesOrPullRequests, pr, presence] = await Promise.all([ const [previousLineDiffUris, autolinkedIssuesOrPullRequests, pr, presence] = await Promise.all([
commit.isUncommitted ? commit.getPreviousLineDiffUris(uri, editorLine, uri.sha) : undefined, commit.isUncommitted ? commit.getPreviousLineDiffUris(uri, editorLine, uri.sha) : undefined,
@ -218,7 +218,7 @@ export namespace Hovers {
'pullRequestState', 'pullRequestState',
), ),
}), }),
Container.vsls.maybeGetPresence(commit.email),
Container.instance.vsls.maybeGetPresence(commit.email),
]); ]);
const details = await CommitFormatter.fromTemplateAsync(format, commit, { const details = await CommitFormatter.fromTemplateAsync(format, commit, {
@ -247,7 +247,7 @@ export namespace Hovers {
} }
function getDiffFromHunkLine(hunkLine: GitDiffHunkLine, diffStyle?: 'line' | 'hunk'): string { function getDiffFromHunkLine(hunkLine: GitDiffHunkLine, diffStyle?: 'line' | 'hunk'): string {
if (diffStyle === 'hunk' || (diffStyle == null && Container.config.hovers.changesDiff === 'hunk')) {
if (diffStyle === 'hunk' || (diffStyle == null && Container.instance.config.hovers.changesDiff === 'hunk')) {
return getDiffFromHunk(hunkLine.hunk); return getDiffFromHunk(hunkLine.hunk);
} }
@ -263,16 +263,16 @@ export namespace Hovers {
const start = process.hrtime(); const start = process.hrtime();
if ( if (
!Container.config.hovers.autolinks.enabled ||
!Container.config.hovers.autolinks.enhanced ||
!CommitFormatter.has(Container.config.hovers.detailsMarkdownFormat, 'message')
!Container.instance.config.hovers.autolinks.enabled ||
!Container.instance.config.hovers.autolinks.enhanced ||
!CommitFormatter.has(Container.instance.config.hovers.detailsMarkdownFormat, 'message')
) { ) {
Logger.debug(cc, `completed ${GlyphChars.Dot} ${Strings.getDurationMilliseconds(start)} ms`); Logger.debug(cc, `completed ${GlyphChars.Dot} ${Strings.getDurationMilliseconds(start)} ms`);
return undefined; return undefined;
} }
const remote = await Container.git.getRichRemoteProvider(remotes);
const remote = await Container.instance.git.getRichRemoteProvider(remotes);
if (remote?.provider == null) { if (remote?.provider == null) {
Logger.debug(cc, `completed ${GlyphChars.Dot} ${Strings.getDurationMilliseconds(start)} ms`); Logger.debug(cc, `completed ${GlyphChars.Dot} ${Strings.getDurationMilliseconds(start)} ms`);
@ -283,7 +283,7 @@ export namespace Hovers {
const timeout = 250; const timeout = 250;
try { try {
const autolinks = await Container.autolinks.getIssueOrPullRequestLinks(message, remote, {
const autolinks = await Container.instance.autolinks.getIssueOrPullRequestLinks(message, remote, {
timeout: timeout, timeout: timeout,
}); });
@ -347,7 +347,7 @@ export namespace Hovers {
return undefined; return undefined;
} }
const remote = await Container.git.getRichRemoteProvider(remotes, { includeDisconnected: true });
const remote = await Container.instance.git.getRichRemoteProvider(remotes, { includeDisconnected: true });
if (remote?.provider == null) { if (remote?.provider == null) {
Logger.debug(cc, `completed ${GlyphChars.Dot} ${Strings.getDurationMilliseconds(start)} ms`); Logger.debug(cc, `completed ${GlyphChars.Dot} ${Strings.getDurationMilliseconds(start)} ms`);
@ -363,7 +363,7 @@ export namespace Hovers {
} }
try { try {
const pr = await Container.git.getPullRequestForCommit(ref, provider, { timeout: 250 });
const pr = await Container.instance.git.getPullRequestForCommit(ref, provider, { timeout: 250 });
Logger.debug(cc, `completed ${GlyphChars.Dot} ${Strings.getDurationMilliseconds(start)} ms`); Logger.debug(cc, `completed ${GlyphChars.Dot} ${Strings.getDurationMilliseconds(start)} ms`);

+ 34
- 28
src/hovers/lineHoverController.ts View File

@ -24,32 +24,38 @@ export class LineHoverController implements Disposable {
private _hoverProviderDisposable: Disposable | undefined; private _hoverProviderDisposable: Disposable | undefined;
private _uri: Uri | undefined; private _uri: Uri | undefined;
constructor() {
this._disposable = Disposable.from(configuration.onDidChange(this.onConfigurationChanged, this));
this.onConfigurationChanged();
constructor(private readonly container: Container) {
this._disposable = Disposable.from(
container.onReady(this.onReady, this),
configuration.onDidChange(this.onConfigurationChanged, this),
);
} }
dispose() { dispose() {
this.unregister(); this.unregister();
Container.lineTracker.stop(this);
this.container.lineTracker.stop(this);
this._disposable.dispose(); this._disposable.dispose();
} }
private onReady(): void {
this.onConfigurationChanged();
}
private onConfigurationChanged(e?: ConfigurationChangeEvent) { private onConfigurationChanged(e?: ConfigurationChangeEvent) {
if (!configuration.changed(e, 'hovers.enabled') && !configuration.changed(e, 'hovers.currentLine.enabled')) { if (!configuration.changed(e, 'hovers.enabled') && !configuration.changed(e, 'hovers.currentLine.enabled')) {
return; return;
} }
if (Container.config.hovers.enabled && Container.config.hovers.currentLine.enabled) {
Container.lineTracker.start(
if (this.container.config.hovers.enabled && this.container.config.hovers.currentLine.enabled) {
this.container.lineTracker.start(
this, this,
Container.lineTracker.onDidChangeActiveLines(this.onActiveLinesChanged, this),
this.container.lineTracker.onDidChangeActiveLines(this.onActiveLinesChanged, this),
); );
this.register(window.activeTextEditor); this.register(window.activeTextEditor);
} else { } else {
Container.lineTracker.stop(this);
this.container.lineTracker.stop(this);
this.unregister(); this.unregister();
} }
} }
@ -88,21 +94,21 @@ export class LineHoverController implements Disposable {
position: Position, position: Position,
_token: CancellationToken, _token: CancellationToken,
): Promise<Hover | undefined> { ): Promise<Hover | undefined> {
if (!Container.lineTracker.includes(position.line)) return undefined;
if (!this.container.lineTracker.includes(position.line)) return undefined;
const lineState = Container.lineTracker.getState(position.line);
const lineState = this.container.lineTracker.getState(position.line);
const commit = lineState?.commit; const commit = lineState?.commit;
if (commit == null) return undefined; if (commit == null) return undefined;
// Avoid double annotations if we are showing the whole-file hover blame annotations // Avoid double annotations if we are showing the whole-file hover blame annotations
if (Container.config.hovers.annotations.details) {
const fileAnnotations = await Container.fileAnnotations.getAnnotationType(window.activeTextEditor);
if (this.container.config.hovers.annotations.details) {
const fileAnnotations = await this.container.fileAnnotations.getAnnotationType(window.activeTextEditor);
if (fileAnnotations === FileAnnotationType.Blame) return undefined; if (fileAnnotations === FileAnnotationType.Blame) return undefined;
} }
const wholeLine = Container.config.hovers.currentLine.over === 'line';
const wholeLine = this.container.config.hovers.currentLine.over === 'line';
// If we aren't showing the hover over the whole line, make sure the annotation is on // If we aren't showing the hover over the whole line, make sure the annotation is on
if (!wholeLine && Container.lineAnnotations.suspended) return undefined;
if (!wholeLine && this.container.lineAnnotations.suspended) return undefined;
const range = document.validateRange( const range = document.validateRange(
new Range(position.line, wholeLine ? 0 : Number.MAX_SAFE_INTEGER, position.line, Number.MAX_SAFE_INTEGER), new Range(position.line, wholeLine ? 0 : Number.MAX_SAFE_INTEGER, position.line, Number.MAX_SAFE_INTEGER),
@ -112,7 +118,7 @@ export class LineHoverController implements Disposable {
// Get the full commit message -- since blame only returns the summary // Get the full commit message -- since blame only returns the summary
let logCommit = lineState?.logCommit; let logCommit = lineState?.logCommit;
if (logCommit == null && !commit.isUncommitted) { if (logCommit == null && !commit.isUncommitted) {
logCommit = await Container.git.getCommitForFile(commit.repoPath, commit.uri.fsPath, {
logCommit = await this.container.git.getCommitForFile(commit.repoPath, commit.uri.fsPath, {
ref: commit.sha, ref: commit.sha,
}); });
if (logCommit != null) { if (logCommit != null) {
@ -131,19 +137,19 @@ export class LineHoverController implements Disposable {
const commitLine = commit.lines.find(l => l.line === line) ?? commit.lines[0]; const commitLine = commit.lines.find(l => l.line === line) ?? commit.lines[0];
editorLine = commitLine.originalLine - 1; editorLine = commitLine.originalLine - 1;
const trackedDocument = await Container.tracker.get(document);
const trackedDocument = await this.container.tracker.get(document);
if (trackedDocument == null) return undefined; if (trackedDocument == null) return undefined;
const message = await Hovers.detailsMessage( const message = await Hovers.detailsMessage(
logCommit ?? commit, logCommit ?? commit,
trackedDocument.uri, trackedDocument.uri,
editorLine, editorLine,
Container.config.hovers.detailsMarkdownFormat,
Container.config.defaultDateFormat,
this.container.config.hovers.detailsMarkdownFormat,
this.container.config.defaultDateFormat,
{ {
autolinks: Container.config.hovers.autolinks.enabled,
autolinks: this.container.config.hovers.autolinks.enabled,
pullRequests: { pullRequests: {
enabled: Container.config.hovers.pullRequests.enabled,
enabled: this.container.config.hovers.pullRequests.enabled,
}, },
}, },
); );
@ -162,28 +168,28 @@ export class LineHoverController implements Disposable {
position: Position, position: Position,
_token: CancellationToken, _token: CancellationToken,
): Promise<Hover | undefined> { ): Promise<Hover | undefined> {
if (!Container.lineTracker.includes(position.line)) return undefined;
if (!this.container.lineTracker.includes(position.line)) return undefined;
const lineState = Container.lineTracker.getState(position.line);
const lineState = this.container.lineTracker.getState(position.line);
const commit = lineState?.commit; const commit = lineState?.commit;
if (commit == null) return undefined; if (commit == null) return undefined;
// Avoid double annotations if we are showing the whole-file hover blame annotations // Avoid double annotations if we are showing the whole-file hover blame annotations
if (Container.config.hovers.annotations.changes) {
const fileAnnotations = await Container.fileAnnotations.getAnnotationType(window.activeTextEditor);
if (this.container.config.hovers.annotations.changes) {
const fileAnnotations = await this.container.fileAnnotations.getAnnotationType(window.activeTextEditor);
if (fileAnnotations === FileAnnotationType.Blame) return undefined; if (fileAnnotations === FileAnnotationType.Blame) return undefined;
} }
const wholeLine = Container.config.hovers.currentLine.over === 'line';
const wholeLine = this.container.config.hovers.currentLine.over === 'line';
// If we aren't showing the hover over the whole line, make sure the annotation is on // If we aren't showing the hover over the whole line, make sure the annotation is on
if (!wholeLine && Container.lineAnnotations.suspended) return undefined;
if (!wholeLine && this.container.lineAnnotations.suspended) return undefined;
const range = document.validateRange( const range = document.validateRange(
new Range(position.line, wholeLine ? 0 : Number.MAX_SAFE_INTEGER, position.line, Number.MAX_SAFE_INTEGER), new Range(position.line, wholeLine ? 0 : Number.MAX_SAFE_INTEGER, position.line, Number.MAX_SAFE_INTEGER),
); );
if (!wholeLine && range.start.character !== position.character) return undefined; if (!wholeLine && range.start.character !== position.character) return undefined;
const trackedDocument = await Container.tracker.get(document);
const trackedDocument = await this.container.tracker.get(document);
if (trackedDocument == null) return undefined; if (trackedDocument == null) return undefined;
const message = await Hovers.changesMessage(commit, trackedDocument.uri, position.line); const message = await Hovers.changesMessage(commit, trackedDocument.uri, position.line);
@ -201,7 +207,7 @@ export class LineHoverController implements Disposable {
if (editor == null) return; if (editor == null) return;
const cfg = Container.config.hovers;
const cfg = this.container.config.hovers;
if (!cfg.enabled || !cfg.currentLine.enabled || (!cfg.currentLine.details && !cfg.currentLine.changes)) return; if (!cfg.enabled || !cfg.currentLine.enabled || (!cfg.currentLine.details && !cfg.currentLine.changes)) return;
this._uri = editor.document.uri; this._uri = editor.document.uri;

+ 27
- 23
src/partners.ts View File

@ -48,33 +48,37 @@ export function registerPartnerActionRunners(context: ExtensionContext): void {
function registerLiveShare(context: ExtensionContext) { function registerLiveShare(context: ExtensionContext) {
context.subscriptions.push( context.subscriptions.push(
Container.actionRunners.registerBuiltInPartner<HoverCommandsActionContext>('liveshare', 'hover.commands', {
name: 'Live Share',
label: (context: ActionContext) => {
if (context.type === 'hover.commands') {
if (context.commit.author.name !== 'You') {
return `$(live-share) Invite ${context.commit.author.name}${
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
context.commit.author.presence?.statusText
? ` (${context.commit.author.presence?.statusText})`
: ''
} to a Live Share Session`;
Container.instance.actionRunners.registerBuiltInPartner<HoverCommandsActionContext>(
'liveshare',
'hover.commands',
{
name: 'Live Share',
label: (context: ActionContext) => {
if (context.type === 'hover.commands') {
if (context.commit.author.name !== 'You') {
return `$(live-share) Invite ${context.commit.author.name}${
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
context.commit.author.presence?.statusText
? ` (${context.commit.author.presence?.statusText})`
: ''
} to a Live Share Session`;
}
} }
}
return '$(live-share) Start a Live Share Session';
},
run: async (context: ActionContext) => {
if (context.type !== 'hover.commands' || context.commit.author.name === 'You') {
await executeCommand<InviteToLiveShareCommandArgs>(Commands.InviteToLiveShare, {});
return '$(live-share) Start a Live Share Session';
},
run: async (context: ActionContext) => {
if (context.type !== 'hover.commands' || context.commit.author.name === 'You') {
await executeCommand<InviteToLiveShareCommandArgs>(Commands.InviteToLiveShare, {});
return;
}
return;
}
await executeCommand<InviteToLiveShareCommandArgs>(Commands.InviteToLiveShare, {
email: context.commit.author.email,
});
await executeCommand<InviteToLiveShareCommandArgs>(Commands.InviteToLiveShare, {
email: context.commit.author.email,
});
},
}, },
}),
),
); );
} }

+ 1
- 1
src/quickpicks/commitPicker.ts View File

@ -100,7 +100,7 @@ export namespace CommitPicker {
let scope: KeyboardScope | undefined; let scope: KeyboardScope | undefined;
if (options?.keys != null && options.keys.length !== 0 && options?.onDidPressKey !== null) { if (options?.keys != null && options.keys.length !== 0 && options?.onDidPressKey !== null) {
scope = Container.keyboard.createScope(
scope = Container.instance.keyboard.createScope(
Object.fromEntries( Object.fromEntries(
options.keys.map(key => [ options.keys.map(key => [
key, key,

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save