diff --git a/extensions/git/src/decorationProvider.ts b/extensions/git/src/decorationProvider.ts index ace68c22524..8c86834c92c 100644 --- a/extensions/git/src/decorationProvider.ts +++ b/extensions/git/src/decorationProvider.ts @@ -224,12 +224,12 @@ class GitIncomingChangesFileDecorationProvider implements FileDecorationProvider return []; } - const ancestor = await historyProvider.resolveHistoryItemGroupCommonAncestor(currentHistoryItemGroup.id, currentHistoryItemGroup.remote.id); + const ancestor = await historyProvider.resolveHistoryItemGroupCommonAncestor([currentHistoryItemGroup.id, currentHistoryItemGroup.remote.id]); if (!ancestor) { return []; } - const changes = await this.repository.diffBetween(ancestor.id, currentHistoryItemGroup.remote.id); + const changes = await this.repository.diffBetween(ancestor, currentHistoryItemGroup.remote.id); return changes; } catch (err) { return []; diff --git a/extensions/git/src/git.ts b/extensions/git/src/git.ts index 9940ae535c7..2e4e64f7daa 100644 --- a/extensions/git/src/git.ts +++ b/extensions/git/src/git.ts @@ -2647,7 +2647,7 @@ export class Repository { async getDefaultBranch(): Promise { const result = await this.exec(['symbolic-ref', '--short', 'refs/remotes/origin/HEAD']); - if (!result.stdout) { + if (!result.stdout || result.stderr) { throw new Error('No default branch'); } @@ -2714,24 +2714,6 @@ export class Repository { return commits[0]; } - async getCommitFiles(ref: string): Promise { - const result = await this.exec(['diff-tree', '--no-commit-id', '--name-only', '-r', ref]); - return result.stdout.split('\n').filter(l => !!l); - } - - async getCommitCount(range: string): Promise<{ ahead: number; behind: number }> { - const args = ['rev-list', '--count', '--left-right', range]; - - if (isWindows) { - args.splice(0, 0, '-c', 'core.longpaths=true'); - } - - const result = await this.exec(args); - const [ahead, behind] = result.stdout.trim().split('\t'); - - return { ahead: Number(ahead) || 0, behind: Number(behind) || 0 }; - } - async revParse(ref: string): Promise { try { const result = await fs.readFile(path.join(this.dotGit.path, ref), 'utf8'); diff --git a/extensions/git/src/historyProvider.ts b/extensions/git/src/historyProvider.ts index 931e071b35f..272a68bbb32 100644 --- a/extensions/git/src/historyProvider.ts +++ b/extensions/git/src/historyProvider.ts @@ -8,7 +8,7 @@ import { Disposable, Event, EventEmitter, FileDecoration, FileDecorationProvider import { Repository, Resource } from './repository'; import { IDisposable, dispose } from './util'; import { toGitUri } from './uri'; -import { Branch, LogOptions, RefType, UpstreamRef } from './api/git'; +import { Branch, LogOptions, RefType } from './api/git'; import { emojify, ensureEmojis } from './emoji'; import { Commit } from './git'; @@ -97,42 +97,7 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec this.logger.trace(`[GitHistoryProvider][onDidRunGitStatus] currentHistoryItemGroup: ${JSON.stringify(this.currentHistoryItemGroup)}`); } - async provideHistoryItems(historyItemGroupId: string, options: SourceControlHistoryOptions): Promise { - //TODO@lszomoru - support limit and cursor - if (typeof options.limit === 'number') { - throw new Error('Unsupported options.'); - } - if (typeof options.limit?.id !== 'string') { - throw new Error('Unsupported options.'); - } - - const refParentId = options.limit.id; - const refId = await this.repository.revParse(historyItemGroupId) ?? ''; - - const historyItems: SourceControlHistoryItem[] = []; - const commits = await this.repository.log({ range: `${refParentId}..${refId}`, shortStats: true, sortByAuthorDate: true }); - - await ensureEmojis(); - - historyItems.push(...commits.map(commit => { - const newLineIndex = commit.message.indexOf('\n'); - const subject = newLineIndex !== -1 ? commit.message.substring(0, newLineIndex) : commit.message; - - return { - id: commit.hash, - parentIds: commit.parents, - message: emojify(subject), - author: commit.authorName, - icon: new ThemeIcon('git-commit'), - timestamp: commit.authorDate?.getTime(), - statistics: commit.shortStat ?? { files: 0, insertions: 0, deletions: 0 }, - }; - })); - - return historyItems; - } - - async provideHistoryItems2(options: SourceControlHistoryOptions): Promise { + async provideHistoryItems(options: SourceControlHistoryOptions): Promise { if (!this.currentHistoryItemGroup || !options.historyItemGroupIds) { return []; } @@ -180,18 +145,11 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec }; }); } catch (err) { - this.logger.error(`[GitHistoryProvider][provideHistoryItems2] Failed to get history items with options '${JSON.stringify(options)}': ${err}`); + this.logger.error(`[GitHistoryProvider][provideHistoryItems] Failed to get history items with options '${JSON.stringify(options)}': ${err}`); return []; } } - async provideHistoryItemSummary(historyItemId: string, historyItemParentId: string | undefined): Promise { - historyItemParentId = historyItemParentId ?? await this.repository.getEmptyTree(); - const allChanges = await this.repository.diffBetweenShortStat(historyItemParentId, historyItemId); - - return { id: historyItemId, parentIds: [historyItemParentId], message: '', statistics: allChanges }; - } - async provideHistoryItemChanges(historyItemId: string, historyItemParentId: string | undefined): Promise { historyItemParentId = historyItemParentId ?? await this.repository.getEmptyTree(); @@ -226,35 +184,7 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec return historyItemChanges; } - async resolveHistoryItemGroupCommonAncestor(historyItemId1: string, historyItemId2: string | undefined): Promise<{ id: string; ahead: number; behind: number } | undefined> { - if (!historyItemId2) { - const upstreamRef = await this.resolveHistoryItemGroupMergeBase(historyItemId1); - if (!upstreamRef) { - this.logger.info(`[GitHistoryProvider][resolveHistoryItemGroupCommonAncestor] Failed to resolve history item group base for '${historyItemId1}'`); - return undefined; - } - - historyItemId2 = `refs/remotes/${upstreamRef.remote}/${upstreamRef.name}`; - } - - const ancestor = await this.repository.getMergeBase(historyItemId1, historyItemId2); - if (!ancestor) { - this.logger.info(`[GitHistoryProvider][resolveHistoryItemGroupCommonAncestor] Failed to resolve common ancestor for '${historyItemId1}' and '${historyItemId2}'`); - return undefined; - } - - try { - const commitCount = await this.repository.getCommitCount(`${historyItemId1}...${historyItemId2}`); - this.logger.trace(`[GitHistoryProvider][resolveHistoryItemGroupCommonAncestor] Resolved common ancestor for '${historyItemId1}' and '${historyItemId2}': ${JSON.stringify({ id: ancestor, ahead: commitCount.ahead, behind: commitCount.behind })}`); - return { id: ancestor, ahead: commitCount.ahead, behind: commitCount.behind }; - } catch (err) { - this.logger.error(`[GitHistoryProvider][resolveHistoryItemGroupCommonAncestor] Failed to get ahead/behind for '${historyItemId1}...${historyItemId2}': ${err.message}`); - } - - return undefined; - } - - async resolveHistoryItemGroupCommonAncestor2(historyItemGroupIds: string[]): Promise { + async resolveHistoryItemGroupCommonAncestor(historyItemGroupIds: string[]): Promise { try { if (historyItemGroupIds.length === 0) { // TODO@lszomoru - log @@ -283,7 +213,7 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec } } catch (err) { - this.logger.error(`[GitHistoryProvider][resolveHistoryItemGroupCommonAncestor2] Failed to resolve common ancestor for ${historyItemGroupIds.join(',')}: ${err}`); + this.logger.error(`[GitHistoryProvider][resolveHistoryItemGroupCommonAncestor] Failed to resolve common ancestor for ${historyItemGroupIds.join(',')}: ${err}`); } return undefined; @@ -311,34 +241,6 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec return labels; } - private async resolveHistoryItemGroupMergeBase(historyItemId: string): Promise { - try { - // Upstream - const branch = await this.repository.getBranch(historyItemId); - if (branch.upstream) { - return branch.upstream; - } - - // Base (config -> reflog -> default) - const remoteBranch = await this.repository.getBranchBase(historyItemId); - if (!remoteBranch?.remote || !remoteBranch?.name || !remoteBranch?.commit || remoteBranch?.type !== RefType.RemoteHead) { - this.logger.info(`[GitHistoryProvider][resolveHistoryItemGroupUpstreamOrBase] Failed to resolve history item group base for '${historyItemId}'`); - return undefined; - } - - return { - name: remoteBranch.name, - remote: remoteBranch.remote, - commit: remoteBranch.commit - }; - } - catch (err) { - this.logger.error(`[GitHistoryProvider][resolveHistoryItemGroupUpstreamOrBase] Failed to get branch base for '${historyItemId}': ${err.message}`); - } - - return undefined; - } - private async resolveHEADMergeBase(): Promise { if (this.repository.HEAD?.type !== RefType.Head || !this.repository.HEAD?.name) { return undefined; diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index 8ba56b1a1ed..704c549f5ac 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -1508,16 +1508,13 @@ export class Repository implements Disposable { private async getDefaultBranch(): Promise { try { - const defaultBranchResult = await this.repository.exec(['symbolic-ref', '--short', 'refs/remotes/origin/HEAD']); - if (defaultBranchResult.stdout.trim() === '' || defaultBranchResult.stderr) { - return undefined; - } - - return this.getBranch(defaultBranchResult.stdout.trim()); + const defaultBranch = await this.repository.getDefaultBranch(); + return defaultBranch; + } + catch (err) { + this.logger.warn(`[Repository][getDefaultBranch] Failed to get default branch details: ${err.message}.`); + return undefined; } - catch (err) { } - - return undefined; } private async getUpstreamBranch(branch: Branch): Promise { @@ -1618,14 +1615,6 @@ export class Repository implements Disposable { return this._EMPTY_TREE; } - async getCommitCount(range: string): Promise<{ ahead: number; behind: number }> { - return await this.run(Operation.RevList, () => this.repository.getCommitCount(range)); - } - - async revParse(ref: string): Promise { - return await this.run(Operation.RevParse, () => this.repository.revParse(ref)); - } - async reset(treeish: string, hard?: boolean): Promise { await this.run(Operation.Reset, () => this.repository.reset(treeish, hard)); } diff --git a/src/vs/workbench/api/browser/mainThreadSCM.ts b/src/vs/workbench/api/browser/mainThreadSCM.ts index 099edc8b258..00cbe6240e2 100644 --- a/src/vs/workbench/api/browser/mainThreadSCM.ts +++ b/src/vs/workbench/api/browser/mainThreadSCM.ts @@ -170,29 +170,15 @@ class MainThreadSCMHistoryProvider implements ISCMHistoryProvider { constructor(private readonly proxy: ExtHostSCMShape, private readonly handle: number) { } - 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); + async resolveHistoryItemGroupCommonAncestor(historyItemGroupIds: string[]): Promise { + return this.proxy.$resolveHistoryItemGroupCommonAncestor(this.handle, historyItemGroupIds, CancellationToken.None); } - async resolveHistoryItemGroupCommonAncestor2(historyItemGroupIds: string[]): Promise { - return this.proxy.$resolveHistoryItemGroupCommonAncestor2(this.handle, historyItemGroupIds, CancellationToken.None); - } - - async provideHistoryItems(historyItemGroupId: string, options: ISCMHistoryOptions): Promise { - const historyItems = await this.proxy.$provideHistoryItems(this.handle, historyItemGroupId, options, CancellationToken.None); + async provideHistoryItems(options: ISCMHistoryOptions): Promise { + const historyItems = await this.proxy.$provideHistoryItems(this.handle, options, CancellationToken.None); return historyItems?.map(historyItem => toISCMHistoryItem(historyItem)); } - async provideHistoryItems2(options: ISCMHistoryOptions): Promise { - const historyItems = await this.proxy.$provideHistoryItems2(this.handle, options, CancellationToken.None); - return historyItems?.map(historyItem => toISCMHistoryItem(historyItem)); - } - - async provideHistoryItemSummary(historyItemId: string, historyItemParentId: string | undefined): Promise { - const historyItem = await this.proxy.$provideHistoryItemSummary(this.handle, historyItemId, historyItemParentId, CancellationToken.None); - return historyItem ? toISCMHistoryItem(historyItem) : undefined; - } - async provideHistoryItemChanges(historyItemId: string, historyItemParentId: string | undefined): Promise { const changes = await this.proxy.$provideHistoryItemChanges(this.handle, historyItemId, historyItemParentId, CancellationToken.None); return changes?.map(change => ({ diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 26322e60c81..ae704e055be 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -2351,12 +2351,9 @@ export interface ExtHostSCMShape { $executeResourceCommand(sourceControlHandle: number, groupHandle: number, handle: number, preserveFocus: boolean): Promise; $validateInput(sourceControlHandle: number, value: string, cursorPosition: number): Promise<[string | IMarkdownString, number] | undefined>; $setSelectedSourceControl(selectedSourceControlHandle: number | undefined): Promise; - $provideHistoryItems(sourceControlHandle: number, historyItemGroupId: string, options: any, token: CancellationToken): Promise; - $provideHistoryItems2(sourceControlHandle: number, options: any, token: CancellationToken): Promise; - $provideHistoryItemSummary(sourceControlHandle: number, historyItemId: string, historyItemParentId: string | undefined, token: CancellationToken): Promise; + $provideHistoryItems(sourceControlHandle: number, options: any, token: CancellationToken): Promise; $provideHistoryItemChanges(sourceControlHandle: number, historyItemId: string, historyItemParentId: string | undefined, token: CancellationToken): Promise; - $resolveHistoryItemGroupCommonAncestor(sourceControlHandle: number, historyItemGroupId1: string, historyItemGroupId2: string | undefined, token: CancellationToken): Promise<{ id: string; ahead: number; behind: number } | undefined>; - $resolveHistoryItemGroupCommonAncestor2(sourceControlHandle: number, historyItemGroupIds: string[], token: CancellationToken): Promise; + $resolveHistoryItemGroupCommonAncestor(sourceControlHandle: number, historyItemGroupIds: string[], token: CancellationToken): Promise; } export interface ExtHostQuickDiffShape { diff --git a/src/vs/workbench/api/common/extHostSCM.ts b/src/vs/workbench/api/common/extHostSCM.ts index ef5fd2d03e8..35635c49e7f 100644 --- a/src/vs/workbench/api/common/extHostSCM.ts +++ b/src/vs/workbench/api/common/extHostSCM.ts @@ -975,40 +975,18 @@ export class ExtHostSCM implements ExtHostSCMShape { return Promise.resolve(undefined); } - async $resolveHistoryItemGroupCommonAncestor(sourceControlHandle: number, historyItemGroupId1: string, historyItemGroupId2: string | undefined, token: CancellationToken): Promise<{ id: string; ahead: number; behind: number } | undefined> { + async $resolveHistoryItemGroupCommonAncestor(sourceControlHandle: number, historyItemGroupIds: string[], token: CancellationToken): Promise { const historyProvider = this._sourceControls.get(sourceControlHandle)?.historyProvider; - return await historyProvider?.resolveHistoryItemGroupCommonAncestor(historyItemGroupId1, historyItemGroupId2, token) ?? undefined; + return await historyProvider?.resolveHistoryItemGroupCommonAncestor(historyItemGroupIds, token) ?? undefined; } - async $resolveHistoryItemGroupCommonAncestor2(sourceControlHandle: number, historyItemGroupIds: string[], token: CancellationToken): Promise { + async $provideHistoryItems(sourceControlHandle: number, options: any, token: CancellationToken): Promise { const historyProvider = this._sourceControls.get(sourceControlHandle)?.historyProvider; - return await historyProvider?.resolveHistoryItemGroupCommonAncestor2(historyItemGroupIds, token) ?? undefined; - } - - async $provideHistoryItems(sourceControlHandle: number, historyItemGroupId: string, options: any, token: CancellationToken): Promise { - const historyProvider = this._sourceControls.get(sourceControlHandle)?.historyProvider; - const historyItems = await historyProvider?.provideHistoryItems(historyItemGroupId, options, token); + const historyItems = await historyProvider?.provideHistoryItems(options, token); return historyItems?.map(item => toSCMHistoryItemDto(item)) ?? undefined; } - async $provideHistoryItems2(sourceControlHandle: number, options: any, token: CancellationToken): Promise { - const historyProvider = this._sourceControls.get(sourceControlHandle)?.historyProvider; - const historyItems = await historyProvider?.provideHistoryItems2(options, token); - - return historyItems?.map(item => toSCMHistoryItemDto(item)) ?? undefined; - } - - async $provideHistoryItemSummary(sourceControlHandle: number, historyItemId: string, historyItemParentId: string | undefined, token: CancellationToken): Promise { - const historyProvider = this._sourceControls.get(sourceControlHandle)?.historyProvider; - if (typeof historyProvider?.provideHistoryItemSummary !== 'function') { - return undefined; - } - - const historyItem = await historyProvider.provideHistoryItemSummary(historyItemId, historyItemParentId, token); - return historyItem ? toSCMHistoryItemDto(historyItem) : undefined; - } - async $provideHistoryItemChanges(sourceControlHandle: number, historyItemId: string, historyItemParentId: string | undefined, token: CancellationToken): Promise { const historyProvider = this._sourceControls.get(sourceControlHandle)?.historyProvider; return await historyProvider?.provideHistoryItemChanges(historyItemId, historyItemParentId, token) ?? undefined; diff --git a/src/vs/workbench/contrib/scm/browser/scmHistoryViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmHistoryViewPane.ts index e2101d202f9..697b8174ce1 100644 --- a/src/vs/workbench/contrib/scm/browser/scmHistoryViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmHistoryViewPane.ts @@ -149,7 +149,7 @@ registerAction2(class extends Action2 { const historyProvider = provider.historyProvider.get(); if (historyItems.length > 1) { - const ancestor = await historyProvider?.resolveHistoryItemGroupCommonAncestor2([historyItem.id, historyItemLast.id]); + const ancestor = await historyProvider?.resolveHistoryItemGroupCommonAncestor([historyItem.id, historyItemLast.id]); if (!ancestor || (ancestor !== historyItem.id && ancestor !== historyItemLast.id)) { return; } @@ -674,7 +674,7 @@ class SCMHistoryViewModel extends Disposable { const existingHistoryItems = state?.items ?? []; const limit = clamp(this._configurationService.getValue('scm.graph.pageSize'), 1, 1000); - const historyItems = await historyProvider.provideHistoryItems2({ + const historyItems = await historyProvider.provideHistoryItems({ historyItemGroupIds, limit, skip: existingHistoryItems.length }) ?? []; diff --git a/src/vs/workbench/contrib/scm/common/history.ts b/src/vs/workbench/contrib/scm/common/history.ts index e2d6d5c71c2..ca85970b07e 100644 --- a/src/vs/workbench/contrib/scm/common/history.ts +++ b/src/vs/workbench/contrib/scm/common/history.ts @@ -22,12 +22,9 @@ export interface ISCMHistoryProvider { readonly currentHistoryItemGroupRemoteId: IObservable; readonly currentHistoryItemGroupRemoteRevision: IObservable; - provideHistoryItems(historyItemGroupId: string, options: ISCMHistoryOptions): Promise; - provideHistoryItems2(options: ISCMHistoryOptions): Promise; - provideHistoryItemSummary(historyItemId: string, historyItemParentId: string | undefined): Promise; + provideHistoryItems(options: ISCMHistoryOptions): Promise; provideHistoryItemChanges(historyItemId: string, historyItemParentId: string | undefined): Promise; - resolveHistoryItemGroupCommonAncestor(historyItemGroupId1: string, historyItemGroupId2: string | undefined): Promise<{ id: string; ahead: number; behind: number } | undefined>; - resolveHistoryItemGroupCommonAncestor2(historyItemGroupIds: string[]): Promise; + resolveHistoryItemGroupCommonAncestor(historyItemGroupIds: string[]): Promise; } export interface ISCMHistoryOptions { diff --git a/src/vscode-dts/vscode.proposed.scmHistoryProvider.d.ts b/src/vscode-dts/vscode.proposed.scmHistoryProvider.d.ts index c9bc2d84225..39ee5f8281e 100644 --- a/src/vscode-dts/vscode.proposed.scmHistoryProvider.d.ts +++ b/src/vscode-dts/vscode.proposed.scmHistoryProvider.d.ts @@ -24,13 +24,10 @@ declare module 'vscode' { */ // onDidChangeHistoryItemGroups: Event; - provideHistoryItems(historyItemGroupId: string, options: SourceControlHistoryOptions, token: CancellationToken): ProviderResult; - provideHistoryItems2(options: SourceControlHistoryOptions, token: CancellationToken): ProviderResult; - provideHistoryItemSummary?(historyItemId: string, historyItemParentId: string | undefined, token: CancellationToken): ProviderResult; + provideHistoryItems(options: SourceControlHistoryOptions, token: CancellationToken): ProviderResult; provideHistoryItemChanges(historyItemId: string, historyItemParentId: string | undefined, token: CancellationToken): ProviderResult; - resolveHistoryItemGroupCommonAncestor(historyItemGroupId1: string, historyItemGroupId2: string | undefined, token: CancellationToken): ProviderResult<{ id: string; ahead: number; behind: number }>; - resolveHistoryItemGroupCommonAncestor2(historyItemGroupIds: string[], token: CancellationToken): ProviderResult; + resolveHistoryItemGroupCommonAncestor(historyItemGroupIds: string[], token: CancellationToken): ProviderResult; } export interface SourceControlHistoryOptions {