Skip to content

Commit 9a12a14

Browse files
committed
Adds cmd to open revisions from remote URLs
Improves open files from remote URLs - Adds support for short SHAs - Falls back to revision Uri if working tree path not found Standardizes `getRevisionUri` signature to match others
1 parent 3deb186 commit 9a12a14

33 files changed

+334
-242
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
99
### Added
1010

1111
- Adds OpenRouter support for GitLens' AI features ([#3906](https://github.com/gitkraken/vscode-gitlens/issues/3906))
12+
- Adds _Open File at Revision from Remote_ command to open the specific file revision from a remote file URL
1213

1314
### Changed
1415

contributions.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3196,6 +3196,10 @@
31963196
]
31973197
}
31983198
},
3199+
"gitlens.openRevisionFromRemote": {
3200+
"label": "Open File at Revision from Remote",
3201+
"commandPalette": "gitlens:enabled"
3202+
},
31993203
"gitlens.openWorkingFile": {
32003204
"label": "Open File",
32013205
"icon": "$(go-to-file)",

package.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7223,6 +7223,11 @@
72237223
"icon": "$(gitlens-open-revision)",
72247224
"enablement": "gitlens:enabled && resourceScheme =~ /^(gitlens|pr)$/"
72257225
},
7226+
{
7227+
"command": "gitlens.openRevisionFromRemote",
7228+
"title": "Open File at Revision from Remote",
7229+
"category": "GitLens"
7230+
},
72267231
{
72277232
"command": "gitlens.openWorkingFile",
72287233
"title": "Open File",
@@ -11211,6 +11216,10 @@
1121111216
"command": "gitlens.openRevisionFile",
1121211217
"when": "gitlens:enabled && resourceScheme =~ /^(gitlens|git|pr)$/ && isInDiffEditor"
1121311218
},
11219+
{
11220+
"command": "gitlens.openRevisionFromRemote",
11221+
"when": "gitlens:enabled"
11222+
},
1121411223
{
1121511224
"command": "gitlens.openWorkingFile",
1121611225
"when": "gitlens:enabled && resourceScheme =~ /^(gitlens|git|pr)$/"

src/commands/browseRepoAtRevision.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export class BrowseRepoAtRevisionCommand extends ActiveEditorCommand {
6161
const sha = args?.before
6262
? await this.container.git.refs(gitUri.repoPath!).resolveReference(`${gitUri.sha}^`)
6363
: gitUri.sha;
64-
uri = this.container.git.getRevisionUri(sha, gitUri.repoPath!, gitUri.repoPath!);
64+
uri = this.container.git.getRevisionUri(gitUri.repoPath!, sha, gitUri.repoPath!);
6565
gitUri = GitUri.fromRevisionUri(uri);
6666

6767
openWorkspace(uri, {

src/commands/diffWith.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,8 @@ export class DiffWithCommand extends GlCommandBase {
181181
}
182182

183183
await openDiffEditor(
184-
lhs ?? this.container.git.getRevisionUri(deletedOrMissing, args.lhs.uri.fsPath, args.repoPath),
185-
rhs ?? this.container.git.getRevisionUri(deletedOrMissing, args.rhs.uri.fsPath, args.repoPath),
184+
lhs ?? this.container.git.getRevisionUri(args.repoPath, deletedOrMissing, args.lhs.uri.fsPath),
185+
rhs ?? this.container.git.getRevisionUri(args.repoPath, deletedOrMissing, args.rhs.uri.fsPath),
186186
title,
187187
args.showOptions,
188188
);

src/commands/openFileAtRevision.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,15 +71,19 @@ export class OpenFileAtRevisionCommand extends ActiveEditorCommand {
7171
if (blame.commit.isUncommitted) {
7272
const comparisonUris = await blame.commit.getPreviousComparisonUrisForLine(editorLine);
7373
if (comparisonUris?.previous != null) {
74-
args.revisionUri = this.container.git.getRevisionUri(comparisonUris.previous);
74+
args.revisionUri = this.container.git.getRevisionUriFromGitUri(
75+
comparisonUris.previous,
76+
);
7577
} else {
7678
void showCommitHasNoPreviousCommitWarningMessage(blame.commit);
7779
return undefined;
7880
}
7981
} else {
8082
const previousSha = blame != null ? await blame?.commit.getPreviousSha() : undefined;
8183
if (previousSha != null) {
82-
args.revisionUri = this.container.git.getRevisionUri(blame.commit.getGitUri(true));
84+
args.revisionUri = this.container.git.getRevisionUriFromGitUri(
85+
blame.commit.getGitUri(true),
86+
);
8387
} else {
8488
void showCommitHasNoPreviousCommitWarningMessage(blame.commit);
8589
return undefined;

src/commands/openFileAtRevisionFrom.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ export class OpenFileAtRevisionFromCommand extends ActiveEditorCommand {
7070
keys: ['right', 'alt+right', 'ctrl+right'],
7171
onDidPressKey: async (_key, item) => {
7272
await openFileAtRevision(
73-
this.container.git.getRevisionUri(item.ref, gitUri.fsPath, gitUri.repoPath!),
73+
this.container.git.getRevisionUri(gitUri.repoPath!, item.ref, gitUri.fsPath),
7474
{
7575
annotationType: args.annotationType,
7676
line: args.line,
@@ -89,7 +89,7 @@ export class OpenFileAtRevisionFromCommand extends ActiveEditorCommand {
8989
}
9090

9191
await openFileAtRevision(
92-
this.container.git.getRevisionUri(args.reference.ref, gitUri.fsPath, gitUri.repoPath),
92+
this.container.git.getRevisionUri(gitUri.repoPath, args.reference.ref, gitUri.fsPath),
9393
{
9494
annotationType: args.annotationType,
9595
line: args.line,

src/commands/openFileFromRemote.ts

Lines changed: 56 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { env, Range, Uri, window } from 'vscode';
2+
import { Schemes } from '../constants';
23
import type { Container } from '../container';
34
import { command } from '../system/-webview/command';
45
import { openTextEditor } from '../system/-webview/vscode/editors';
@@ -11,59 +12,68 @@ export class OpenFileFromRemoteCommand extends GlCommandBase {
1112
}
1213

1314
async execute(): Promise<void> {
14-
let clipboard: string | undefined = await env.clipboard.readText();
15-
try {
16-
Uri.parse(clipboard, true);
17-
} catch {
18-
clipboard = undefined;
19-
}
15+
await openFileOreRevisionFromRemote(this.container, 'file');
16+
}
17+
}
2018

21-
const url = await window.showInputBox({
22-
prompt: 'Enter a remote file url to open',
23-
placeHolder: 'Remote file url',
24-
value: clipboard,
25-
ignoreFocusOut: true,
26-
});
27-
if (url == null || url.length === 0) return;
19+
@command()
20+
export class OpenRevisionFromRemoteCommand extends GlCommandBase {
21+
constructor(private readonly container: Container) {
22+
super('gitlens.openRevisionFromRemote');
23+
}
2824

29-
let local = await this.container.git.getLocalInfoFromRemoteUri(Uri.parse(url));
30-
if (local == null) {
31-
local = await this.container.git.getLocalInfoFromRemoteUri(Uri.parse(url), { validate: false });
32-
if (local == null) {
33-
void window.showWarningMessage('Unable to parse the provided remote url.');
25+
async execute(): Promise<void> {
26+
await openFileOreRevisionFromRemote(this.container, 'revision');
27+
}
28+
}
3429

35-
return;
36-
}
30+
async function openFileOreRevisionFromRemote(container: Container, type: 'file' | 'revision'): Promise<void> {
31+
let clipboard: string | undefined = await env.clipboard.readText();
32+
try {
33+
Uri.parse(clipboard, true);
34+
} catch {
35+
clipboard = undefined;
36+
}
3737

38-
const confirm = 'Open File...';
39-
const pick = await window.showWarningMessage(
40-
'Unable to find a workspace folder that matches the provided remote url.',
41-
confirm,
42-
);
43-
if (pick !== confirm) return;
44-
}
38+
const url = await window.showInputBox({
39+
prompt: 'Enter a remote file url to open',
40+
placeHolder: 'Remote file url',
41+
value: clipboard,
42+
ignoreFocusOut: true,
43+
});
44+
if (!url?.length) return;
4545

46-
let selection;
47-
if (local.startLine) {
48-
if (local.endLine) {
49-
selection = new Range(local.startLine - 1, 0, local.endLine, 0);
50-
} else {
51-
selection = new Range(local.startLine - 1, 0, local.startLine - 1, 0);
52-
}
53-
}
46+
const local = await container.git.getLocalInfoFromRemoteUri(Uri.parse(url));
47+
if (local == null) {
48+
void window.showWarningMessage('Unable to parse the provided remote url.');
49+
return;
50+
}
5451

55-
try {
56-
await openTextEditor(local.uri, { selection: selection, throwOnError: true });
57-
} catch {
58-
const uris = await window.showOpenDialog({
59-
title: 'Open local file',
60-
defaultUri: local.uri,
61-
canSelectMany: false,
62-
canSelectFolders: false,
63-
});
64-
if (uris == null || uris.length === 0) return;
52+
let { uri } = local;
53+
if (type === 'revision' && uri.scheme === Schemes.File && local.rev) {
54+
uri = (await container.git.getBestRevisionUri(local.repoPath, local.uri.fsPath, local.rev)) ?? uri;
55+
}
6556

66-
await openTextEditor(uris[0]);
57+
let selection;
58+
if (local.startLine) {
59+
if (local.endLine) {
60+
selection = new Range(local.startLine - 1, 0, local.endLine, 0);
61+
} else {
62+
selection = new Range(local.startLine - 1, 0, local.startLine - 1, 0);
6763
}
6864
}
65+
66+
try {
67+
await openTextEditor(uri, { selection: selection, throwOnError: true });
68+
} catch {
69+
const uris = await window.showOpenDialog({
70+
title: 'Open local file',
71+
defaultUri: uri,
72+
canSelectMany: false,
73+
canSelectFolders: false,
74+
});
75+
if (!uris?.length) return;
76+
77+
await openTextEditor(uris[0]);
78+
}
6979
}

src/commands/openRevisionFile.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,13 @@ export class OpenRevisionFileCommand extends ActiveEditorCommand {
4343
args.revisionUri =
4444
commit?.file?.status === 'D'
4545
? this.container.git.getRevisionUri(
46+
commit.repoPath,
4647
(await commit.getPreviousSha()) ?? deletedOrMissing,
4748
commit.file,
48-
commit.repoPath,
4949
)
50-
: this.container.git.getRevisionUri(gitUri);
50+
: this.container.git.getRevisionUriFromGitUri(gitUri);
5151
} else {
52-
args.revisionUri = this.container.git.getRevisionUri(gitUri);
52+
args.revisionUri = this.container.git.getRevisionUriFromGitUri(gitUri);
5353
}
5454
}
5555

src/constants.commands.generated.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,7 @@ export type ContributedPaletteCommands =
705705
| 'gitlens.openPatch'
706706
| 'gitlens.openRepoOnRemote'
707707
| 'gitlens.openRevisionFile'
708+
| 'gitlens.openRevisionFromRemote'
708709
| 'gitlens.openWorkingFile'
709710
| 'gitlens.pastePatchFromClipboard'
710711
| 'gitlens.plus.cloudIntegrations.manage'

0 commit comments

Comments
 (0)