diff --git a/extensions/git/package.json b/extensions/git/package.json index 414c360f5f1..71a59270211 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -936,6 +936,16 @@ "usesOnlineServices" ] }, + "git.branchValidationRegex": { + "type": "string", + "description": "%config.branchValidationRegex%", + "default": "" + }, + "git.branchWhitespaceChar": { + "type": "string", + "description": "%config.branchWhitespaceChar%", + "default": "-" + }, "git.confirmSync": { "type": "boolean", "description": "%config.confirmSync%", diff --git a/extensions/git/package.nls.json b/extensions/git/package.nls.json index 546bea28b64..2887582e89f 100644 --- a/extensions/git/package.nls.json +++ b/extensions/git/package.nls.json @@ -72,6 +72,8 @@ "config.checkoutType.local": "Show only local branches.", "config.checkoutType.tags": "Show only tags.", "config.checkoutType.remote": "Show only remote branches.", + "config.branchValidationRegex": "A regular expression to validate new branch names.", + "config.branchWhitespaceChar": "The character to replace whitespace in new branch names.", "config.ignoreLegacyWarning": "Ignores the legacy Git warning.", "config.ignoreMissingGitWarning": "Ignores the warning when Git is missing.", "config.ignoreLimitWarning": "Ignores the warning when there are too many changes in a repository.", diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index df2100f50c2..59225dd6f46 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -1261,19 +1261,42 @@ export class CommandCenter { await choice.run(repository); } + @command('git.branch', { repository: true }) async branch(repository: Repository): Promise { + const config = workspace.getConfiguration('git'); + const branchValidationRegex = config.get('branchValidationRegex')!; + const branchWhitespaceChar = config.get('branchWhitespaceChar')!; + const validateName = new RegExp(branchValidationRegex); + const sanitize = (name: string) => { + name = name.trim(); + + if (!name) { + return name; + } + + return name.replace(/^\.|\/\.|\.\.|~|\^|:|\/$|\.lock$|\.lock\/|\\|\*|\s|^\s*$|\.|\[|\]$/g, branchWhitespaceChar); + }; + const result = await window.showInputBox({ placeHolder: localize('branch name', "Branch name"), prompt: localize('provide branch name', "Please provide a branch name"), - ignoreFocusOut: true + ignoreFocusOut: true, + validateInput: (name: string) => { + if (validateName.test(sanitize(name))) { + return null; + } + + return localize('branch name format invalid', "Branch name needs to match regex: {0}", branchValidationRegex); + } }); - if (!result) { + const name = sanitize(result || ''); + + if (!name) { return; } - const name = result.replace(/^\.|\/\.|\.\.|~|\^|:|\/$|\.lock$|\.lock\/|\\|\*|\s|^\s*$|\.|\[|\]|$/g, '-'); await repository.branch(name, true); }