提交 23a4df36 编写于 作者: J Joao Moreno

Merge commit 'refs/pull/74345/head' of github.com:microsoft/vscode into pr/74345

......@@ -267,6 +267,16 @@
"title": "%command.createTag%",
"category": "Git"
},
{
"command": "git.deleteTag",
"title": "%command.deleteTag%",
"category": "Git"
},
{
"command": "git.getTags",
"title": "%command.getTags%",
"category": "Git"
},
{
"command": "git.fetch",
"title": "%command.fetch%",
......@@ -564,6 +574,14 @@
"command": "git.createTag",
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.deleteTag",
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.getTags",
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.fetch",
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
......
......@@ -37,6 +37,8 @@
"command.renameBranch": "Rename Branch...",
"command.merge": "Merge Branch...",
"command.createTag": "Create Tag",
"command.deleteTag": "Delete Tag",
"command.getTags": "Get Tags",
"command.fetch": "Fetch",
"command.fetchPrune": "Fetch (Prune)",
"command.fetchAll": "Fetch From All Remotes",
......
......@@ -37,6 +37,11 @@ export interface Branch extends Ref {
readonly behind?: number;
}
export interface Tag extends Ref {
readonly name: string;
readonly message?: string;
}
export interface Commit {
readonly hash: string;
readonly message: string;
......
......@@ -15,7 +15,7 @@ import { lstat, Stats } from 'fs';
import * as os from 'os';
import TelemetryReporter from 'vscode-extension-telemetry';
import * as nls from 'vscode-nls';
import { Ref, RefType, Branch, GitErrorCodes, Status } from './api/git';
import { Ref, RefType, Branch, GitErrorCodes, Status, Tag } from './api/git';
const localize = nls.loadMessageBundle();
......@@ -38,6 +38,25 @@ class CheckoutItem implements QuickPickItem {
}
}
class TagItem implements QuickPickItem {
get label(): string { return (this.tag.name || '').substr(0, 20); }
get name(): string { return (this.tag.name || ''); }
get description(): string {
return (this.tag.message || '');
}
constructor(protected tag: Tag) { }
async run(repository: Repository): Promise<void> {
const name = this.tag.name || '';
if (!name) {
return;
}
await repository.deleteTag(name);
}
}
class CheckoutTagItem extends CheckoutItem {
get description(): string {
......@@ -213,6 +232,11 @@ function createCheckoutItems(repository: Repository): CheckoutItem[] {
return [...heads, ...tags, ...remoteHeads];
}
async function createTagItems(repository: Repository): Promise<TagItem[]> {
const tags = await repository.getTags();
return tags.map(tag => new TagItem(tag)) || [];
}
enum PushType {
Push,
PushTo,
......@@ -1705,6 +1729,20 @@ export class CommandCenter {
await repository.tag(name, message);
}
@command('git.deleteTag', { repository: true })
async deleteTag(repository: Repository): Promise<void> {
const picks = await createTagItems(repository);
if (!picks) {
window.showWarningMessage(localize('no tags', "This repository has no tags."));
}
const placeHolder = localize('select a tag to delete', 'Select a tag to delete');
const choice = await window.showQuickPick<TagItem>(picks, { placeHolder });
if (!choice) {
return;
}
await repository.deleteTag(choice.name);
}
@command('git.fetch', { repository: true })
async fetch(repository: Repository): Promise<void> {
if (repository.remotes.length === 0) {
......
......@@ -15,7 +15,7 @@ import { assign, groupBy, denodeify, IDisposable, toDisposable, dispose, mkdirp,
import { CancellationToken, Progress } from 'vscode';
import { URI } from 'vscode-uri';
import { detectEncoding } from './encoding';
import { Ref, RefType, Branch, Remote, GitErrorCodes, LogOptions, Change, Status } from './api/git';
import { Ref, RefType, Branch, Remote, GitErrorCodes, LogOptions, Change, Status, Tag } from './api/git';
import * as byline from 'byline';
import { StringDecoder } from 'string_decoder';
......@@ -1327,6 +1327,26 @@ export class Repository {
await this.run(args);
}
async deleteTag(name: string): Promise<void> {
let args = ['tag', '-d', name];
await this.run(args);
}
async getTags(): Promise<Tag[]> {
let args = ['tag', '-n1'];
const result = await this.run(args);
return result.stdout.trim().split('\n')
.map(line => line.trim().split('\0'))
.map(([line]) => {
const name = line.split(' ')[0];
return {
name: name,
message: line.replace(name, '').trim() || '',
type: RefType.Tag
} as Tag;
});
}
async clean(paths: string[]): Promise<void> {
const pathsByGroup = groupBy(paths, p => path.dirname(p));
const groups = Object.keys(pathsByGroup).map(k => pathsByGroup[k]);
......
......@@ -13,7 +13,7 @@ import * as path from 'path';
import * as nls from 'vscode-nls';
import * as fs from 'fs';
import { StatusBarCommands } from './statusbar';
import { Branch, Ref, Remote, RefType, GitErrorCodes, Status, LogOptions, Change } from './api/git';
import { Branch, Ref, Remote, RefType, GitErrorCodes, Status, LogOptions, Change, Tag } from './api/git';
import { IFileWatcher, watch } from './watch';
const timeout = (millis: number) => new Promise(c => setTimeout(c, millis));
......@@ -292,6 +292,8 @@ export const enum Operation {
Merge = 'Merge',
Ignore = 'Ignore',
Tag = 'Tag',
DeleteTag = 'DeleteTag',
GetTags = 'GetTags',
Stash = 'Stash',
CheckIgnore = 'CheckIgnore',
GetObjectDetails = 'GetObjectDetails',
......@@ -1021,6 +1023,14 @@ export class Repository implements Disposable {
await this.run(Operation.Tag, () => this.repository.tag(name, message));
}
async deleteTag(name: string): Promise<void> {
await this.run(Operation.DeleteTag, () => this.repository.deleteTag(name));
}
async getTags(): Promise<Tag[]> {
return await this.run(Operation.GetTags, () => this.repository.getTags());
}
async checkout(treeish: string): Promise<void> {
await this.run(Operation.Checkout, () => this.repository.checkout(treeish, []));
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册