Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Git - close diff editors on operation #142513

Merged
merged 2 commits into from Feb 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions extensions/git/package.json
Expand Up @@ -15,6 +15,7 @@
"scmActionButton",
"scmSelectedProvider",
"scmValidation",
"tabs",
"timeline"
],
"categories": [
Expand Down Expand Up @@ -2113,6 +2114,12 @@
"default": true,
"description": "%config.confirmNoVerifyCommit%"
},
"git.closeDiffOnOperation": {
"type": "boolean",
"scope": "resource",
"default": false,
"description": "%config.closeDiffOnOperation%"
},
"git.openDiffOnClick": {
"type": "boolean",
"scope": "resource",
Expand Down
1 change: 1 addition & 0 deletions extensions/git/package.nls.json
Expand Up @@ -175,6 +175,7 @@
"config.confirmForcePush": "Controls whether to ask for confirmation before force-pushing.",
"config.allowNoVerifyCommit": "Controls whether commits without running pre-commit and commit-msg hooks are allowed.",
"config.confirmNoVerifyCommit": "Controls whether to ask for confirmation before committing without verification.",
"config.closeDiffOnOperation": "Controls whether the diff editor should be automatically closed when changes are committed, discarded, staged, or unstaged.",
"config.openDiffOnClick": "Controls whether the diff editor should be opened when clicking a change. Otherwise the regular editor will be opened.",
"config.supportCancellation": "Controls whether a notification comes up when running the Sync action, which allows the user to cancel the operation.",
"config.branchSortOrder": "Controls the sort order for branches.",
Expand Down
52 changes: 47 additions & 5 deletions extensions/git/src/repository.ts
Expand Up @@ -5,7 +5,7 @@

import * as fs from 'fs';
import * as path from 'path';
import { CancellationToken, Command, Disposable, Event, EventEmitter, Memento, OutputChannel, ProgressLocation, ProgressOptions, scm, SourceControl, SourceControlInputBox, SourceControlInputBoxValidation, SourceControlInputBoxValidationType, SourceControlResourceDecorations, SourceControlResourceGroup, SourceControlResourceState, ThemeColor, Uri, window, workspace, WorkspaceEdit, FileDecoration, commands } from 'vscode';
import { CancellationToken, Command, Disposable, Event, EventEmitter, Memento, OutputChannel, ProgressLocation, ProgressOptions, scm, SourceControl, SourceControlInputBox, SourceControlInputBoxValidation, SourceControlInputBoxValidationType, SourceControlResourceDecorations, SourceControlResourceGroup, SourceControlResourceState, ThemeColor, Uri, window, workspace, WorkspaceEdit, FileDecoration, commands, Tab } from 'vscode';
import TelemetryReporter from '@vscode/extension-telemetry';
import * as nls from 'vscode-nls';
import { Branch, Change, ForcePushMode, GitErrorCodes, LogOptions, Ref, RefType, Remote, Status, CommitOptions, BranchQuery, FetchOptions } from './api/git';
Expand All @@ -14,7 +14,7 @@ import { debounce, memoize, throttle } from './decorators';
import { Commit, GitError, Repository as BaseRepository, Stash, Submodule, LogFileOptions } from './git';
import { StatusBarCommands } from './statusbar';
import { toGitUri } from './uri';
import { anyEvent, combinedDisposable, debounceEvent, dispose, EmptyDisposable, eventToPromise, filterEvent, find, IDisposable, isDescendant, logTimestamp, onceEvent, relativePath } from './util';
import { anyEvent, combinedDisposable, debounceEvent, dispose, EmptyDisposable, eventToPromise, filterEvent, find, IDisposable, isDescendant, logTimestamp, onceEvent, pathEquals, relativePath } from './util';
import { IFileWatcher, watch } from './watch';
import { Log, LogLevel } from './log';
import { IPushErrorHandlerRegistry } from './pushError';
Expand Down Expand Up @@ -1159,7 +1159,10 @@ export class Repository implements Disposable {
}

async add(resources: Uri[], opts?: { update?: boolean }): Promise<void> {
await this.run(Operation.Add, () => this.repository.add(resources.map(r => r.fsPath), opts));
await this.run(Operation.Add, async () => {
await this.repository.add(resources.map(r => r.fsPath), opts);
this.closeDiffEditors([], [...resources.map(r => r.fsPath)]);
});
}

async rm(resources: Uri[]): Promise<void> {
Expand All @@ -1168,15 +1171,27 @@ export class Repository implements Disposable {

async stage(resource: Uri, contents: string): Promise<void> {
const path = relativePath(this.repository.root, resource.fsPath).replace(/\\/g, '/');
await this.run(Operation.Stage, () => this.repository.stage(path, contents));
await this.run(Operation.Stage, async () => {
await this.repository.stage(path, contents);
this.closeDiffEditors([], [...resource.fsPath]);
});
this._onDidChangeOriginalResource.fire(resource);
}

async revert(resources: Uri[]): Promise<void> {
await this.run(Operation.RevertFiles, () => this.repository.revert('HEAD', resources.map(r => r.fsPath)));
await this.run(Operation.RevertFiles, async () => {
await this.repository.revert('HEAD', resources.map(r => r.fsPath));
this.closeDiffEditors([...resources.length !== 0 ?
resources.map(r => r.fsPath) :
this.indexGroup.resourceStates.map(r => r.resourceUri.fsPath)], []);
});
}

async commit(message: string | undefined, opts: CommitOptions = Object.create(null)): Promise<void> {
const indexResources = [...this.indexGroup.resourceStates.map(r => r.resourceUri.fsPath)];
const workingGroupResources = opts.all && opts.all !== 'tracked' ?
[...this.workingTreeGroup.resourceStates.map(r => r.resourceUri.fsPath)] : [];

if (this.rebaseCommit) {
await this.run(Operation.RebaseContinue, async () => {
if (opts.all) {
Expand All @@ -1185,6 +1200,7 @@ export class Repository implements Disposable {
}

await this.repository.rebaseContinue();
this.closeDiffEditors(indexResources, workingGroupResources);
});
} else {
await this.run(Operation.Commit, async () => {
Expand All @@ -1201,6 +1217,7 @@ export class Repository implements Disposable {
}

await this.repository.commit(message, opts);
this.closeDiffEditors(indexResources, workingGroupResources);
});
}
}
Expand Down Expand Up @@ -1244,9 +1261,34 @@ export class Repository implements Disposable {
await this.repository.clean(toClean);
await this.repository.checkout('', toCheckout);
await this.repository.updateSubmodules(submodulesToUpdate);

this.closeDiffEditors([], [...toClean, ...toCheckout]);
});
}

private closeDiffEditors(indexResources: string[], workingTreeResources: string[]): void {
const config = workspace.getConfiguration('git', Uri.file(this.root));
if (!config.get<boolean>('closeDiffOnOperation', false)) { return; }

const diffEditorTabsToClose: Tab[] = [];

// Index
diffEditorTabsToClose.push(...window.tabs
.filter(t =>
t.resource && t.resource.scheme === 'git' && t.viewId === 'diff' &&
indexResources.some(r => pathEquals(r, t.resource!.fsPath))));

// Working Tree
diffEditorTabsToClose.push(...window.tabs
.filter(t =>
t.resource && t.resource.scheme === 'file' && t.viewId === 'diff' &&
workingTreeResources.some(r => pathEquals(r, t.resource!.fsPath)) &&
t.additionalResourcesAndViewIds.find(r => r.resource!.scheme === 'git')));

// Close editors
diffEditorTabsToClose.forEach(t => t.close());
}

async branch(name: string, _checkout: boolean, _ref?: string): Promise<void> {
await this.run(Operation.Branch, () => this.repository.branch(name, _checkout, _ref));
}
Expand Down
1 change: 1 addition & 0 deletions extensions/git/tsconfig.json
Expand Up @@ -14,6 +14,7 @@
"../../src/vscode-dts/vscode.proposed.scmActionButton.d.ts",
"../../src/vscode-dts/vscode.proposed.scmSelectedProvider.d.ts",
"../../src/vscode-dts/vscode.proposed.scmValidation.d.ts",
"../../src/vscode-dts/vscode.proposed.tabs.d.ts",
"../../src/vscode-dts/vscode.proposed.timeline.d.ts",
"../types/lib.textEncoder.d.ts"
]
Expand Down