Skip to content

Commit b976b36

Browse files
committed
Adds Open tag on remote option to tagView
1 parent 06f8cf2 commit b976b36

23 files changed

+330
-17
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)",
@@ -3315,6 +3320,11 @@
33153320
]
33163321
}
33173322
},
3323+
"gitlens.openTagOnRemote": {
3324+
"label": "Open Tag on Remote",
3325+
"icon": "$(globe)",
3326+
"commandPalette": "gitlens:repos:withRemotes"
3327+
},
33183328
"gitlens.openWorkingFile": {
33193329
"label": "Open File",
33203330
"icon": "$(go-to-file)",
@@ -6206,6 +6216,10 @@
62066216
]
62076217
}
62086218
},
6219+
"gitlens.views.copyRemoteTagUrl": {
6220+
"label": "Copy Remote Tag URL",
6221+
"icon": "$(copy)"
6222+
},
62096223
"gitlens.views.copyUrl": {
62106224
"label": "Copy URL",
62116225
"icon": "$(copy)",
@@ -7762,6 +7776,38 @@
77627776
]
77637777
}
77647778
},
7779+
"gitlens.views.openTagOnRemote": {
7780+
"label": "Open Tag on Remote",
7781+
"icon": "$(globe)",
7782+
"menus": {
7783+
"view/item/context": [
7784+
{
7785+
"when": "viewItem =~ /gitlens:tag\\b/ && gitlens:repos:withRemotes",
7786+
"group": "inline",
7787+
"order": 100,
7788+
"alt": "gitlens.views.copyRemoteTagUrl"
7789+
},
7790+
{
7791+
"when": "viewItem =~ /gitlens:tag\\b/ && !listMultiSelection && gitlens:repos:withRemotes",
7792+
"group": "3_gitlens_explore",
7793+
"order": 3
7794+
}
7795+
]
7796+
}
7797+
},
7798+
"gitlens.views.openTagOnRemote.multi": {
7799+
"label": "Open Tags on Remote",
7800+
"icon": "$(globe)",
7801+
"menus": {
7802+
"view/item/context": [
7803+
{
7804+
"when": "viewItem =~ /gitlens:tag\\b/ && listMultiSelection && gitlens:repos:withRemotes",
7805+
"group": "3_gitlens_explore",
7806+
"order": 3
7807+
}
7808+
]
7809+
}
7810+
},
77657811
"gitlens.views.openUrl": {
77667812
"label": "Open URL",
77677813
"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
@@ -4754,6 +4759,7 @@
47544759
"default": {
47554760
"suppressCommitHasNoPreviousCommitWarning": false,
47564761
"suppressCommitNotFoundWarning": false,
4762+
"suppressTagNotFoundWarning": false,
47574763
"suppressCreatePullRequestPrompt": false,
47584764
"suppressDebugLoggingWarning": false,
47594765
"suppressFileNotUnderSourceControlWarning": false,
@@ -4780,6 +4786,11 @@
47804786
"default": false,
47814787
"description": "Commit Not Found Warning"
47824788
},
4789+
"suppressTagNotFoundWarning": {
4790+
"type": "boolean",
4791+
"default": false,
4792+
"description": "Tag Not Found Warning"
4793+
},
47834794
"suppressCreatePullRequestPrompt": {
47844795
"type": "boolean",
47854796
"default": false,
@@ -5986,6 +5997,12 @@
59865997
"title": "Copy Remote Repository URL",
59875998
"icon": "$(copy)"
59885999
},
6000+
{
6001+
"command": "gitlens.copyRemoteTagUrl",
6002+
"title": "Copy Remote Tag URL",
6003+
"category": "GitLens",
6004+
"icon": "$(copy)"
6005+
},
59896006
{
59906007
"command": "gitlens.copyShaToClipboard",
59916008
"title": "Copy SHA",
@@ -7019,6 +7036,12 @@
70197036
"icon": "$(gitlens-open-revision)",
70207037
"enablement": "gitlens:enabled && resourceScheme =~ /^(gitlens|pr)$/ "
70217038
},
7039+
{
7040+
"command": "gitlens.openTagOnRemote",
7041+
"title": "Open Tag on Remote",
7042+
"category": "GitLens",
7043+
"icon": "$(globe)"
7044+
},
70227045
{
70237046
"command": "gitlens.openWorkingFile",
70247047
"title": "Open File",
@@ -7960,6 +7983,11 @@
79607983
"title": "Copy Remote Commit URLs",
79617984
"icon": "$(copy)"
79627985
},
7986+
{
7987+
"command": "gitlens.views.copyRemoteTagUrl",
7988+
"title": "Copy Remote Tag URL",
7989+
"icon": "$(copy)"
7990+
},
79637991
{
79647992
"command": "gitlens.views.copyUrl",
79657993
"title": "Copy URL",
@@ -8435,6 +8463,16 @@
84358463
"title": "Compare Pull Request",
84368464
"icon": "$(compare-changes)"
84378465
},
8466+
{
8467+
"command": "gitlens.views.openTagOnRemote",
8468+
"title": "Open Tag on Remote",
8469+
"icon": "$(globe)"
8470+
},
8471+
{
8472+
"command": "gitlens.views.openTagOnRemote.multi",
8473+
"title": "Open Tags on Remote",
8474+
"icon": "$(globe)"
8475+
},
84388476
{
84398477
"command": "gitlens.views.openUrl",
84408478
"title": "Open URL",
@@ -10081,6 +10119,10 @@
1008110119
"command": "gitlens.copyRemoteRepositoryUrl",
1008210120
"when": "false"
1008310121
},
10122+
{
10123+
"command": "gitlens.copyRemoteTagUrl",
10124+
"when": "gitlens:repos:withRemotes"
10125+
},
1008410126
{
1008510127
"command": "gitlens.copyShaToClipboard",
1008610128
"when": "resource in gitlens:tabs:blameable"
@@ -10893,6 +10935,10 @@
1089310935
"command": "gitlens.openRevisionFileInDiffRight",
1089410936
"when": "false"
1089510937
},
10938+
{
10939+
"command": "gitlens.openTagOnRemote",
10940+
"when": "gitlens:repos:withRemotes"
10941+
},
1089610942
{
1089710943
"command": "gitlens.openWorkingFile",
1089810944
"when": "gitlens:enabled && resourceScheme =~ /^(gitlens|git|pr)$/"
@@ -11621,6 +11667,10 @@
1162111667
"command": "gitlens.views.copyRemoteCommitUrl.multi",
1162211668
"when": "false"
1162311669
},
11670+
{
11671+
"command": "gitlens.views.copyRemoteTagUrl",
11672+
"when": "false"
11673+
},
1162411674
{
1162511675
"command": "gitlens.views.copyUrl",
1162611676
"when": "false"
@@ -12017,6 +12067,14 @@
1201712067
"command": "gitlens.views.openPullRequestComparison",
1201812068
"when": "false"
1201912069
},
12070+
{
12071+
"command": "gitlens.views.openTagOnRemote",
12072+
"when": "false"
12073+
},
12074+
{
12075+
"command": "gitlens.views.openTagOnRemote.multi",
12076+
"when": "false"
12077+
},
1202012078
{
1202112079
"command": "gitlens.views.openUrl",
1202212080
"when": "false"
@@ -16884,6 +16942,12 @@
1688416942
"when": "viewItem =~ /gitlens:tag\\b/ && !gitlens:hasVirtualFolders && !gitlens:readonly && !gitlens:untrusted",
1688516943
"group": "inline@10"
1688616944
},
16945+
{
16946+
"command": "gitlens.views.openTagOnRemote",
16947+
"when": "viewItem =~ /gitlens:tag\\b/ && gitlens:repos:withRemotes",
16948+
"group": "inline@100",
16949+
"alt": "gitlens.views.copyRemoteTagUrl"
16950+
},
1688716951
{
1688816952
"command": "gitlens.views.switchToTag",
1688916953
"when": "viewItem =~ /gitlens:tag\\b/ && !listMultiSelection && !gitlens:hasVirtualFolders && !gitlens:readonly && !gitlens:untrusted",
@@ -16904,6 +16968,16 @@
1690416968
"when": "viewItem =~ /gitlens:tag\\b/ && !listMultiSelection && !gitlens:hasVirtualFolders && !gitlens:readonly && !gitlens:untrusted",
1690516969
"group": "1_gitlens_actions@3"
1690616970
},
16971+
{
16972+
"command": "gitlens.views.openTagOnRemote",
16973+
"when": "viewItem =~ /gitlens:tag\\b/ && !listMultiSelection && gitlens:repos:withRemotes",
16974+
"group": "3_gitlens_explore@3"
16975+
},
16976+
{
16977+
"command": "gitlens.views.openTagOnRemote.multi",
16978+
"when": "viewItem =~ /gitlens:tag\\b/ && listMultiSelection && gitlens:repos:withRemotes",
16979+
"group": "3_gitlens_explore@3"
16980+
},
1690716981
{
1690816982
"command": "gitlens.views.createTag",
1690916983
"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

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

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'
@@ -626,6 +627,7 @@ export interface RemotesUrlsConfig {
626627
readonly fileInCommit: string;
627628
readonly fileLine: string;
628629
readonly fileRange: string;
630+
readonly tag: string;
629631
}
630632

631633
interface StatusBarConfig {

0 commit comments

Comments
 (0)