Skip to content

Commit

Permalink
add deleteBranch
Browse files Browse the repository at this point in the history
  • Loading branch information
sergiolms committed Sep 27, 2024
1 parent 09b08cb commit c6b352d
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 63 deletions.
15 changes: 11 additions & 4 deletions src/commands/git/branch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -516,10 +516,17 @@ export class BranchGitCommand extends QuickCommand {
state.flags = result;

endSteps(state);
state.repo.branchDelete(state.references, {
force: state.flags.includes('--force'),
remote: state.flags.includes('--remotes'),
});

try {
await state.repo.git.deleteBranch(state.references, {
force: state.flags.includes('--force'),
remote: state.flags.includes('--remotes'),
});
} catch (ex) {
Logger.error(ex);
// TODO likely need some better error handling here
return showGenericErrorMessage('Unable to delete branch');
}
}
}

Expand Down
32 changes: 21 additions & 11 deletions src/env/node/git/git.ts
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ export class Git {
}
}

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

Expand Down Expand Up @@ -962,6 +962,10 @@ export class Git {
publish?: boolean;
remote?: string;
upstream?: string;
delete?: {
remote: string;
branches: string[];
};
},
): Promise<void> {
const params = ['push'];
Expand All @@ -979,16 +983,22 @@ export class Git {
}
}

