Revert "Merge from vscode merge-base (#22769)" (#22779)

This reverts commit 6bd0a17d3c.
This commit is contained in:
Karl Burtram
2023-04-18 21:44:05 -07:00
committed by GitHub
parent 6bd0a17d3c
commit 47a1745180
2389 changed files with 42588 additions and 92170 deletions

View File

@@ -5,8 +5,7 @@
import * as fs from 'fs';
import * as path from 'path';
import * as picomatch from 'picomatch';
import { CancellationToken, Command, Disposable, Event, EventEmitter, Memento, ProgressLocation, ProgressOptions, scm, SourceControl, SourceControlInputBox, SourceControlInputBoxValidation, SourceControlInputBoxValidationType, SourceControlResourceDecorations, SourceControlResourceGroup, SourceControlResourceState, ThemeColor, Uri, window, workspace, WorkspaceEdit, FileDecoration, commands, Tab, TabInputTextDiff, TabInputNotebookDiff, RelativePattern } 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, TabInputTextDiff, TabInputNotebookDiff, RelativePattern } 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';
@@ -15,14 +14,13 @@ 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, onceEvent, pathEquals, 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 { LogLevel, OutputChannelLogger } from './log';
import { Log, LogLevel } from './log';
import { IPushErrorHandlerRegistry } from './pushError';
import { ApiRepository } from './api/api1';
import { IRemoteSourcePublisherRegistry } from './remotePublisher';
import { ActionButtonCommand } from './actionButton';
import { IPostCommitCommandsProviderRegistry } from './postCommitCommands';
const timeout = (millis: number) => new Promise(c => setTimeout(c, millis));
@@ -298,10 +296,6 @@ export class Resource implements SourceControlResourceState {
const command = this._commandResolver.resolveChangeCommand(this);
await commands.executeCommand<void>(command.command, ...(command.arguments || []));
}
clone() {
return new Resource(this._commandResolver, this._resourceGroupType, this._resourceUri, this._type, this._useIcons, this._renameResourceUri);
}
}
export const enum Operation {
@@ -456,13 +450,6 @@ class ProgressManager {
const onDidChange = filterEvent(workspace.onDidChangeConfiguration, e => e.affectsConfiguration('git', Uri.file(this.repository.root)));
onDidChange(_ => this.updateEnablement());
this.updateEnablement();
this.repository.onDidChangeOperations(() => {
const commitInProgress = this.repository.operations.isRunning(Operation.Commit);
this.repository.sourceControl.inputBox.enabled = !commitInProgress;
commands.executeCommand('setContext', 'commitInProgress', commitInProgress);
});
}
private updateEnablement(): void {
@@ -517,10 +504,10 @@ class FileEventLogger {
constructor(
private onWorkspaceWorkingTreeFileChange: Event<Uri>,
private onDotGitFileChange: Event<Uri>,
private outputChannelLogger: OutputChannelLogger
private outputChannel: OutputChannel
) {
this.logLevelDisposable = outputChannelLogger.onDidChangeLogLevel(this.onDidChangeLogLevel, this);
this.onDidChangeLogLevel(outputChannelLogger.currentLogLevel);
this.logLevelDisposable = Log.onDidChangeLogLevel(this.onDidChangeLogLevel, this);
this.onDidChangeLogLevel(Log.logLevel);
}
private onDidChangeLogLevel(level: LogLevel): void {
@@ -531,8 +518,8 @@ class FileEventLogger {
}
this.eventDisposable = combinedDisposable([
this.onWorkspaceWorkingTreeFileChange(uri => this.outputChannelLogger.logDebug(`[wt] Change: ${uri.fsPath}`)),
this.onDotGitFileChange(uri => this.outputChannelLogger.logDebug(`[.git] Change: ${uri.fsPath}`))
this.onWorkspaceWorkingTreeFileChange(uri => this.outputChannel.appendLine(`${logTimestamp()} [debug] [wt] Change: ${uri.fsPath}`)),
this.onDotGitFileChange(uri => this.outputChannel.appendLine(`${logTimestamp()} [debug] [.git] Change: ${uri.fsPath}`))
]);
}
@@ -552,14 +539,14 @@ class DotGitWatcher implements IFileWatcher {
constructor(
private repository: Repository,
private outputChannelLogger: OutputChannelLogger
private outputChannel: OutputChannel
) {
const rootWatcher = watch(repository.dotGit.path);
this.disposables.push(rootWatcher);
// Ignore changes to the "index.lock" file, and watchman fsmonitor hook (https://git-scm.com/docs/githooks#_fsmonitor_watchman) cookie files.
// Watchman creates a cookie file inside the git directory whenever a query is run (https://facebook.github.io/watchman/docs/cookies.html).
const filteredRootWatcher = filterEvent(rootWatcher.event, uri => uri.scheme === 'file' && !/\/\.git(\/index\.lock)?$|\/\.watchman-cookie-/.test(uri.path));
const filteredRootWatcher = filterEvent(rootWatcher.event, uri => !/\/\.git(\/index\.lock)?$|\/\.watchman-cookie-/.test(uri.path));
this.event = anyEvent(filteredRootWatcher, this.emitter.event);
repository.onDidRunGitStatus(this.updateTransientWatchers, this, this.disposables);
@@ -583,7 +570,9 @@ class DotGitWatcher implements IFileWatcher {
this.transientDisposables.push(upstreamWatcher);
upstreamWatcher.event(this.emitter.fire, this.emitter, this.transientDisposables);
} catch (err) {
this.outputChannelLogger.logWarning(`Failed to watch ref '${upstreamPath}', is most likely packed.`);
if (Log.logLevel <= LogLevel.Error) {
this.outputChannel.appendLine(`${logTimestamp()} Warning: Failed to watch ref '${upstreamPath}', is most likely packed.`);
}
}
}
@@ -616,20 +605,11 @@ class ResourceCommandResolver {
const title = this.getTitle(resource);
if (!resource.leftUri) {
const bothModified = resource.type === Status.BOTH_MODIFIED;
if (resource.rightUri && workspace.getConfiguration('git').get<boolean>('mergeEditor', false) && (bothModified || resource.type === Status.BOTH_ADDED)) {
return {
command: '_git.openMergeEditor',
title: localize('open.merge', "Open Merge"),
arguments: [resource.rightUri]
};
} else {
return {
command: 'vscode.open',
title: localize('open', "Open"),
arguments: [resource.rightUri, { override: bothModified ? false : undefined }, title]
};
}
return {
command: 'vscode.open',
title: localize('open', "Open"),
arguments: [resource.rightUri, { override: resource.type === Status.BOTH_MODIFIED ? false : undefined }, title]
};
} else {
return {
command: 'vscode.diff',
@@ -869,7 +849,6 @@ export class Repository implements Disposable {
private isRepositoryHuge: false | { limit: number } = false;
private didWarnAboutLimit = false;
private isBranchProtectedMatcher: picomatch.Matcher | undefined;
private resourceCommandResolver = new ResourceCommandResolver(this);
private disposables: Disposable[] = [];
@@ -877,9 +856,8 @@ export class Repository implements Disposable {
private readonly repository: BaseRepository,
private pushErrorHandlerRegistry: IPushErrorHandlerRegistry,
remoteSourcePublisherRegistry: IRemoteSourcePublisherRegistry,
postCommitCommandsProviderRegistry: IPostCommitCommandsProviderRegistry,
globalState: Memento,
outputChannelLogger: OutputChannelLogger,
outputChannel: OutputChannel,
private telemetryReporter: TelemetryReporter
) {
const repositoryWatcher = workspace.createFileSystemWatcher(new RelativePattern(Uri.file(repository.root), '**'));
@@ -891,11 +869,13 @@ export class Repository implements Disposable {
let onRepositoryDotGitFileChange: Event<Uri>;
try {
const dotGitFileWatcher = new DotGitWatcher(this, outputChannelLogger);
const dotGitFileWatcher = new DotGitWatcher(this, outputChannel);
onRepositoryDotGitFileChange = dotGitFileWatcher.event;
this.disposables.push(dotGitFileWatcher);
} catch (err) {
outputChannelLogger.logError(`Failed to watch path:'${this.dotGit.path}' or commonPath:'${this.dotGit.commonPath}', reverting to legacy API file watched. Some events might be lost.\n${err.stack || err}`);
if (Log.logLevel <= LogLevel.Error) {
outputChannel.appendLine(`${logTimestamp()} Failed to watch path:'${this.dotGit.path}' or commonPath:'${this.dotGit.commonPath}', reverting to legacy API file watched. Some events might be lost.\n${err.stack || err}`);
}
onRepositoryDotGitFileChange = filterEvent(onRepositoryFileChange, uri => /\.git($|\/)/.test(uri.path));
}
@@ -909,7 +889,7 @@ export class Repository implements Disposable {
// Relevate repository changes should trigger virtual document change events
onRepositoryDotGitFileChange(this._onDidChangeRepository.fire, this._onDidChangeRepository, this.disposables);
this.disposables.push(new FileEventLogger(onRepositoryWorkingTreeFileChange, onRepositoryDotGitFileChange, outputChannelLogger));
this.disposables.push(new FileEventLogger(onRepositoryWorkingTreeFileChange, onRepositoryDotGitFileChange, outputChannel));
const root = Uri.file(repository.root);
this._sourceControl = scm.createSourceControl('git', 'Git', root);
@@ -936,19 +916,13 @@ export class Repository implements Disposable {
onConfigListener(updateIndexGroupVisibility, this, this.disposables);
updateIndexGroupVisibility();
workspace.onDidChangeConfiguration(e => {
if (e.affectsConfiguration('git.mergeEditor')) {
this.mergeGroup.resourceStates = this.mergeGroup.resourceStates.map(r => r.clone());
}
}, undefined, this.disposables);
filterEvent(workspace.onDidChangeConfiguration, e =>
e.affectsConfiguration('git.branchProtection', root)
|| e.affectsConfiguration('git.branchSortOrder', root)
e.affectsConfiguration('git.branchSortOrder', root)
|| e.affectsConfiguration('git.untrackedChanges', root)
|| e.affectsConfiguration('git.ignoreSubmodules', root)
|| e.affectsConfiguration('git.openDiffOnClick', root)
|| e.affectsConfiguration('git.showActionButton', root)
|| e.affectsConfiguration('git.rebaseWhenSync', root)
|| e.affectsConfiguration('git.showUnpublishedCommitsButton', root)
)(this.updateModelState, this, this.disposables);
const updateInputBoxVisibility = () => {
@@ -989,16 +963,12 @@ export class Repository implements Disposable {
}
}, null, this.disposables);
const onDidChangeBranchProtection = filterEvent(workspace.onDidChangeConfiguration, e => e.affectsConfiguration('git.branchProtection', root));
onDidChangeBranchProtection(this.updateBranchProtectionMatcher, this, this.disposables);
this.updateBranchProtectionMatcher();
const statusBar = new StatusBarCommands(this, remoteSourcePublisherRegistry);
this.disposables.push(statusBar);
statusBar.onDidChange(() => this._sourceControl.statusBarCommands = statusBar.commands, null, this.disposables);
this._sourceControl.statusBarCommands = statusBar.commands;
const actionButton = new ActionButtonCommand(this, postCommitCommandsProviderRegistry);
const actionButton = new ActionButtonCommand(this);
this.disposables.push(actionButton);
actionButton.onDidChange(() => this._sourceControl.actionButton = actionButton.button);
this._sourceControl.actionButton = actionButton.button;
@@ -1044,7 +1014,7 @@ export class Repository implements Disposable {
}
let lineNumber = 0;
let start = 0;
let start = 0, end;
let match: RegExpExecArray | null;
const regex = /\r?\n/g;
@@ -1053,7 +1023,7 @@ export class Repository implements Disposable {
lineNumber++;
}
const end = match ? match.index : text.length;
end = match ? match.index : text.length;
const line = text.substring(start, end);
@@ -1297,7 +1267,7 @@ export class Repository implements Disposable {
});
}
closeDiffEditors(indexResources: string[] | undefined, workingTreeResources: string[] | undefined, ignoreSetting: boolean = false): void {
closeDiffEditors(indexResources: string[], workingTreeResources: string[], ignoreSetting: boolean = false): void {
const config = workspace.getConfiguration('git', Uri.file(this.root));
if (!config.get<boolean>('closeDiffOnOperation', false) && !ignoreSetting) { return; }
@@ -1306,11 +1276,11 @@ export class Repository implements Disposable {
for (const tab of window.tabGroups.all.map(g => g.tabs).flat()) {
const { input } = tab;
if (input instanceof TabInputTextDiff || input instanceof TabInputNotebookDiff) {
if (input.modified.scheme === 'git' && (indexResources === undefined || indexResources.some(r => pathEquals(r, input.modified.fsPath)))) {
if (input.modified.scheme === 'git' && indexResources.some(r => pathEquals(r, input.modified.fsPath))) {
// Index
diffEditorTabsToClose.push(tab);
}
if (input.modified.scheme === 'file' && input.original.scheme === 'git' && (workingTreeResources === undefined || workingTreeResources.some(r => pathEquals(r, input.modified.fsPath)))) {
if (input.modified.scheme === 'file' && input.original.scheme === 'git' && workingTreeResources.some(r => pathEquals(r, input.modified.fsPath))) {
// Working Tree
diffEditorTabsToClose.push(tab);
}
@@ -1416,15 +1386,15 @@ export class Repository implements Disposable {
}
@throttle
async fetchAll(cancellationToken?: CancellationToken): Promise<void> {
await this._fetch({ all: true, cancellationToken });
async fetchAll(): Promise<void> {
await this._fetch({ all: true });
}
async fetch(options: FetchOptions): Promise<void> {
await this._fetch(options);
}
private async _fetch(options: { remote?: string; ref?: string; all?: boolean; prune?: boolean; depth?: number; silent?: boolean; cancellationToken?: CancellationToken } = {}): Promise<void> {
private async _fetch(options: { remote?: string; ref?: string; all?: boolean; prune?: boolean; depth?: number; silent?: boolean } = {}): Promise<void> {
if (!options.prune) {
const config = workspace.getConfiguration('git', Uri.file(this.root));
const prune = config.get<boolean>('pruneOnFetch');
@@ -1469,7 +1439,7 @@ export class Repository implements Disposable {
// When fetchOnPull is enabled, fetch all branches when pulling
if (fetchOnPull) {
await this.fetchAll();
await this.repository.fetch({ all: true });
}
if (await this.checkIfMaybeRebased(this.HEAD?.name)) {
@@ -1509,8 +1479,13 @@ export class Repository implements Disposable {
}
@throttle
sync(head: Branch, rebase: boolean): Promise<void> {
return this._sync(head, rebase);
sync(head: Branch): Promise<void> {
return this._sync(head, false);
}
@throttle
async syncRebase(head: Branch): Promise<void> {
return this._sync(head, true);
}
private async _sync(head: Branch, rebase: boolean): Promise<void> {
@@ -1535,7 +1510,7 @@ export class Repository implements Disposable {
const fn = async (cancellationToken?: CancellationToken) => {
// When fetchOnPull is enabled, fetch all branches when pulling
if (fetchOnPull) {
await this.fetchAll(cancellationToken);
await this.repository.fetch({ all: true, cancellationToken });
}
if (await this.checkIfMaybeRebased(this.HEAD?.name)) {
@@ -1893,10 +1868,9 @@ export class Repository implements Disposable {
if (didHitLimit) {
/* __GDPR__
"statusLimit" : {
"owner": "lszomoru",
"ignoreSubmodules": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "Setting indicating whether submodules are ignored" },
"limit": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "comment": "Setting indicating the limit of status entries" },
"statusLength": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "comment": "Total number of status entries" }
"ignoreSubmodules": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"limit": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"statusLength": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }
}
*/
this.telemetryReporter.sendTelemetryEvent('statusLimit', { ignoreSubmodules: String(ignoreSubmodules) }, { limit, statusLength });
@@ -2028,9 +2002,6 @@ export class Repository implements Disposable {
// set count badge
this.setCountBadge();
// set mergeChanges context
commands.executeCommand('setContext', 'git.mergeChanges', merge.map(item => item.resourceUri.toString()));
this._onDidChangeStatus.fire();
this._sourceControl.commitTemplate = await this.getInputTemplate();
@@ -2217,21 +2188,6 @@ export class Repository implements Disposable {
}
}
private updateBranchProtectionMatcher(): void {
const scopedConfig = workspace.getConfiguration('git', Uri.file(this.repository.root));
const branchProtectionGlobs = scopedConfig.get<string[]>('branchProtection')!.map(bp => bp.trim()).filter(bp => bp !== '');
if (branchProtectionGlobs.length === 0) {
this.isBranchProtectedMatcher = undefined;
} else {
this.isBranchProtectedMatcher = picomatch(branchProtectionGlobs);
}
}
public isBranchProtected(name: string = this.HEAD?.name ?? ''): boolean {
return this.isBranchProtectedMatcher ? this.isBranchProtectedMatcher(name) : false;
}
dispose(): void {
this.disposables = dispose(this.disposables);
}