Git - branch protection (#149360)

* Initial implementation of branch protection

* Pull request feedback

* Update extensions/git/src/commands.ts

Co-authored-by: João Moreno <joao.moreno@microsoft.com>
This commit is contained in:
Ladislau Szomoru 2022-05-13 11:15:01 +02:00 committed by GitHub
parent 9701a364ac
commit a28eab6873
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 71 additions and 0 deletions

View file

@ -1854,6 +1854,29 @@
"description": "%config.branchPrefix%",
"default": ""
},
"git.branchProtection": {
"type": "array",
"markdownDescription": "%config.branchProtection%",
"items": {
"type": "string"
},
"default": []
},
"git.branchProtectionPrompt": {
"type": "string",
"description": "%config.branchProtectionPrompt%",
"enum": [
"alwaysCommit",
"alwaysCommitToNewBranch",
"alwaysPrompt"
],
"enumDescriptions": [
"%config.branchProtectionPrompt.alwaysCommit%",
"%config.branchProtectionPrompt.alwaysCommitToNewBranch%",
"%config.branchProtectionPrompt.alwaysPrompt%"
],
"default": "alwaysPrompt"
},
"git.branchValidationRegex": {
"type": "string",
"description": "%config.branchValidationRegex%",
@ -2602,6 +2625,7 @@
"byline": "^5.0.0",
"file-type": "^7.2.0",
"jschardet": "3.0.0",
"picomatch": "2.3.1",
"vscode-nls": "^4.0.0",
"vscode-uri": "^2.0.0",
"which": "^1.3.0"
@ -2611,6 +2635,7 @@
"@types/file-type": "^5.2.1",
"@types/mocha": "^9.1.1",
"@types/node": "16.x",
"@types/picomatch": "2.3.0",
"@types/which": "^1.0.28"
},
"repository": {

View file

@ -120,6 +120,11 @@
"config.checkoutType.tags": "Tags",
"config.checkoutType.remote": "Remote branches",
"config.branchPrefix": "Prefix used when creating a new branch.",
"config.branchProtection": "List of protected branches. By default, a prompt is shown before changes are committed to a protected branch. The prompt can be controlled using the `#git.branchProtectionPrompt#` setting.",
"config.branchProtectionPrompt": "Controls whether a prompt is being before changes are committed to a protected branch.",
"config.branchProtectionPrompt.alwaysCommit": "Always commit changes to the protected branch.",
"config.branchProtectionPrompt.alwaysCommitToNewBranch": "Always commit changes to a new branch.",
"config.branchProtectionPrompt.alwaysPrompt": "Always prompt before changes are committed to a protected branch.",
"config.branchRandomNameDictionary": "List of dictionaries used when the branch name that is randomly generated. Supported values: `adjectives`, `animals`, `colors`, `numbers`.",
"config.branchRandomNameEnable": "Controls whether a random name is generated when creating a new branch.",
"config.branchValidationRegex": "A regular expression to validate new branch names.",

View file

@ -5,6 +5,7 @@
import * as os from 'os';
import * as path from 'path';
import * as picomatch from 'picomatch';
import { Command, commands, Disposable, LineChange, MessageOptions, Position, ProgressLocation, QuickPickItem, Range, SourceControlResourceState, TextDocumentShowOptions, TextEditor, Uri, ViewColumn, window, workspace, WorkspaceEdit, WorkspaceFolder, TimelineItem, env, Selection, TextDocumentContentProvider, InputBoxValidationSeverity } from 'vscode';
import TelemetryReporter from '@vscode/extension-telemetry';
import * as nls from 'vscode-nls';
@ -1496,6 +1497,36 @@ export class CommandCenter {
opts.all = 'tracked';
}
// Branch protection
const branchProtection = config.get<string[]>('branchProtection')!.map(bp => bp.trim()).filter(bp => bp !== '');
const branchProtectionPrompt = config.get<'alwaysCommit' | 'alwaysCommitToNewBranch' | 'alwaysPrompt'>('branchProtectionPrompt')!;
const branchIsProtected = branchProtection.some(bp => picomatch.isMatch(repository.HEAD?.name ?? '', bp));
if (branchIsProtected && (branchProtectionPrompt === 'alwaysPrompt' || branchProtectionPrompt === 'alwaysCommitToNewBranch')) {
const commitToNewBranch = localize('commit to branch', "Commit to a New Branch");
let pick: string | undefined = commitToNewBranch;
if (branchProtectionPrompt === 'alwaysPrompt') {
const message = localize('confirm branch protection commit', "You are trying to commit to a protected branch and you might not have permission to push your commits to the remote.\n\nHow would you like to proceed?");
const commit = localize('commit changes', "Commit Anyway");
pick = await window.showWarningMessage(message, { modal: true }, commitToNewBranch, commit);
}
if (!pick) {
return false;
} else if (pick === commitToNewBranch) {
const branchName = await this.promptForBranchName(repository);
if (!branchName) {
return false;
}
await repository.branch(branchName, true);
}
}
await repository.commit(message, opts);
const postCommitCommand = config.get<'none' | 'push' | 'sync'>('postCommitCommand');

View file

@ -36,6 +36,11 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae"
integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w==
"@types/picomatch@2.3.0":
version "2.3.0"
resolved "https://registry.yarnpkg.com/@types/picomatch/-/picomatch-2.3.0.tgz#75db5e75a713c5a83d5b76780c3da84a82806003"
integrity sha512-O397rnSS9iQI4OirieAtsDqvCj4+3eY1J+EPdNTKuHuRWIfUoGyzX294o8C4KJYaLqgSrd2o60c5EqCU8Zv02g==
"@types/which@^1.0.28":
version "1.0.28"
resolved "https://registry.yarnpkg.com/@types/which/-/which-1.0.28.tgz#016e387629b8817bed653fe32eab5d11279c8df6"
@ -71,6 +76,11 @@ jschardet@3.0.0:
resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-3.0.0.tgz#898d2332e45ebabbdb6bf2feece9feea9a99e882"
integrity sha512-lJH6tJ77V8Nzd5QWRkFYCLc13a3vADkh3r/Fi8HupZGWk2OVVDfnZP8V/VgQgZ+lzW0kG2UGb5hFgt3V3ndotQ==
picomatch@2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
vscode-nls@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.0.0.tgz#4001c8a6caba5cedb23a9c5ce1090395c0e44002"