diff --git a/extensions/git/src/git.ts b/extensions/git/src/git.ts index 2b0e2d321ee..d9f930dd398 100644 --- a/extensions/git/src/git.ts +++ b/extensions/git/src/git.ts @@ -1688,9 +1688,8 @@ export class Repository { return result.stdout.trim(); } - async diffBetween2(ref1: string, ref2: string, options: { similarityThreshold?: number; symmetric?: boolean }): Promise { - const range = options.symmetric ? `${ref1}...${ref2}` : `${ref1}..${ref2}`; - return await this.diffFiles(range, { cached: false, similarityThreshold: options.similarityThreshold }); + async diffBetween2(ref1: string, ref2: string, options: { similarityThreshold?: number }): Promise { + return await this.diffFiles(`${ref1}...${ref2}`, { cached: false, similarityThreshold: options.similarityThreshold }); } private async diffFiles(ref: string | undefined, options: { cached: boolean; similarityThreshold?: number }): Promise { @@ -1718,6 +1717,29 @@ export class Repository { return parseGitChanges(this.repositoryRoot, gitResult.stdout); } + async diffTrees(treeish1: string, treeish2?: string, options?: { similarityThreshold?: number }): Promise { + const args = ['diff-tree', '-r', '--name-status', '-z', '--diff-filter=ADMR']; + + if (options?.similarityThreshold) { + args.push(`--find-renames=${options.similarityThreshold}%`); + } + + args.push(treeish1); + + if (treeish2) { + args.push(treeish2); + } + + args.push('--'); + + const gitResult = await this.exec(args); + if (gitResult.exitCode) { + return []; + } + + return parseGitChanges(this.repositoryRoot, gitResult.stdout); + } + async getMergeBase(ref1: string, ref2: string, ...refs: string[]): Promise { try { const args = ['merge-base']; diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index 12516966e3d..00d9186fd46 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -1232,12 +1232,25 @@ export class Repository implements Disposable { } diffBetween2(ref1: string, ref2: string): Promise { + if (ref1 === this._EMPTY_TREE) { + // Use git diff-tree to get the + // changes in the first commit + return this.diffTrees(ref1, ref2); + } + const scopedConfig = workspace.getConfiguration('git', Uri.file(this.root)); const similarityThreshold = scopedConfig.get('similarityThreshold', 50); return this.run(Operation.Diff, () => this.repository.diffBetween2(ref1, ref2, { similarityThreshold })); } + diffTrees(treeish1: string, treeish2?: string): Promise { + const scopedConfig = workspace.getConfiguration('git', Uri.file(this.root)); + const similarityThreshold = scopedConfig.get('similarityThreshold', 50); + + return this.run(Operation.Diff, () => this.repository.diffTrees(treeish1, treeish2, { similarityThreshold })); + } + getMergeBase(ref1: string, ref2: string, ...refs: string[]): Promise { return this.run(Operation.MergeBase, () => this.repository.getMergeBase(ref1, ref2, ...refs)); }