Skip to content

Commit e3b09b8

Browse files
committed
Adds Open tag on remote option to tagView
1 parent f884fc6 commit e3b09b8

22 files changed

+327
-19
lines changed

contributions.json

+46
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,11 @@
629629
]
630630
}
631631
},
632+
"gitlens.copyRemoteTagUrl": {
633+
"label": "Copy Remote Tag URL",
634+
"icon": "$(copy)",
635+
"commandPalette": "gitlens:repos:withRemotes"
636+
},
632637
"gitlens.copyShaToClipboard": {
633638
"label": "Copy SHA",
634639
"icon": "$(copy)",
@@ -3310,6 +3315,11 @@
33103315
]
33113316
}
33123317
},
3318+
"gitlens.openTagOnRemote": {
3319+
"label": "Open Tag on Remote",
3320+
"icon": "$(globe)",
3321+
"commandPalette": "gitlens:repos:withRemotes"
3322+
},
33133323
"gitlens.openWorkingFile": {
33143324
"label": "Open File",
33153325
"icon": "$(go-to-file)",
@@ -6187,6 +6197,10 @@
61876197
]
61886198
}
61896199
},
6200+
"gitlens.views.copyRemoteTagUrl": {
6201+
"label": "Copy Remote Tag URL",
6202+
"icon": "$(copy)"
6203+
},
61906204
"gitlens.views.copyUrl": {
61916205
"label": "Copy URL",
61926206
"icon": "$(copy)",
@@ -7738,6 +7752,38 @@
77387752
]
77397753
}
77407754
},
7755+
"gitlens.views.openTagOnRemote": {
7756+
"label": "Open Tag on Remote",
7757+
"icon": "$(globe)",
7758+
"menus": {
7759+
"view/item/context": [
7760+
{
7761+
"when": "viewItem =~ /gitlens:tag\\b/ && gitlens:repos:withRemotes",
7762+
"group": "inline",
7763+
"order": 100,
7764+
"alt": "gitlens.views.copyRemoteTagUrl"
7765+
},
7766+
{
7767+
"when": "viewItem =~ /gitlens:tag\\b/ && !listMultiSelection && gitlens:repos:withRemotes",
7768+
"group": "3_gitlens_explore",
7769+
"order": 3
7770+
}
7771+
]
7772+
}
7773+
},
7774+
"gitlens.views.openTagOnRemote.multi": {
7775+
"label": "Open Tags on Remote",
7776+
"icon": "$(globe)",
7777+
"menus": {
7778+
"view/item/context": [
7779+
{
7780+
"when": "viewItem =~ /gitlens:tag\\b/ && listMultiSelection && gitlens:repos:withRemotes",
7781+
"group": "3_gitlens_explore",
7782+
"order": 3
7783+
}
7784+
]
7785+
}
7786+
},
77417787
"gitlens.views.openUrl": {
77427788
"label": "Open URL",
77437789
"icon": "$(globe)",

package.json

+75-1
Original file line numberDiff line numberDiff line change
@@ -3733,7 +3733,8 @@
37333733
"fileInCommit",
37343734
"fileInBranch",
37353735
"fileLine",
3736-
"fileRange"
3736+
"fileRange",
3737+
"tag"
37373738
],
37383739
"properties": {
37393740
"repository": {
@@ -3771,6 +3772,10 @@
37713772
"fileRange": {
37723773
"type": "string",
37733774
"markdownDescription": "Specifies the format of a range in a file URL for the custom remote service\n\nAvailable tokens\\\n`${start}` — starting line\\\n`${end}` — ending line"
3775+
},
3776+
"tag": {
3777+
"type": "string",
3778+
"markdownDescription": "Specifies the format of a tag URL for the custom remote service\n\nAvailable tokens\\\n`${repo}` — repository path\\\n`${tagName}` — name of the tag"
37743779
}
37753780
},
37763781
"additionalProperties": false
@@ -4742,6 +4747,7 @@
47424747
"default": {
47434748
"suppressCommitHasNoPreviousCommitWarning": false,
47444749
"suppressCommitNotFoundWarning": false,
4750+
"suppressTagNotFoundWarning": false,
47454751
"suppressCreatePullRequestPrompt": false,
47464752
"suppressDebugLoggingWarning": false,
47474753
"suppressFileNotUnderSourceControlWarning": false,
@@ -4768,6 +4774,11 @@
47684774
"default": false,
47694775
"description": "Commit Not Found Warning"
47704776
},
4777+
"suppressTagNotFoundWarning": {
4778+
"type": "boolean",
4779+
"default": false,
4780+
"description": "Tag Not Found Warning"
4781+
},
47714782
"suppressCreatePullRequestPrompt": {
47724783
"type": "boolean",
47734784
"default": false,
@@ -5974,6 +5985,12 @@
59745985
"title": "Copy Remote Repository URL",
59755986
"icon": "$(copy)"
59765987
},
5988+
{
5989+
"command": "gitlens.copyRemoteTagUrl",
5990+
"title": "Copy Remote Tag URL",
5991+
"category": "GitLens",
5992+
"icon": "$(copy)"
5993+
},
59775994
{
59785995
"command": "gitlens.copyShaToClipboard",
59795996
"title": "Copy SHA",
@@ -7007,6 +7024,12 @@
70077024
"icon": "$(gitlens-open-revision)",
70087025
"enablement": "gitlens:enabled && resourceScheme =~ /^(gitlens|pr)$/ "
70097026
},
7027+
{
7028+
"command": "gitlens.openTagOnRemote",
7029+
"title": "Open Tag on Remote",
7030+
"category": "GitLens",
7031+
"icon": "$(globe)"
7032+
},
70107033
{
70117034
"command": "gitlens.openWorkingFile",
70127035
"title": "Open File",
@@ -7948,6 +7971,11 @@
79487971
"title": "Copy Remote Commit URLs",
79497972
"icon": "$(copy)"
79507973
},
7974+
{
7975+
"command": "gitlens.views.copyRemoteTagUrl",
7976+
"title": "Copy Remote Tag URL",
7977+
"icon": "$(copy)"
7978+
},
79517979
{
79527980
"command": "gitlens.views.copyUrl",
79537981
"title": "Copy URL",
@@ -8423,6 +8451,16 @@
84238451
"title": "Compare Pull Request",
84248452
"icon": "$(compare-changes)"
84258453
},
8454+
{
8455+
"command": "gitlens.views.openTagOnRemote",
8456+
"title": "Open Tag on Remote",
8457+
"icon": "$(globe)"
8458+
},
8459+
{
8460+
"command": "gitlens.views.openTagOnRemote.multi",
8461+
"title": "Open Tags on Remote",
8462+
"icon": "$(globe)"
8463+
},
84268464
{
84278465
"command": "gitlens.views.openUrl",
84288466
"title": "Open URL",
@@ -10069,6 +10107,10 @@
1006910107
"command": "gitlens.copyRemoteRepositoryUrl",
1007010108
"when": "false"
1007110109
},
10110+
{
10111+
"command": "gitlens.copyRemoteTagUrl",
10112+
"when": "gitlens:repos:withRemotes"
10113+
},
1007210114
{
1007310115
"command": "gitlens.copyShaToClipboard",
1007410116
"when": "resource in gitlens:tabs:blameable"
@@ -10881,6 +10923,10 @@
1088110923
"command": "gitlens.openRevisionFileInDiffRight",
1088210924
"when": "false"
1088310925
},
10926+
{
10927+
"command": "gitlens.openTagOnRemote",
10928+
"when": "gitlens:repos:withRemotes"
10929+
},
1088410930
{
1088510931
"command": "gitlens.openWorkingFile",
1088610932
"when": "gitlens:enabled && resourceScheme =~ /^(gitlens|git|pr)$/"
@@ -11609,6 +11655,10 @@
1160911655
"command": "gitlens.views.copyRemoteCommitUrl.multi",
1161011656
"when": "false"
1161111657
},
11658+
{
11659+
"command": "gitlens.views.copyRemoteTagUrl",
11660+
"when": "false"
11661+
},
1161211662
{
1161311663
"command": "gitlens.views.copyUrl",
1161411664
"when": "false"
@@ -12005,6 +12055,14 @@
1200512055
"command": "gitlens.views.openPullRequestComparison",
1200612056
"when": "false"
1200712057
},
12058+
{
12059+
"command": "gitlens.views.openTagOnRemote",
12060+
"when": "false"
12061+
},
12062+
{
12063+
"command": "gitlens.views.openTagOnRemote.multi",
12064+
"when": "false"
12065+
},
1200812066
{
1200912067
"command": "gitlens.views.openUrl",
1201012068
"when": "false"
@@ -16840,6 +16898,12 @@
1684016898
"when": "viewItem =~ /gitlens:tag\\b/ && !gitlens:hasVirtualFolders && !gitlens:readonly && !gitlens:untrusted",
1684116899
"group": "inline@10"
1684216900
},
16901+
{
16902+
"command": "gitlens.views.openTagOnRemote",
16903+
"when": "viewItem =~ /gitlens:tag\\b/ && gitlens:repos:withRemotes",
16904+
"group": "inline@100",
16905+
"alt": "gitlens.views.copyRemoteTagUrl"
16906+
},
1684316907
{
1684416908
"command": "gitlens.views.switchToTag",
1684516909
"when": "viewItem =~ /gitlens:tag\\b/ && !listMultiSelection && !gitlens:hasVirtualFolders && !gitlens:readonly && !gitlens:untrusted",
@@ -16860,6 +16924,16 @@
1686016924
"when": "viewItem =~ /gitlens:tag\\b/ && !listMultiSelection && !gitlens:hasVirtualFolders && !gitlens:readonly && !gitlens:untrusted",
1686116925
"group": "1_gitlens_actions@3"
1686216926
},
16927+
{
16928+
"command": "gitlens.views.openTagOnRemote",
16929+
"when": "viewItem =~ /gitlens:tag\\b/ && !listMultiSelection && gitlens:repos:withRemotes",
16930+
"group": "3_gitlens_explore@3"
16931+
},
16932+
{
16933+
"command": "gitlens.views.openTagOnRemote.multi",
16934+
"when": "viewItem =~ /gitlens:tag\\b/ && listMultiSelection && gitlens:repos:withRemotes",
16935+
"group": "3_gitlens_explore@3"
16936+
},
1686316937
{
1686416938
"command": "gitlens.views.createTag",
1686516939
"when": "viewItem =~ /gitlens:tags\\b/ && !gitlens:hasVirtualFolders && !gitlens:readonly && !gitlens:untrusted",

src/commands.ts

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import './commands/openBranchOnRemote';
3333
import './commands/openCurrentBranchOnRemote';
3434
import './commands/openChangedFiles';
3535
import './commands/openCommitOnRemote';
36+
import './commands/openTagOnRemote';
3637
import './commands/openComparisonOnRemote';
3738
import './commands/openFileFromRemote';
3839
import './commands/openFileOnRemote';

src/commands/openOnRemote.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -196,13 +196,13 @@ export class OpenOnRemoteCommand extends GlCommandBase {
196196
break;
197197
}
198198

199-
// case RemoteResourceType.Tag: {
200-
// title = getTitlePrefix('Tag');
201-
// if (resources.length === 1) {
202-
// title += `${pad(GlyphChars.Dot, 2, 2)}${args.resource.tag}`;
203-
// }
204-
// break;
205-
// }
199+
case RemoteResourceType.Tag: {
200+
title = getTitlePrefix('Tag');
201+
if (resources.length === 1) {
202+
title += `${pad(GlyphChars.Dot, 2, 2)}${resource.tag}`;
203+
}
204+
break;
205+
}
206206
}
207207

208208
const pick = await showRemoteProviderPicker(title, placeholder, resources, remotes, options);

src/commands/openTagOnRemote.ts

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import type { TextEditor, Uri } from 'vscode';
2+
import { GlCommand } from '../constants.commands';
3+
import type { Container } from '../container';
4+
import { GitUri } from '../git/gitUri';
5+
// import { getTagNameWithoutRemote, getRemoteNameFromTagName } from '../git/models/tag';
6+
import { RemoteResourceType } from '../git/models/remoteResource';
7+
import { showGenericErrorMessage } from '../messages';
8+
import { CommandQuickPickItem } from '../quickpicks/items/common';
9+
import { ReferencesQuickPickIncludes, showReferencePicker } from '../quickpicks/referencePicker';
10+
import { getBestRepositoryOrShowPicker } from '../quickpicks/repositoryPicker';
11+
import { Logger } from '../system/logger';
12+
import { command, executeCommand } from '../system/vscode/command';
13+
import type { CommandContext } from './base';
14+
import { ActiveEditorCommand, getCommandUri, isCommandContextViewNodeHasTag } from './base';
15+
import type { OpenOnRemoteCommandArgs } from './openOnRemote';
16+
17+
export interface OpenTagOnRemoteCommandArgs {
18+
tag?: string;
19+
clipboard?: boolean;
20+
remote?: string;
21+
}
22+
23+
@command()
24+
export class OpenTagOnRemoteCommand extends ActiveEditorCommand {
25+
constructor(private readonly container: Container) {
26+
super([GlCommand.OpenTagOnRemote, GlCommand.CopyRemoteTagUrl]);
27+
}
28+
29+
protected override preExecute(context: CommandContext, args?: OpenTagOnRemoteCommandArgs) {
30+
if (isCommandContextViewNodeHasTag(context)) {
31+
args = {
32+
...args,
33+
tag: context.node.tag.name,
34+
remote: context.node.tag.name,
35+
};
36+
}
37+
38+
if (context.command === GlCommand.CopyRemoteTagUrl) {
39+
args = { ...args, clipboard: true };
40+
}
41+
42+
return this.execute(context.editor, context.uri, args);
43+
}
44+
45+
async execute(editor?: TextEditor, uri?: Uri, args?: OpenTagOnRemoteCommandArgs) {
46+
uri = getCommandUri(uri, editor);
47+
48+
const gitUri = uri != null ? await GitUri.fromUri(uri) : undefined;
49+
50+
const repoPath = (
51+
await getBestRepositoryOrShowPicker(
52+
gitUri,
53+
editor,
54+
args?.clipboard ? 'Copy Remote Tag URL' : 'Open Tag On Remote',
55+
)
56+
)?.path;
57+
if (!repoPath) return;
58+
59+
args = { ...args };
60+
61+
try {
62+
if (args.tag == null) {
63+
const pick = await showReferencePicker(
64+
repoPath,
65+
args.clipboard ? 'Copy Remote Tag URL' : 'Open Tag On Remote',
66+
args.clipboard ? 'Choose a Tag to copy the URL from' : 'Choose a Tag to open',
67+
{
68+
autoPick: true,
69+
filter: { tags: () => true, branches: () => false },
70+
include: ReferencesQuickPickIncludes.Tags,
71+
sort: { tags: { current: true } },
72+
},
73+
);
74+
if (pick == null || pick instanceof CommandQuickPickItem) return;
75+
76+
if (pick.refType === 'tag') {
77+
args.tag = pick.name;
78+
} else {
79+
args.tag = pick.ref;
80+
}
81+
}
82+
83+
void (await executeCommand<OpenOnRemoteCommandArgs>(GlCommand.OpenOnRemote, {
84+
resource: {
85+
type: RemoteResourceType.Tag,
86+
tag: args.tag,
87+
},
88+
repoPath: repoPath,
89+
remote: args.remote,
90+
clipboard: args.clipboard,
91+
}));
92+
} catch (ex) {
93+
Logger.error(ex, 'OpenTagOnRemoteCommand');
94+
void showGenericErrorMessage('Unable to open Tag on remote provider');
95+
}
96+
}
97+
}

src/config.ts

+2
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ export const enum StatusBarCommand {
155155
export type SuppressedMessages =
156156
| 'suppressCommitHasNoPreviousCommitWarning'
157157
| 'suppressCommitNotFoundWarning'
158+
| 'suppressTagNotFoundWarning'
158159
| 'suppressCreatePullRequestPrompt'
159160
| 'suppressDebugLoggingWarning'
160161
| 'suppressFileNotUnderSourceControlWarning'
@@ -623,6 +624,7 @@ export interface RemotesUrlsConfig {
623624
readonly fileInCommit: string;
624625
readonly fileLine: string;
625626
readonly fileRange: string;
627+
readonly tag: string;
626628
}
627629

628630
interface StatusBarConfig {

0 commit comments

Comments
 (0)