From 1abe67051be9d2d64418229976288682ef8216a6 Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Thu, 8 Feb 2024 18:09:42 -0500 Subject: [PATCH] Closes #3138 adds create branch option to switch --- CHANGELOG.md | 4 ++++ src/commands/git/branch.ts | 4 +++- src/commands/git/switch.ts | 21 +++++++++++++++++++++ src/commands/quickCommand.steps.ts | 29 ++++++++++++++++++++++++----- 4 files changed, 52 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d37b3310cd23..65df11528e728 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p ## [Unreleased] +### Added + +- Adds a _Create New Branch..._ option to the _Git Switch to..._ command to easily create a new branch to switch to — closes [#3138](https://github.com/gitkraken/vscode-gitlens/issues/3138) + ## [14.8.0] - 2024-02-08 ### Added diff --git a/src/commands/git/branch.ts b/src/commands/git/branch.ts index 21f7de1e4dc1d..3eb0f429013ab 100644 --- a/src/commands/git/branch.ts +++ b/src/commands/git/branch.ts @@ -50,6 +50,8 @@ interface CreateState { reference: GitReference; name: string; flags: CreateFlags[]; + + suggestNameOnly?: boolean; } type DeleteFlags = '--force' | '--remotes'; @@ -151,7 +153,7 @@ export class BranchGitCommand extends QuickCommand { counter++; } - if (args.state.name != null) { + if (!args.state.suggestNameOnly && args.state.name != null) { counter++; } diff --git a/src/commands/git/switch.ts b/src/commands/git/switch.ts index 8528af2c18602..d98ca4e562330 100644 --- a/src/commands/git/switch.ts +++ b/src/commands/git/switch.ts @@ -155,6 +155,7 @@ export class SwitchGitCommand extends QuickCommand { if (state.counter < 2 || state.reference == null) { const result = yield* pickBranchOrTagStepMultiRepo(state as SwitchStepState, context, { placeholder: context => `Choose a branch${context.showTags ? ' or tag' : ''} to switch to`, + allowCreate: state.repos.length === 1, }); if (result === StepResultBreak) { // If we skipped the previous step, make sure we back up past it @@ -165,6 +166,26 @@ export class SwitchGitCommand extends QuickCommand { continue; } + if (typeof result == 'string') { + yield* getSteps( + this.container, + { + command: 'branch', + state: { + subcommand: 'create', + repo: state.repos[0], + name: result, + suggestNameOnly: true, + flags: ['--switch'], + }, + }, + this.pickedVia, + ); + + endSteps(state); + return; + } + state.reference = result; } diff --git a/src/commands/quickCommand.steps.ts b/src/commands/quickCommand.steps.ts index f240f8c8e7f35..e5ca11324b40a 100644 --- a/src/commands/quickCommand.steps.ts +++ b/src/commands/quickCommand.steps.ts @@ -1,4 +1,4 @@ -import type { QuickInputButton, QuickPick } from 'vscode'; +import type { QuickInputButton, QuickPick, QuickPickItem } from 'vscode'; import { ThemeIcon } from 'vscode'; import { Commands, GlyphChars, quickPickTitleMaxChars } from '../constants'; import { Container } from '../container'; @@ -931,28 +931,37 @@ export function* pickBranchOrTagStep< export function* pickBranchOrTagStepMultiRepo< State extends StepState & { repos: Repository[]; reference?: GitReference }, - Context extends { repos: Repository[]; showTags?: boolean; title: string }, + Context extends { allowCreate?: boolean; repos: Repository[]; showTags?: boolean; title: string }, >( state: State, context: Context, { + allowCreate, filter, picked, placeholder, titleContext, value, }: { + allowCreate?: boolean; filter?: { branches?: (b: GitBranch) => boolean; tags?: (t: GitTag) => boolean }; picked?: string | string[]; placeholder: string | ((context: Context) => string); titleContext?: string; value?: string; }, -): StepResultGenerator { +): StepResultGenerator { context.showTags = state.repos.length === 1; const showTagsButton = new ShowTagsToggleQuickInputButton(context.showTags); + const createNewBranchItem: QuickPickItem & { item: string } = { + label: 'Create New Branch...', + iconPath: new ThemeIcon('plus'), + alwaysShow: true, + item: '', + }; + const getBranchesAndOrTagsFn = () => { return getBranchesAndOrTags(state.repos, context.showTags ? ['branches', 'tags'] : ['branches'], { buttons: [RevealInSideBarQuickInputButton], @@ -965,10 +974,12 @@ export function* pickBranchOrTagStepMultiRepo< const items = getBranchesAndOrTagsFn().then(branchesAndOrTags => branchesAndOrTags.length === 0 ? [createDirectiveQuickPickItem(Directive.Back, true), createDirectiveQuickPickItem(Directive.Cancel)] - : branchesAndOrTags, + : allowCreate + ? [createNewBranchItem, ...branchesAndOrTags] + : branchesAndOrTags, ); - const step = createPickStep({ + const step = createPickStep({ title: appendReposToTitle(`${context.title}${titleContext ?? ''}`, state, context), placeholder: count => !count @@ -984,7 +995,13 @@ export function* pickBranchOrTagStepMultiRepo< selectValueWhenShown: true, items: items, additionalButtons: [showTagsButton], + onDidChangeValue: quickpick => { + createNewBranchItem.item = quickpick.value; + return true; + }, onDidClickItemButton: (quickpick, button, { item }) => { + if (typeof item === 'string') return; + if (button === RevealInSideBarQuickInputButton) { if (isBranchReference(item)) { void BranchActions.reveal(item, { select: true, focus: false, expand: true }); @@ -1024,6 +1041,8 @@ export function* pickBranchOrTagStepMultiRepo< }, keys: ['right', 'alt+right', 'ctrl+right'], onDidPressKey: (_quickpick, _key, { item }) => { + if (typeof item === 'string') return; + if (isBranchReference(item)) { void BranchActions.reveal(item, { select: true, focus: false, expand: true }); } else if (isTagReference(item)) {