Skip to content

Commit c3639e7

Browse files
committed
add deleteBranch
# Conflicts: # src/env/node/git/localGitProvider.ts
1 parent 00a56b2 commit c3639e7

File tree

6 files changed

+99
-52
lines changed

6 files changed

+99
-52
lines changed

src/commands/git/branch.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -558,10 +558,17 @@ export class BranchGitCommand extends QuickCommand {
558558
state.flags = result;
559559

560560
endSteps(state);
561-
state.repo.branchDelete(state.references, {
562-
force: state.flags.includes('--force'),
563-
remote: state.flags.includes('--remotes'),
564-
});
561+
562+
try {
563+
await state.repo.git.deleteBranch(state.references, {
564+
force: state.flags.includes('--force'),
565+
remote: state.flags.includes('--remotes'),
566+
});
567+
} catch (ex) {
568+
Logger.error(ex);
569+
// TODO likely need some better error handling here
570+
return showGenericErrorMessage('Unable to delete branch');
571+
}
565572
}
566573
}
567574

src/env/node/git/git.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import { GitErrorHandling } from '../../../git/commandOptions';
1212
import {
1313
BlameIgnoreRevsFileBadRevisionError,
1414
BlameIgnoreRevsFileError,
15+
BranchError,
16+
BranchErrorReason,
1517
CherryPickError,
1618
CherryPickErrorReason,
1719
FetchError,
@@ -520,7 +522,7 @@ export class Git {
520522
}
521523
}
522524

523-
branch(repoPath: string, ...args: string[]) {
525+
async branch(repoPath: string, ...args: string[]): Promise<void> {
524526
return this.git<string>({ cwd: repoPath }, 'branch', ...args);
525527
}
526528

@@ -976,6 +978,10 @@ export class Git {
976978
publish?: boolean;
977979
remote?: string;
978980
upstream?: string;
981+
delete?: {
982+
remote: string;
983+
branches: string[];
984+
};
979985
},
980986
): Promise<void> {
981987
const params = ['push'];
@@ -1001,8 +1007,10 @@ export class Git {
10011007
} else {
10021008
params.push(options.remote, options.branch);
10031009
}
1004-
} else if (options.remote) {
1010+
} else if (options.remote != null) {
10051011
params.push(options.remote);
1012+
} else if (options.delete != null) {
1013+
params.push('-d', options.delete.remote, ...options.delete.branches);
10061014
}
10071015