if (options.branch && options.remote) {
if (options.upstream) {
params.push('-u', options.remote, `${options.branch}:${options.upstream}`);
} else if (options.publish) {
params.push('--set-upstream', options.remote, options.branch);
} else {
params.push(options.remote, options.branch);
}
} else if (options.remote) {
params.push(options.remote);
switch (true) {
case options.branch && options.remote:
if (options.upstream) {
params.push('-u', options.remote, `${options.branch}:${options.upstream}`);
} else if (options.publish) {
params.push('--set-upstream', options.remote, options.branch);
} else {
params.push(options.remote, options.branch);
}
break;
case options.remote:
params.push(options.remote);
break;
case options.delete:
params.push('-d', options.delete.remote, ...options.delete.branches);
break;
}

try {
Expand Down
63 changes: 62 additions & 1 deletion src/env/node/git/localGitProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,17 @@ import { countStringLength, filterMap } from '../../../system/array';
import { gate } from '../../../system/decorators/gate';
import { debug, log } from '../../../system/decorators/log';
import { debounce } from '../../../system/function';
import { filterMap as filterMapIterable, find, first, join, last, map, skip, some } from '../../../system/iterable';
import {
filterMap as filterMapIterable,
find,
first,
groupByMap,
join,
last,
map,
skip,
some,
} from '../../../system/iterable';
import { Logger } from '../../../system/logger';
import type { LogScope } from '../../../system/logger.scope';
import { getLogScope, setLogScopeExit } from '../../../system/logger.scope';
Expand Down Expand Up @@ -1240,6 +1250,57 @@ export class LocalGitProvider implements GitProvider, Disposable {
await this.git.branch(repoPath, '-m', oldName, newName);
}

@log()
async deleteBranch(
repoPath: string,
branches: GitBranchReference[],
options: { force?: boolean; remote?: boolean },
): Promise<void> {
const localBranches = branches.filter((b: GitBranchReference) => !b.remote);
if (localBranches.length !== 0) {
const args = ['--delete'];
if (options.force) {
args.push('--force');
}

await this.git.branch(repoPath, ...args, ...branches.map((b: GitBranchReference) => b.ref));

if (options.remote) {
const trackingBranches = localBranches.filter(b => b.upstream != null);
if (trackingBranches.length !== 0) {
const branchesByOrigin = groupByMap(trackingBranches, b =>
getRemoteNameFromBranchName(b.upstream!.name),
);

for (const [remote, branches] of branchesByOrigin.entries()) {
await this.git.push(repoPath, {
delete: {
remote: remote,
branches: branches.map(b => getBranchNameWithoutRemote(b.upstream!.name)),
},
});
}
}
}
}

const remoteBranches = branches.filter((b: GitBranchReference) => b.remote);
if (remoteBranches.length !== 0) {
const branchesByOrigin = groupByMap(remoteBranches, b => getRemoteNameFromBranchName(b.name));

for (const [remote, branches] of branchesByOrigin.entries()) {
await this.git.push(repoPath, {
delete: {
remote: remote,
branches: branches.map((b: GitBranchReference) =>
b.remote ? getBranchNameWithoutRemote(b.name) : b.name,
),
},
});
}
}
}

@log()
async checkout(
repoPath: string,
Expand Down
6 changes: 5 additions & 1 deletion src/git/gitProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,11 @@ export interface RepositoryVisibilityInfo {
export interface GitProviderRepository {
createBranch?(repoPath: string, name: string, ref: string): Promise<void>;
renameBranch?(repoPath: string, oldName: string, newName: string): Promise<void>;

deleteBranch?(
repoPath: string,
branches: GitBranchReference | GitBranchReference[],
options?: { force?: boolean; remote?: boolean },
): Promise<void>;
addRemote?(repoPath: string, name: string, url: string, options?: { fetch?: boolean }): Promise<void>;
pruneRemote?(repoPath: string, name: string): Promise<void>;
removeRemote?(repoPath: string, name: string): Promise<void>;
Expand Down
19 changes: 19 additions & 0 deletions src/git/gitProviderService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1354,6 +1354,25 @@ export class GitProviderService implements Disposable {
return provider.renameBranch(path, oldName, newName);
}

@log()
deleteBranch(
repoPath: string,
branches: GitBranchReference | GitBranchReference[],
options?: { force?: boolean; remote?: boolean },
): Promise<void> {
const { provider, path } = this.getProvider(repoPath);
if (provider.deleteBranch == null) throw new ProviderNotSupportedError(provider.descriptor.name);

if (!Array.isArray(branches)) {
branches = [branches];
}

return provider.deleteBranch(path, branches, {
force: options?.force,
remote: options?.remote,
});
}

@log()
checkout(
repoPath: string | Uri,
Expand Down
48 changes: 2 additions & 46 deletions src/git/models/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { debug, log, logName } from '../../system/decorators/log';
import { memoize } from '../../system/decorators/memoize';
import type { Deferrable } from '../../system/function';
import { debounce } from '../../system/function';
import { filter, groupByMap, join, map, min, some } from '../../system/iterable';
import { filter, join, map, min, some } from '../../system/iterable';
import { getLoggableName, Logger } from '../../system/logger';
import { getLogScope } from '../../system/logger.scope';
import { updateRecordValue } from '../../system/object';
Expand All @@ -26,9 +26,8 @@ import { configuration } from '../../system/vscode/configuration';
import type { GitProviderDescriptor, GitProviderRepository } from '../gitProvider';
import type { GitProviderService } from '../gitProviderService';
import type { GitBranch } from './branch';
import { getBranchNameWithoutRemote, getRemoteNameFromBranchName } from './branch';
import type { GitBranchReference, GitReference, GitTagReference } from './reference';
import { getNameWithoutRemote, isBranchReference } from './reference';
import { isBranchReference } from './reference';
import type { GitRemote } from './remote';
import type { GitWorktree } from './worktree';

Expand Down Expand Up @@ -560,49 +559,6 @@ export class Repository implements Disposable {
return remote;
}

@log()
branchDelete(branches: GitBranchReference | GitBranchReference[], options?: { force?: boolean; remote?: boolean }) {
if (!Array.isArray(branches)) {
branches = [branches];
}

const localBranches = branches.filter(b => !b.remote);
if (localBranches.length !== 0) {
const args = ['--delete'];
if (options?.force) {
args.push('--force');
}
void this.runTerminalCommand('branch', ...args, ...branches.map(b => b.ref));

if (options?.remote) {
const trackingBranches = localBranches.filter(b => b.upstream != null);
if (trackingBranches.length !== 0) {
const branchesByOrigin = groupByMap(trackingBranches, b =>
getRemoteNameFromBranchName(b.upstream!.name),
);

for (const [remote, branches] of branchesByOrigin.entries()) {
void this.runTerminalCommand(
'push',
'-d',
remote,
...branches.map(b => getBranchNameWithoutRemote(b.upstream!.name)),
);
}
}
}
}

const remoteBranches = branches.filter(b => b.remote);
if (remoteBranches.length !== 0) {
const branchesByOrigin = groupByMap(remoteBranches, b => getRemoteNameFromBranchName(b.name));

for (const [remote, branches] of branchesByOrigin.entries()) {
void this.runTerminalCommand('push', '-d', remote, ...branches.map(b => getNameWithoutRemote(b)));
}
}
}

@log()
cherryPick(...args: string[]) {
void this.runTerminalCommand('cherry-pick', ...args);
Expand Down

0 comments on commit c6b352d

Please sign in to comment.