Update to VS Code 1.52.1

This commit is contained in:
Asher
2021-02-09 16:08:37 +00:00
1351 changed files with 56560 additions and 38990 deletions

View File

@@ -75,13 +75,21 @@ export class Resource implements SourceControlResourceState {
return this._resourceUri;
}
@memoize
get leftUri(): Uri | undefined {
return this.resources[0];
}
get rightUri(): Uri {
return this.resources[1];
}
get command(): Command {
return {
command: 'git.openResource',
title: localize('open', "Open"),
arguments: [this]
};
return this._commandResolver.resolveDefaultCommand(this);
}
@memoize
private get resources(): [Uri | undefined, Uri] {
return this._commandResolver.getResources(this);
}
get resourceGroupType(): ResourceGroupType { return this._resourceGroupType; }
@@ -262,12 +270,28 @@ export class Resource implements SourceControlResourceState {
}
constructor(
private _commandResolver: ResourceCommandResolver,
private _resourceGroupType: ResourceGroupType,
private _resourceUri: Uri,
private _type: Status,
private _useIcons: boolean,
private _renameResourceUri?: Uri
private _renameResourceUri?: Uri,
) { }
async open(): Promise<void> {
const command = this.command;
await commands.executeCommand<void>(command.command, ...(command.arguments || []));
}
async openFile(): Promise<void> {
const command = this._commandResolver.resolveFileCommand(this);
await commands.executeCommand<void>(command.command, ...(command.arguments || []));
}
async openChange(): Promise<void> {
const command = this._commandResolver.resolveChangeCommand(this);
await commands.executeCommand<void>(command.command, ...(command.arguments || []));
}
}
export const enum Operation {
@@ -292,6 +316,7 @@ export const enum Operation {
Fetch = 'Fetch',
Pull = 'Pull',
Push = 'Push',
CherryPick = 'CherryPick',
Sync = 'Sync',
Show = 'Show',
Stage = 'Stage',
@@ -315,6 +340,8 @@ export const enum Operation {
Blame = 'Blame',
Log = 'Log',
LogFile = 'LogFile',
Move = 'Move'
}
function isReadOnly(operation: Operation): boolean {
@@ -550,6 +577,142 @@ class DotGitWatcher implements IFileWatcher {
}
}
class ResourceCommandResolver {
constructor(private repository: Repository) { }
resolveDefaultCommand(resource: Resource): Command {
const config = workspace.getConfiguration('git', Uri.file(this.repository.root));
const openDiffOnClick = config.get<boolean>('openDiffOnClick', true);
return openDiffOnClick ? this.resolveChangeCommand(resource) : this.resolveFileCommand(resource);
}
resolveFileCommand(resource: Resource): Command {
return {
command: 'vscode.open',
title: localize('open', "Open"),
arguments: [resource.resourceUri]
};
}
resolveChangeCommand(resource: Resource): Command {
const title = this.getTitle(resource);
if (!resource.leftUri) {
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',
title: localize('open', "Open"),
arguments: [resource.leftUri, resource.rightUri, title]
};
}
}
getResources(resource: Resource): [Uri | undefined, Uri] {
for (const submodule of this.repository.submodules) {
if (path.join(this.repository.root, submodule.path) === resource.resourceUri.fsPath) {
return [undefined, toGitUri(resource.resourceUri, resource.resourceGroupType === ResourceGroupType.Index ? 'index' : 'wt', { submoduleOf: this.repository.root })];
}
}
return [this.getLeftResource(resource), this.getRightResource(resource)];
}
private getLeftResource(resource: Resource): Uri | undefined {
switch (resource.type) {
case Status.INDEX_MODIFIED:
case Status.INDEX_RENAMED:
case Status.INDEX_ADDED:
return toGitUri(resource.original, 'HEAD');
case Status.MODIFIED:
case Status.UNTRACKED:
return toGitUri(resource.resourceUri, '~');
case Status.DELETED_BY_US:
case Status.DELETED_BY_THEM:
return toGitUri(resource.resourceUri, '~1');
}
return undefined;
}
private getRightResource(resource: Resource): Uri {
switch (resource.type) {
case Status.INDEX_MODIFIED:
case Status.INDEX_ADDED:
case Status.INDEX_COPIED:
case Status.INDEX_RENAMED:
return toGitUri(resource.resourceUri, '');
case Status.INDEX_DELETED:
case Status.DELETED:
return toGitUri(resource.resourceUri, 'HEAD');
case Status.DELETED_BY_US:
return toGitUri(resource.resourceUri, '~3');
case Status.DELETED_BY_THEM:
return toGitUri(resource.resourceUri, '~2');
case Status.MODIFIED:
case Status.UNTRACKED:
case Status.IGNORED:
case Status.INTENT_TO_ADD:
const uriString = resource.resourceUri.toString();
const [indexStatus] = this.repository.indexGroup.resourceStates.filter(r => r.resourceUri.toString() === uriString);
if (indexStatus && indexStatus.renameResourceUri) {
return indexStatus.renameResourceUri;
}
return resource.resourceUri;
case Status.BOTH_ADDED:
case Status.BOTH_MODIFIED:
return resource.resourceUri;
}
throw new Error('Should never happen');
}
private getTitle(resource: Resource): string {
const basename = path.basename(resource.resourceUri.fsPath);
switch (resource.type) {
case Status.INDEX_MODIFIED:
case Status.INDEX_RENAMED:
case Status.INDEX_ADDED:
return localize('git.title.index', '{0} (Index)', basename);
case Status.MODIFIED:
case Status.BOTH_ADDED:
case Status.BOTH_MODIFIED:
return localize('git.title.workingTree', '{0} (Working Tree)', basename);
case Status.INDEX_DELETED:
case Status.DELETED:
return localize('git.title.deleted', '{0} (Deleted)', basename);
case Status.DELETED_BY_US:
return localize('git.title.theirs', '{0} (Theirs)', basename);
case Status.DELETED_BY_THEM:
return localize('git.title.ours', '{0} (Ours)', basename);
case Status.UNTRACKED:
return localize('git.title.untracked', '{0} (Untracked)', basename);
default:
return '';
}
}
}
export class Repository implements Disposable {
private _onDidChangeRepository = new EventEmitter<Uri>();
@@ -680,6 +843,7 @@ export class Repository implements Disposable {
private isRepositoryHuge = false;
private didWarnAboutLimit = false;
private resourceCommandResolver = new ResourceCommandResolver(this);
private disposables: Disposable[] = [];
constructor(
@@ -746,11 +910,12 @@ export class Repository implements Disposable {
onConfigListener(updateIndexGroupVisibility, this, this.disposables);
updateIndexGroupVisibility();
const onConfigListenerForBranchSortOrder = filterEvent(workspace.onDidChangeConfiguration, e => e.affectsConfiguration('git.branchSortOrder', root));
onConfigListenerForBranchSortOrder(this.updateModelState, this, this.disposables);
const onConfigListenerForUntracked = filterEvent(workspace.onDidChangeConfiguration, e => e.affectsConfiguration('git.untrackedChanges', root));
onConfigListenerForUntracked(this.updateModelState, this, this.disposables);
filterEvent(workspace.onDidChangeConfiguration, e =>
e.affectsConfiguration('git.branchSortOrder', root)
|| e.affectsConfiguration('git.untrackedChanges', root)
|| e.affectsConfiguration('git.ignoreSubmodules', root)
|| e.affectsConfiguration('git.openDiffOnClick', root)
)(this.updateModelState, this, this.disposables);
const updateInputBoxVisibility = () => {
const config = workspace.getConfiguration('git', root);
@@ -864,6 +1029,12 @@ export class Repository implements Disposable {
return;
}
const path = uri.path;
if (this.mergeGroup.resourceStates.some(r => r.resourceUri.path === path)) {
return undefined;
}
return toGitUri(uri, '', { replaceFileExtension: true });
}
@@ -976,7 +1147,7 @@ export class Repository implements Disposable {
await this.run(Operation.RevertFiles, () => this.repository.revert('HEAD', resources.map(r => r.fsPath)));
}
async commit(message: string, opts: CommitOptions = Object.create(null)): Promise<void> {
async commit(message: string | undefined, opts: CommitOptions = Object.create(null)): Promise<void> {
if (this.rebaseCommit) {
await this.run(Operation.RebaseContinue, async () => {
if (opts.all) {
@@ -1053,6 +1224,14 @@ export class Repository implements Disposable {
await this.run(Operation.RenameBranch, () => this.repository.renameBranch(name));
}
async cherryPick(commitHash: string): Promise<void> {
await this.run(Operation.CherryPick, () => this.repository.cherryPick(commitHash));
}
async move(from: string, to: string): Promise<void> {
await this.run(Operation.Move, () => this.repository.move(from, to));
}
async getBranch(name: string): Promise<Branch> {
return await this.run(Operation.GetBranch, () => this.repository.getBranch(name));
}
@@ -1081,12 +1260,12 @@ export class Repository implements Disposable {
await this.run(Operation.DeleteTag, () => this.repository.deleteTag(name));
}
async checkout(treeish: string): Promise<void> {
await this.run(Operation.Checkout, () => this.repository.checkout(treeish, []));
async checkout(treeish: string, opts?: { detached?: boolean }): Promise<void> {
await this.run(Operation.Checkout, () => this.repository.checkout(treeish, [], opts));
}
async checkoutTracking(treeish: string): Promise<void> {
await this.run(Operation.CheckoutTracking, () => this.repository.checkout(treeish, [], { track: true }));
async checkoutTracking(treeish: string, opts: { detached?: boolean } = {}): Promise<void> {
await this.run(Operation.CheckoutTracking, () => this.repository.checkout(treeish, [], { ...opts, track: true }));
}
async findTrackingBranches(upstreamRef: string): Promise<Branch[]> {
@@ -1119,21 +1298,31 @@ export class Repository implements Disposable {
@throttle
async fetchDefault(options: { silent?: boolean } = {}): Promise<void> {
await this.run(Operation.Fetch, () => this.repository.fetch(options));
await this._fetch({ silent: options.silent });
}
@throttle
async fetchPrune(): Promise<void> {
await this.run(Operation.Fetch, () => this.repository.fetch({ prune: true }));
await this._fetch({ prune: true });
}
@throttle
async fetchAll(): Promise<void> {
await this.run(Operation.Fetch, () => this.repository.fetch({ all: true }));
await this._fetch({ all: true });
}
async fetch(remote?: string, ref?: string, depth?: number): Promise<void> {
await this.run(Operation.Fetch, () => this.repository.fetch({ remote, ref, depth }));
await this._fetch({ remote, ref, depth });
}
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');
options.prune = prune;
}
await this.run(Operation.Fetch, async () => this.repository.fetch(options));
}
@throttle
@@ -1169,11 +1358,12 @@ export class Repository implements Disposable {
const fetchOnPull = config.get<boolean>('fetchOnPull');
const tags = config.get<boolean>('pullTags');
// When fetchOnPull is enabled, fetch all branches when pulling
if (fetchOnPull) {
await this.repository.pull(rebase, undefined, undefined, { unshallow, tags });
} else {
await this.repository.pull(rebase, remote, branch, { unshallow, tags });
await this.repository.fetch({ all: true });
}
await this.repository.pull(rebase, remote, branch, { unshallow, tags });
});
});
}
@@ -1199,6 +1389,10 @@ export class Repository implements Disposable {
await this.run(Operation.Push, () => this._push(remote, undefined, false, true, forcePushMode));
}
async pushTags(remote?: string, forcePushMode?: ForcePushMode): Promise<void> {
await this.run(Operation.Push, () => this._push(remote, undefined, false, false, forcePushMode, true));
}
async blame(path: string): Promise<string> {
return await this.run(Operation.Blame, () => this.repository.blame(path));
}
@@ -1229,11 +1423,18 @@ export class Repository implements Disposable {
const config = workspace.getConfiguration('git', Uri.file(this.root));
const fetchOnPull = config.get<boolean>('fetchOnPull');
const tags = config.get<boolean>('pullTags');
const followTags = config.get<boolean>('followTagsWhenSync');
const supportCancellation = config.get<boolean>('supportCancellation');
const fn = fetchOnPull
? async (cancellationToken?: CancellationToken) => await this.repository.pull(rebase, undefined, undefined, { tags, cancellationToken })
: async (cancellationToken?: CancellationToken) => await this.repository.pull(rebase, remoteName, pullBranch, { tags, cancellationToken });
const fn = async (cancellationToken?: CancellationToken) => {
// When fetchOnPull is enabled, fetch all branches when pulling
if (fetchOnPull) {
await this.repository.fetch({ all: true, cancellationToken });
}
await this.repository.pull(rebase, remoteName, pullBranch, { tags, cancellationToken });
};
if (supportCancellation) {
const opts: ProgressOptions = {
@@ -1256,7 +1457,7 @@ export class Repository implements Disposable {
const shouldPush = this.HEAD && (typeof this.HEAD.ahead === 'number' ? this.HEAD.ahead > 0 : true);
if (shouldPush) {
await this._push(remoteName, pushBranch);
await this._push(remoteName, pushBranch, false, followTags);
}
});
});
@@ -1418,9 +1619,9 @@ export class Repository implements Disposable {
return ignored;
}
private async _push(remote?: string, refspec?: string, setUpstream: boolean = false, tags = false, forcePushMode?: ForcePushMode): Promise<void> {
private async _push(remote?: string, refspec?: string, setUpstream: boolean = false, followTags = false, forcePushMode?: ForcePushMode, tags = false): Promise<void> {
try {
await this.repository.push(remote, refspec, setUpstream, tags, forcePushMode);
await this.repository.push(remote, refspec, setUpstream, followTags, forcePushMode, tags);
} catch (err) {
if (!remote || !refspec) {
throw err;
@@ -1518,9 +1719,12 @@ export class Repository implements Disposable {
@throttle
private async updateModelState(): Promise<void> {
const { status, didHitLimit } = await this.repository.getStatus();
const config = workspace.getConfiguration('git');
const scopedConfig = workspace.getConfiguration('git', Uri.file(this.repository.root));
const ignoreSubmodules = scopedConfig.get<boolean>('ignoreSubmodules');
const { status, didHitLimit } = await this.repository.getStatus({ ignoreSubmodules });
const config = workspace.getConfiguration('git');
const shouldIgnore = config.get<boolean>('ignoreLimitWarning') === true;
const useIcons = !config.get<boolean>('decorations.enabled', true);
this.isRepositoryHuge = didHitLimit;
@@ -1595,36 +1799,36 @@ export class Repository implements Disposable {
switch (raw.x + raw.y) {
case '??': switch (untrackedChanges) {
case 'mixed': return workingTree.push(new Resource(ResourceGroupType.WorkingTree, uri, Status.UNTRACKED, useIcons));
case 'separate': return untracked.push(new Resource(ResourceGroupType.Untracked, uri, Status.UNTRACKED, useIcons));
case 'mixed': return workingTree.push(new Resource(this.resourceCommandResolver, ResourceGroupType.WorkingTree, uri, Status.UNTRACKED, useIcons));
case 'separate': return untracked.push(new Resource(this.resourceCommandResolver, ResourceGroupType.Untracked, uri, Status.UNTRACKED, useIcons));
default: return undefined;
}
case '!!': switch (untrackedChanges) {
case 'mixed': return workingTree.push(new Resource(ResourceGroupType.WorkingTree, uri, Status.IGNORED, useIcons));
case 'separate': return untracked.push(new Resource(ResourceGroupType.Untracked, uri, Status.IGNORED, useIcons));
case 'mixed': return workingTree.push(new Resource(this.resourceCommandResolver, ResourceGroupType.WorkingTree, uri, Status.IGNORED, useIcons));
case 'separate': return untracked.push(new Resource(this.resourceCommandResolver, ResourceGroupType.Untracked, uri, Status.IGNORED, useIcons));
default: return undefined;
}
case 'DD': return merge.push(new Resource(ResourceGroupType.Merge, uri, Status.BOTH_DELETED, useIcons));
case 'AU': return merge.push(new Resource(ResourceGroupType.Merge, uri, Status.ADDED_BY_US, useIcons));
case 'UD': return merge.push(new Resource(ResourceGroupType.Merge, uri, Status.DELETED_BY_THEM, useIcons));
case 'UA': return merge.push(new Resource(ResourceGroupType.Merge, uri, Status.ADDED_BY_THEM, useIcons));
case 'DU': return merge.push(new Resource(ResourceGroupType.Merge, uri, Status.DELETED_BY_US, useIcons));
case 'AA': return merge.push(new Resource(ResourceGroupType.Merge, uri, Status.BOTH_ADDED, useIcons));
case 'UU': return merge.push(new Resource(ResourceGroupType.Merge, uri, Status.BOTH_MODIFIED, useIcons));
case 'DD': return merge.push(new Resource(this.resourceCommandResolver, ResourceGroupType.Merge, uri, Status.BOTH_DELETED, useIcons));
case 'AU': return merge.push(new Resource(this.resourceCommandResolver, ResourceGroupType.Merge, uri, Status.ADDED_BY_US, useIcons));
case 'UD': return merge.push(new Resource(this.resourceCommandResolver, ResourceGroupType.Merge, uri, Status.DELETED_BY_THEM, useIcons));
case 'UA': return merge.push(new Resource(this.resourceCommandResolver, ResourceGroupType.Merge, uri, Status.ADDED_BY_THEM, useIcons));
case 'DU': return merge.push(new Resource(this.resourceCommandResolver, ResourceGroupType.Merge, uri, Status.DELETED_BY_US, useIcons));
case 'AA': return merge.push(new Resource(this.resourceCommandResolver, ResourceGroupType.Merge, uri, Status.BOTH_ADDED, useIcons));
case 'UU': return merge.push(new Resource(this.resourceCommandResolver, ResourceGroupType.Merge, uri, Status.BOTH_MODIFIED, useIcons));
}
switch (raw.x) {
case 'M': index.push(new Resource(ResourceGroupType.Index, uri, Status.INDEX_MODIFIED, useIcons)); break;
case 'A': index.push(new Resource(ResourceGroupType.Index, uri, Status.INDEX_ADDED, useIcons)); break;
case 'D': index.push(new Resource(ResourceGroupType.Index, uri, Status.INDEX_DELETED, useIcons)); break;
case 'R': index.push(new Resource(ResourceGroupType.Index, uri, Status.INDEX_RENAMED, useIcons, renameUri)); break;
case 'C': index.push(new Resource(ResourceGroupType.Index, uri, Status.INDEX_COPIED, useIcons, renameUri)); break;
case 'M': index.push(new Resource(this.resourceCommandResolver, ResourceGroupType.Index, uri, Status.INDEX_MODIFIED, useIcons)); break;
case 'A': index.push(new Resource(this.resourceCommandResolver, ResourceGroupType.Index, uri, Status.INDEX_ADDED, useIcons)); break;
case 'D': index.push(new Resource(this.resourceCommandResolver, ResourceGroupType.Index, uri, Status.INDEX_DELETED, useIcons)); break;
case 'R': index.push(new Resource(this.resourceCommandResolver, ResourceGroupType.Index, uri, Status.INDEX_RENAMED, useIcons, renameUri)); break;
case 'C': index.push(new Resource(this.resourceCommandResolver, ResourceGroupType.Index, uri, Status.INDEX_COPIED, useIcons, renameUri)); break;
}
switch (raw.y) {
case 'M': workingTree.push(new Resource(ResourceGroupType.WorkingTree, uri, Status.MODIFIED, useIcons, renameUri)); break;
case 'D': workingTree.push(new Resource(ResourceGroupType.WorkingTree, uri, Status.DELETED, useIcons, renameUri)); break;
case 'A': workingTree.push(new Resource(ResourceGroupType.WorkingTree, uri, Status.INTENT_TO_ADD, useIcons, renameUri)); break;
case 'M': workingTree.push(new Resource(this.resourceCommandResolver, ResourceGroupType.WorkingTree, uri, Status.MODIFIED, useIcons, renameUri)); break;
case 'D': workingTree.push(new Resource(this.resourceCommandResolver, ResourceGroupType.WorkingTree, uri, Status.DELETED, useIcons, renameUri)); break;
case 'A': workingTree.push(new Resource(this.resourceCommandResolver, ResourceGroupType.WorkingTree, uri, Status.INTENT_TO_ADD, useIcons, renameUri)); break;
}
return undefined;