mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-23 01:58:53 +01:00
Merge branch 'master' into pr/104312
This commit is contained in:
@@ -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, Decoration } 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 } from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { Branch, Change, GitErrorCodes, LogOptions, Ref, RefType, Remote, Status, CommitOptions, BranchQuery } from './api/git';
|
||||
import { AutoFetcher } from './autofetch';
|
||||
@@ -205,9 +205,11 @@ export class Resource implements SourceControlResourceState {
|
||||
get color(): ThemeColor {
|
||||
switch (this.type) {
|
||||
case Status.INDEX_MODIFIED:
|
||||
return new ThemeColor('gitDecoration.stageModifiedResourceForeground');
|
||||
case Status.MODIFIED:
|
||||
return new ThemeColor('gitDecoration.modifiedResourceForeground');
|
||||
case Status.INDEX_DELETED:
|
||||
return new ThemeColor('gitDecoration.stageDeletedResourceForeground');
|
||||
case Status.DELETED:
|
||||
return new ThemeColor('gitDecoration.deletedResourceForeground');
|
||||
case Status.INDEX_ADDED:
|
||||
@@ -253,14 +255,10 @@ export class Resource implements SourceControlResourceState {
|
||||
}
|
||||
}
|
||||
|
||||
get resourceDecoration(): Decoration {
|
||||
return {
|
||||
bubble: this.type !== Status.DELETED && this.type !== Status.INDEX_DELETED,
|
||||
title: this.tooltip,
|
||||
letter: this.letter,
|
||||
color: this.color,
|
||||
priority: this.priority
|
||||
};
|
||||
get resourceDecoration(): FileDecoration {
|
||||
const res = new FileDecoration(this.letter, this.tooltip, this.color);
|
||||
res.propagate = this.type !== Status.DELETED && this.type !== Status.INDEX_DELETED;
|
||||
return res;
|
||||
}
|
||||
|
||||
constructor(
|
||||
@@ -302,6 +300,7 @@ export const enum Operation {
|
||||
RenameBranch = 'RenameBranch',
|
||||
DeleteRef = 'DeleteRef',
|
||||
Merge = 'Merge',
|
||||
Rebase = 'Rebase',
|
||||
Ignore = 'Ignore',
|
||||
Tag = 'Tag',
|
||||
DeleteTag = 'DeleteTag',
|
||||
@@ -316,6 +315,8 @@ export const enum Operation {
|
||||
Blame = 'Blame',
|
||||
Log = 'Log',
|
||||
LogFile = 'LogFile',
|
||||
|
||||
Move = 'Move'
|
||||
}
|
||||
|
||||
function isReadOnly(operation: Operation): boolean {
|
||||
@@ -644,6 +645,7 @@ export class Repository implements Disposable {
|
||||
}
|
||||
|
||||
this._rebaseCommit = rebaseCommit;
|
||||
commands.executeCommand('setContext', 'gitRebaseInProgress', !!this._rebaseCommit);
|
||||
}
|
||||
|
||||
get rebaseCommit(): Commit | undefined {
|
||||
@@ -746,11 +748,11 @@ 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)
|
||||
)(this.updateModelState, this, this.disposables);
|
||||
|
||||
const updateInputBoxVisibility = () => {
|
||||
const config = workspace.getConfiguration('git', root);
|
||||
@@ -771,7 +773,7 @@ export class Repository implements Disposable {
|
||||
|
||||
this.disposables.push(new AutoFetcher(this, globalState));
|
||||
|
||||
// https://github.com/Microsoft/vscode/issues/39039
|
||||
// https://github.com/microsoft/vscode/issues/39039
|
||||
const onSuccessfulPush = filterEvent(this.onDidRunOperation, e => e.operation === Operation.Push && !e.error);
|
||||
onSuccessfulPush(() => {
|
||||
const gitConfig = workspace.getConfiguration('git');
|
||||
@@ -864,6 +866,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 });
|
||||
}
|
||||
|
||||
@@ -1053,6 +1061,10 @@ export class Repository implements Disposable {
|
||||
await this.run(Operation.RenameBranch, () => this.repository.renameBranch(name));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
@@ -1069,6 +1081,10 @@ export class Repository implements Disposable {
|
||||
await this.run(Operation.Merge, () => this.repository.merge(ref));
|
||||
}
|
||||
|
||||
async rebase(branch: string): Promise<void> {
|
||||
await this.run(Operation.Rebase, () => this.repository.rebase(branch));
|
||||
}
|
||||
|
||||
async tag(name: string, message?: string): Promise<void> {
|
||||
await this.run(Operation.Tag, () => this.repository.tag(name, message));
|
||||
}
|
||||
@@ -1077,8 +1093,8 @@ 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> {
|
||||
@@ -1115,21 +1131,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
|
||||
@@ -1195,6 +1221,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));
|
||||
}
|
||||
@@ -1415,9 +1445,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;
|
||||
@@ -1515,9 +1545,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;
|
||||
@@ -1789,6 +1822,28 @@ export class Repository implements Disposable {
|
||||
return `${this.HEAD.behind}↓ ${this.HEAD.ahead}↑`;
|
||||
}
|
||||
|
||||
get syncTooltip(): string {
|
||||
if (!this.HEAD
|
||||
|| !this.HEAD.name
|
||||
|| !this.HEAD.commit
|
||||
|| !this.HEAD.upstream
|
||||
|| !(this.HEAD.ahead || this.HEAD.behind)
|
||||
) {
|
||||
return localize('sync changes', "Synchronize Changes");
|
||||
}
|
||||
|
||||
const remoteName = this.HEAD && this.HEAD.remote || this.HEAD.upstream.remote;
|
||||
const remote = this.remotes.find(r => r.name === remoteName);
|
||||
|
||||
if ((remote && remote.isReadOnly) || !this.HEAD.ahead) {
|
||||
return localize('pull n', "Pull {0} commits from {1}/{2}", this.HEAD.behind, this.HEAD.upstream.remote, this.HEAD.upstream.name);
|
||||
} else if (!this.HEAD.behind) {
|
||||
return localize('push n', "Push {0} commits to {1}/{2}", this.HEAD.ahead, this.HEAD.upstream.remote, this.HEAD.upstream.name);
|
||||
} else {
|
||||
return localize('pull push n', "Pull {0} and push {1} commits between {2}/{3}", this.HEAD.behind, this.HEAD.ahead, this.HEAD.upstream.remote, this.HEAD.upstream.name);
|
||||
}
|
||||
}
|
||||
|
||||
private updateInputBoxPlaceholder(): void {
|
||||
const branchName = this.headShortName;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user