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

SCM - more work related to history #216641

Merged
merged 6 commits into from
Jun 19, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions extensions/git/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
],
Expand Down
6 changes: 3 additions & 3 deletions extensions/git/src/decorationProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 [];
Expand Down
1 change: 1 addition & 0 deletions extensions/git/src/git.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1167,6 +1167,7 @@ export class Repository {

if (options?.refNames) {
args.push('--topo-order');
args.push('--decorate=full');
args.push(...options.refNames);
}

Expand Down
65 changes: 36 additions & 29 deletions extensions/git/src/historyProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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) {
Expand All @@ -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)}`);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -268,34 +266,34 @@ 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')
}
);
continue;
}

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')
});
}
Expand All @@ -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);
Expand Down Expand Up @@ -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);
}
Expand Down
4 changes: 0 additions & 4 deletions src/vs/workbench/api/browser/mainThreadSCM.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
4 changes: 2 additions & 2 deletions src/vs/workbench/api/common/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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>;
}

Expand Down
7 changes: 1 addition & 6 deletions src/vs/workbench/api/common/extHostSCM.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/vs/workbench/contrib/scm/browser/menus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
13 changes: 6 additions & 7 deletions src/vs/workbench/contrib/scm/browser/scmViewPane.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 }) ?? [];
Expand Down
4 changes: 2 additions & 2 deletions src/vs/workbench/contrib/scm/common/history.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
}

Expand All @@ -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 {
Expand Down
4 changes: 2 additions & 2 deletions src/vscode-dts/vscode.proposed.scmHistoryProvider.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 }>;
}

Expand All @@ -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 {
Expand Down
Loading