Skip to content

Commit 35a3849

Browse files
authored
Use word dict for git branch naming (#7933)
1 parent ccd4b86 commit 35a3849

File tree

4 files changed

+64
-29
lines changed

4 files changed

+64
-29
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4322,6 +4322,7 @@
43224322
"webpack-cli": "4.2.0"
43234323
},
43244324
"dependencies": {
4325+
"@joaomoreno/unique-names-generator": "^5.2.0",
43254326
"@octokit/rest": "22.0.0",
43264327
"@octokit/types": "14.1.0",
43274328
"@vscode/codicons": "^0.0.36",

src/common/settingKeys.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ export const PULL_BEFORE_CHECKOUT = 'pullBeforeCheckout';
6969
export const OPEN_DIFF_ON_CLICK = 'openDiffOnClick';
7070
export const SHOW_INLINE_OPEN_FILE_ACTION = 'showInlineOpenFileAction';
7171
export const AUTO_STASH = 'autoStash';
72+
export const BRANCH_WHITESPACE_CHAR = 'branchWhitespaceChar';
73+
export const BRANCH_RANDOM_NAME_DICTIONARY = 'branchRandomName.dictionary';
7274

7375
// GitHub Enterprise
7476
export const GITHUB_ENTERPRISE = 'github-enterprise';

src/github/copilotRemoteAgent/gitOperationsManager.ts

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,19 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6+
import { adjectives, animals, colors, NumberDictionary, uniqueNamesGenerator } from '@joaomoreno/unique-names-generator';
67
import vscode from 'vscode';
78
import { Repository } from '../../api/api';
89
import Logger from '../../common/logger';
10+
import { BRANCH_RANDOM_NAME_DICTIONARY, BRANCH_WHITESPACE_CHAR, GIT } from '../../common/settingKeys';
911
import { RepoInfo } from '../common';
1012

1113
export class GitOperationsManager {
1214
constructor(private loggerID: string) { }
1315

1416
async commitAndPushChanges(repoInfo: RepoInfo) {
1517
const { repository, remote, baseRef } = repoInfo;
16-
const asyncBranch = `copilot/vscode${Date.now()}`;
18+
const asyncBranch = await this.generateRandomBranchName(repository, 'copilot');
1719

1820
try {
1921
await repository.createBranch(asyncBranch, true);
@@ -138,4 +140,54 @@ export class GitOperationsManager {
138140
}
139141
}
140142
}
143+
144+
// Adapted from https://github.com/microsoft/vscode/blob/e35e3b4e057450ea3d90c724fae5e3e9619b96fe/extensions/git/src/commands.ts#L3007
145+
private async generateRandomBranchName(repository: Repository, prefix: string): Promise<string> {
146+
const config = vscode.workspace.getConfiguration(GIT);
147+
const branchWhitespaceChar = config.get<string>(BRANCH_WHITESPACE_CHAR);
148+
const branchRandomNameDictionary = config.get<string[]>(BRANCH_RANDOM_NAME_DICTIONARY);
149+
150+
// Default to legacy behaviour if config mismatches core
151+
if (branchWhitespaceChar === undefined || branchRandomNameDictionary === undefined) {
152+
return `copilot/vscode${Date.now()}`;
153+
}
154+
155+
const separator = branchWhitespaceChar;
156+
const dictionaries: string[][] = [];
157+
for (const dictionary of branchRandomNameDictionary) {
158+
if (dictionary.toLowerCase() === 'adjectives') {
159+
dictionaries.push(adjectives);
160+
}
161+
if (dictionary.toLowerCase() === 'animals') {
162+
dictionaries.push(animals);
163+
}
164+
if (dictionary.toLowerCase() === 'colors') {
165+
dictionaries.push(colors);
166+
}
167+
if (dictionary.toLowerCase() === 'numbers') {
168+
dictionaries.push(NumberDictionary.generate({ length: 3 }));
169+
}
170+
}
171+
172+
if (dictionaries.length === 0) {
173+
return '';
174+
}
175+
176+
// 5 attempts to generate a random branch name
177+
for (let index = 0; index < 5; index++) {
178+
const randomName = `${prefix}/${uniqueNamesGenerator({
179+
dictionaries,
180+
length: dictionaries.length,
181+
separator
182+
})}`;
183+
184+
// Check for local ref conflict
185+
const refs = await repository.getRefs?.({ pattern: `refs/heads/${randomName}` });
186+
if (!refs || refs.length === 0) {
187+
return randomName;
188+
}
189+
}
190+
191+
return '';
192+
}
141193
}

yarn.lock

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,11 @@
354354
"@types/istanbul-reports" "^1.1.1"
355355
"@types/yargs" "^13.0.0"
356356

357+
"@joaomoreno/unique-names-generator@^5.2.0":
358+
version "5.2.0"
359+
resolved "https://registry.yarnpkg.com/@joaomoreno/unique-names-generator/-/unique-names-generator-5.2.0.tgz#f7cf42c8734ef4b8f2c8d2ecb2baf9d4e08664ce"
360+
integrity sha512-JEh3qZ85Z6syFvQlhRGRyTPI1M5VticiiP8Xl8EV0XfyfI4Mwzd6Zw28BBrEgUJCYv/cpKCQClVj3J8Tn0KFiA==
361+
357362
"@jridgewell/gen-mapping@^0.3.0":
358363
version "0.3.2"
359364
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9"
@@ -6771,16 +6776,7 @@ streamx@^2.15.0, streamx@^2.21.0:
67716776
optionalDependencies:
67726777
bare-events "^2.2.0"
67736778

6774-
"string-width-cjs@npm:string-width@^4.2.0":
6775-
version "4.2.3"
6776-
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
6777-
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
6778-
dependencies:
6779-
emoji-regex "^8.0.0"
6780-
is-fullwidth-code-point "^3.0.0"
6781-
strip-ansi "^6.0.1"
6782-
6783-
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
6779+
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
67846780
version "4.2.3"
67856781
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
67866782
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -6870,7 +6866,7 @@ stringify-entities@^4.0.0:
68706866
character-entities-html4 "^2.0.0"
68716867
character-entities-legacy "^3.0.0"
68726868

6873-
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
6869+
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
68746870
version "6.0.1"
68756871
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
68766872
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -6884,13 +6880,6 @@ strip-ansi@^4.0.0:
68846880
dependencies:
68856881
ansi-regex "^3.0.0"
68866882

6887-
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
6888-
version "6.0.1"
6889-
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
6890-
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
6891-
dependencies:
6892-
ansi-regex "^5.0.1"
6893-
68946883
strip-ansi@^7.0.1:
68956884
version "7.1.2"
68966885
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.2.tgz#132875abde678c7ea8d691533f2e7e22bb744dba"
@@ -7901,16 +7890,7 @@ workerpool@^9.2.0:
79017890
resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-9.3.4.tgz#f6c92395b2141afd78e2a889e80cb338fe9fca41"
79027891
integrity sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==
79037892

7904-
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
7905-
version "7.0.0"
7906-
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
7907-
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
7908-
dependencies:
7909-
ansi-styles "^4.0.0"
7910-
string-width "^4.1.0"
7911-
strip-ansi "^6.0.0"
7912-
7913-
wrap-ansi@^7.0.0:
7893+
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
79147894
version "7.0.0"
79157895
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
79167896
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==

0 commit comments

Comments
 (0)