Skip to content

Commit d3f465e

Browse files
committed
add deleteBranch
1 parent 09b08cb commit d3f465e

File tree

6 files changed

+107
-54
lines changed

6 files changed

+107
-54
lines changed

src/commands/git/branch.ts

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

518518
endSteps(state);
519-
state.repo.branchDelete(state.references, {
520-
force: state.flags.includes('--force'),
521-
remote: state.flags.includes('--remotes'),
522-
});
519+
520+
try {
521+
await state.repo.git.deleteBranch(state.references, {
522+
force: state.flags.includes('--force'),
523+
remote: state.flags.includes('--remotes'),
524+
});
525+
} catch (ex) {
526+
Logger.error(ex);
527+
// TODO likely need some better error handling here
528+
return showGenericErrorMessage('Unable to delete branch');
529+
}
523530
}
524531
}
525532

src/env/node/git/git.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ export class Git {
506506
}
507507
}
508508

509-
branch(repoPath: string, ...args: string[]) {
509+
async branch(repoPath: string, ...args: string[]): Promise<void> {
510510
return this.git<string>({ cwd: repoPath }, 'branch', ...args);
511511
}
512512

@@ -962,6 +962,10 @@ export class Git {
962962
publish?: boolean;
963963
remote?: string;
964964
upstream?: string;
965+
delete?: {
966+
remote: string;
967+
branches: string[];
968+
};
965969
},
966970
): Promise<void> {
967971
const params = ['push'];
@@ -987,8 +991,10 @@ export class Git {
987991
} else {
988992
params.push(options.remote, options.branch);
989993
}
990-
} else if (options.remote) {
994+
} else if (options.remote != null) {
991995
params.push(options.remote);
996+
} else if (options.delete != null) {
997+
params.push('-d', options.delete.remote, ...options.delete.branches);
992998
}
993999

