Skip to content

Commit 9bbc9bf

Browse files
committed
add deleteBranch
1 parent ccf72bb commit 9bbc9bf

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
@@ -187,7 +187,17 @@ import { countStringLength, filterMap } from '../../../system/array';
187187
import { gate } from '../../../system/decorators/gate';
188188
import { debug, log } from '../../../system/decorators/log';
189189
import { debounce } from '../../../system/function';
190-
import { filterMap as filterMapIterable, find, first, join, last, map, skip, some } from '../../../system/iterable';
190+
import {
191+
filterMap as filterMapIterable,
192+
find,
193+
first,
194+
groupByMap,
195+
join,
196+
last,
197+
map,
198+
skip,
199+
some,
200+
} from '../../../system/iterable';
191201
import { Logger } from '../../../system/logger';
192202
import type { LogScope } from '../../../system/logger.scope';
193203
import { getLogScope, setLogScopeExit } from '../../../system/logger.scope';
@@ -1263,6 +1273,57 @@ export class LocalGitProvider implements GitProvider, Disposable {
12631273
await this.git.branch(repoPath, '-m', oldName, newName);
12641274
}
12651275

1276+
@log()
1277+
async deleteBranch(
1278+
repoPath: string,
1279+
branches: GitBranchReference[],
1280+
options: { force?: boolean; remote?: boolean },
1281+
): Promise<void> {
1282+
const localBranches = branches.filter((b: GitBranchReference) => !b.remote);
1283+
if (localBranches.length !== 0) {
1284+
const args = ['--delete'];
1285+
if (options.force) {
1286+
args.push('--force');
1287+
}
1288+
1289+
await this.git.branch(repoPath, ...args, ...branches.map((b: GitBranchReference) => b.ref));
1290+
1291+
if (options.remote) {
1292+
const trackingBranches = localBranches.filter(b => b.upstream != null);
1293+
if (trackingBranches.length !== 0) {
1294+
const branchesByOrigin = groupByMap(trackingBranches, b =>
1295+
getRemoteNameFromBranchName(b.upstream!.name),
1296+
);
1297+
1298+
for (const [remote, branches] of branchesByOrigin.entries()) {
1299+
await this.git.push(repoPath, {
1300+
delete: {
1301+
remote: remote,
1302+
branches: branches.map(b => getBranchNameWithoutRemote(b.upstream!.name)),
1303+
},
1304+
});
1305+
}
1306+
}
1307+
}
1308+
}
1309+
1310+
const remoteBranches = branches.filter((b: GitBranchReference) => b.remote);
1311+
if (remoteBranches.length !== 0) {
1312+
const branchesByOrigin = groupByMap(remoteBranches, b => getRemoteNameFromBranchName(b.name));
1313+
1314+
for (const [remote, branches] of branchesByOrigin.entries()) {
1315+
await this.git.push(repoPath, {
1316+
delete: {
1317+
remote: remote,
1318+
branches: branches.map((b: GitBranchReference) =>
1319+
b.remote ? getBranchNameWithoutRemote(b.name) : b.name,
1320+
),
1321+
},
1322+
});
1323+
}
1324+
}
1325+
}
1326+
12661327
@log()
12671328
async checkout(
12681329
repoPath: string,

src/git/gitProvider.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +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-
123+
deleteBranch?(
124+
repoPath: string,
125+
branches: GitBranchReference | GitBranchReference[],
126+
options?: { force?: boolean; remote?: boolean },
127+
): Promise<void>;
124128
addRemote?(repoPath: string, name: string, url: string, options?: { fetch?: boolean }): Promise<void>;
125129
pruneRemote?(repoPath: string, name: string): Promise<void>;
126130
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
@@ -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
checkout(
13821401
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)