10081016
try {

src/env/node/git/localGitProvider.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,6 +1285,57 @@ export class LocalGitProvider implements GitProvider, Disposable {
12851285
await this.git.branch(repoPath, '-m', oldName, newName);
12861286
}
12871287

1288+
@log()
1289+
async deleteBranch(
1290+
repoPath: string,
1291+
branches: GitBranchReference[],
1292+
options: { force?: boolean; remote?: boolean },
1293+
): Promise<void> {
1294+
const localBranches = branches.filter((b: GitBranchReference) => !b.remote);
1295+
if (localBranches.length !== 0) {
1296+
const args = ['--delete'];
1297+
if (options.force) {
1298+
args.push('--force');
1299+
}
1300+
1301+
await this.git.branch(repoPath, ...args, ...branches.map((b: GitBranchReference) => b.ref));
1302+
1303+
if (options.remote) {
1304+
const trackingBranches = localBranches.filter(b => b.upstream != null);
1305+
if (trackingBranches.length !== 0) {
1306+
const branchesByOrigin = groupByMap(trackingBranches, b =>
1307+
getRemoteNameFromBranchName(b.upstream!.name),
1308+
);
1309+
1310+
for (const [remote, branches] of branchesByOrigin.entries()) {
1311+
await this.git.push(repoPath, {
1312+
delete: {
1313+
remote: remote,
1314+
branches: branches.map(b => getBranchNameWithoutRemote(b.upstream!.name)),
1315+
},
1316+
});
1317+
}
1318+
}
1319+
}
1320+
}
1321+
1322+
const remoteBranches = branches.filter((b: GitBranchReference) => b.remote);
1323+
if (remoteBranches.length !== 0) {
1324+
const branchesByOrigin = groupByMap(remoteBranches, b => getRemoteNameFromBranchName(b.name));
1325+
1326+
for (const [remote, branches] of branchesByOrigin.entries()) {
1327+
await this.git.push(repoPath, {
1328+
delete: {
1329+
remote: remote,
1330+
branches: branches.map((b: GitBranchReference) =>
1331+
b.remote ? getBranchNameWithoutRemote(b.name) : b.name,
1332+
),
1333+
},
1334+
});
1335+
}
1336+
}
1337+
}
1338+
12881339
@log()
12891340
async createTag(repoPath: string, name: string, ref: string, message?: string): Promise<void> {
12901341
try {

src/git/gitProvider.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,11 @@ export interface BranchContributorOverview {
120120
export interface GitProviderRepository {
121121
createBranch?(repoPath: string, name: string, ref: string): Promise<void>;
122122
renameBranch?(repoPath: string, oldName: string, newName: string): Promise<void>;
123+
deleteBranch?(
124+
repoPath: string,
125+
branches: GitBranchReference | GitBranchReference[],
126+
options?: { force?: boolean; remote?: boolean },
127+
): Promise<void>;
123128
createTag?(repoPath: string, name: string, ref: string, message?: string): Promise<void>;
124129
deleteTag?(repoPath: string, name: string): Promise<void>;
125130
addRemote?(repoPath: string, name: string, url: string, options?: { fetch?: boolean }): Promise<void>;

src/git/gitProviderService.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1377,6 +1377,25 @@ export class GitProviderService implements Disposable {
13771377
return provider.renameBranch(path, oldName, newName);
13781378
}
13791379

1380+
@log()
1381+
deleteBranch(
1382+
repoPath: string,
1383+
branches: GitBranchReference | GitBranchReference[],
1384+
options?: { force?: boolean; remote?: boolean },
1385+
): Promise<void> {
1386+
const { provider, path } = this.getProvider(repoPath);
1387+
if (provider.deleteBranch == null) throw new ProviderNotSupportedError(provider.descriptor.name);
1388+
1389+
if (!Array.isArray(branches)) {
1390+
branches = [branches];
1391+
}
1392+
1393+
return provider.deleteBranch(path, branches, {
1394+
force: options?.force,
1395+
remote: options?.remote,
1396+
});
1397+
}
1398+
13801399
@log()
13811400
createTag(repoPath: string | Uri, name: string, ref: string, message?: string): Promise<void> {
13821401
const { provider, path } = this.getProvider(repoPath);

src/git/models/repository.ts

Lines changed: 3 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { debug, log, logName } from '../../system/decorators/log';
1515
import { memoize } from '../../system/decorators/memoize';
1616
import type { Deferrable } from '../../system/function';
1717
import { debounce } from '../../system/function';
18-
import { filter, groupByMap, join, map, min, some } from '../../system/iterable';
18+
import { filter, join, map, min, some } from '../../system/iterable';
1919
import { getLoggableName, Logger } from '../../system/logger';
2020
import { getLogScope } from '../../system/logger.scope';
2121
import { updateRecordValue } from '../../system/object';
@@ -26,9 +26,9 @@ import { configuration } from '../../system/vscode/configuration';
2626
import type { GitProviderDescriptor, GitProviderRepository } from '../gitProvider';
2727
import type { GitProviderService } from '../gitProviderService';
2828
import type { GitBranch } from './branch';
29-
import { getBranchNameWithoutRemote, getRemoteNameFromBranchName } from './branch';
30-
import type { GitBranchReference, GitReference } from './reference';
29+
import type { GitBranchReference, GitReference, GitTagReference } from './reference';
3130
import { getNameWithoutRemote, isBranchReference } from './reference';
31+
import { getBranchNameWithoutRemote, getRemoteNameFromBranchName } from './branch';
3232
import type { GitRemote } from './remote';
3333
import type { GitWorktree } from './worktree';
3434

@@ -591,49 +591,6 @@ export class Repository implements Disposable {
591591
return remote;
592592
}
593593

594-
@log()
595-
branchDelete(branches: GitBranchReference | GitBranchReference[], options?: { force?: boolean; remote?: boolean }) {
596-
if (!Array.isArray(branches)) {
597-
branches = [branches];
598-
}
599-
600-
const localBranches = branches.filter(b => !b.remote);
601-
if (localBranches.length !== 0) {
602-
const args = ['--delete'];
603-
if (options?.force) {
604-
args.push('--force');
605-
}
606-
void this.runTerminalCommand('branch', ...args, ...branches.map(b => b.ref));
607-
608-
if (options?.remote) {
609-
const trackingBranches = localBranches.filter(b => b.upstream != null);
610-
if (trackingBranches.length !== 0) {
611-
const branchesByOrigin = groupByMap(trackingBranches, b =>
612-
getRemoteNameFromBranchName(b.upstream!.name),
613-
);
614-
615-
for (const [remote, branches] of branchesByOrigin.entries()) {
616-
void this.runTerminalCommand(
617-
'push',
618-
'-d',
619-
remote,
620-
...branches.map(b => getBranchNameWithoutRemote(b.upstream!.name)),
621-
);
622-
}
623-
}
624-
}
625-
}
626-
627-
const remoteBranches = branches.filter(b => b.remote);
628-
if (remoteBranches.length !== 0) {
629-
const branchesByOrigin = groupByMap(remoteBranches, b => getRemoteNameFromBranchName(b.name));
630-
631-
for (const [remote, branches] of branchesByOrigin.entries()) {
632-
void this.runTerminalCommand('push', '-d', remote, ...branches.map(b => getNameWithoutRemote(b)));
633-
}
634-
}
635-
}
636-
637594
@log()
638595
cherryPick(...args: string[]) {
639596
void this.runTerminalCommand('cherry-pick', ...args);

0 commit comments

Comments
 (0)