Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 61 additions & 66 deletions src/commands/git/worktree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
} from '../../git/models/reference';
import type { Repository } from '../../git/models/repository';
import type { GitWorktree } from '../../git/models/worktree';
import { getWorktreeForBranch } from '../../git/models/worktree';
import { showGenericErrorMessage } from '../../messages';
import type { QuickPickItemOfT } from '../../quickpicks/items/common';
import { createQuickPickSeparator } from '../../quickpicks/items/common';
Expand Down Expand Up @@ -86,6 +87,7 @@ type CreateFlags = '--force' | '-b' | '--detach' | '--direct';
interface CreateState {
subcommand: 'create';
repo: string | Repository;
worktree?: GitWorktree;
uri: Uri;
reference?: GitReference;
addRemote?: { name: string; url: string };
Expand Down Expand Up @@ -410,6 +412,58 @@ export class WorktreeGitCommand extends QuickCommand<State> {
state.uri = context.defaultUri!;
}

state.worktree =
isBranchReference(state.reference) && !state.reference.remote
? await getWorktreeForBranch(state.repo, state.reference.name, undefined, context.worktrees)
: undefined;

const isRemoteBranch = isBranchReference(state.reference) && state.reference?.remote;
if ((isRemoteBranch || state.worktree != null) && !state.flags.includes('-b')) {
state.flags.push('-b');
}

if (isRemoteBranch) {
state.createBranch = getNameWithoutRemote(state.reference);
const branch = await state.repo.getBranch(state.createBranch);
if (branch != null && !branch.remote) {
state.createBranch = branch.name;
}
}

if (state.flags.includes('-b')) {
let createBranchOverride: string | undefined;
if (state.createBranch != null) {
let valid = await this.container.git.validateBranchOrTagName(state.repo.path, state.createBranch);
if (valid) {
const alreadyExists = await state.repo.getBranch(state.createBranch);
valid = alreadyExists == null;
}

if (!valid) {
createBranchOverride = state.createBranch;
state.createBranch = undefined;
}
}

if (state.createBranch == null) {
const result = yield* inputBranchNameStep(state, context, {
titleContext: ` and New Branch from ${getReferenceLabel(state.reference, {
capitalize: true,
icon: false,
label: state.reference.refType !== 'branch',
})}`,
value: createBranchOverride ?? getNameWithoutRemote(state.reference),
});
if (result === StepResultBreak) {
// Clear the flags, since we can backup after the confirm step below (which is non-standard)
state.flags = [];
continue;
}

state.createBranch = result;
}
}

if (this.confirm(state.confirm)) {
const result = yield* this.createCommandConfirmStep(state, context);
if (result === StepResultBreak) continue;
Expand Down Expand Up @@ -456,51 +510,6 @@ export class WorktreeGitCommand extends QuickCommand<State> {
state.confirm = true;
this._canSkipConfirmOverride = undefined;

const isRemoteBranch = state.reference?.refType === 'branch' && state.reference?.remote;
if (isRemoteBranch && !state.flags.includes('-b')) {
state.flags.push('-b');

state.createBranch = getNameWithoutRemote(state.reference);
const branch = await state.repo.getBranch(state.createBranch);
if (branch != null) {
state.createBranch = state.reference.name;
}
}

if (state.flags.includes('-b')) {
let createBranchOverride: string | undefined;
if (state.createBranch != null) {
let valid = await this.container.git.validateBranchOrTagName(state.repo.path, state.createBranch);
if (valid) {
const alreadyExists = await state.repo.getBranch(state.createBranch);
valid = alreadyExists == null;
}

if (!valid) {
createBranchOverride = state.createBranch;
state.createBranch = undefined;
}
}

if (state.createBranch == null) {
const result = yield* inputBranchNameStep(state, context, {
titleContext: ` and New Branch from ${getReferenceLabel(state.reference, {
capitalize: true,
icon: false,
label: state.reference.refType !== 'branch',
})}`,
value: createBranchOverride ?? state.createBranch ?? getNameWithoutRemote(state.reference),
});
if (result === StepResultBreak) {
// Clear the flags, since we can backup after the confirm step below (which is non-standard)
state.flags = [];
continue;
}

state.createBranch = result;
}
}

const uri = state.flags.includes('--direct')
? state.uri
: Uri.joinPath(
Expand Down Expand Up @@ -708,42 +717,28 @@ export class WorktreeGitCommand extends QuickCommand<State> {
type StepType = FlagsQuickPickItem<CreateFlags, CreateConfirmationChoice>;
const defaultOption = createFlagsQuickPickItem<CreateFlags, Uri>(
state.flags,
[],
state.createBranch ? ['-b'] : [],
{
label: isRemoteBranch
? 'Create Worktree for New Local Branch'
: isBranch
? 'Create Worktree for Branch'
: context.title,
description: '',
detail: `Will create worktree in $(folder) ${recommendedFriendlyPath}`,
detail: `Will create worktree in $(folder) ${
state.createBranch ? recommendedNewBranchFriendlyPath : recommendedFriendlyPath
}`,
},
recommendedRootUri,
);

const confirmations: StepType[] = [];
if (!createDirectlyInFolder) {
if (!state.createBranch) {
if (state.skipWorktreeConfirmations) {
return [defaultOption.context, defaultOption.item];
}
confirmations.push(defaultOption);
if (!state.createBranch && state.skipWorktreeConfirmations) {
return [defaultOption.context, defaultOption.item];
}

confirmations.push(
createFlagsQuickPickItem<CreateFlags, Uri>(
state.flags,
['-b'],
{
label: isRemoteBranch
? 'Create Worktree for New Local Branch Named...'
: 'Create Worktree for New Branch Named...',
description: '',
detail: `Will create worktree in $(folder) ${recommendedNewBranchFriendlyPath}`,
},
recommendedRootUri,
),
);
confirmations.push(defaultOption);
} else {
if (!state.createBranch) {
confirmations.push(
Expand Down
2 changes: 1 addition & 1 deletion src/git/models/worktree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ export function createWorktreeQuickPickItem(
export async function getWorktreeForBranch(
repo: Repository,
branchName: string,
upstreamNames: string | string[],
upstreamNames?: string | string[],
worktrees?: GitWorktree[],
branches?: PageableResult<GitBranch> | Map<unknown, GitBranch>,
): Promise<GitWorktree | undefined> {
Expand Down
Loading