diff --git a/src/github/pullRequestGitHelper.ts b/src/github/pullRequestGitHelper.ts index 6d93d2b176..343377ded0 100644 --- a/src/github/pullRequestGitHelper.ts +++ b/src/github/pullRequestGitHelper.ts @@ -307,6 +307,17 @@ export class PullRequestGitHelper { return `${owner}#${repository}#${baseBranch}`; } + private static async setConfig(repository: Repository, key: string, value: string): Promise { + const existingConfigs = (await repository.getConfigs()).filter(config => config.key === key); + if (existingConfigs.some(config => config.value === value)) { + return; + } + if (existingConfigs.length === 1 && repository.unsetConfig) { + await repository.unsetConfig(key); + } + await repository.setConfig(key, value); + } + static parsePullRequestMetadata(value: string): PullRequestMetadata | undefined { if (value) { const matches = /(.*)#(.*)#(.*)/g.exec(value); @@ -434,7 +445,7 @@ export class PullRequestGitHelper { } const prConfigKey = `branch.${branchName}.${PullRequestMetadataKey}`; if (pullRequest) { - await repository.setConfig(prConfigKey, PullRequestGitHelper.buildPullRequestMetadata(pullRequest)); + await PullRequestGitHelper.setConfig(repository, prConfigKey, PullRequestGitHelper.buildPullRequestMetadata(pullRequest)); } else if (repository.unsetConfig) { await repository.unsetConfig(prConfigKey); } @@ -458,7 +469,7 @@ export class PullRequestGitHelper { const prConfigKey = `branch.${branch}.${BaseBranchMetadataKey}`; if (base) { Logger.appendLine(`associate ${branch} with base branch ${base.owner}/${base.repo}#${base.branch}`, PullRequestGitHelper.ID); - await repository.setConfig(prConfigKey, PullRequestGitHelper.buildBaseBranchMetadata(base.owner, base.repo, base.branch)); + await PullRequestGitHelper.setConfig(repository, prConfigKey, PullRequestGitHelper.buildBaseBranchMetadata(base.owner, base.repo, base.branch)); } else if (repository.unsetConfig) { await repository.unsetConfig(prConfigKey); const vscodeBaseBranchConfigKey = `branch.${branch}.${VscodeBaseBranchMetadataKey}`; diff --git a/src/test/github/pullRequestGitHelper.test.ts b/src/test/github/pullRequestGitHelper.test.ts index 8c51164df0..9c50b09e11 100644 --- a/src/test/github/pullRequestGitHelper.test.ts +++ b/src/test/github/pullRequestGitHelper.test.ts @@ -189,6 +189,52 @@ describe('PullRequestGitHelper', function () { }); }); + describe('associateBranchWithPullRequest', function () { + const pullRequest = (number: number) => ({ + number, + base: { + repositoryCloneUrl: { + owner: 'owner', + repositoryName: 'name', + }, + }, + }) as PullRequestModel; + + it('replaces pull request metadata instead of appending values', async function () { + await PullRequestGitHelper.associateBranchWithPullRequest(repository, pullRequest(100), 'feature'); + await PullRequestGitHelper.associateBranchWithPullRequest(repository, pullRequest(100), 'feature'); + await PullRequestGitHelper.associateBranchWithPullRequest(repository, pullRequest(101), 'feature'); + + const key = 'branch.feature.github-pr-owner-number'; + assert.deepStrictEqual((await repository.getConfigs()).filter(config => config.key === key), [ + { key, value: 'owner#name#101' }, + ]); + }); + + it('does not append to existing duplicate metadata', async function () { + const key = 'branch.feature.github-pr-owner-number'; + await repository.setConfig(key, 'owner#name#100'); + await repository.setConfig(key, 'owner#name#100'); + + await PullRequestGitHelper.associateBranchWithPullRequest(repository, pullRequest(100), 'feature'); + + assert.strictEqual((await repository.getConfigs()).filter(config => config.key === key).length, 2); + }); + }); + + describe('associateBaseBranchWithBranch', function () { + it('replaces base branch metadata instead of appending values', async function () { + await PullRequestGitHelper.associateBaseBranchWithBranch(repository, 'feature', { owner: 'owner', repo: 'name', branch: 'main' }); + await PullRequestGitHelper.associateBaseBranchWithBranch(repository, 'feature', { owner: 'owner', repo: 'name', branch: 'main' }); + await PullRequestGitHelper.associateBaseBranchWithBranch(repository, 'feature', { owner: 'owner', repo: 'name', branch: 'next' }); + + const key = 'branch.feature.github-pr-base-branch'; + assert.deepStrictEqual((await repository.getConfigs()).filter(config => config.key === key), [ + { key, value: 'owner#name#next' }, + ]); + }); + }); + describe('getMatchingPullRequestMetadataForBranch', function () { it('returns the highest-numbered PR when duplicate config entries exist for the branch', async function () { // Simulate the case where a branch name has been associated with multiple