Skip to content

Commit d2a7a1c

Browse files
committed
Fixes #399 - "Open x in Remote" commands aren't always available
Closes #209 - Open File in Remote should ask for a branch if no upstream
1 parent fa00c94 commit d2a7a1c

File tree

10 files changed

+63
-33
lines changed

10 files changed

+63
-33
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
77
## [Unreleased]
88
### Added
99
- Adds clipboard support for Linux without requiring any external dependencies — thanks to [PR #394](https://github.com/eamodio/vscode-gitlens/pull/394) by Cédric Malard ([@cmalard](https://github.com/cmalard))
10+
- Adds a select branch quick pick menu to the *Open File in Remote* command (`gitlens.openFileInRemote`) when the current branch has no upstream tracking branch — closes [#209](https://github.com/eamodio/vscode-gitlens/issues/209)
1011

1112
### Fixed
1213
- Fixes [#400](https://github.com/eamodio/vscode-gitlens/issues/400) - Reset TO commit also resets chosen one
14+
- Fixes [#399](https://github.com/eamodio/vscode-gitlens/issues/399) - "Open x in Remote" commands aren't always available
1315
- Fixes [#397](https://github.com/eamodio/vscode-gitlens/issues/397) - Error while opening the gitlens view using `Open View` command
1416
- Fixes [#391](https://github.com/eamodio/vscode-gitlens/issues/391) - GitLens adds some settings in settings.json
1517
- Fixes another case of [#343](https://github.com/eamodio/vscode-gitlens/issues/343) - Can't show blame when VSCode starts on branch without upstream — thanks to [PR #390](https://github.com/eamodio/vscode-gitlens/pull/390) by ryenus ([@ryenus](https://github.com/ryenus))

package.json

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2068,27 +2068,27 @@
20682068
},
20692069
{
20702070
"command": "gitlens.openBranchesInRemote",
2071-
"when": "gitlens:activeHasRemote"
2071+
"when": "gitlens:hasRemotes"
20722072
},
20732073
{
20742074
"command": "gitlens.openBranchInRemote",
2075-
"when": "gitlens:activeHasRemote"
2075+
"when": "gitlens:hasRemotes"
20762076
},
20772077
{
20782078
"command": "gitlens.openCommitInRemote",
2079-
"when": "gitlens:activeIsBlameable && gitlens:activeHasRemote"
2079+
"when": "gitlens:activeIsBlameable && gitlens:activeHasRemotes"
20802080
},
20812081
{
20822082
"command": "gitlens.openFileInRemote",
2083-
"when": "gitlens:activeIsTracked && gitlens:activeHasRemote"
2083+
"when": "gitlens:activeIsTracked && gitlens:activeHasRemotes"
20842084
},
20852085
{
20862086
"command": "gitlens.openFileRevision",
20872087
"when": "gitlens:activeIsTracked"
20882088
},
20892089
{
20902090
"command": "gitlens.openRepoInRemote",
2091-
"when": "gitlens:activeHasRemote"
2091+
"when": "gitlens:hasRemotes"
20922092
},
20932093
{
20942094
"command": "gitlens.openWorkingFile",
@@ -2372,12 +2372,12 @@
23722372
},
23732373
{
23742374
"command": "gitlens.openFileInRemote",
2375-
"when": "editorTextFocus && gitlens:activeHasRemote && config.gitlens.menus.editor.remote",
2375+
"when": "editorTextFocus && gitlens:activeHasRemotes && config.gitlens.menus.editor.remote",
23762376
"group": "1_gitlens_1@1"
23772377
},
23782378
{
23792379
"command": "gitlens.openCommitInRemote",
2380-
"when": "editorTextFocus && gitlens:activeHasRemote && config.gitlens.menus.editor.remote",
2380+
"when": "editorTextFocus && gitlens:activeHasRemotes && config.gitlens.menus.editor.remote",
23812381
"group": "1_gitlens_1@2"
23822382
},
23832383
{
@@ -2450,7 +2450,7 @@
24502450
},
24512451
{
24522452
"command": "gitlens.openFileInRemote",
2453-
"when": "gitlens:enabled && gitlens:activeHasRemote && config.gitlens.menus.editorGroup.remote",
2453+
"when": "gitlens:enabled && gitlens:activeHasRemotes && config.gitlens.menus.editorGroup.remote",
24542454
"group": "4_gitlens"
24552455
},
24562456
{
@@ -2462,7 +2462,7 @@
24622462
"editor/title/context": [
24632463
{
24642464
"command": "gitlens.openFileInRemote",
2465-
"when": "gitlens:enabled && gitlens:activeHasRemote && config.gitlens.menus.editorTab.remote",
2465+
"when": "gitlens:enabled && gitlens:activeHasRemotes && config.gitlens.menus.editorTab.remote",
24662466
"group": "2_files@100"
24672467
},
24682468
{

src/commands/openBranchInRemote.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,23 +41,26 @@ export class OpenBranchInRemoteCommand extends ActiveEditorCommand {
4141
if (args.branch === undefined) {
4242
args = { ...args };
4343

44-
const branches = await Container.git.getBranches(repoPath);
44+
const branches = (await Container.git.getBranches(repoPath)).filter(b => b.tracking !== undefined);
45+
if (branches.length > 1) {
46+
const pick = await BranchesQuickPick.show(branches, `Open which branch in remote${GlyphChars.Ellipsis}`);
47+
if (pick === undefined) return undefined;
4548

46-
const pick = await BranchesQuickPick.show(branches, `Open which branch in remote${GlyphChars.Ellipsis}`);
47-
if (pick === undefined) return undefined;
49+
if (pick instanceof CommandQuickPickItem) return undefined;
4850

49-
if (pick instanceof CommandQuickPickItem) return undefined;
50-
51-
args.branch = pick.branch.name;
52-
if (args.branch === undefined) return undefined;
51+
args.branch = pick.branch.name;
52+
}
53+
else if (branches.length === 1) {
54+
args.branch = branches[0].name;
55+
}
5356
}
5457

5558
const remotes = await Container.git.getRemotes(repoPath);
5659

5760
return commands.executeCommand(Commands.OpenInRemote, uri, {
5861
resource: {
5962
type: 'branch',
60-
branch: args.branch
63+
branch: args.branch || 'HEAD'
6164
},
6265
remote: args.remote,
6366
remotes

src/commands/openFileInRemote.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
'use strict';
22
import { commands, Range, TextEditor, Uri, window } from 'vscode';
33
import { ActiveEditorCommand, CommandContext, Commands, getCommandUri, isCommandViewContextWithBranch, isCommandViewContextWithCommit } from './common';
4+
import { GlyphChars } from '../constants';
45
import { Container } from '../container';
56
import { GitUri } from '../gitService';
67
import { Logger } from '../logger';
78
import { OpenInRemoteCommandArgs } from './openInRemote';
9+
import { BranchesQuickPick, CommandQuickPickItem } from '../quickPicks/quickPicks';
810

911
export interface OpenFileInRemoteCommandArgs {
1012
branch?: string;
@@ -39,7 +41,21 @@ export class OpenFileInRemoteCommand extends ActiveEditorCommand {
3941

4042
if (args.branch === undefined) {
4143
const branch = await Container.git.getBranch(gitUri.repoPath);
42-
if (branch !== undefined) {
44+
if (branch === undefined || branch.tracking === undefined) {
45+
const branches = (await Container.git.getBranches(gitUri.repoPath)).filter(b => b.tracking !== undefined);
46+
if (branches.length > 1) {
47+
const pick = await BranchesQuickPick.show(branches, `Open ${gitUri.getRelativePath()} in remote for which branch${GlyphChars.Ellipsis}`);
48+
if (pick === undefined) return undefined;
49+
50+
if (pick instanceof CommandQuickPickItem) return undefined;
51+
52+
args.branch = pick.branch.name;
53+
}
54+
else if (branches.length === 1) {
55+
args.branch = branches[0].name;
56+
}
57+
}
58+
else {
4359
args.branch = branch.name;
4460
}
4561
}
@@ -53,7 +69,7 @@ export class OpenFileInRemoteCommand extends ActiveEditorCommand {
5369
return commands.executeCommand(Commands.OpenInRemote, uri, {
5470
resource: {
5571
type: gitUri.sha === undefined ? 'file' : 'revision',
56-
branch: args.branch,
72+
branch: args.branch || 'HEAD',
5773
fileName: gitUri.getRelativePath(),
5874
range: range,
5975
sha: gitUri.sha

src/constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export enum BuiltInCommands {
2424
}
2525

2626
export enum CommandContext {
27-
ActiveHasRemote = 'gitlens:activeHasRemote',
27+
ActiveHasRemotes = 'gitlens:activeHasRemotes',
2828
ActiveIsBlameable = 'gitlens:activeIsBlameable',
2929
ActiveFileIsTracked = 'gitlens:activeIsTracked',
3030
ActiveIsRevision = 'gitlens:activeIsRevision',

src/git/git.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,15 @@ export class Git {
333333
return gitCommand({ cwd: repoPath }, ...params);
334334
}
335335

336+
static branch_contains(repoPath: string, ref: string, options: { remote: boolean } = { remote: false }) {
337+
const params = ['branch', '--contains'];
338+
if (options.remote) {
339+
params.push('-r');
340+
}
341+
342+
return gitCommand({ cwd: repoPath }, ...params, ref);
343+
}
344+
336345
static checkout(repoPath: string, fileName: string, sha: string) {
337346
const [file, root] = Git.splitPath(fileName, repoPath);
338347

src/git/models/repository.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -249,16 +249,16 @@ export class Repository extends Disposable {
249249
return Container.git.getTags(this.path);
250250
}
251251

252-
async hasRemote(): Promise<boolean> {
253-
const branch = await this.getBranch();
254-
return branch !== undefined && branch.tracking !== undefined;
255-
}
256-
257252
async hasRemotes(): Promise<boolean> {
258253
const remotes = await this.getRemotes();
259254
return remotes !== undefined && remotes.length > 0;
260255
}
261256

257+
async hasTrackingBranch(): Promise<boolean> {
258+
const branch = await this.getBranch();
259+
return branch !== undefined && branch.tracking !== undefined;
260+
}
261+
262262
resume() {
263263
if (!this._suspended) return;
264264

src/gitService.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1132,22 +1132,22 @@ export class GitService extends Disposable {
11321132
}
11331133
}
11341134

1135-
async hasRemote(repoPath: string | undefined): Promise<boolean> {
1135+
async hasRemotes(repoPath: string | undefined): Promise<boolean> {
11361136
if (repoPath === undefined) return false;
11371137

11381138
const repository = await this.getRepository(repoPath);
11391139
if (repository === undefined) return false;
11401140

1141-
return repository.hasRemote();
1141+
return repository.hasRemotes();
11421142
}
11431143

1144-
async hasRemotes(repoPath: string | undefined): Promise<boolean> {
1144+
async hasTrackingBranch(repoPath: string | undefined): Promise<boolean> {
11451145
if (repoPath === undefined) return false;
11461146

11471147
const repository = await this.getRepository(repoPath);
11481148
if (repository === undefined) return false;
11491149

1150-
return repository.hasRemotes();
1150+
return repository.hasTrackingBranch();
11511151
}
11521152

11531153
async getMergeBase(repoPath: string, ref1: string, ref2: string, options: { forkPoint?: boolean } = {}) {

src/trackers/documentTracker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ export class DocumentTracker<T> extends Disposable {
9191
setCommandContext(CommandContext.ActiveIsRevision, false);
9292
setCommandContext(CommandContext.ActiveFileIsTracked, false);
9393
setCommandContext(CommandContext.ActiveIsBlameable, false);
94-
setCommandContext(CommandContext.ActiveHasRemote, false);
94+
setCommandContext(CommandContext.ActiveHasRemotes, false);
9595

9696
return;
9797
}

src/trackers/trackedDocument.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ export class TrackedDocument<T> extends Disposable {
120120
setCommandContext(CommandContext.ActiveIsRevision, this.isRevision);
121121
setCommandContext(CommandContext.ActiveFileIsTracked, this.isTracked);
122122
setCommandContext(CommandContext.ActiveIsBlameable, this.isBlameable);
123-
setCommandContext(CommandContext.ActiveHasRemote, this.hasRemotes);
123+
setCommandContext(CommandContext.ActiveHasRemotes, this.hasRemotes);
124124
}
125125

126126
async ensureInitialized() {
@@ -189,7 +189,7 @@ export class TrackedDocument<T> extends Disposable {
189189
}
190190

191191
if (repo !== undefined) {
192-
this._hasRemotes = await repo.hasRemote();
192+
this._hasRemotes = await repo.hasRemotes();
193193
}
194194
else {
195195
this._hasRemotes = false;
@@ -201,7 +201,7 @@ export class TrackedDocument<T> extends Disposable {
201201
setCommandContext(CommandContext.ActiveIsRevision, this.isRevision);
202202
setCommandContext(CommandContext.ActiveFileIsTracked, this.isTracked);
203203
setCommandContext(CommandContext.ActiveIsBlameable, blameable);
204-
setCommandContext(CommandContext.ActiveHasRemote, this.hasRemotes);
204+
setCommandContext(CommandContext.ActiveHasRemotes, this.hasRemotes);
205205

206206
if (!options.initializing && wasBlameable !== blameable) {
207207
const e = { editor: active, document: this, blameable: blameable } as DocumentBlameStateChangeEvent<T>;

0 commit comments

Comments
 (0)