Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add fetch prune & delete command #183955

Closed
6 changes: 6 additions & 0 deletions extensions/git/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,12 @@
"category": "Git",
"enablement": "!operationInProgress"
},
{
"command": "git.fetchPruneAndDelete",
"title": "%command.fetchPruneAndDelete%",
"category": "Git",
"enablement": "!operationInProgress"
},
{
"command": "git.renameBranch",
"title": "%command.renameBranch%",
Expand Down
1 change: 1 addition & 0 deletions extensions/git/package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"command.branch": "Create Branch...",
"command.branchFrom": "Create Branch From...",
"command.deleteBranch": "Delete Branch...",
"command.fetchPruneAndDelete": "Fetch (Prune) & Delete...",
"command.renameBranch": "Rename Branch...",
"command.cherryPick": "Cherry Pick...",
"command.merge": "Merge Branch...",
Expand Down
5 changes: 5 additions & 0 deletions extensions/git/src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2408,6 +2408,11 @@ export class CommandCenter {
}
}

@command('git.fetchPruneAndDelete', { repository: true })
async fetchPruneAndDelete(repository: Repository): Promise<void> {
repository.fetchPruneAndDelete();
}

@command('git.renameBranch', { repository: true })
async renameBranch(repository: Repository): Promise<void> {
const currentBranchName = repository.HEAD && repository.HEAD.name;
Expand Down
29 changes: 28 additions & 1 deletion extensions/git/src/git.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { EventEmitter } from 'events';
import * as iconv from '@vscode/iconv-lite-umd';
import * as filetype from 'file-type';
import { assign, groupBy, IDisposable, toDisposable, dispose, mkdirp, readBytes, detectUnicodeEncoding, Encoding, onceEvent, splitInChunks, Limiter, Versions, isWindows, pathEquals, isMacintosh } from './util';
import { CancellationError, CancellationToken, ConfigurationChangeEvent, LogOutputChannel, Progress, Uri, workspace } from 'vscode';
import { CancellationError, CancellationToken, ConfigurationChangeEvent, LogOutputChannel, l10n, Progress, Uri, window, workspace } from 'vscode';
import { detectEncoding } from './encoding';
import { Ref, RefType, Branch, Remote, ForcePushMode, GitErrorCodes, LogOptions, Change, Status, CommitOptions, RefQuery, InitOptions } from './api/git';
import * as byline from 'byline';
Expand Down Expand Up @@ -1588,6 +1588,33 @@ export class Repository {
await this.exec(args);
}

async fetchPruneAndDelete(): Promise<void> {
try {
const fetchPrune = await this.exec(['fetch', '--prune']);
const result = Object.values(fetchPrune).toString().split('\n');
result.shift();
result.pop();
result?.forEach(async (element) => {
const branch = element.split('origin/')[1];
try {
await this.exec(['branch', '-d', branch]);
} catch (error) {
if (error.gitErrorCode !== GitErrorCodes.BranchNotFullyMerged) {
throw error;
}
const message = l10n.t(`The branch "${branch}" is not fully merged. Delete anyway?`);
const yes = l10n.t('Delete Branch');
const pick = await window.showWarningMessage(message, { modal: true }, yes);
if (pick === yes) {
await this.exec(['branch', '-D', branch]);
}
}
});
} catch (error) {
throw error;
}
}

async renameBranch(name: string): Promise<void> {
const args = ['branch', '-m', name];
await this.exec(args);
Expand Down
5 changes: 4 additions & 1 deletion extensions/git/src/operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const enum OperationKind {
Commit = 'Commit',
Config = 'Config',
DeleteBranch = 'DeleteBranch',
fetchPruneAndDelete = 'fetchPruneAndDelete',
DeleteRef = 'DeleteRef',
DeleteRemoteTag = 'DeleteRemoteTag',
DeleteTag = 'DeleteTag',
Expand Down Expand Up @@ -64,7 +65,7 @@ export const enum OperationKind {
}

export type Operation = AddOperation | ApplyOperation | BlameOperation | BranchOperation | CheckIgnoreOperation | CherryPickOperation |
CheckoutOperation | CheckoutTrackingOperation | CleanOperation | CommitOperation | ConfigOperation | DeleteBranchOperation |
CheckoutOperation | CheckoutTrackingOperation | CleanOperation | CommitOperation | ConfigOperation | DeleteBranchOperation | fetchPruneAndDeleteOperation |
DeleteRefOperation | DeleteRemoteTagOperation | DeleteTagOperation | DiffOperation | FetchOperation | FindTrackingBranchesOperation |
GetBranchOperation | GetBranchesOperation | GetCommitTemplateOperation | GetObjectDetailsOperation | GetRefsOperation | GetRemoteRefsOperation |
HashObjectOperation | IgnoreOperation | LogOperation | LogFileOperation | MergeOperation | MergeAbortOperation | MergeBaseOperation |
Expand All @@ -85,6 +86,7 @@ export type CleanOperation = BaseOperation & { kind: OperationKind.Clean };
export type CommitOperation = BaseOperation & { kind: OperationKind.Commit };
export type ConfigOperation = BaseOperation & { kind: OperationKind.Config };
export type DeleteBranchOperation = BaseOperation & { kind: OperationKind.DeleteBranch };
export type fetchPruneAndDeleteOperation = BaseOperation & { kind: OperationKind.fetchPruneAndDelete };
export type DeleteRefOperation = BaseOperation & { kind: OperationKind.DeleteRef };
export type DeleteRemoteTagOperation = BaseOperation & { kind: OperationKind.DeleteRemoteTag };
export type DeleteTagOperation = BaseOperation & { kind: OperationKind.DeleteTag };
Expand Down Expand Up @@ -138,6 +140,7 @@ export const Operation = {
Commit: { kind: OperationKind.Commit, blocking: true, readOnly: false, remote: false, retry: false, showProgress: true } as CommitOperation,
Config: { kind: OperationKind.Config, blocking: false, readOnly: false, remote: false, retry: false, showProgress: true } as ConfigOperation,
DeleteBranch: { kind: OperationKind.DeleteBranch, blocking: false, readOnly: false, remote: false, retry: false, showProgress: true } as DeleteBranchOperation,
fetchPruneAndDelete: { kind: OperationKind.fetchPruneAndDelete, blocking: false, readOnly: false, remote: false, retry: false, showProgress: true } as fetchPruneAndDeleteOperation,
DeleteRef: { kind: OperationKind.DeleteRef, blocking: false, readOnly: false, remote: false, retry: false, showProgress: true } as DeleteRefOperation,
DeleteRemoteTag: { kind: OperationKind.DeleteRemoteTag, blocking: false, readOnly: false, remote: true, retry: false, showProgress: true } as DeleteRemoteTagOperation,
DeleteTag: { kind: OperationKind.DeleteTag, blocking: false, readOnly: false, remote: false, retry: false, showProgress: true } as DeleteTagOperation,
Expand Down
5 changes: 5 additions & 0 deletions extensions/git/src/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1362,6 +1362,11 @@ export class Repository implements Disposable {
await this.run(Operation.DeleteBranch, () => this.repository.deleteBranch(name, force));
}

async fetchPruneAndDelete(): Promise<void> {
// await this.run(Operation.fetchPruneAndDelete, () => this.repository.fetchPruneAndDelete(force));
await this.run(Operation.fetchPruneAndDelete, () => this.repository.fetchPruneAndDelete());
}

async renameBranch(name: string): Promise<void> {
await this.run(Operation.RenameBranch, () => this.repository.renameBranch(name));
}
Expand Down