From ad6660d0c4610025b2fb94488fe3612df27145e7 Mon Sep 17 00:00:00 2001 From: Guy Waldman Date: Fri, 21 Sep 2018 04:09:29 +0300 Subject: [PATCH] Add command to create branch from specific ref --- extensions/git/package.json | 5 ++ extensions/git/package.nls.json | 1 + extensions/git/src/commands.ts | 106 ++++++++++++++++++-------------- 3 files changed, 65 insertions(+), 47 deletions(-) diff --git a/extensions/git/package.json b/extensions/git/package.json index 59e4100e4e7..abffd8a8db8 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -240,6 +240,11 @@ "title": "%command.branch%", "category": "Git" }, + { + "command": "git.branchFrom", + "title": "%command.branchFrom%", + "category": "Git" + }, { "command": "git.deleteBranch", "title": "%command.deleteBranch%", diff --git a/extensions/git/package.nls.json b/extensions/git/package.nls.json index 4d73891f818..5c6b69cb32e 100644 --- a/extensions/git/package.nls.json +++ b/extensions/git/package.nls.json @@ -32,6 +32,7 @@ "command.undoCommit": "Undo Last Commit", "command.checkout": "Checkout to...", "command.branch": "Create Branch...", + "command.branchFrom": "Create Branch From...", "command.deleteBranch": "Delete Branch...", "command.renameBranch": "Rename Branch...", "command.merge": "Merge Branch...", diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index 9c838715840..d5f9abbdeda 100755 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -154,6 +154,47 @@ async function categorizeResourceByResolution(resources: Resource[]): Promise<{ return { merge, resolved, unresolved, deletionConflicts }; } +function repositoryRefsToItems(repository: Repository): Array { + const config = workspace.getConfiguration('git'); + const checkoutType = config.get('checkoutType') || 'all'; + const includeTags = checkoutType === 'all' || checkoutType === 'tags'; + const includeRemotes = checkoutType === 'all' || checkoutType === 'remote'; + + const heads = repository.refs.filter(ref => ref.type === RefType.Head) + .map(ref => new CheckoutItem(ref)); + const tags = (includeTags ? repository.refs.filter(ref => ref.type === RefType.Tag) : []) + .map(ref => new CheckoutTagItem(ref)); + const remoteHeads = (includeRemotes ? repository.refs.filter(ref => ref.type === RefType.RemoteHead) : []) + .map(ref => new CheckoutRemoteHeadItem(ref)); + + return [...heads, ...tags, ...remoteHeads]; +} + +async function inputNameForBranch(): Promise { + const config = workspace.getConfiguration('git'); + const branchWhitespaceChar = config.get('branchWhitespaceChar')!; + const branchValidationRegex = config.get('branchValidationRegex')!; + const sanitize = (name: string) => name ? + name.trim().replace(/^\.|\/\.|\.\.|~|\^|:|\/$|\.lock$|\.lock\/|\\|\*|\s|^\s*$|\.$|\[|\]$/g, branchWhitespaceChar) + : name; + + const result = await window.showInputBox({ + placeHolder: localize('branch name', "Branch name"), + prompt: localize('provide branch name', "Please provide a branch name"), + ignoreFocusOut: true, + validateInput: (name: string) => { + const validateName = new RegExp(branchValidationRegex); + if (validateName.test(sanitize(name))) { + return null; + } + + return localize('branch name format invalid', "Branch name needs to match regex: {0}", branchValidationRegex); + } + }); + + return sanitize(result || ''); +} + enum PushType { Push, PushTo, @@ -1352,24 +1393,9 @@ export class CommandCenter { await repository.checkout(treeish); return true; } - - const config = workspace.getConfiguration('git'); - const checkoutType = config.get('checkoutType') || 'all'; - const includeTags = checkoutType === 'all' || checkoutType === 'tags'; - const includeRemotes = checkoutType === 'all' || checkoutType === 'remote'; - const createBranch = new CreateBranchItem(this); - const heads = repository.refs.filter(ref => ref.type === RefType.Head) - .map(ref => new CheckoutItem(ref)); - - const tags = (includeTags ? repository.refs.filter(ref => ref.type === RefType.Tag) : []) - .map(ref => new CheckoutTagItem(ref)); - - const remoteHeads = (includeRemotes ? repository.refs.filter(ref => ref.type === RefType.RemoteHead) : []) - .map(ref => new CheckoutRemoteHeadItem(ref)); - - const picks = [createBranch, ...heads, ...tags, ...remoteHeads]; + const picks = [createBranch, ...repositoryRefsToItems(repository)]; const placeHolder = localize('select a ref to checkout', 'Select a ref to checkout'); const choice = await window.showQuickPick(picks, { placeHolder }); @@ -1382,41 +1408,27 @@ export class CommandCenter { } @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, - validateInput: (name: string) => { - if (validateName.test(sanitize(name))) { - return null; - } - - return localize('branch name format invalid', "Branch name needs to match regex: {0}", branchValidationRegex); - } - }); - - const name = sanitize(result || ''); + async branch(repository: Repository, ref?: string): Promise { + const name = await inputNameForBranch(); if (!name) { return; } - await repository.branch(name, true); + await repository.branch(name, true, ref); + } + + @command('git.branchFrom', { repository: true }) + async createBranchFrom(repository: Repository): Promise { + const refs = repositoryRefsToItems(repository); + const placeHolder = localize('select a ref to create a new branch from', 'Select a ref to create a new branch from'); + const choice = await window.showQuickPick(refs, { placeHolder }); + + if (!choice) { + return; + } + + await this.branch(repository, choice.label); } @command('git.deleteBranch', { repository: true }) @@ -1937,7 +1949,7 @@ export class CommandCenter { return Promise.resolve(); } - return Promise.resolve(method.apply(this, [repository, ...args])); + return Promise.resolve(method.apply(this, [repository, ...args.slice(1)])); }); }