Skip to content

Commit bfa69cf

Browse files
committed
add deleteBranch
1 parent 6b54385 commit bfa69cf

File tree

6 files changed

+109
-54
lines changed

6 files changed

+109
-54
lines changed

src/commands/git/branch.ts

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

531531
endSteps(state);
532-
state.repo.branchDelete(state.references, {
533-
force: state.flags.includes('--force'),
534-
remote: state.flags.includes('--remotes'),
535-
});
532+
533+
try {
534+
await state.repo.git.deleteBranch(state.references, {
535+
force: state.flags.includes('--force'),
536+
remote: state.flags.includes('--remotes'),
537+
});
538+
} catch (ex) {
539+
Logger.error(ex);
540+
// TODO likely need some better error handling here
541+
return showGenericErrorMessage('Unable to delete branch');
542+
}
536543
}
537544
}
538545

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,
@@ -507,7 +509,7 @@ export class Git {
507509
}
508510
}
509511

510-
branch(repoPath: string, ...args: string[]) {
512+
async branch(repoPath: string, ...args: string[]): Promise<void> {
511513
return this.git<string>({ cwd: repoPath }, 'branch', ...args);
512514
}
513515

@@ -963,6 +965,10 @@ export class Git {
963965
publish?: boolean;
964966
remote?: string;
965967
upstream?: string;
968+
delete?: {
969+
remote: string;
970+
branches: string[];
971+
};
966972
},
967973
): Promise<void> {
968974
const params = ['push'];
@@ -988,8 +994,10 @@ export class Git {
988994
} else {
989995
params.push(options.remote, options.branch);
990996
}
991-
} else if (options.remote) {
997+
} else if (options.remote != null) {
992998
params.push(options.remote);
999+
} else if (options.delete != null) {
1000+
params.push('-d', options.delete.remote, ...options.delete.branches);
9931001
}
9941002

9951003
try {

src/env/node/git/localGitProvider.ts

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,17 @@ import { countStringLength, filterMap } from '../../../system/array';
185185
import { gate } from '../../../system/decorators/gate';
186186
import { debug, log } from '../../../system/decorators/log';
187187
import { debounce } from '../../../system/function';
188-
import { filterMap as filterMapIterable, find, first, join, last, map, skip, some } from '../../../system/iterable';
188+
import {
189+
filterMap as filterMapIterable,
190+
find,
191+
first,
192+
groupByMap,
193+
join,
194+
last,
195+
map,
196+
skip,
197+
some,
198+
} from '../../../system/iterable';
189199
import { Logger } from '../../../system/logger';
190200
import type { LogScope } from '../../../system/logger.scope';
191201
import { getLogScope, setLogScopeExit } from '../../../system/logger.scope';
@@ -1261,6 +1271,57 @@ export class LocalGitProvider implements GitProvider, Disposable {
12611271
await this.git.branch(repoPath, '-m', oldName, newName);
12621272
}
12631273

1274+
@log()
1275+
async deleteBranch(
1276+
repoPath: string,
1277+
branches: GitBranchReference[],
1278+
options: { force?: boolean; remote?: boolean },
1279+
): Promise<void> {
1280+
const localBranches = branches.filter((b: GitBranchReference) => !b.remote);
1281+
if (localBranches.length !== 0) {
1282+
const args = ['--delete'];
1283+
if (options.force) {
1284+
args.push('--force');
1285+
}
1286+
1287+
await this.git.branch(repoPath, ...args, ...branches.map((b: GitBranchReference) => b.ref));
1288+
1289+
if (options.remote) {
1290+
const trackingBranches = localBranches.filter(b => b.upstream != null);
1291+
if (trackingBranches.length !== 0) {
1292+
const branchesByOrigin = groupByMap(trackingBranches, b =>
1293+
getRemoteNameFromBranchName(b.upstream!.name),
1294+
);
1295+
1296+
for (const [remote, branches] of branchesByOrigin.entries()) {
1297+
await this.git.push(repoPath, {
1298+
delete: {
1299+
remote: remote,
1300+
branches: branches.map(b => getBranchNameWithoutRemote(b.upstream!.name)),
1301+
},
1302+
});
1303+
}
1304+
}
1305+
}
1306+
}
1307+
1308+
const remoteBranches = branches.filter((b: GitBranchReference) => b.remote);
1309+
if (remoteBranches.length !== 0) {
1310+
const branchesByOrigin = groupByMap(remoteBranches, b => getRemoteNameFromBranchName(b.name));
1311+
1312+
for (const [remote, branches] of branchesByOrigin.entries()) {
1313+
await this.git.push(repoPath, {
1314+
delete: {
1315+
remote: remote,
1316+
branches: branches.map((b: GitBranchReference) =>
1317+
b.remote ? getBranchNameWithoutRemote(b.name) : b.name,
1318+
),
1319+
},
1320+
});
1321+
}
1322+
}
1323+
}
1324+
12641325
@log()
12651326
async checkout(
12661327
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
@@ -1376,6 +1376,25 @@ export class GitProviderService implements Disposable {
13761376
return provider.renameBranch(path, oldName, newName);
13771377
}
13781378

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

@@ -584,49 +583,6 @@ export class Repository implements Disposable {
584583
return remote;
585584
}
586585

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

0 commit comments

Comments
 (0)