Skip to content

Commit 32d59ba

Browse files
committed
Added quickpick option and display of tag annotation on menu
1 parent 98ed0fc commit 32d59ba

6 files changed

Lines changed: 70 additions & 13 deletions

File tree

extensions/git/package.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,11 @@
272272
"title": "%command.deleteTag%",
273273
"category": "Git"
274274
},
275+
{
276+
"command": "git.getTags",
277+
"title": "%command.getTags%",
278+
"category": "Git"
279+
},
275280
{
276281
"command": "git.fetch",
277282
"title": "%command.fetch%",
@@ -564,6 +569,10 @@
564569
"command": "git.deleteTag",
565570
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
566571
},
572+
{
573+
"command": "git.getTags",
574+
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
575+
},
567576
{
568577
"command": "git.fetch",
569578
"when": "config.git.enabled && gitOpenRepositoryCount != 0"

extensions/git/package.nls.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
"command.merge": "Merge Branch...",
3939
"command.createTag": "Create Tag",
4040
"command.deleteTag": "Delete Tag",
41+
"command.getTags": "Get Tags",
4142
"command.fetch": "Fetch",
4243
"command.fetchPrune": "Fetch (Prune)",
4344
"command.fetchAll": "Fetch From All Remotes",

extensions/git/src/api/git.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ export interface Branch extends Ref {
3737
readonly behind?: number;
3838
}
3939

40+
export interface Tag extends Ref {
41+
readonly name: string;
42+
readonly message?: string;
43+
}
44+
4045
export interface Commit {
4146
readonly hash: string;
4247
readonly message: string;

extensions/git/src/commands.ts

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { lstat, Stats } from 'fs';
1515
import * as os from 'os';
1616
import TelemetryReporter from 'vscode-extension-telemetry';
1717
import * as nls from 'vscode-nls';
18-
import { Ref, RefType, Branch, GitErrorCodes, Status } from './api/git';
18+
import { Ref, RefType, Branch, GitErrorCodes, Status, Tag } from './api/git';
1919

2020
const localize = nls.loadMessageBundle();
2121

@@ -38,6 +38,25 @@ class CheckoutItem implements QuickPickItem {
3838
}
3939
}
4040

41+
class TagItem implements QuickPickItem {
42+
43+
get label(): string { return (this.tag.name || '').substr(0, 20); }
44+
get name(): string { return (this.tag.name || ''); }
45+
get description(): string {
46+
return (this.tag.message || '');
47+
}
48+
constructor(protected tag: Tag) { }
49+
50+
async run(repository: Repository): Promise<void> {
51+
const name = this.tag.name || '';
52+
if (!name) {
53+
return;
54+
}
55+
56+
await repository.deleteTag(name);
57+
}
58+
}
59+
4160
class CheckoutTagItem extends CheckoutItem {
4261

4362
get description(): string {
@@ -199,6 +218,11 @@ function createCheckoutItems(repository: Repository): CheckoutItem[] {
199218
return [...heads, ...tags, ...remoteHeads];
200219
}
201220

221+
async function createTagItems(repository: Repository): Promise<TagItem[]> {
222+
const tags = await repository.getTags();
223+
return tags.map(tag => new TagItem(tag)) || [];
224+
}
225+
202226
enum PushType {
203227
Push,
204228
PushTo,
@@ -1667,18 +1691,16 @@ export class CommandCenter {
16671691

16681692
@command('git.deleteTag', { repository: true })
16691693
async deleteTag(repository: Repository): Promise<void> {
1670-
const inputTagName = await window.showInputBox({
1671-
placeHolder: localize('tag name', "Tag name"),
1672-
prompt: localize('provide tag name', "Please provide a tag name"),
1673-
ignoreFocusOut: true
1674-
});
1675-
1676-
if (!inputTagName) {
1694+
const picks = await createTagItems(repository);
1695+
if (!picks) {
1696+
window.showWarningMessage(localize('no tags', "This repository has no tags."));
1697+
}
1698+
const placeHolder = localize('select a tag to delete', 'Select a tag to delete');
1699+
const choice = await window.showQuickPick<TagItem>(picks, { placeHolder });
1700+
if (!choice) {
16771701
return;
16781702
}
1679-
1680-
const name = inputTagName.replace(/^\.|\/\.|\.\.|~|\^|:|\/$|\.lock$|\.lock\/|\\|\*|\s|^\s*$|\.$/g, '-');
1681-
await repository.deleteTag(name);
1703+
await repository.deleteTag(choice.name);
16821704
}
16831705

16841706
@command('git.fetch', { repository: true })

extensions/git/src/git.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { assign, groupBy, denodeify, IDisposable, toDisposable, dispose, mkdirp,
1515
import { CancellationToken } from 'vscode';
1616
import { URI } from 'vscode-uri';
1717
import { detectEncoding } from './encoding';
18-
import { Ref, RefType, Branch, Remote, GitErrorCodes, LogOptions, Change, Status } from './api/git';
18+
import { Ref, RefType, Branch, Remote, GitErrorCodes, LogOptions, Change, Status, Tag } from './api/git';
1919

2020
// https://github.com/microsoft/vscode/issues/65693
2121
const MAX_CLI_LENGTH = 30000;
@@ -1290,6 +1290,21 @@ export class Repository {
12901290
await this.run(args);
12911291
}
12921292

1293+
async getTags(): Promise<Tag[]> {
1294+
let args = ['tag', '-n1'];
1295+
const result = await this.run(args);
1296+
return result.stdout.trim().split('\n')
1297+
.map(line => line.trim().split('\0'))
1298+
.map(([line]) => {
1299+
const name = line.split(' ')[0];
1300+
return {
1301+
name: name,
1302+
message: line.replace(name, '').trim() || '',
1303+
type: RefType.Tag
1304+
} as Tag;
1305+
});
1306+
}
1307+
12931308
async clean(paths: string[]): Promise<void> {
12941309
const pathsByGroup = groupBy(paths, p => path.dirname(p));
12951310
const groups = Object.keys(pathsByGroup).map(k => pathsByGroup[k]);

extensions/git/src/repository.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import * as path from 'path';
1313
import * as nls from 'vscode-nls';
1414
import * as fs from 'fs';
1515
import { StatusBarCommands } from './statusbar';
16-
import { Branch, Ref, Remote, RefType, GitErrorCodes, Status, LogOptions, Change } from './api/git';
16+
import { Branch, Ref, Remote, RefType, GitErrorCodes, Status, LogOptions, Change, Tag } from './api/git';
1717
import { IFileWatcher, watch } from './watch';
1818

1919
const timeout = (millis: number) => new Promise(c => setTimeout(c, millis));
@@ -296,6 +296,7 @@ export const enum Operation {
296296
Ignore = 'Ignore',
297297
Tag = 'Tag',
298298
DeleteTag = 'DeleteTag',
299+
GetTags = 'GetTags',
299300
Stash = 'Stash',
300301
CheckIgnore = 'CheckIgnore',
301302
GetObjectDetails = 'GetObjectDetails',
@@ -1006,6 +1007,10 @@ export class Repository implements Disposable {
10061007
await this.run(Operation.DeleteTag, () => this.repository.deleteTag(name));
10071008
}
10081009

1010+
async getTags(): Promise<Tag[]> {
1011+
return await this.run(Operation.GetTags, () => this.repository.getTags());
1012+
}
1013+
10091014
async checkout(treeish: string): Promise<void> {
10101015
await this.run(Operation.Checkout, () => this.repository.checkout(treeish, []));
10111016
}

0 commit comments

Comments
 (0)