9941000
try {

src/env/node/git/localGitProvider.ts

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,17 @@ import { countStringLength, filterMap } from '../../../system/array';
182182
import { gate } from '../../../system/decorators/gate';
183183
import { debug, log } from '../../../system/decorators/log';
184184
import { debounce } from '../../../system/function';
185-
import { filterMap as filterMapIterable, find, first, join, last, map, skip, some } from '../../../system/iterable';
185+
import {
186+
filterMap as filterMapIterable,
187+
find,
188+
first,
189+
groupByMap,
190+
join,
191+
last,
192+
map,
193+
skip,
194+
some,
195+
} from '../../../system/iterable';
186196
import { Logger } from '../../../system/logger';
187197
import type { LogScope } from '../../../system/logger.scope';
188198
import { getLogScope, setLogScopeExit } from '../../../system/logger.scope';
@@ -1240,6 +1250,57 @@ export class LocalGitProvider implements GitProvider, Disposable {
12401250
await this.git.branch(repoPath, '-m', oldName, newName);
12411251
}
12421252

1253+
@log()
1254+
async deleteBranch(
1255+
repoPath: string,
1256+
branches: GitBranchReference[],
1257+
options: { force?: boolean; remote?: boolean },
1258+
): Promise<void> {
1259+
const localBranches = branches.filter((b: GitBranchReference) => !b.remote);
1260+
if (localBranches.length !== 0) {
1261+
const args = ['--delete'];
1262+
if (options.force) {
1263+
args.push('--force');
1264+
}
1265+
1266+
await this.git.branch(repoPath, ...args, ...branches.map((b: GitBranchReference) => b.ref));
1267+
1268+
if (options.remote) {
1269+
const trackingBranches = localBranches.filter(b => b.upstream != null);
1270+
if (trackingBranches.length !== 0) {
1271+
const branchesByOrigin = groupByMap(trackingBranches, b =>
1272+
getRemoteNameFromBranchName(b.upstream!.name),
1273+
);
1274+
1275+
for (const [remote, branches] of branchesByOrigin.entries()) {
1276+
await this.git.push(repoPath, {
1277+
delete: {
1278+
remote: remote,
1279+
branches: branches.map(b => getBranchNameWithoutRemote(b.upstream!.name)),
1280+
},
1281+
});
1282+
}
1283+
}
1284+
}
1285+
}
1286+
1287+
const remoteBranches = branches.filter((b: GitBranchReference) => b.remote);
1288+
if (remoteBranches.length !== 0) {
1289+
const branchesByOrigin = groupByMap(remoteBranches, b => getRemoteNameFromBranchName(b.name));
1290+
1291+
for (const [remote, branches] of branchesByOrigin.entries()) {
1292+
await this.git.push(repoPath, {
1293+
delete: {
1294+
remote: remote,
1295+
branches: branches.map((b: GitBranchReference) =>
1296+
b.remote ? getBranchNameWithoutRemote(b.name) : b.name,
1297+
),
1298+
},
1299+
});
1300+
}
1301+
}
1302+
}
1303+
12431304
@log()
12441305
async checkout(
12451306
repoPath: string,

src/git/gitProvider.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,11 @@ export interface RepositoryVisibilityInfo {
115115
export interface GitProviderRepository {
116116
createBranch?(repoPath: string, name: string, ref: string): Promise<void>;
117117
renameBranch?(repoPath: string, oldName: string, newName: string): Promise<void>;
118-
118+
deleteBranch?(
119+
repoPath: string,
120+
branches: GitBranchReference | GitBranchReference[],
121+
options?: { force?: boolean; remote?: boolean },
122+
): Promise<void>;
119123
addRemote?(repoPath: string, name: string, url: string, options?: { fetch?: boolean }): Promise<void>;
120124
pruneRemote?(repoPath: string, name: string): Promise<void>;
121125
removeRemote?(repoPath: string, name: string): Promise<void>;

src/git/gitProviderService.ts

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

1357+
@log()
1358+
deleteBranch(
1359+
repoPath: string,
1360+
branches: GitBranchReference | GitBranchReference[],
1361+
options?: { force?: boolean; remote?: boolean },
1362+
): Promise<void> {
1363+
const { provider, path } = this.getProvider(repoPath);
1364+
if (provider.deleteBranch == null) throw new ProviderNotSupportedError(provider.descriptor.name);
1365+
1366+
if (!Array.isArray(branches)) {
1367+
branches = [branches];
1368+
}
1369+
1370+
return provider.deleteBranch(path, branches, {
1371+
force: options?.force,
1372+
remote: options?.remote,
1373+
});
1374+
}
1375+
13571376
@log()
13581377
checkout(
13591378
repoPath: string | Uri,

src/git/models/repository.ts

Lines changed: 2 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,8 @@ 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';
3029
import type { GitBranchReference, GitReference, GitTagReference } from './reference';
31-
import { getNameWithoutRemote, isBranchReference } from './reference';
30+
import { isBranchReference } from './reference';
3231
import type { GitRemote } from './remote';
3332
import type { GitWorktree } from './worktree';
3433

@@ -560,49 +559,6 @@ export class Repository implements Disposable {
560559
return remote;
561560
}
562561

563-
@log()
564-
branchDelete(branches: GitBranchReference | GitBranchReference[], options?: { force?: boolean; remote?: boolean }) {
565-
if (!Array.isArray(branches)) {
566-
branches = [branches];
567-
}
568-
569-
const localBranches = branches.filter(b => !b.remote);
570-
if (localBranches.length !== 0) {
571-
const args = ['--delete'];
572-
if (options?.force) {
573-
args.push('--force');
574-
}
575-
void this.runTerminalCommand('branch', ...args, ...branches.map(b => b.ref));
576-
577-
if (options?.remote) {
578-
const trackingBranches = localBranches.filter(b => b.upstream != null);
579-
if (trackingBranches.length !== 0) {
580-
const branchesByOrigin = groupByMap(trackingBranches, b =>
581-
getRemoteNameFromBranchName(b.upstream!.name),
582-
);
583-
584-
for (const [remote, branches] of branchesByOrigin.entries()) {
585-
void this.runTerminalCommand(
586-
'push',
587-
'-d',
588-
remote,
589-
...branches.map(b => getBranchNameWithoutRemote(b.upstream!.name)),
590-
);
591-
}
592-
}
593-
}
594-
}
595-
596-
const remoteBranches = branches.filter(b => b.remote);
597-
if (remoteBranches.length !== 0) {
598-
const branchesByOrigin = groupByMap(remoteBranches, b => getRemoteNameFromBranchName(b.name));
599-
600-
for (const [remote, branches] of branchesByOrigin.entries()) {
601-
void this.runTerminalCommand('push', '-d', remote, ...branches.map(b => getNameWithoutRemote(b)));
602-
}
603-
}
604-
}
605-
606562
@log()
607563
cherryPick(...args: string[]) {
608564
void this.runTerminalCommand('cherry-pick', ...args);

0 commit comments

Comments
 (0)