mirror of
https://github.com/Microsoft/vscode
synced 2024-10-01 08:50:48 +00:00
SCM - more work related to history (#216641)
* Rename base to remote * introduce base * Remove resolveHistoryItemGroupBase * 💄 * More 💄 * Remove file that is out of scope
This commit is contained in:
parent
5c1b006c49
commit
856fba0b67
|
@ -1967,23 +1967,23 @@
|
|||
{
|
||||
"command": "git.pushRef",
|
||||
"group": "navigation",
|
||||
"when": "scmProvider == git && scmHistoryItemGroupHasUpstream"
|
||||
"when": "scmProvider == git && scmHistoryItemGroupHasRemote"
|
||||
},
|
||||
{
|
||||
"command": "git.publish",
|
||||
"group": "navigation",
|
||||
"when": "scmProvider == git && !scmHistoryItemGroupHasUpstream"
|
||||
"when": "scmProvider == git && !scmHistoryItemGroupHasRemote"
|
||||
}
|
||||
],
|
||||
"scm/outgoingChanges/context": [
|
||||
{
|
||||
"command": "git.pushRef",
|
||||
"when": "scmProvider == git && scmHistoryItemGroupHasUpstream",
|
||||
"when": "scmProvider == git && scmHistoryItemGroupHasRemote",
|
||||
"group": "1_modification@1"
|
||||
},
|
||||
{
|
||||
"command": "git.publish",
|
||||
"when": "scmProvider == git && !scmHistoryItemGroupHasUpstream",
|
||||
"when": "scmProvider == git && !scmHistoryItemGroupHasRemote",
|
||||
"group": "1_modification@1"
|
||||
}
|
||||
],
|
||||
|
|
|
@ -220,16 +220,16 @@ class GitIncomingChangesFileDecorationProvider implements FileDecorationProvider
|
|||
const historyProvider = this.repository.historyProvider;
|
||||
const currentHistoryItemGroup = historyProvider.currentHistoryItemGroup;
|
||||
|
||||
if (!currentHistoryItemGroup?.base) {
|
||||
if (!currentHistoryItemGroup?.remote) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const ancestor = await historyProvider.resolveHistoryItemGroupCommonAncestor(currentHistoryItemGroup.id, currentHistoryItemGroup.base.id);
|
||||
const ancestor = await historyProvider.resolveHistoryItemGroupCommonAncestor(currentHistoryItemGroup.id, currentHistoryItemGroup.remote.id);
|
||||
if (!ancestor) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const changes = await this.repository.diffBetween(ancestor.id, currentHistoryItemGroup.base.id);
|
||||
const changes = await this.repository.diffBetween(ancestor.id, currentHistoryItemGroup.remote.id);
|
||||
return changes;
|
||||
} catch (err) {
|
||||
return [];
|
||||
|
|
|
@ -1167,6 +1167,7 @@ export class Repository {
|
|||
|
||||
if (options?.refNames) {
|
||||
args.push('--topo-order');
|
||||
args.push('--decorate=full');
|
||||
args.push(...options.refNames);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,8 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec
|
|||
readonly onDidChangeFileDecorations: Event<Uri[]> = this._onDidChangeDecorations.event;
|
||||
|
||||
private _HEAD: Branch | undefined;
|
||||
private _HEADMergeBase: Branch | undefined;
|
||||
|
||||
private _currentHistoryItemGroup: SourceControlHistoryItemGroup | undefined;
|
||||
get currentHistoryItemGroup(): SourceControlHistoryItemGroup | undefined { return this._currentHistoryItemGroup; }
|
||||
set currentHistoryItemGroup(value: SourceControlHistoryItemGroup | undefined) {
|
||||
|
@ -44,18 +46,25 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec
|
|||
this.logger.trace('GitHistoryProvider:onDidRunGitStatus - HEAD:', JSON.stringify(this._HEAD));
|
||||
this.logger.trace('GitHistoryProvider:onDidRunGitStatus - repository.HEAD:', JSON.stringify(this.repository.HEAD));
|
||||
|
||||
// Get the merge base of the current history item group
|
||||
const mergeBase = await this.resolveHEADMergeBase();
|
||||
|
||||
// Check if HEAD has changed
|
||||
if (!force &&
|
||||
this._HEAD?.name === this.repository.HEAD?.name &&
|
||||
this._HEAD?.commit === this.repository.HEAD?.commit &&
|
||||
this._HEAD?.upstream?.name === this.repository.HEAD?.upstream?.name &&
|
||||
this._HEAD?.upstream?.remote === this.repository.HEAD?.upstream?.remote &&
|
||||
this._HEAD?.upstream?.commit === this.repository.HEAD?.upstream?.commit) {
|
||||
this._HEAD?.upstream?.commit === this.repository.HEAD?.upstream?.commit &&
|
||||
this._HEADMergeBase?.name === mergeBase?.name &&
|
||||
this._HEADMergeBase?.remote === mergeBase?.remote &&
|
||||
this._HEADMergeBase?.commit === mergeBase?.commit) {
|
||||
this.logger.trace('GitHistoryProvider:onDidRunGitStatus - HEAD has not changed');
|
||||
return;
|
||||
}
|
||||
|
||||
this._HEAD = this.repository.HEAD;
|
||||
this._HEADMergeBase = mergeBase;
|
||||
|
||||
// Check if HEAD does not support incoming/outgoing (detached commit, tag)
|
||||
if (!this.repository.HEAD?.name || !this.repository.HEAD?.commit || this.repository.HEAD.type === RefType.Tag) {
|
||||
|
@ -68,11 +77,14 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec
|
|||
this.currentHistoryItemGroup = {
|
||||
id: `refs/heads/${this.repository.HEAD.name ?? ''}`,
|
||||
name: this.repository.HEAD.name ?? '',
|
||||
base: this.repository.HEAD.upstream ?
|
||||
{
|
||||
id: `refs/remotes/${this.repository.HEAD.upstream.remote}/${this.repository.HEAD.upstream.name}`,
|
||||
name: `${this.repository.HEAD.upstream.remote}/${this.repository.HEAD.upstream.name}`,
|
||||
} : undefined
|
||||
remote: this.repository.HEAD.upstream ? {
|
||||
id: `refs/remotes/${this.repository.HEAD.upstream.remote}/${this.repository.HEAD.upstream.name}`,
|
||||
name: `${this.repository.HEAD.upstream.remote}/${this.repository.HEAD.upstream.name}`,
|
||||
} : undefined,
|
||||
base: mergeBase ? {
|
||||
id: `refs/remotes/${mergeBase.remote}/${mergeBase.name}`,
|
||||
name: `${mergeBase.remote}/${mergeBase.name}`,
|
||||
} : undefined
|
||||
};
|
||||
|
||||
this.logger.trace(`GitHistoryProvider:onDidRunGitStatus - currentHistoryItemGroup (${force}): ${JSON.stringify(this.currentHistoryItemGroup)}`);
|
||||
|
@ -201,23 +213,9 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec
|
|||
return historyItemChanges;
|
||||
}
|
||||
|
||||
async resolveHistoryItemGroupBase(historyItemGroupId: string): Promise<SourceControlHistoryItemGroup | undefined> {
|
||||
// Base (config -> reflog -> default)
|
||||
const remoteBranch = await this.repository.getBranchBase(historyItemGroupId);
|
||||
if (!remoteBranch?.remote || !remoteBranch?.name || !remoteBranch?.commit || remoteBranch?.type !== RefType.RemoteHead) {
|
||||
this.logger.info(`GitHistoryProvider:resolveHistoryItemGroupBase - Failed to resolve history item group base for '${historyItemGroupId}'`);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
id: `refs/remotes/${remoteBranch.remote}/${remoteBranch.name}`,
|
||||
name: `${remoteBranch.remote}/${remoteBranch.name}`,
|
||||
};
|
||||
}
|
||||
|
||||
async resolveHistoryItemGroupCommonAncestor(historyItemId1: string, historyItemId2: string | undefined): Promise<{ id: string; ahead: number; behind: number } | undefined> {
|
||||
if (!historyItemId2) {
|
||||
const upstreamRef = await this.resolveHistoryItemGroupUpstreamOrBase(historyItemId1);
|
||||
const upstreamRef = await this.resolveHistoryItemGroupMergeBase(historyItemId1);
|
||||
if (!upstreamRef) {
|
||||
this.logger.info(`GitHistoryProvider:resolveHistoryItemGroupCommonAncestor - Failed to resolve history item group base for '${historyItemId1}'`);
|
||||
return undefined;
|
||||
|
@ -268,14 +266,14 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec
|
|||
const labels: SourceControlHistoryItemLabel[] = [];
|
||||
|
||||
for (const label of commit.refNames) {
|
||||
if (label === 'origin/HEAD' || label === '') {
|
||||
if (label === 'refs/remotes/origin/HEAD' || label === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (label.startsWith('HEAD -> ')) {
|
||||
labels.push(
|
||||
{
|
||||
title: label.substring(8),
|
||||
title: label.substring(19),
|
||||
icon: new ThemeIcon('git-branch')
|
||||
}
|
||||
);
|
||||
|
@ -283,19 +281,19 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec
|
|||
}
|
||||
|
||||
if (refNames.has(label)) {
|
||||
if (label.startsWith('tag: ')) {
|
||||
if (label.startsWith('refs/tags/')) {
|
||||
labels.push({
|
||||
title: label.substring(5),
|
||||
title: label.substring(10),
|
||||
icon: new ThemeIcon('tag')
|
||||
});
|
||||
} else if (label.startsWith('origin/')) {
|
||||
} else if (label.startsWith('refs/remotes/')) {
|
||||
labels.push({
|
||||
title: label,
|
||||
title: label.substring(13),
|
||||
icon: new ThemeIcon('cloud')
|
||||
});
|
||||
} else {
|
||||
labels.push({
|
||||
title: label,
|
||||
title: label.substring(11),
|
||||
icon: new ThemeIcon('git-branch')
|
||||
});
|
||||
}
|
||||
|
@ -305,7 +303,7 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec
|
|||
return labels;
|
||||
}
|
||||
|
||||
private async resolveHistoryItemGroupUpstreamOrBase(historyItemId: string): Promise<UpstreamRef | undefined> {
|
||||
private async resolveHistoryItemGroupMergeBase(historyItemId: string): Promise<UpstreamRef | undefined> {
|
||||
try {
|
||||
// Upstream
|
||||
const branch = await this.repository.getBranch(historyItemId);
|
||||
|
@ -333,6 +331,15 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec
|
|||
return undefined;
|
||||
}
|
||||
|
||||
private async resolveHEADMergeBase(): Promise<Branch | undefined> {
|
||||
if (this.repository.HEAD?.type !== RefType.Head || !this.repository.HEAD?.name) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const mergeBase = await this.repository.getBranchBase(this.repository.HEAD.name);
|
||||
return mergeBase;
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
dispose(this.disposables);
|
||||
}
|
||||
|
|
|
@ -177,10 +177,6 @@ class MainThreadSCMHistoryProvider implements ISCMHistoryProvider {
|
|||
|
||||
constructor(private readonly proxy: ExtHostSCMShape, private readonly handle: number) { }
|
||||
|
||||
async resolveHistoryItemGroupBase(historyItemGroupId: string): Promise<ISCMHistoryItemGroup | undefined> {
|
||||
return this.proxy.$resolveHistoryItemGroupBase(this.handle, historyItemGroupId, CancellationToken.None);
|
||||
}
|
||||
|
||||
async resolveHistoryItemGroupCommonAncestor(historyItemGroupId1: string, historyItemGroupId2: string | undefined): Promise<{ id: string; ahead: number; behind: number } | undefined> {
|
||||
return this.proxy.$resolveHistoryItemGroupCommonAncestor(this.handle, historyItemGroupId1, historyItemGroupId2, CancellationToken.None);
|
||||
}
|
||||
|
|
|
@ -1515,7 +1515,8 @@ export type SCMRawResourceSplices = [
|
|||
export interface SCMHistoryItemGroupDto {
|
||||
readonly id: string;
|
||||
readonly name: string;
|
||||
readonly base?: Omit<SCMHistoryItemGroupDto, 'base'>;
|
||||
readonly base?: Omit<Omit<SCMHistoryItemGroupDto, 'base'>, 'remote'>;
|
||||
readonly remote?: Omit<Omit<SCMHistoryItemGroupDto, 'base'>, 'remote'>;
|
||||
}
|
||||
|
||||
export interface SCMHistoryItemDto {
|
||||
|
@ -2329,7 +2330,6 @@ export interface ExtHostSCMShape {
|
|||
$provideHistoryItems2(sourceControlHandle: number, options: any, token: CancellationToken): Promise<SCMHistoryItemDto[] | undefined>;
|
||||
$provideHistoryItemSummary(sourceControlHandle: number, historyItemId: string, historyItemParentId: string | undefined, token: CancellationToken): Promise<SCMHistoryItemDto | undefined>;
|
||||
$provideHistoryItemChanges(sourceControlHandle: number, historyItemId: string, historyItemParentId: string | undefined, token: CancellationToken): Promise<SCMHistoryItemChangeDto[] | undefined>;
|
||||
$resolveHistoryItemGroupBase(sourceControlHandle: number, historyItemGroupId: string, token: CancellationToken): Promise<SCMHistoryItemGroupDto | undefined>;
|
||||
$resolveHistoryItemGroupCommonAncestor(sourceControlHandle: number, historyItemGroupId1: string, historyItemGroupId2: string | undefined, token: CancellationToken): Promise<{ id: string; ahead: number; behind: number } | undefined>;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ import { debounce } from 'vs/base/common/decorators';
|
|||
import { DisposableStore, IDisposable, MutableDisposable } from 'vs/base/common/lifecycle';
|
||||
import { asPromise } from 'vs/base/common/async';
|
||||
import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { MainContext, MainThreadSCMShape, SCMRawResource, SCMRawResourceSplice, SCMRawResourceSplices, IMainContext, ExtHostSCMShape, ICommandDto, MainThreadTelemetryShape, SCMGroupFeatures, SCMHistoryItemDto, SCMHistoryItemChangeDto, SCMHistoryItemGroupDto } from './extHost.protocol';
|
||||
import { MainContext, MainThreadSCMShape, SCMRawResource, SCMRawResourceSplice, SCMRawResourceSplices, IMainContext, ExtHostSCMShape, ICommandDto, MainThreadTelemetryShape, SCMGroupFeatures, SCMHistoryItemDto, SCMHistoryItemChangeDto } from './extHost.protocol';
|
||||
import { sortedDiff, equals } from 'vs/base/common/arrays';
|
||||
import { comparePaths } from 'vs/base/common/comparers';
|
||||
import type * as vscode from 'vscode';
|
||||
|
@ -970,11 +970,6 @@ export class ExtHostSCM implements ExtHostSCMShape {
|
|||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
async $resolveHistoryItemGroupBase(sourceControlHandle: number, historyItemGroupId: string, token: CancellationToken): Promise<SCMHistoryItemGroupDto | undefined> {
|
||||
const historyProvider = this._sourceControls.get(sourceControlHandle)?.historyProvider;
|
||||
return await historyProvider?.resolveHistoryItemGroupBase(historyItemGroupId, token) ?? undefined;
|
||||
}
|
||||
|
||||
async $resolveHistoryItemGroupCommonAncestor(sourceControlHandle: number, historyItemGroupId1: string, historyItemGroupId2: string | undefined, token: CancellationToken): Promise<{ id: string; ahead: number; behind: number } | undefined> {
|
||||
const historyProvider = this._sourceControls.get(sourceControlHandle)?.historyProvider;
|
||||
return await historyProvider?.resolveHistoryItemGroupCommonAncestor(historyItemGroupId1, historyItemGroupId2, token) ?? undefined;
|
||||
|
|
|
@ -306,7 +306,7 @@ export class SCMHistoryProviderMenus implements ISCMHistoryProviderMenus, IDispo
|
|||
|
||||
private getOutgoingHistoryItemGroupMenu(menuId: MenuId, historyItemGroup: SCMHistoryItemGroupTreeElement): IMenu {
|
||||
const contextKeyService = this.contextKeyService.createOverlay([
|
||||
['scmHistoryItemGroupHasUpstream', !!historyItemGroup.repository.provider.historyProvider?.currentHistoryItemGroup?.base],
|
||||
['scmHistoryItemGroupHasRemote', !!historyItemGroup.repository.provider.historyProvider?.currentHistoryItemGroup?.remote],
|
||||
]);
|
||||
|
||||
return this.menuService.createMenu(menuId, contextKeyService);
|
||||
|
|
|
@ -3855,16 +3855,16 @@ class SCMTreeDataSource implements IAsyncDataSource<ISCMViewService, TreeElement
|
|||
|
||||
if (!incomingHistoryItemGroup && !outgoingHistoryItemGroup) {
|
||||
// Common ancestor, ahead, behind
|
||||
const ancestor = await historyProvider.resolveHistoryItemGroupCommonAncestor(currentHistoryItemGroup.id, currentHistoryItemGroup.base?.id);
|
||||
const ancestor = await historyProvider.resolveHistoryItemGroupCommonAncestor(currentHistoryItemGroup.id, currentHistoryItemGroup.remote?.id);
|
||||
if (!ancestor) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Only show "Incoming" node if there is a base branch
|
||||
incomingHistoryItemGroup = currentHistoryItemGroup.base ? {
|
||||
id: currentHistoryItemGroup.base.id,
|
||||
label: currentHistoryItemGroup.base.name,
|
||||
ariaLabel: localize('incomingChangesAriaLabel', "Incoming changes from {0}", currentHistoryItemGroup.base.name),
|
||||
incomingHistoryItemGroup = currentHistoryItemGroup.remote ? {
|
||||
id: currentHistoryItemGroup.remote.id,
|
||||
label: currentHistoryItemGroup.remote.name,
|
||||
ariaLabel: localize('incomingChangesAriaLabel', "Incoming changes from {0}", currentHistoryItemGroup.remote.name),
|
||||
icon: Codicon.arrowCircleDown,
|
||||
direction: 'incoming',
|
||||
ancestor: ancestor.id,
|
||||
|
@ -3973,11 +3973,10 @@ class SCMTreeDataSource implements IAsyncDataSource<ISCMViewService, TreeElement
|
|||
const historyItemsMap = historyProviderCacheEntry.historyItems2;
|
||||
|
||||
if (!historyItemsElement) {
|
||||
const historyItemGroupBase = await historyProvider.resolveHistoryItemGroupBase(currentHistoryItemGroup.id);
|
||||
const historyItemGroupIds = [
|
||||
currentHistoryItemGroup.id,
|
||||
...currentHistoryItemGroup.remote ? [currentHistoryItemGroup.remote.id] : [],
|
||||
...currentHistoryItemGroup.base ? [currentHistoryItemGroup.base.id] : [],
|
||||
...historyItemGroupBase ? [historyItemGroupBase.id] : []
|
||||
];
|
||||
|
||||
historyItemsElement = await historyProvider.provideHistoryItems2({ historyItemGroupIds }) ?? [];
|
||||
|
|
|
@ -29,7 +29,6 @@ export interface ISCMHistoryProvider {
|
|||
provideHistoryItems2(options: ISCMHistoryOptions): Promise<ISCMHistoryItem[] | undefined>;
|
||||
provideHistoryItemSummary(historyItemId: string, historyItemParentId: string | undefined): Promise<ISCMHistoryItem | undefined>;
|
||||
provideHistoryItemChanges(historyItemId: string, historyItemParentId: string | undefined): Promise<ISCMHistoryItemChange[] | undefined>;
|
||||
resolveHistoryItemGroupBase(historyItemGroupId: string): Promise<ISCMHistoryItemGroup | undefined>;
|
||||
resolveHistoryItemGroupCommonAncestor(historyItemGroupId1: string, historyItemGroupId2: string | undefined): Promise<{ id: string; ahead: number; behind: number } | undefined>;
|
||||
}
|
||||
|
||||
|
@ -50,7 +49,8 @@ export interface ISCMHistoryOptions {
|
|||
export interface ISCMHistoryItemGroup {
|
||||
readonly id: string;
|
||||
readonly name: string;
|
||||
readonly base?: Omit<ISCMHistoryItemGroup, 'base'>;
|
||||
readonly base?: Omit<Omit<ISCMHistoryItemGroup, 'base'>, 'remote'>;
|
||||
readonly remote?: Omit<Omit<ISCMHistoryItemGroup, 'base'>, 'remote'>;
|
||||
}
|
||||
|
||||
export interface SCMHistoryItemGroupTreeElement {
|
||||
|
|
|
@ -29,7 +29,6 @@ declare module 'vscode' {
|
|||
provideHistoryItemSummary?(historyItemId: string, historyItemParentId: string | undefined, token: CancellationToken): ProviderResult<SourceControlHistoryItem>;
|
||||
provideHistoryItemChanges(historyItemId: string, historyItemParentId: string | undefined, token: CancellationToken): ProviderResult<SourceControlHistoryItemChange[]>;
|
||||
|
||||
resolveHistoryItemGroupBase(historyItemGroupId: string, token: CancellationToken): ProviderResult<SourceControlHistoryItemGroup>;
|
||||
resolveHistoryItemGroupCommonAncestor(historyItemGroupId1: string, historyItemGroupId2: string | undefined, token: CancellationToken): ProviderResult<{ id: string; ahead: number; behind: number }>;
|
||||
}
|
||||
|
||||
|
@ -42,7 +41,8 @@ declare module 'vscode' {
|
|||
export interface SourceControlHistoryItemGroup {
|
||||
readonly id: string;
|
||||
readonly name: string;
|
||||
readonly base?: Omit<SourceControlHistoryItemGroup, 'base'>;
|
||||
readonly base?: Omit<Omit<SourceControlHistoryItemGroup, 'base'>, 'remote'>;
|
||||
readonly remote?: Omit<Omit<SourceControlHistoryItemGroup, 'base'>, 'remote'>;
|
||||
}
|
||||
|
||||
export interface SourceControlHistoryItemStatistics {
|
||||
|
|
Loading…
Reference in a new issue