diff --git a/src/commands/openFileInRemote.ts b/src/commands/openFileInRemote.ts index fa4f160..b691e8e 100644 --- a/src/commands/openFileInRemote.ts +++ b/src/commands/openFileInRemote.ts @@ -18,10 +18,11 @@ export class OpenFileInRemoteCommand extends ActiveEditorCommand { } const gitUri = await GitUri.fromUri(uri, this.git); + const branch = await this.git.getBranch(gitUri.repoPath || this.repoPath); try { const remotes = Arrays.uniqueBy(await this.git.getRemotes(this.repoPath), _ => _.url, _ => !!_.provider); - return commands.executeCommand(Commands.OpenInRemote, uri, remotes, 'file', [gitUri.getRelativePath(), gitUri.sha]); + return commands.executeCommand(Commands.OpenInRemote, uri, remotes, 'file', [gitUri.getRelativePath(), branch.name, gitUri.sha]); } catch (ex) { Logger.error('[GitLens.OpenFileInRemoteCommand]', ex); diff --git a/src/commands/openInRemote.ts b/src/commands/openInRemote.ts index d68543f..69ca28c 100644 --- a/src/commands/openInRemote.ts +++ b/src/commands/openInRemote.ts @@ -1,7 +1,7 @@ 'use strict'; import { TextEditor, Uri, window } from 'vscode'; import { ActiveEditorCommand, Commands } from './commands'; -import { GitRemote, RemoteProviderOpenType } from '../gitService'; +import { GitRemote, RemoteOpenType } from '../gitService'; import { Logger } from '../logger'; import { CommandQuickPickItem, OpenRemoteCommandQuickPickItem, RemotesQuickPick } from '../quickPicks'; @@ -11,7 +11,7 @@ export class OpenInRemoteCommand extends ActiveEditorCommand { super(Commands.OpenInRemote); } - async execute(editor: TextEditor, uri?: Uri, remotes?: GitRemote[], type?: RemoteProviderOpenType, args?: string[], name?: string, goBackCommand?: CommandQuickPickItem) { + async execute(editor: TextEditor, uri?: Uri, remotes?: GitRemote[], type?: RemoteOpenType, args?: string[], goBackCommand?: CommandQuickPickItem) { if (!(uri instanceof Uri)) { uri = editor && editor.document && editor.document.uri; } @@ -20,7 +20,7 @@ export class OpenInRemoteCommand extends ActiveEditorCommand { if (!remotes) return undefined; if (remotes.length === 1) { - const command = new OpenRemoteCommandQuickPickItem(remotes[0], type, ...args, name); + const command = new OpenRemoteCommandQuickPickItem(remotes[0], type, ...args); return command.execute(); } @@ -34,14 +34,15 @@ export class OpenInRemoteCommand extends ActiveEditorCommand { placeHolder = `open commit ${shortSha} in\u2026`; break; case 'file': - const shortFileSha = (args[1] && args[1].substring(0, 8)) || ''; + case 'working-file': + const shortFileSha = (args[2] && args[2].substring(0, 8)) || ''; const shaSuffix = shortFileSha ? ` \u00a0\u2022\u00a0 ${shortFileSha}` : ''; placeHolder = `open ${args[0]}${shaSuffix} in\u2026`; break; } - const pick = await RemotesQuickPick.show(remotes, placeHolder, type, args, name, goBackCommand); + const pick = await RemotesQuickPick.show(remotes, placeHolder, type, args, goBackCommand); return pick && pick.execute(); } diff --git a/src/git/remotes/github.ts b/src/git/remotes/github.ts index 07a07ee..4f73eb3 100644 --- a/src/git/remotes/github.ts +++ b/src/git/remotes/github.ts @@ -19,8 +19,9 @@ export class GitHubService extends RemoteProvider { return `${this.baseUrl}/commit/${sha}`; } - protected getUrlForFile(fileName: string, sha?: string): string { + protected getUrlForFile(fileName: string, branch?: string, sha?: string): string { if (sha) return `${this.baseUrl}/blob/${sha}/${fileName}`; + if (branch) return `${this.baseUrl}/blob/${branch}/${fileName}`; return `${this.baseUrl}?path=${fileName}`; } } \ No newline at end of file diff --git a/src/git/remotes/provider.ts b/src/git/remotes/provider.ts index a093b42..0a42947 100644 --- a/src/git/remotes/provider.ts +++ b/src/git/remotes/provider.ts @@ -2,7 +2,7 @@ import { commands, Uri } from 'vscode'; import { BuiltInCommands } from '../../constants'; -export type RemoteProviderOpenType = 'branch' | 'commit' | 'file'; +export type RemoteOpenType = 'branch' | 'commit' | 'file' | 'working-file'; export abstract class RemoteProvider { @@ -16,7 +16,7 @@ export abstract class RemoteProvider { protected abstract getUrlForBranch(branch: string): string; protected abstract getUrlForCommit(sha: string): string; - protected abstract getUrlForFile(fileName: string, sha?: string): string; + protected abstract getUrlForFile(fileName: string, branch: string, sha?: string): string; private async _openUrl(url: string): Promise<{}> { return url && commands.executeCommand(BuiltInCommands.Open, Uri.parse(url)); @@ -24,13 +24,17 @@ export abstract class RemoteProvider { open(type: 'branch', branch: string): Promise<{}>; open(type: 'commit', sha: string): Promise<{}>; - open(type: 'file', fileName: string, sha?: string): Promise<{}>; - open(type: RemoteProviderOpenType, ...args: string[]): Promise<{}>; - open(type: RemoteProviderOpenType, branchOrShaOrFileName: string, sha?: string): Promise<{}> { + open(type: 'file', fileName: string, branch?: string, sha?: string): Promise<{}>; + open(type: RemoteOpenType, ...args: string[]): Promise<{}>; + open(type: RemoteOpenType, branchOrShaOrFileName: string, fileBranch?: string, fileSha?: string): Promise<{}> { switch (type) { - case 'branch': return this.openBranch(branchOrShaOrFileName); - case 'commit': return this.openCommit(branchOrShaOrFileName); - case 'file': return this.openFile(branchOrShaOrFileName, sha); + case 'branch': + return this.openBranch(branchOrShaOrFileName); + case 'commit': + return this.openCommit(branchOrShaOrFileName); + case 'file': + case 'working-file': + return this.openFile(branchOrShaOrFileName, fileBranch, fileSha); } } @@ -42,7 +46,7 @@ export abstract class RemoteProvider { return this._openUrl(this.getUrlForCommit(sha)); } - openFile(fileName: string, sha?: string) { - return this._openUrl(this.getUrlForFile(fileName, sha)); + openFile(fileName: string, branch?: string, sha?: string) { + return this._openUrl(this.getUrlForFile(fileName, branch, sha)); } } \ No newline at end of file diff --git a/src/quickPicks/commitFileDetails.ts b/src/quickPicks/commitFileDetails.ts index 455ba62..543e514 100644 --- a/src/quickPicks/commitFileDetails.ts +++ b/src/quickPicks/commitFileDetails.ts @@ -81,9 +81,10 @@ export class CommitFileDetailsQuickPick { const remotes = Arrays.uniqueBy(await git.getRemotes(git.repoPath), _ => _.url, _ => !!_.provider); if (remotes.length) { - items.push(new OpenRemotesCommandQuickPickItem(remotes, 'file', commit.fileName, commit.sha, undefined, currentCommand)); + items.push(new OpenRemotesCommandQuickPickItem(remotes, 'file', commit.fileName, undefined, commit.sha, currentCommand)); if (commit.workingFileName) { - items.push(new OpenRemotesCommandQuickPickItem(remotes, 'file', commit.workingFileName, undefined, 'Working File', currentCommand)); + const branch = await git.getBranch(commit.repoPath || git.repoPath); + items.push(new OpenRemotesCommandQuickPickItem(remotes, 'working-file', commit.workingFileName, branch.name, undefined, currentCommand)); } } diff --git a/src/quickPicks/fileHistory.ts b/src/quickPicks/fileHistory.ts index 7b1a37e..556685e 100644 --- a/src/quickPicks/fileHistory.ts +++ b/src/quickPicks/fileHistory.ts @@ -73,6 +73,8 @@ export class FileHistoryQuickPick { } } + const branch = await git.getBranch(uri.repoPath || git.repoPath); + const currentCommand = new CommandQuickPickItem({ label: `go back \u21A9`, description: `\u00a0 \u2014 \u00a0\u00a0 to history of \u00a0$(file-text) ${path.basename(uri.fsPath)}${uri.sha ? ` from \u00a0$(git-commit) ${uri.shortSha}` : ''}` @@ -82,7 +84,7 @@ export class FileHistoryQuickPick { if (!goBackCommand) { items.splice(index++, 0, new CommandQuickPickItem({ label: `$(history) Show Branch History`, - description: `\u00a0 \u2014 \u00a0\u00a0 shows the current branch history` + description: `\u00a0 \u2014 \u00a0\u00a0 shows \u00a0$(git-branch) ${branch.name} history` }, Commands.ShowQuickCurrentBranchHistory, [ undefined, @@ -92,7 +94,7 @@ export class FileHistoryQuickPick { const remotes = Arrays.uniqueBy(await git.getRemotes(git.repoPath), _ => _.url, _ => !!_.provider); if (remotes.length) { - items.splice(index++, 0, new OpenRemotesCommandQuickPickItem(remotes, 'file', uri.getRelativePath(), uri.sha, undefined, currentCommand)); + items.splice(index++, 0, new OpenRemotesCommandQuickPickItem(remotes, 'file', uri.getRelativePath(), branch.name, uri.sha, currentCommand)); } if (goBackCommand) { diff --git a/src/quickPicks/remotes.ts b/src/quickPicks/remotes.ts index 97a7640..86261f4 100644 --- a/src/quickPicks/remotes.ts +++ b/src/quickPicks/remotes.ts @@ -1,29 +1,34 @@ 'use strict'; import { QuickPickOptions, window } from 'vscode'; import { Commands } from '../commands'; -import { GitRemote, RemoteProviderOpenType } from '../gitService'; +import { GitRemote, RemoteOpenType } from '../gitService'; import { CommandQuickPickItem, getQuickPickIgnoreFocusOut } from './quickPicks'; import * as path from 'path'; +function getNameFromRemoteOpenType(type: RemoteOpenType) { + switch (type) { + case 'branch': return 'Branch'; + case 'commit': return 'Commit'; + case 'file': return 'File'; + case 'working-file': return 'Working File'; + default: return ''; + } +} + export class OpenRemoteCommandQuickPickItem extends CommandQuickPickItem { - private type: RemoteProviderOpenType; private remote: GitRemote; + private type: RemoteOpenType; - constructor(remote: GitRemote, type: RemoteProviderOpenType, ...args: string[]); - constructor(remote: GitRemote, type: RemoteProviderOpenType, branchOrShaOrFileName: string, fileSha?: string, name?: string) { - if (!name) { - name = `${type[0].toUpperCase()}${type.substring(1)}`; - } - + constructor(remote: GitRemote, type: RemoteOpenType, ...args: string[]) { super({ - label: `$(link-external) Open ${name} in ${remote.provider.name}`, + label: `$(link-external) Open ${getNameFromRemoteOpenType(type)} in ${remote.provider.name}`, description: `\u00a0 \u2014 \u00a0\u00a0 $(repo) ${remote.provider.path}` }, undefined, undefined); - this.type = type; this.remote = remote; - this.args = [branchOrShaOrFileName, fileSha]; + this.type = type; + this.args = args; } async execute(): Promise<{}> { @@ -35,37 +40,37 @@ export class OpenRemotesCommandQuickPickItem extends CommandQuickPickItem { constructor(remotes: GitRemote[], type: 'branch', branch: string, goBackCommand?: CommandQuickPickItem); constructor(remotes: GitRemote[], type: 'commit', sha: string, goBackCommand?: CommandQuickPickItem); - constructor(remotes: GitRemote[], type: 'file', fileName: string, sha?: string, name?: string, goBackCommand?: CommandQuickPickItem); - constructor(remotes: GitRemote[], type: RemoteProviderOpenType, branchOrShaOrFileName: string, shaOrGoBackCommand?: string | CommandQuickPickItem, name?: string, goBackCommand?: CommandQuickPickItem) { - let fileSha: string; - if (typeof shaOrGoBackCommand === 'string') { - fileSha = shaOrGoBackCommand; + constructor(remotes: GitRemote[], type: 'file' | 'working-file', fileName: string, branch?: string, sha?: string, goBackCommand?: CommandQuickPickItem); + constructor(remotes: GitRemote[], type: RemoteOpenType, branchOrShaOrFileName: string, goBackCommandOrFileBranch?: CommandQuickPickItem | string, fileSha?: string, goBackCommand?: CommandQuickPickItem) { + let fileBranch: string; + if (typeof goBackCommandOrFileBranch === 'string') { + fileBranch = goBackCommandOrFileBranch; } else if (!goBackCommand) { - goBackCommand = shaOrGoBackCommand; + goBackCommand = goBackCommandOrFileBranch; } + const name = getNameFromRemoteOpenType(type); + let description: string; let placeHolder: string; switch (type) { case 'branch': - name = name || 'Branch'; description = `$(git-branch) ${branchOrShaOrFileName}`; placeHolder = `open ${branchOrShaOrFileName} ${name.toLowerCase()} in\u2026`; break; case 'commit': const shortSha = branchOrShaOrFileName.substring(0, 8); - name = name || 'Commit'; description = `$(git-commit) ${shortSha}`; placeHolder = `open ${name.toLowerCase()} ${shortSha} in\u2026`; break; case 'file': + case 'working-file': const fileName = path.basename(branchOrShaOrFileName); const shortFileSha = (fileSha && fileSha.substring(0, 8)) || ''; const shaSuffix = shortFileSha ? ` \u00a0\u2022\u00a0 ${shortFileSha}` : ''; - name = name || 'File'; description = `$(file-text) ${fileName}${shortFileSha ? ` in \u00a0$(git-commit) ${shortFileSha}` : ''}`; placeHolder = `open ${branchOrShaOrFileName}${shaSuffix} in\u2026`; break; @@ -76,7 +81,7 @@ export class OpenRemotesCommandQuickPickItem extends CommandQuickPickItem { super({ label: `$(link-external) Open ${name} in ${remote.provider.name}`, description: `\u00a0 \u2014 \u00a0\u00a0 $(repo) ${remote.provider.path} \u00a0\u2022\u00a0 ${description}` - }, Commands.OpenInRemote, [undefined, remotes, type, [branchOrShaOrFileName, fileSha], name, goBackCommand]); + }, Commands.OpenInRemote, [undefined, remotes, type, [branchOrShaOrFileName, fileBranch, fileSha], goBackCommand]); return; } @@ -88,15 +93,15 @@ export class OpenRemotesCommandQuickPickItem extends CommandQuickPickItem { super({ label: `$(link-external) Open ${name} in ${provider}\u2026`, description: `\u00a0 \u2014 \u00a0\u00a0 ${description}` - }, Commands.OpenInRemote, [undefined, remotes, type, [branchOrShaOrFileName, fileSha], name, goBackCommand]); + }, Commands.OpenInRemote, [undefined, remotes, type, [branchOrShaOrFileName, fileBranch, fileSha], goBackCommand]); } } export class RemotesQuickPick { - static async show(remotes: GitRemote[], placeHolder: string, type: RemoteProviderOpenType, args: string[], name: string, goBackCommand?: CommandQuickPickItem): Promise { + static async show(remotes: GitRemote[], placeHolder: string, type: RemoteOpenType, args: string[], goBackCommand?: CommandQuickPickItem): Promise { - const items = remotes.map(_ => new OpenRemoteCommandQuickPickItem(_, type, ...args, name)) as (OpenRemoteCommandQuickPickItem | CommandQuickPickItem)[]; + const items = remotes.map(_ => new OpenRemoteCommandQuickPickItem(_, type, ...args)) as (OpenRemoteCommandQuickPickItem | CommandQuickPickItem)[]; if (goBackCommand) { items.splice(0, 0, goBackCommand);