diff --git a/extensions/git/package.json b/extensions/git/package.json index bf8fe767cdf..e705bdf50a1 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -187,6 +187,16 @@ "title": "%command.merge%", "category": "Git" }, + { + "command": "git.createTag", + "title": "%command.createTag%", + "category": "Git" + }, + { + "command": "git.showTags", + "title": "%command.showTags%", + "category": "Git" + }, { "command": "git.pull", "title": "%command.pull%", @@ -212,6 +222,11 @@ "title": "%command.pushTo%", "category": "Git" }, + { + "command": "git.pushWithTags", + "title": "%command.pushWithTags%", + "category": "Git" + }, { "command": "git.sync", "title": "%command.sync%", @@ -347,6 +362,14 @@ "command": "git.pullFrom", "when": "config.git.enabled && scmProvider == git && gitState == idle" }, + { + "command": "git.showTags", + "when": "config.git.enabled && scmProvider == git && gitState == idle" + }, + { + "command": "git.createTag", + "when": "config.git.enabled && scmProvider == git && gitState == idle" + }, { "command": "git.push", "when": "config.git.enabled && scmProvider == git && gitState == idle" @@ -355,6 +378,10 @@ "command": "git.pushTo", "when": "config.git.enabled && scmProvider == git && gitState == idle" }, + { + "command": "git.pushWithTags", + "when": "config.git.enabled && scmProvider == git && gitState == idle" + }, { "command": "git.sync", "when": "config.git.enabled && scmProvider == git && gitState == idle" diff --git a/extensions/git/package.nls.json b/extensions/git/package.nls.json index bc8bc381786..92c17288868 100644 --- a/extensions/git/package.nls.json +++ b/extensions/git/package.nls.json @@ -24,11 +24,14 @@ "command.branch": "Create Branch...", "command.deleteBranch": "Delete Branch...", "command.merge": "Merge Branch...", + "command.createTag": "Create Tag", + "command.showTags": "Show Tags", "command.pull": "Pull", "command.pullRebase": "Pull (Rebase)", "command.pullFrom": "Pull from...", "command.push": "Push", "command.pushTo": "Push to...", + "command.pushWithTags": "Push With Tags", "command.sync": "Sync", "command.publish": "Publish Branch", "command.showOutput": "Show Git Output", diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index 31f4fcf408a..48642e25125 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -837,6 +837,31 @@ export class CommandCenter { } } + @command('git.createTag') + async createTag(): Promise { + const inputTagName = await window.showInputBox({ + placeHolder: localize('tag name', "Tag name"), + prompt: localize('provide tag name', "Please provide a tag name"), + ignoreFocusOut: true + }); + + if (!inputTagName) { + return; + } + + const inputMessage = await window.showInputBox({ + placeHolder: localize('tag message', "Message"), + prompt: localize('provide tag message', "Please provide a message"), + ignoreFocusOut: true + }); + + const name = inputTagName.replace(/^\.|\/\.|\.\.|~|\^|:|\/$|\.lock$|\.lock\/|\\|\*|\s|^\s*$|\.$/g, '-'); + const message = inputMessage || name; + await this.model.tag(name, message); + + window.showInformationMessage(localize('tag creation success', "Successfully created tag.")); + } + @command('git.pullFrom') async pullFrom(): Promise { const remotes = this.model.remotes; @@ -903,6 +928,20 @@ export class CommandCenter { await this.model.push(); } + @command('git.pushWithTags') + async pushWithTags(): Promise { + const remotes = this.model.remotes; + + if (remotes.length === 0) { + window.showWarningMessage(localize('no remotes to push', "Your repository has no remotes configured to push to.")); + return; + } + + await this.model.pushTags(); + + window.showInformationMessage(localize('push with tags success', "Successfully pushed with tags.")); + } + @command('git.pushTo') async pushTo(): Promise { const remotes = this.model.remotes; diff --git a/extensions/git/src/git.ts b/extensions/git/src/git.ts index afd5961ab25..87f08af2977 100644 --- a/extensions/git/src/git.ts +++ b/extensions/git/src/git.ts @@ -677,6 +677,18 @@ export class Repository { } } + async tag(name: string, message: string, lightweight: boolean): Promise { + let args = ['tag']; + + if (lightweight) { + args.push(name); + } else { + args = args.concat(['-a', name, '-m', message]); + } + + await this.run(args); + } + async clean(paths: string[]): Promise { const pathsByGroup = groupBy(paths, p => path.dirname(p)); const groups = Object.keys(pathsByGroup).map(k => pathsByGroup[k]); @@ -786,13 +798,17 @@ export class Repository { } } - async push(remote?: string, name?: string, setUpstream: boolean = false): Promise { + async push(remote?: string, name?: string, setUpstream: boolean = false, tags = false): Promise { const args = ['push']; if (setUpstream) { args.push('-u'); } + if (tags) { + args.push('--tags'); + } + if (remote) { args.push(remote); } diff --git a/extensions/git/src/model.ts b/extensions/git/src/model.ts index 7d852bc8a39..ad15d2e7efb 100644 --- a/extensions/git/src/model.ts +++ b/extensions/git/src/model.ts @@ -214,7 +214,8 @@ export enum Operation { GetCommitTemplate = 1 << 15, DeleteBranch = 1 << 16, Merge = 1 << 17, - Ignore = 1 << 18 + Ignore = 1 << 18, + Tag = 1 << 19 } // function getOperationName(operation: Operation): string { @@ -465,6 +466,10 @@ export class Model implements Disposable { await this.run(Operation.Merge, () => this.repository.merge(ref)); } + async tag(name: string, message: string): Promise { + await this.run(Operation.Tag, () => this.repository.tag(name, message, false)); + } + async checkout(treeish: string): Promise { await this.run(Operation.Checkout, () => this.repository.checkout(treeish, [])); } @@ -509,6 +514,10 @@ export class Model implements Disposable { await this.run(Operation.Push, () => this.repository.push(remote, name, setUpstream)); } + async pushTags(remote?: string): Promise { + await this.run(Operation.Push, () => this.repository.push(remote, undefined, false, true)); + } + @throttle async sync(): Promise { await this.run(Operation.Sync, async () => {