From 27ab08cf783b649d779ca5d890b9ec875529958a Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Wed, 10 Jul 2019 22:20:36 -0400 Subject: [PATCH] Reworks many quickpick menus --- src/commands/diffWithRef.ts | 2 +- src/commands/diffWithRevision.ts | 12 +- src/commands/openFileRevision.ts | 12 +- src/commands/searchCommits.ts | 10 +- src/commands/showQuickBranchHistory.ts | 13 +- src/commands/showQuickCommitDetails.ts | 7 +- src/commands/showQuickCommitFileDetails.ts | 10 +- src/commands/showQuickFileHistory.ts | 19 +- src/commands/showQuickStashList.ts | 9 +- src/commands/stashApply.ts | 5 +- src/container.ts | 2 +- src/git/git.ts | 2 +- src/git/gitService.ts | 27 ++- src/git/models/branch.ts | 10 + src/git/models/remote.ts | 8 + src/git/models/repository.ts | 4 + src/git/models/tag.ts | 4 + src/quickpicks.ts | 4 +- src/quickpicks/branchHistoryQuickPick.ts | 22 +-- src/quickpicks/commitFileQuickPick.ts | 49 +++-- src/quickpicks/commitQuickPick.ts | 26 ++- src/quickpicks/commitsQuickPick.ts | 4 +- src/quickpicks/commonQuickPicks.ts | 58 +----- src/quickpicks/fileHistoryQuickPick.ts | 25 +-- src/quickpicks/gitQuickPicks.ts | 306 +++++++++++++++++++++++++++++ src/quickpicks/referencesQuickPick.ts | 193 +++++++----------- src/quickpicks/remotesQuickPick.ts | 23 +-- src/quickpicks/repoStatusQuickPick.ts | 14 +- src/quickpicks/repositoriesQuickPick.ts | 27 +-- src/quickpicks/stashListQuickPick.ts | 14 +- src/terminal.ts | 42 ++++ src/views/nodes.ts | 2 + src/views/viewCommands.ts | 89 +++------ 33 files changed, 615 insertions(+), 439 deletions(-) create mode 100644 src/quickpicks/gitQuickPicks.ts create mode 100644 src/terminal.ts diff --git a/src/commands/diffWithRef.ts b/src/commands/diffWithRef.ts index feefbf2..7275c5a 100644 --- a/src/commands/diffWithRef.ts +++ b/src/commands/diffWithRef.ts @@ -36,7 +36,7 @@ export class DiffWithRefCommand extends ActiveEditorCommand { if (!gitUri.repoPath) return Messages.showNoRepositoryWarningMessage('Unable to open file compare'); const pick = await new ReferencesQuickPick(gitUri.repoPath).show( - `Compare ${paths.basename(gitUri.fsPath)} with${GlyphChars.Ellipsis}`, + `Compare ${gitUri.getFormattedPath()} with${GlyphChars.Ellipsis}`, { allowEnteringRefs: true, checkmarks: false, diff --git a/src/commands/diffWithRevision.ts b/src/commands/diffWithRevision.ts index 58b4600..ea3b1e5 100644 --- a/src/commands/diffWithRevision.ts +++ b/src/commands/diffWithRevision.ts @@ -65,7 +65,7 @@ export class DiffWithRevisionCommand extends ActiveEditorCommand { const npc = new CommandQuickPickItem( { label: '$(arrow-right) Show Next Commits', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} shows ${log.maxCount} newer commits` + description: `shows ${log.maxCount} newer commits` }, Commands.DiffWithRevision, [uri, commandArgs] @@ -77,7 +77,7 @@ export class DiffWithRevisionCommand extends ActiveEditorCommand { previousPageCommand = new CommandQuickPickItem( { label: '$(arrow-left) Show Previous Commits', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} shows ${log.maxCount} older commits` + description: `shows ${log.maxCount} older commits` }, Commands.DiffWithRevision, [new GitUri(uri, last), commandArgs] @@ -90,9 +90,7 @@ export class DiffWithRevisionCommand extends ActiveEditorCommand { const currentCommand = new CommandQuickPickItem( { label: `go back ${GlyphChars.ArrowBack}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} to history of ${ - GlyphChars.Space - }$(file-text) ${gitUri.getFormattedPath()}${ + description: `to history of ${gitUri.getFormattedPath()}${ args.reference ? ` from ${GlyphChars.Space}${icon}${args.reference.name}` : gitUri.sha @@ -115,7 +113,7 @@ export class DiffWithRevisionCommand extends ActiveEditorCommand { ? new CommandQuickPickItem( { label: '$(sync) Show All Commits', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} this may take a while` + description: 'this may take a while' }, Commands.DiffWithRevision, [uri, commandArgs] @@ -138,7 +136,7 @@ export class DiffWithRevisionCommand extends ActiveEditorCommand { if (pick instanceof CommandQuickPickItem) return pick.execute(); - const ref = pick.commit.sha; + const ref = pick.item.sha; const diffArgs: DiffWithCommandArgs = { repoPath: gitUri.repoPath, diff --git a/src/commands/openFileRevision.ts b/src/commands/openFileRevision.ts index 0ab6217..3963b6e 100644 --- a/src/commands/openFileRevision.ts +++ b/src/commands/openFileRevision.ts @@ -96,7 +96,7 @@ export class OpenFileRevisionCommand extends ActiveEditorCommand { const npc = new CommandQuickPickItem( { label: '$(arrow-right) Show Next Commits', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} shows ${log.maxCount} newer commits` + description: `shows ${log.maxCount} newer commits` }, Commands.OpenFileRevision, [uri, commandArgs] @@ -108,7 +108,7 @@ export class OpenFileRevisionCommand extends ActiveEditorCommand { previousPageCommand = new CommandQuickPickItem( { label: '$(arrow-left) Show Previous Commits', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} shows ${log.maxCount} older commits` + description: `shows ${log.maxCount} older commits` }, Commands.OpenFileRevision, [new GitUri(uri, last), commandArgs] @@ -125,9 +125,7 @@ export class OpenFileRevisionCommand extends ActiveEditorCommand { const currentCommand = new CommandQuickPickItem( { label: `go back ${GlyphChars.ArrowBack}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} to history of ${ - GlyphChars.Space - }$(file-text) ${gitUri.getFormattedPath()}${ + description: `to history of ${gitUri.getFormattedPath()}${ args.reference ? ` from ${GlyphChars.Space}${icon}${args.reference.name}` : gitUri.sha @@ -150,7 +148,7 @@ export class OpenFileRevisionCommand extends ActiveEditorCommand { ? new CommandQuickPickItem( { label: '$(sync) Show All Commits', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} this may take a while` + description: 'this may take a while' }, Commands.OpenFileRevision, [uri, commandArgs] @@ -173,7 +171,7 @@ export class OpenFileRevisionCommand extends ActiveEditorCommand { if (pick instanceof CommandQuickPickItem) return pick.execute(); - args.uri = GitUri.toRevisionUri(pick.commit.sha, pick.commit.uri.fsPath, pick.commit.repoPath); + args.uri = GitUri.toRevisionUri(pick.item.sha, pick.item.uri.fsPath, pick.item.repoPath); } if (args.line !== undefined && args.line !== 0) { diff --git a/src/commands/searchCommits.ts b/src/commands/searchCommits.ts index 4eebe91..cdf43cf 100644 --- a/src/commands/searchCommits.ts +++ b/src/commands/searchCommits.ts @@ -6,7 +6,7 @@ import { GitRepoSearchBy, GitService } from '../git/gitService'; import { Logger } from '../logger'; import { Messages } from '../messages'; import { CommandQuickPickItem, CommitsQuickPick, ShowCommitSearchResultsInViewQuickPickItem } from '../quickpicks'; -import { Iterables, Strings } from '../system'; +import { Iterables } from '../system'; import { SearchResultsCommitsNode } from '../views/nodes'; import { ActiveEditorCachedCommand, @@ -183,7 +183,7 @@ export class SearchCommitsCommand extends ActiveEditorCachedCommand { new CommandQuickPickItem( { label: `go back ${GlyphChars.ArrowBack}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} to commit search` + description: 'to commit search' }, Commands.SearchCommits, [uri, originalArgs] @@ -198,7 +198,7 @@ export class SearchCommitsCommand extends ActiveEditorCachedCommand { ? new CommandQuickPickItem( { label: '$(sync) Show All Commits', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} this may take a while` + description: 'this may take a while' }, Commands.SearchCommits, [uri, { ...args, maxCount: 0, goBackCommand: goBackCommand }] @@ -215,7 +215,7 @@ export class SearchCommitsCommand extends ActiveEditorCachedCommand { if (pick instanceof CommandQuickPickItem) return pick.execute(); - commit = pick.commit; + commit = pick.item; goBackCommand = undefined; } else { @@ -230,7 +230,7 @@ export class SearchCommitsCommand extends ActiveEditorCachedCommand { new CommandQuickPickItem( { label: `go back ${GlyphChars.ArrowBack}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 2)} to search for ${searchLabel}` + description: `to search for ${searchLabel}` }, Commands.SearchCommits, [uri, args] diff --git a/src/commands/showQuickBranchHistory.ts b/src/commands/showQuickBranchHistory.ts index b5796b5..20a7970 100644 --- a/src/commands/showQuickBranchHistory.ts +++ b/src/commands/showQuickBranchHistory.ts @@ -6,7 +6,6 @@ import { GitLog, GitUri } from '../git/gitService'; import { Logger } from '../logger'; import { Messages } from '../messages'; import { BranchHistoryQuickPick, CommandQuickPickItem, ReferencesQuickPick } from '../quickpicks'; -import { Strings } from '../system'; import { ActiveEditorCachedCommand, command, Commands, getCommandUri, getRepoPathOrActiveOrPrompt } from './common'; import { ShowQuickCommitDetailsCommandArgs } from './showQuickCommitDetails'; @@ -51,7 +50,7 @@ export class ShowQuickBranchHistoryCommand extends ActiveEditorCachedCommand { goBackCommand = new CommandQuickPickItem( { label: `go back ${GlyphChars.ArrowBack}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} to which repository` + description: 'to which repository' }, Commands.ShowQuickBranchHistory, [uri, args] @@ -103,21 +102,19 @@ export class ShowQuickBranchHistoryCommand extends ActiveEditorCachedCommand { const currentCommand = new CommandQuickPickItem( { label: `go back ${GlyphChars.ArrowBack}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} to ${GlyphChars.Space}$(git-branch) ${ - args.branch - } history` + description: `to history of ${GlyphChars.Space}$(git-branch) ${args.branch}` }, Commands.ShowQuickBranchHistory, [uri, { ...args }] ); const commandArgs: ShowQuickCommitDetailsCommandArgs = { - sha: pick.commit.sha, - commit: pick.commit, + sha: pick.item.sha, + commit: pick.item, repoLog: args.log, goBackCommand: currentCommand }; - return commands.executeCommand(Commands.ShowQuickCommitDetails, pick.commit.toGitUri(), commandArgs); + return commands.executeCommand(Commands.ShowQuickCommitDetails, pick.item.toGitUri(), commandArgs); } catch (ex) { Logger.error(ex, 'ShowQuickBranchHistoryCommand'); diff --git a/src/commands/showQuickCommitDetails.ts b/src/commands/showQuickCommitDetails.ts index 34ba129..3f472bb 100644 --- a/src/commands/showQuickCommitDetails.ts +++ b/src/commands/showQuickCommitDetails.ts @@ -6,7 +6,6 @@ import { GitCommit, GitLog, GitLogCommit, GitRepoSearchBy, GitUri } from '../git import { Logger } from '../logger'; import { Messages } from '../messages'; import { CommandQuickPickItem, CommitQuickPick, CommitWithFileStatusQuickPickItem } from '../quickpicks'; -import { Strings } from '../system'; import { ActiveEditorCachedCommand, command, @@ -136,7 +135,7 @@ export class ShowQuickCommitDetailsCommand extends ActiveEditorCachedCommand { args.goBackCommand = new CommandQuickPickItem( { label: `go back ${GlyphChars.ArrowBack}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} to ${branch.name} history` + description: `to ${branch.name} history` }, Commands.ShowQuickCurrentBranchHistory, [args.commit.toGitUri()] @@ -148,9 +147,7 @@ export class ShowQuickCommitDetailsCommand extends ActiveEditorCachedCommand { const currentCommand = new CommandQuickPickItem( { label: `go back ${GlyphChars.ArrowBack}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} to details of ${ - GlyphChars.Space - }$(git-commit) ${args.commit.shortSha}` + description: `to details of ${GlyphChars.Space}$(git-commit) ${args.commit.shortSha}` }, Commands.ShowQuickCommitDetails, [args.commit.toGitUri(), args] diff --git a/src/commands/showQuickCommitFileDetails.ts b/src/commands/showQuickCommitFileDetails.ts index 4f68ddb..f262039 100644 --- a/src/commands/showQuickCommitFileDetails.ts +++ b/src/commands/showQuickCommitFileDetails.ts @@ -1,5 +1,4 @@ 'use strict'; -import * as paths from 'path'; import { TextEditor, Uri, window } from 'vscode'; import { GlyphChars } from '../constants'; import { Container } from '../container'; @@ -7,7 +6,6 @@ import { GitCommit, GitLog, GitLogCommit, GitService, GitUri } from '../git/gitS import { Logger } from '../logger'; import { Messages } from '../messages'; import { CommandQuickPickItem, CommitFileQuickPick } from '../quickpicks'; -import { Strings } from '../system'; import { ActiveEditorCachedCommand, command, @@ -138,9 +136,7 @@ export class ShowQuickCommitFileDetailsCommand extends ActiveEditorCachedCommand args.goBackCommand = new CommandQuickPickItem( { label: `go back ${GlyphChars.ArrowBack}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} to details of ${ - GlyphChars.Space - }$(git-commit) ${shortSha}` + description: `to details of ${GlyphChars.Space}$(git-commit) ${shortSha}` }, Commands.ShowQuickCommitDetails, [args.commit.toGitUri(), commandArgs] @@ -151,9 +147,7 @@ export class ShowQuickCommitFileDetailsCommand extends ActiveEditorCachedCommand const currentCommand = new CommandQuickPickItem( { label: `go back ${GlyphChars.ArrowBack}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} to details of ${ - GlyphChars.Space - }$(file-text) ${paths.basename(args.commit.fileName)} in ${ + description: `to details of ${args.commit.getFormattedPath()} from ${ GlyphChars.Space }$(git-commit) ${shortSha}` }, diff --git a/src/commands/showQuickFileHistory.ts b/src/commands/showQuickFileHistory.ts index 155e85b..b132394 100644 --- a/src/commands/showQuickFileHistory.ts +++ b/src/commands/showQuickFileHistory.ts @@ -1,5 +1,4 @@ 'use strict'; -import * as paths from 'path'; import { commands, Range, TextEditor, Uri, window } from 'vscode'; import { GlyphChars } from '../constants'; import { Container } from '../container'; @@ -89,7 +88,7 @@ export class ShowQuickFileHistoryCommand extends ActiveEditorCachedCommand { const npc = new CommandQuickPickItem( { label: '$(arrow-right) Show Next Commits', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} shows ${args.log.maxCount} newer commits` + description: `shows ${args.log.maxCount} newer commits` }, Commands.ShowQuickFileHistory, [gitUri, commandArgs] @@ -101,9 +100,7 @@ export class ShowQuickFileHistoryCommand extends ActiveEditorCachedCommand { previousPageCommand = new CommandQuickPickItem( { label: '$(arrow-left) Show Previous Commits', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} shows ${ - args.log.maxCount - } older commits` + description: `shows ${args.log.maxCount} older commits` }, Commands.ShowQuickFileHistory, [new GitUri(uri, last), commandArgs] @@ -116,9 +113,7 @@ export class ShowQuickFileHistoryCommand extends ActiveEditorCachedCommand { const currentCommand = new CommandQuickPickItem( { label: `go back ${GlyphChars.ArrowBack}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} to history of ${ - GlyphChars.Space - }$(file-text) ${paths.basename(gitUri.fsPath)}${ + description: `to history of ${gitUri.getFormattedPath()}${ args.reference ? ` from ${GlyphChars.Space}${icon}${args.reference.name}` : gitUri.sha @@ -141,7 +136,7 @@ export class ShowQuickFileHistoryCommand extends ActiveEditorCachedCommand { ? new CommandQuickPickItem( { label: '$(sync) Show All Commits', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} this may take a while` + description: 'this may take a while' }, Commands.ShowQuickFileHistory, [uri, { ...args, log: undefined, maxCount: 0 }] @@ -174,13 +169,13 @@ export class ShowQuickFileHistoryCommand extends ActiveEditorCachedCommand { if (pick instanceof CommandQuickPickItem) return pick.execute(); const commandArgs: ShowQuickCommitFileDetailsCommandArgs = { - commit: pick.commit, + commit: pick.item, fileLog: args.log, - sha: pick.commit.sha, + sha: pick.item.sha, goBackCommand: currentCommand }; - return commands.executeCommand(Commands.ShowQuickCommitFileDetails, pick.commit.toGitUri(), commandArgs); + return commands.executeCommand(Commands.ShowQuickCommitFileDetails, pick.item.toGitUri(), commandArgs); } catch (ex) { Logger.error(ex, 'ShowQuickFileHistoryCommand'); diff --git a/src/commands/showQuickStashList.ts b/src/commands/showQuickStashList.ts index 37f5e14..447d84b 100644 --- a/src/commands/showQuickStashList.ts +++ b/src/commands/showQuickStashList.ts @@ -5,7 +5,6 @@ import { Container } from '../container'; import { Logger } from '../logger'; import { Messages } from '../messages'; import { CommandQuickPickItem, StashListQuickPick } from '../quickpicks'; -import { Strings } from '../system'; import { ActiveEditorCachedCommand, command, Commands, getCommandUri, getRepoPathOrActiveOrPrompt } from './common'; import { ShowQuickCommitDetailsCommandArgs } from './showQuickCommitDetails'; @@ -44,7 +43,7 @@ export class ShowQuickStashListCommand extends ActiveEditorCachedCommand { const currentCommand = new CommandQuickPickItem( { label: `go back ${GlyphChars.ArrowBack}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} to stashed changes` + description: 'to stashed changes' }, Commands.ShowQuickStashList, [uri, currentCommandArgs] @@ -62,11 +61,11 @@ export class ShowQuickStashListCommand extends ActiveEditorCachedCommand { if (pick instanceof CommandQuickPickItem) return pick.execute(); const commandArgs: ShowQuickCommitDetailsCommandArgs = { - commit: pick.commit, - sha: pick.commit.sha, + commit: pick.item, + sha: pick.item.sha, goBackCommand: currentCommand }; - return commands.executeCommand(Commands.ShowQuickCommitDetails, pick.commit.toGitUri(), commandArgs); + return commands.executeCommand(Commands.ShowQuickCommitDetails, pick.item.toGitUri(), commandArgs); } catch (ex) { Logger.error(ex, 'ShowQuickStashListCommand'); diff --git a/src/commands/stashApply.ts b/src/commands/stashApply.ts index a959cb8..671b105 100644 --- a/src/commands/stashApply.ts +++ b/src/commands/stashApply.ts @@ -6,7 +6,6 @@ import { GitStashCommit } from '../git/gitService'; import { Logger } from '../logger'; import { Messages } from '../messages'; import { CommandQuickPickItem, StashListQuickPick } from '../quickpicks'; -import { Strings } from '../system'; import { command, Command, @@ -69,7 +68,7 @@ export class StashApplyCommand extends Command { const currentCommand = new CommandQuickPickItem( { label: `go back ${GlyphChars.ArrowBack}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} to apply stashed changes` + description: 'to apply stashed changes' }, Commands.StashApply, [args] @@ -88,7 +87,7 @@ export class StashApplyCommand extends Command { } args.goBackCommand = currentCommand; - args.stashItem = pick.commit; + args.stashItem = pick.item; } finally { progressCancellation.cancel(); diff --git a/src/container.ts b/src/container.ts index d7bff6d..00e6914 100644 --- a/src/container.ts +++ b/src/container.ts @@ -260,7 +260,7 @@ export class Container { private static _viewCommands: ViewCommands | undefined; static get viewCommands() { if (this._viewCommands === undefined) { - this._context.subscriptions.push((this._viewCommands = new ViewCommands())); + this._viewCommands = new ViewCommands(); } return this._viewCommands; } diff --git a/src/git/git.ts b/src/git/git.ts index 09c33b5..9a546b6 100644 --- a/src/git/git.ts +++ b/src/git/git.ts @@ -205,7 +205,7 @@ export class Git { static deletedOrMissingSha = '0000000000000000000000000000000000000000-'; static shaLikeRegex = /(^[0-9a-f]{40}([\^@~:]\S*)?$)|(^[0]{40}(:|-)$)/; static shaRegex = /(^[0-9a-f]{40}$)|(^[0]{40}(:|-)$)/; - static shaParentRegex = /^[0-9a-f]{40}\^[0-3]?$/; + static shaParentRegex = /(^[0-9a-f]{40})\^[0-3]?$/; static shaShortenRegex = /^(.*?)([\^@~:].*)?$/; static uncommittedRegex = /^[0]{40}(?:[\^@~:]\S*)?:?$/; static uncommittedSha = '0000000000000000000000000000000000000000'; diff --git a/src/git/gitService.ts b/src/git/gitService.ts index 4846e79..07a9e98 100644 --- a/src/git/gitService.ts +++ b/src/git/gitService.ts @@ -1010,12 +1010,7 @@ export class GitService implements Disposable { } if (options.sort) { - branches!.sort( - (a, b) => - (a.starred ? -1 : 1) - (b.starred ? -1 : 1) || - (b.remote ? -1 : 1) - (a.remote ? -1 : 1) || - a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: 'base' }) - ); + GitBranch.sort(branches!); } if (options.filter !== undefined) { @@ -2102,11 +2097,7 @@ export class GitService implements Disposable { if (remotes === undefined) return []; if (options.sort) { - remotes.sort( - (a, b) => - (a.default ? -1 : 1) - (b.default ? -1 : 1) || - a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: 'base' }) - ); + GitRemote.sort(remotes); } return remotes; @@ -2213,9 +2204,7 @@ export class GitService implements Disposable { const repositories = [...(await this.getRepositories())]; if (repositories.length === 0) return repositories; - return repositories - .filter(r => !r.closed) - .sort((a, b) => (a.starred ? -1 : 1) - (b.starred ? -1 : 1) || a.index - b.index); + return Repository.sort(repositories.filter(r => !r.closed)); } private async getRepositoryTree(): Promise> { @@ -2384,7 +2373,7 @@ export class GitService implements Disposable { } if (options.sort) { - tags!.sort((a, b) => a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: 'base' })); + GitTag.sort(tags!); } if (options.filter !== undefined) { @@ -2630,6 +2619,14 @@ export class GitService implements Disposable { return (await Git.rev_parse(repoPath, ref)) || ref; } + const match = Git.shaParentRegex.exec(ref); + if (match != null) { + const previousUri = await Container.git.getPreviousUri(repoPath, uri, match[1]); + if (previousUri !== undefined && previousUri.sha !== undefined) { + return previousUri.sha; + } + } + const ensuredRef = await Git.cat_file__resolve( repoPath, Strings.normalizePath(paths.relative(repoPath, uri.fsPath)), diff --git a/src/git/models/branch.ts b/src/git/models/branch.ts index af998ee..a53cf2c 100644 --- a/src/git/models/branch.ts +++ b/src/git/models/branch.ts @@ -15,6 +15,16 @@ export class GitBranch { return branch instanceof GitBranch; } + static sort(branches: GitBranch[]) { + return branches.sort( + (a, b) => + (a.current ? -1 : 1) - (b.current ? -1 : 1) || + (a.starred ? -1 : 1) - (b.starred ? -1 : 1) || + (b.remote ? -1 : 1) - (a.remote ? -1 : 1) || + a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: 'base' }) + ); + } + readonly detached: boolean; readonly id: string; readonly tracking?: string; diff --git a/src/git/models/remote.ts b/src/git/models/remote.ts index 36a26ac..28960e7 100644 --- a/src/git/models/remote.ts +++ b/src/git/models/remote.ts @@ -13,6 +13,14 @@ export class GitRemote { return remote instanceof GitRemote; } + static sort(remotes: GitRemote[]) { + return remotes.sort( + (a, b) => + (a.default ? -1 : 1) - (b.default ? -1 : 1) || + a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: 'base' }) + ); + } + constructor( public readonly repoPath: string, public readonly id: string, diff --git a/src/git/models/repository.ts b/src/git/models/repository.ts index 21bebd2..296597d 100644 --- a/src/git/models/repository.ts +++ b/src/git/models/repository.ts @@ -61,6 +61,10 @@ export interface RepositoryFileSystemChangeEvent { } export class Repository implements Disposable { + static sort(repositories: Repository[]) { + return repositories.sort((a, b) => (a.starred ? -1 : 1) - (b.starred ? -1 : 1) || a.index - b.index); + } + private _onDidChange = new EventEmitter(); get onDidChange(): Event { return this._onDidChange.event; diff --git a/src/git/models/tag.ts b/src/git/models/tag.ts index 2b14606..8041cd3 100644 --- a/src/git/models/tag.ts +++ b/src/git/models/tag.ts @@ -6,6 +6,10 @@ export class GitTag { return tag instanceof GitTag; } + static sort(tags: GitTag[]) { + return tags.sort((a, b) => a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: 'base' })); + } + constructor( public readonly repoPath: string, public readonly name: string, diff --git a/src/quickpicks.ts b/src/quickpicks.ts index d5f8700..3cc2469 100644 --- a/src/quickpicks.ts +++ b/src/quickpicks.ts @@ -1,10 +1,12 @@ 'use strict'; +export * from './quickpicks/commonQuickPicks'; +export * from './quickpicks/gitQuickPicks'; + export * from './quickpicks/branchHistoryQuickPick'; export * from './quickpicks/commitFileQuickPick'; export * from './quickpicks/commitQuickPick'; export * from './quickpicks/commitsQuickPick'; -export * from './quickpicks/commonQuickPicks'; export * from './quickpicks/fileHistoryQuickPick'; export * from './quickpicks/modesQuickPick'; export * from './quickpicks/referencesQuickPick'; diff --git a/src/quickpicks/branchHistoryQuickPick.ts b/src/quickpicks/branchHistoryQuickPick.ts index 691a62d..87faabb 100644 --- a/src/quickpicks/branchHistoryQuickPick.ts +++ b/src/quickpicks/branchHistoryQuickPick.ts @@ -5,14 +5,10 @@ import { GlyphChars } from '../constants'; import { Container } from '../container'; import { GitLog, GitUri, RemoteResourceType } from '../git/gitService'; import { KeyNoopCommand } from '../keyboard'; -import { Iterables, Strings } from '../system'; -import { - CommandQuickPickItem, - CommitQuickPickItem, - getQuickPickIgnoreFocusOut, - showQuickPickProgress -} from './commonQuickPicks'; +import { Iterables } from '../system'; +import { CommandQuickPickItem, getQuickPickIgnoreFocusOut, showQuickPickProgress } from './commonQuickPicks'; import { OpenRemotesCommandQuickPickItem } from './remotesQuickPick'; +import { CommitQuickPickItem } from './gitQuickPicks'; export class BranchHistoryQuickPick { static showProgress(branch: string) { @@ -34,7 +30,7 @@ export class BranchHistoryQuickPick { goBackCommand?: CommandQuickPickItem, nextPageCommand?: CommandQuickPickItem ): Promise { - const items = Array.from(Iterables.map(log.commits.values(), c => new CommitQuickPickItem(c))) as ( + const items = Array.from(Iterables.map(log.commits.values(), c => CommitQuickPickItem.create(c))) as ( | CommitQuickPickItem | CommandQuickPickItem)[]; @@ -47,9 +43,7 @@ export class BranchHistoryQuickPick { const currentCommand = new CommandQuickPickItem( { label: `go back ${GlyphChars.ArrowBack}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} to ${ - GlyphChars.Space - }$(git-branch) ${branch} history` + description: `to history of ${GlyphChars.Space}$(git-branch) ${branch}` }, Commands.ShowQuickBranchHistory, [uri, currentCommandArgs] @@ -86,7 +80,7 @@ export class BranchHistoryQuickPick { new CommandQuickPickItem( { label: '$(sync) Show All Commits', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} this may take a while` + description: 'this may take a while' }, Commands.ShowQuickBranchHistory, [GitUri.fromRepoPath(log.repoPath), commandArgs] @@ -107,7 +101,7 @@ export class BranchHistoryQuickPick { const npc = new CommandQuickPickItem( { label: '$(arrow-right) Show Next Commits', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} shows ${log.maxCount} newer commits` + description: `shows ${log.maxCount} newer commits` }, Commands.ShowQuickBranchHistory, [uri, commandArgs] @@ -124,7 +118,7 @@ export class BranchHistoryQuickPick { previousPageCommand = new CommandQuickPickItem( { label: '$(arrow-left) Show Previous Commits', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} shows ${log.maxCount} older commits` + description: `shows ${log.maxCount} older commits` }, Commands.ShowQuickBranchHistory, [new GitUri(uri ? uri : last.uri, last), commandArgs] diff --git a/src/quickpicks/commitFileQuickPick.ts b/src/quickpicks/commitFileQuickPick.ts index 974794f..070f1bf 100644 --- a/src/quickpicks/commitFileQuickPick.ts +++ b/src/quickpicks/commitFileQuickPick.ts @@ -1,5 +1,4 @@ 'use strict'; -import * as paths from 'path'; import { commands, QuickPickItem, TextDocumentShowOptions, TextEditor, Uri, window } from 'vscode'; import { Commands, @@ -27,9 +26,7 @@ export class ApplyCommitFileChangesCommandQuickPickItem extends CommandQuickPick super( item || { label: '$(git-pull-request) Apply Changes', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(file-text) ${paths.basename( - commit.fileName - )} in ${GlyphChars.Space}$(git-commit) ${commit.shortSha}` + description: `${commit.getFormattedPath()} from ${GlyphChars.Space}$(git-commit) ${commit.shortSha}` }, undefined, undefined @@ -57,7 +54,7 @@ export class OpenCommitFileCommandQuickPickItem extends CommandQuickPickItem { super( item || { label: '$(file-symlink-file) Open File', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} ${paths.basename(_commit.fileName)}` + description: `${_commit.getFormattedPath()}` } ); } @@ -87,15 +84,13 @@ export class OpenCommitFileRevisionCommandQuickPickItem extends CommandQuickPick let uri: Uri; if (commit.status === 'D') { uri = GitUri.toRevisionUri(commit.previousFileSha, commit.previousUri.fsPath, commit.repoPath); - description = `${Strings.pad(GlyphChars.Dash, 2, 3)} ${paths.basename(commit.fileName)} in ${ - GlyphChars.Space - }$(git-commit) ${commit.previousShortSha} (deleted in ${GlyphChars.Space}$(git-commit) ${commit.shortSha})`; + description = `${commit.getFormattedPath()} from ${GlyphChars.Space}$(git-commit) ${ + commit.previousShortSha + } (deleted in ${GlyphChars.Space}$(git-commit) ${commit.shortSha})`; } else { uri = GitUri.toRevisionUri(commit.sha, commit.uri.fsPath, commit.repoPath); - description = `${Strings.pad(GlyphChars.Dash, 2, 3)} ${paths.basename(commit.fileName)} in ${ - GlyphChars.Space - }$(git-commit) ${commit.shortSha}`; + description = `${commit.getFormattedPath()} from ${GlyphChars.Space}$(git-commit) ${commit.shortSha}`; } super( @@ -151,13 +146,20 @@ export class CommitFileQuickPick { const commandArgs: DiffWithPreviousCommandArgs = { commit: commit }; + + const previousSha = await Container.git.resolveReference( + commit.repoPath, + commit.previousFileSha, + commit.previousUri + ); + items.push( new CommandQuickPickItem( { label: '$(git-compare) Open Changes', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(git-commit) ${GitService.shortenSha( - commit.previousFileSha - )} ${GlyphChars.Space} $(git-compare) ${GlyphChars.Space} $(git-commit) ${commit.shortSha}` + description: `$(git-commit) ${GitService.shortenSha(previousSha)} ${ + GlyphChars.Space + } $(git-compare) ${GlyphChars.Space} $(git-commit) ${commit.shortSha}` }, Commands.DiffWithPrevious, [commit.uri, commandArgs] @@ -173,12 +175,9 @@ export class CommitFileQuickPick { new CommandQuickPickItem( { label: '$(git-compare) Open Changes with Working File', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(git-commit) ${commit.shortSha} ${ + description: `$(git-commit) ${commit.shortSha} ${GlyphChars.Space} $(git-compare) ${ GlyphChars.Space - } $(git-compare) ${GlyphChars.Space} $(file-text) ${GitUri.relativeTo( - workingUri, - commit.repoPath - )}` + } ${GitUri.getFormattedPath(workingUri, { relativeTo: commit.repoPath })}` }, Commands.DiffWithWorking, [workingUri, commandArgs] @@ -235,7 +234,7 @@ export class CommitFileQuickPick { new CommandQuickPickItem( { label: '$(clippy) Copy Commit ID to Clipboard', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} ${commit.shortSha}` + description: `${commit.shortSha}` }, Commands.CopyShaToClipboard, [uri, copyShaCommandArgs] @@ -250,7 +249,7 @@ export class CommitFileQuickPick { new CommandQuickPickItem( { label: '$(clippy) Copy Commit Message to Clipboard', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} ${commit.getShortMessage()}` + description: `${commit.getShortMessage()}` }, Commands.CopyMessageToClipboard, [uri, copyMessageCommandArgs] @@ -282,7 +281,7 @@ export class CommitFileQuickPick { new CommandQuickPickItem( { label: '$(history) Show File History', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} of ${paths.basename(commit.fileName)}` + description: `of ${commit.getFormattedPath()}` }, Commands.ShowQuickFileHistory, [workingUri, commandArgs] @@ -300,9 +299,7 @@ export class CommitFileQuickPick { label: `$(history) Show ${ GitUri.relativeTo(workingUri || commit.uri, commit.repoPath) ? 'Previous ' : '' }File History`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} of ${paths.basename( - commit.fileName - )} ${Strings.pad(GlyphChars.Dot, 1, 1)} from ${GlyphChars.Space}$(git-commit) ${ + description: `of ${commit.getFormattedPath()} from ${GlyphChars.Space}$(git-commit) ${ commit.shortSha }` }, @@ -320,7 +317,7 @@ export class CommitFileQuickPick { new CommandQuickPickItem( { label: '$(git-commit) Show Commit Details', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(git-commit) ${commit.shortSha}` + description: `$(git-commit) ${commit.shortSha}` }, Commands.ShowQuickCommitDetails, [commit.toGitUri(), commitDetailsCommandArgs] diff --git a/src/quickpicks/commitQuickPick.ts b/src/quickpicks/commitQuickPick.ts index e5cc0a4..84741d8 100644 --- a/src/quickpicks/commitQuickPick.ts +++ b/src/quickpicks/commitQuickPick.ts @@ -109,9 +109,7 @@ export class OpenCommitFileRevisionsCommandQuickPickItem extends CommandQuickPic super( item || { label: '$(file-symlink-file) Open Revisions', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} in ${GlyphChars.Space}$(git-commit) ${ - _commit.shortSha - }` + description: `from ${GlyphChars.Space}$(git-commit) ${_commit.shortSha}` // detail: `Opens all of the changed files in $(git-commit) ${commit.shortSha}` } ); @@ -263,7 +261,7 @@ export class CommitQuickPick { new CommandQuickPickItem( { label: '$(git-pull-request) Apply Stashed Changes', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} ${commit.getShortMessage()}` + description: `${commit.getShortMessage()}` }, Commands.StashApply, [stashApplyCommmandArgs] @@ -281,7 +279,7 @@ export class CommitQuickPick { new CommandQuickPickItem( { label: '$(x) Delete Stashed Changes', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} ${commit.getShortMessage()}` + description: `${commit.getShortMessage()}` }, Commands.StashDelete, [stashDeleteCommmandArgs] @@ -313,8 +311,10 @@ export class CommitQuickPick { items.splice(index++, 0, new OpenCommitFilesCommandQuickPickItem(commit)); items.splice(index++, 0, new OpenCommitFileRevisionsCommandQuickPickItem(commit)); + const previousSha = await Container.git.resolveReference(commit.repoPath, commit.previousFileSha); + let diffDirectoryCommmandArgs: DiffDirectoryCommandArgs = { - ref1: commit.previousFileSha, + ref1: previousSha, ref2: commit.sha }; items.splice( @@ -323,9 +323,9 @@ export class CommitQuickPick { new CommandQuickPickItem( { label: '$(git-compare) Open Directory Compare with Previous Revision', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(git-commit) ${GitService.shortenSha( - commit.previousFileSha - )} ${GlyphChars.Space} $(git-compare) ${GlyphChars.Space} $(git-commit) ${commit.shortSha}` + description: `$(git-commit) ${GitService.shortenSha(previousSha)} ${ + GlyphChars.Space + } $(git-compare) ${GlyphChars.Space} $(git-commit) ${commit.shortSha}` }, Commands.DiffDirectory, [commit.uri, diffDirectoryCommmandArgs] @@ -341,9 +341,7 @@ export class CommitQuickPick { new CommandQuickPickItem( { label: '$(git-compare) Open Directory Compare with Working Tree', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(git-commit) ${commit.shortSha} ${ - GlyphChars.Space - } $(git-compare) ${GlyphChars.Space} $(file-directory) Working Tree` + description: `$(git-commit) ${commit.shortSha} ${GlyphChars.Space} $(git-compare) ${GlyphChars.Space} Working Tree` }, Commands.DiffDirectory, [uri, diffDirectoryCommmandArgs] @@ -360,7 +358,7 @@ export class CommitQuickPick { new CommandQuickPickItem( { label: '$(clippy) Copy Commit ID to Clipboard', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} ${commit.shortSha}` + description: `${commit.shortSha}` }, Commands.CopyShaToClipboard, [uri, copyShaCommandArgs] @@ -378,7 +376,7 @@ export class CommitQuickPick { new CommandQuickPickItem( { label: '$(clippy) Copy Commit Message to Clipboard', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} ${commit.getShortMessage()}` + description: `${commit.getShortMessage()}` }, Commands.CopyMessageToClipboard, [uri, copyMessageCommandArgs] diff --git a/src/quickpicks/commitsQuickPick.ts b/src/quickpicks/commitsQuickPick.ts index 75f1942..8f3d87c 100644 --- a/src/quickpicks/commitsQuickPick.ts +++ b/src/quickpicks/commitsQuickPick.ts @@ -6,11 +6,11 @@ import { KeyNoopCommand } from '../keyboard'; import { Iterables } from '../system'; import { CommandQuickPickItem, - CommitQuickPickItem, getQuickPickIgnoreFocusOut, MessageQuickPickItem, showQuickPickProgress } from './commonQuickPicks'; +import { CommitQuickPickItem } from './gitQuickPicks'; export class CommitsQuickPick { static showProgress(message: string) { @@ -31,7 +31,7 @@ export class CommitsQuickPick { showInViewCommand?: CommandQuickPickItem; } ): Promise { - const items = ((log && [...Iterables.map(log.commits.values(), c => new CommitQuickPickItem(c))]) || [ + const items = ((log && [...Iterables.map(log.commits.values(), c => CommitQuickPickItem.create(c))]) || [ new MessageQuickPickItem('No results found') ]) as (CommitQuickPickItem | CommandQuickPickItem)[]; diff --git a/src/quickpicks/commonQuickPicks.ts b/src/quickpicks/commonQuickPicks.ts index d7d2e4c..ec666af 100644 --- a/src/quickpicks/commonQuickPicks.ts +++ b/src/quickpicks/commonQuickPicks.ts @@ -2,11 +2,9 @@ import { CancellationTokenSource, commands, QuickPickItem, window } from 'vscode'; import { Commands } from '../commands'; import { configuration } from '../configuration'; -import { GlyphChars } from '../constants'; import { Container } from '../container'; -import { GitLog, GitLogCommit, GitRepoSearchBy, GitStashCommit, GitUri } from '../git/gitService'; +import { GitLog, GitLogCommit, GitRepoSearchBy, GitUri } from '../git/gitService'; import { KeyMapping, Keys } from '../keyboard'; -import { Strings } from '../system'; import { ReferencesQuickPick, ReferencesQuickPickItem } from './referencesQuickPick'; export function getQuickPickIgnoreFocusOut() { @@ -91,36 +89,6 @@ export class CommandQuickPickItem implements QuickPickItem { } } -export class CommitQuickPickItem implements QuickPickItem { - label: string; - description: string; - detail: string; - - constructor(public readonly commit: T) { - const message = commit.getShortMessage(); - if (GitStashCommit.is(commit)) { - this.label = message; - this.description = ''; - this.detail = `${GlyphChars.Space} ${commit.stashName || commit.shortSha} ${Strings.pad( - GlyphChars.Dot, - 1, - 1 - )} ${commit.formattedDate} ${Strings.pad(GlyphChars.Dot, 1, 1)} ${commit.getFormattedDiffStatus({ - compact: true - })}`; - } - else { - this.label = message; - this.description = `${Strings.pad('$(git-commit)', 1, 1)} ${commit.shortSha}`; - this.detail = `${GlyphChars.Space} ${commit.author}, ${commit.formattedDate}${ - commit.isFile - ? '' - : ` ${Strings.pad(GlyphChars.Dot, 1, 1)} ${commit.getFormattedDiffStatus({ compact: true })}` - }`; - } - } -} - export class KeyCommandQuickPickItem extends CommandQuickPickItem { constructor(command: Commands, args?: any[]) { super({ label: '', description: '' }, command, args); @@ -137,8 +105,8 @@ export class ShowCommitInViewQuickPickItem extends CommandQuickPickItem { constructor( public readonly commit: GitLogCommit, item: QuickPickItem = { - label: 'Show in View', - description: `${Strings.pad(GlyphChars.Dash, 2, 2)} displays the commit in the GitLens Search Commits view` + label: '$(eye) Show in View', + description: `shows the ${commit.isStash ? 'stashed changes' : 'commit'} in the Search Commits view` } ) { super(item, undefined, undefined); @@ -158,12 +126,8 @@ export class ShowCommitSearchResultsInViewQuickPickItem extends CommandQuickPick public readonly results: GitLog, public readonly resultsLabel: string | { label: string; resultsType?: { singular: string; plural: string } }, item: QuickPickItem = { - label: 'Show in View', - description: `${Strings.pad( - GlyphChars.Dash, - 2, - 2 - )} displays the search results in the GitLens Search Commits view` + label: '$(eye) Show in View', + description: 'shows the search results in the Search Commits view' } ) { super(item, undefined, undefined); @@ -188,8 +152,8 @@ export class ShowFileHistoryFromQuickPickItem extends CommandQuickPickItem { private readonly placeHolder: string, private readonly _goBack?: CommandQuickPickItem, item: QuickPickItem = { - label: 'Show File History from...', - description: `${Strings.pad(GlyphChars.Dash, 2, 2)} shows an alternate file history` + label: '$(history) Show File History from...', + description: 'shows an alternate file history' } ) { super(item, undefined, undefined); @@ -209,12 +173,8 @@ export class ShowFileHistoryInViewQuickPickItem extends CommandQuickPickItem { public readonly uri: GitUri, public readonly baseRef: string | undefined, item: QuickPickItem = { - label: 'Show in View', - description: `${Strings.pad( - GlyphChars.Dash, - 2, - 2 - )} displays the file history in the GitLens File History view` + label: '$(eye) Show in View', + description: 'shows the file history in the File History view' } ) { super(item, undefined, undefined); diff --git a/src/quickpicks/fileHistoryQuickPick.ts b/src/quickpicks/fileHistoryQuickPick.ts index 4f8f8b0..274a1e5 100644 --- a/src/quickpicks/fileHistoryQuickPick.ts +++ b/src/quickpicks/fileHistoryQuickPick.ts @@ -1,20 +1,19 @@ 'use strict'; -import * as paths from 'path'; import { CancellationTokenSource, window } from 'vscode'; import { Commands, ShowQuickCurrentBranchHistoryCommandArgs, ShowQuickFileHistoryCommandArgs } from '../commands'; import { GlyphChars } from '../constants'; import { Container } from '../container'; import { GitLog, GitUri, RemoteResource, RemoteResourceType } from '../git/gitService'; import { KeyNoopCommand } from '../keyboard'; -import { Iterables, Strings } from '../system'; +import { Iterables } from '../system'; import { CommandQuickPickItem, - CommitQuickPickItem, getQuickPickIgnoreFocusOut, ShowFileHistoryFromQuickPickItem, showQuickPickProgress } from './commonQuickPicks'; import { OpenRemotesCommandQuickPickItem } from './remotesQuickPick'; +import { CommitQuickPickItem } from './gitQuickPicks'; export class FileHistoryQuickPick { static showProgress(placeHolder: string) { @@ -42,7 +41,7 @@ export class FileHistoryQuickPick { ): Promise { options = { pickerOnly: false, ...options }; - const items = Array.from(Iterables.map(log.commits.values(), c => new CommitQuickPickItem(c))) as ( + const items = Array.from(Iterables.map(log.commits.values(), c => CommitQuickPickItem.create(c))) as ( | CommitQuickPickItem | CommandQuickPickItem)[]; @@ -75,9 +74,7 @@ export class FileHistoryQuickPick { goBackCommand: new CommandQuickPickItem( { label: `go back ${GlyphChars.ArrowBack}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} to history of ${ - GlyphChars.Space - }$(file-text) ${paths.basename(uri.fsPath)}${ + description: `to history of ${uri.getFormattedPath()}${ uri.sha ? ` from ${GlyphChars.Space}$(git-commit) ${uri.shortSha}` : '' }` }, @@ -93,9 +90,7 @@ export class FileHistoryQuickPick { new CommandQuickPickItem( { label: '$(history) Show File History', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} of ${paths.basename( - workingUri.fsPath - )}` + description: `of ${GitUri.getFormattedPath(workingUri, { relativeTo: log.repoPath })}` }, Commands.ShowQuickFileHistory, [workingUri, commandArgs] @@ -128,9 +123,7 @@ export class FileHistoryQuickPick { const currentCommand = new CommandQuickPickItem( { label: `go back ${GlyphChars.ArrowBack}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} to history of ${ - GlyphChars.Space - }$(file-text) ${paths.basename(uri.fsPath)}${ + description: `to history of ${uri.getFormattedPath()}${ uri.sha ? ` from ${GlyphChars.Space}$(git-commit) ${uri.shortSha}` : '' }` }, @@ -148,10 +141,8 @@ export class FileHistoryQuickPick { 0, new CommandQuickPickItem( { - label: '$(history) Show Branch History', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} shows ${ - GlyphChars.Space - }$(git-branch) ${branch.name} history` + label: `${GlyphChars.SpaceThin}$(git-branch) Show Branch History`, + description: `shows history of ${GlyphChars.Space}$(git-branch) ${branch.name}` }, Commands.ShowQuickCurrentBranchHistory, [undefined, commandArgs] diff --git a/src/quickpicks/gitQuickPicks.ts b/src/quickpicks/gitQuickPicks.ts new file mode 100644 index 0000000..ac1c8b5 --- /dev/null +++ b/src/quickpicks/gitQuickPicks.ts @@ -0,0 +1,306 @@ +'use strict'; +import { QuickPickItem } from 'vscode'; +import { GlyphChars } from '../constants'; +import { Dates, Strings } from '../system'; +import { + GitBranch, + GitLogCommit, + GitReference, + GitRemoteType, + GitService, + GitStashCommit, + GitTag, + Repository +} from '../git/gitService'; +import { emojify } from '../emojis'; + +export interface BranchQuickPickItem extends QuickPickItem { + readonly item: GitBranch; + readonly current: boolean; + readonly ref: string; + readonly remote: boolean; +} + +export namespace BranchQuickPickItem { + export async function create( + branch: GitBranch, + picked?: boolean, + options: { + current?: boolean | 'checkmark'; + checked?: boolean; + ref?: boolean; + status?: boolean; + type?: boolean | 'remote'; + } = {} + ) { + let description = ''; + if (options.type === true) { + if (options.current === true && branch.current) { + description = 'current branch'; + } + else { + description = 'branch'; + } + } + else if (options.type === 'remote') { + if (branch.remote) { + description = 'remote branch'; + } + } + else if (options.current === true && branch.current) { + description = 'current branch'; + } + + if (options.status && !branch.remote && branch.tracking !== undefined) { + let arrows = GlyphChars.Dash; + + const remote = await branch.getRemote(); + if (remote !== undefined) { + let left; + let right; + for (const { type } of remote.types) { + if (type === GitRemoteType.Fetch) { + left = true; + + if (right) break; + } + else if (type === GitRemoteType.Push) { + right = true; + + if (left) break; + } + } + + if (left && right) { + arrows = GlyphChars.ArrowsRightLeft; + } + else if (right) { + arrows = GlyphChars.ArrowRight; + } + else if (left) { + arrows = GlyphChars.ArrowLeft; + } + } + + const status = `${branch.getTrackingStatus({ suffix: `${GlyphChars.Space} ` })}${arrows}${ + GlyphChars.Space + } ${branch.tracking}`; + description = `${description ? `${description}${GlyphChars.Space.repeat(2)}${status}` : status}`; + } + + if (options.ref && branch.sha) { + description = description + ? `${description}${Strings.pad('$(git-commit)', 2, 2)}${GitService.shortenSha(branch.sha)}` + : `${Strings.pad('$(git-commit)', 0, 2)}${GitService.shortenSha(branch.sha)}`; + } + + const checked = + options.checked || (options.checked === undefined && options.current === 'checkmark' && branch.current); + const item: BranchQuickPickItem = { + label: `${GlyphChars.SpaceThin}${Strings.pad('$(git-branch)', 0, 2)}${GlyphChars.SpaceThinnest}${ + branch.name + }${checked ? `${GlyphChars.Space.repeat(2)}$(check)${GlyphChars.Space}` : ''}`, + description: description, + picked: picked === undefined ? branch.current : picked, + item: branch, + current: branch.current, + ref: branch.name, + remote: branch.remote + }; + + return item; + } +} + +export interface CommitQuickPickItem extends QuickPickItem { + readonly item: T; +} + +export namespace CommitQuickPickItem { + export function create( + commit: T, + picked?: boolean, + options: { compact?: boolean } = {} + ) { + if (GitStashCommit.is(commit)) { + const item: CommitQuickPickItem = { + label: commit.getShortMessage(), + description: '', + detail: `${GlyphChars.Space.repeat(2)}${commit.stashName || commit.shortSha}${Strings.pad( + GlyphChars.Dot, + 2, + 2 + )}${commit.formattedDate}${Strings.pad(GlyphChars.Dot, 2, 2)}${commit.getFormattedDiffStatus({ + compact: true + })}`, + picked: picked, + item: commit + }; + + return item; + } + + if (options.compact) { + const item: CommitQuickPickItem = { + label: commit.getShortMessage(), + description: `${commit.author}, ${commit.formattedDate}${Strings.pad('$(git-commit)', 2, 2)}${ + commit.shortSha + }${Strings.pad(GlyphChars.Dot, 2, 2)}${commit.getFormattedDiffStatus({ compact: true })}`, + picked: picked, + item: commit + }; + return item; + } + + const item: CommitQuickPickItem = { + label: commit.getShortMessage(), + description: '', + detail: `${GlyphChars.Space.repeat(2)}${commit.author}, ${commit.formattedDate}${Strings.pad( + '$(git-commit)', + 2, + 2 + )}${commit.shortSha}${Strings.pad(GlyphChars.Dot, 2, 2)}${commit.getFormattedDiffStatus({ + compact: true + })}`, + picked: picked, + item: commit + }; + return item; + } +} + +export namespace RefQuickPickItem { + export function create(ref: string, picked?: boolean, options: { checked?: boolean } = {}) { + const item: RefQuickPickItem = { + label: `${ + options.checked ? `$(check)${GlyphChars.Space}` : GlyphChars.Space.repeat(4) + } ${GitService.shortenSha(ref)}`, + picked: picked, + item: { name: ref, ref: ref }, + current: false, + ref: ref, + remote: false + }; + + return item; + } +} + +export interface RefQuickPickItem extends QuickPickItem { + readonly item: GitReference; + readonly current: boolean; + readonly ref: string; + readonly remote: boolean; +} + +export interface RepositoryQuickPickItem extends QuickPickItem { + readonly item: Repository; + readonly repoPath: string; +} + +export namespace RepositoryQuickPickItem { + export async function create( + repository: Repository, + picked?: boolean, + options: { branch?: boolean; fetched?: boolean; status?: boolean } = {} + ) { + let repoStatus; + if (options.branch || options.status) { + repoStatus = await repository.getStatus(); + } + + let description = ''; + if (options.branch && repoStatus) { + description = repoStatus.branch; + } + + if (options.status && repoStatus) { + let workingStatus = ''; + if (repoStatus.files.length !== 0) { + workingStatus = repoStatus.getFormattedDiffStatus({ + compact: true, + prefix: Strings.pad(GlyphChars.Dot, 2, 2) + }); + } + + const upstreamStatus = repoStatus.getUpstreamStatus({ + prefix: description ? `${GlyphChars.Space} ` : '' + }); + + const status = `${upstreamStatus}${workingStatus}`; + if (status) { + description = `${description ? `${description}${status}` : status}`; + } + } + + if (options.fetched) { + const lastFetched = await repository.getLastFetched(); + if (lastFetched !== 0) { + const fetched = `Last fetched ${Dates.getFormatter(new Date(lastFetched)).fromNow()}`; + description = `${ + description ? `${description}${Strings.pad(GlyphChars.Dot, 2, 2)}${fetched}` : fetched + }`; + } + } + + const item: RepositoryQuickPickItem = { + label: repository.formattedName, + description: description, + picked: picked, + item: repository, + repoPath: repository.path + }; + + return item; + } +} + +export interface TagQuickPickItem extends QuickPickItem { + readonly item: GitTag; + readonly current: boolean; + readonly ref: string; + readonly remote: boolean; +} + +export namespace TagQuickPickItem { + export function create( + tag: GitTag, + picked?: boolean, + options: { + annotation?: boolean; + checked?: boolean; + ref?: boolean; + type?: boolean; + } = {} + ) { + let description = ''; + if (options.type) { + description = 'tag'; + } + + if (options.ref && tag.sha) { + description = description + ? `${description}${Strings.pad('$(git-commit)', 2, 2)}${GitService.shortenSha(tag.sha)}` + : `${Strings.pad('$(git-commit)', 0, 2)}${GitService.shortenSha(tag.sha)}`; + } + + if (options.annotation && tag.annotation) { + const annotation = emojify(tag.annotation); + description = description ? `${description}${Strings.pad(GlyphChars.Dot, 2, 2)}${annotation}` : annotation; + } + + const item: TagQuickPickItem = { + label: `${Strings.pad('$(tag)', 0, 2)}${tag.name}${ + options.checked ? `${GlyphChars.Space.repeat(2)}$(check)${GlyphChars.Space}` : '' + }`, + description: description, + picked: picked, + item: tag, + current: false, + ref: tag.name, + remote: false + }; + + return item; + } +} diff --git a/src/quickpicks/referencesQuickPick.ts b/src/quickpicks/referencesQuickPick.ts index d01fee0..3f1145a 100644 --- a/src/quickpicks/referencesQuickPick.ts +++ b/src/quickpicks/referencesQuickPick.ts @@ -2,99 +2,10 @@ import { CancellationToken, CancellationTokenSource, QuickPickItem, window } from 'vscode'; import { GlyphChars } from '../constants'; import { Container } from '../container'; -import { GitBranch, GitReference, GitService, GitTag } from '../git/gitService'; +import { GitBranch, GitTag } from '../git/gitService'; import { Functions } from '../system'; import { CommandQuickPickItem, getQuickPickIgnoreFocusOut } from './commonQuickPicks'; - -export class RefQuickPickItem implements QuickPickItem { - label: string; - description: string; - detail: string | undefined; - - constructor(public readonly ref: string, checked?: boolean) { - this.label = `${checked ? `$(check)${GlyphChars.Space}` : GlyphChars.Space.repeat(4)} ${GitService.shortenSha( - ref - )}`; - this.description = ''; - } - - get current() { - return false; - } - - get item() { - const ref: GitReference = { name: this.ref, ref: this.ref }; - return ref; - } - - get remote() { - return false; - } -} - -export class BranchQuickPickItem implements QuickPickItem { - label: string; - description: string; - detail: string | undefined; - - constructor(public readonly branch: GitBranch, showCheckmarks: boolean, checked?: boolean) { - checked = showCheckmarks && (checked || (checked === undefined && branch.current)); - this.label = `${ - checked ? `$(check)${GlyphChars.Space.repeat(2)}` : showCheckmarks ? GlyphChars.Space.repeat(6) : '' - }${branch.name}`; - this.description = branch.remote - ? `${GlyphChars.Space.repeat(2)} remote branch` - : branch.current - ? 'current branch' - : ''; - } - - get current() { - return this.branch.current; - } - - get item() { - return this.branch; - } - - get ref() { - return this.branch.name; - } - - get remote() { - return this.branch.remote; - } -} - -export class TagQuickPickItem implements QuickPickItem { - label: string; - description: string; - detail: string | undefined; - - constructor(public readonly tag: GitTag, showCheckmarks: boolean, checked?: boolean) { - checked = showCheckmarks && checked; - this.label = `${ - checked ? `$(check)${GlyphChars.Space.repeat(2)}` : showCheckmarks ? GlyphChars.Space.repeat(6) : '' - }${tag.name}`; - this.description = `${GlyphChars.Space.repeat(2)} tag`; - } - - get current() { - return false; - } - - get item() { - return this.tag; - } - - get ref() { - return this.tag.name; - } - - get remote() { - return false; - } -} +import { BranchQuickPickItem, RefQuickPickItem, TagQuickPickItem } from './gitQuickPicks'; export type ReferencesQuickPickItem = BranchQuickPickItem | TagQuickPickItem | RefQuickPickItem; @@ -165,7 +76,7 @@ export class ReferencesQuickPick { this.repoPath === undefined || (await Container.git.validateReference(this.repoPath, ref)) ) { - resolve(new RefQuickPickItem(ref)); + resolve(RefQuickPickItem.create(ref)); } else { quickpick.title = 'You must enter a valid reference'; @@ -215,43 +126,83 @@ export class ReferencesQuickPick { } private async getItems( - { checked, checkmarks, goBack, ...options }: ReferencesQuickPickOptions, + { checked, checkmarks, filterBranches, filterTags, goBack, include, ...options }: ReferencesQuickPickOptions, token: CancellationToken - ) { - const branchesAndOrTags = await Functions.cancellable( - Container.git.getBranchesAndOrTags(this.repoPath, { - include: options.include || 'all', - filterBranches: options.filterBranches, - filterTags: options.filterTags, - sort: true - }), + ): Promise<(BranchQuickPickItem | TagQuickPickItem | CommandQuickPickItem)[]> { + include = include || 'all'; + + const results = await Functions.cancellable( + Promise.all([ + include === 'all' || include === 'branches' + ? Container.git.getBranches(this.repoPath, { + ...options, + filter: filterBranches && filterBranches + }) + : undefined, + include === 'all' || include === 'tags' + ? Container.git.getTags(this.repoPath, { + ...options, + filter: filterTags && filterTags, + includeRefs: true + }) + : undefined + ]), token ); - if (branchesAndOrTags === undefined || token.isCancellationRequested) return []; - - const items: (BranchQuickPickItem | TagQuickPickItem | CommandQuickPickItem)[] = []; - - for (const bt of branchesAndOrTags) { - if (checkmarks && checked === bt.name) { - items.splice( - 0, - 0, - new (GitBranch.is(bt) ? BranchQuickPickItem : TagQuickPickItem)(bt as any, checkmarks, true) - ); - } - else { - items.push( - new (GitBranch.is(bt) ? BranchQuickPickItem : TagQuickPickItem)( - bt as any, - checkmarks, - checked === undefined ? undefined : false + if (results === undefined || token.isCancellationRequested) return []; + + const [branches, tags] = results; + + let items: (BranchQuickPickItem | TagQuickPickItem)[]; + if (branches !== undefined && tags !== undefined) { + items = await Promise.all([ + ...branches + .filter(b => !b.remote) + .map(b => + BranchQuickPickItem.create(b, checkmarks, { + current: true, + checked: b.name === checked, + ref: true, + status: true + }) + ), + ...tags.map(t => + TagQuickPickItem.create(t, checkmarks, { checked: t.name === checked, ref: true, type: true }) + ), + ...branches + .filter(b => b.remote) + .map(b => + BranchQuickPickItem.create(b, checkmarks, { checked: b.name === checked, type: 'remote' }) ) - ); + ]); + } + else if (branches !== undefined) { + items = await Promise.all( + branches.map(b => + BranchQuickPickItem.create(b, checkmarks, { + current: true, + checked: b.name === checked, + ref: true, + status: true, + type: 'remote' + }) + ) + ); + } + else { + items = tags!.map(t => TagQuickPickItem.create(t, checkmarks, { checked: t.name === checked, ref: true })); + } + + // Move the checked item to the top + if (checked) { + const index = items.findIndex(i => i.ref === checked); + if (index !== -1) { + items.splice(0, 0, ...items.splice(index, 1)); } } if (goBack !== undefined) { - items.splice(0, 0, goBack); + (items as QuickPickItem[]).splice(0, 0, goBack); } return items; diff --git a/src/quickpicks/remotesQuickPick.ts b/src/quickpicks/remotesQuickPick.ts index 61a5475..67ef2d6 100644 --- a/src/quickpicks/remotesQuickPick.ts +++ b/src/quickpicks/remotesQuickPick.ts @@ -1,5 +1,4 @@ 'use strict'; -import * as paths from 'path'; import { window } from 'vscode'; import { Commands, OpenInRemoteCommandArgs } from '../commands'; import { GlyphChars } from '../constants'; @@ -7,10 +6,10 @@ import { getNameFromRemoteResource, GitRemote, GitService, + GitUri, RemoteResource, RemoteResourceType } from '../git/gitService'; -import { Strings } from '../system'; import { CommandQuickPickItem, getQuickPickIgnoreFocusOut } from './commonQuickPicks'; export class OpenRemoteCommandQuickPickItem extends CommandQuickPickItem { @@ -25,7 +24,7 @@ export class OpenRemoteCommandQuickPickItem extends CommandQuickPickItem { remote.provider!.name }` : `$(link-external) Open ${getNameFromRemoteResource(resource)} on ${remote.provider!.name}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(repo) ${remote.provider!.path}` + description: `$(repo) ${remote.provider!.path}` }, undefined, undefined @@ -61,7 +60,7 @@ export class OpenRemotesCommandQuickPickItem extends CommandQuickPickItem { break; case RemoteResourceType.File: - description = `$(file-text) ${paths.basename(resource.fileName)}`; + description = GitUri.getFormattedPath(resource.fileName); break; case RemoteResourceType.Repo: @@ -72,7 +71,7 @@ export class OpenRemotesCommandQuickPickItem extends CommandQuickPickItem { if (resource.commit !== undefined && resource.commit.isFile) { if (resource.commit.status === 'D') { resource.sha = resource.commit.previousSha; - description = `$(file-text) ${paths.basename(resource.fileName)} in ${ + description = `${GitUri.getFormattedPath(resource.fileName)} from ${ GlyphChars.Space }$(git-commit) ${resource.commit.previousShortSha} (deleted in ${ GlyphChars.Space @@ -80,15 +79,15 @@ export class OpenRemotesCommandQuickPickItem extends CommandQuickPickItem { } else { resource.sha = resource.commit.sha; - description = `$(file-text) ${paths.basename(resource.fileName)} in ${ + description = `${GitUri.getFormattedPath(resource.fileName)} from ${ GlyphChars.Space }$(git-commit) ${resource.commit.shortSha}`; } } else { const shortFileSha = resource.sha === undefined ? '' : GitService.shortenSha(resource.sha); - description = `$(file-text) ${paths.basename(resource.fileName)}${ - shortFileSha ? ` in ${GlyphChars.Space}$(git-commit) ${shortFileSha}` : '' + description = `${GitUri.getFormattedPath(resource.fileName)}${ + shortFileSha ? ` from ${GlyphChars.Space}$(git-commit) ${shortFileSha}` : '' }`; } break; @@ -115,11 +114,7 @@ export class OpenRemotesCommandQuickPickItem extends CommandQuickPickItem { super( { label: `$(link-external) Open ${name} on ${remote.provider!.name}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(repo) ${remote.provider!.path} ${Strings.pad( - GlyphChars.Dot, - 1, - 1 - )} ${description}` + description: `${description} in ${GlyphChars.Space}$(repo) ${remote.provider!.path}` }, Commands.OpenInRemote, [undefined, commandArgs] @@ -142,7 +137,7 @@ export class OpenRemotesCommandQuickPickItem extends CommandQuickPickItem { super( { label: `$(link-external) Open ${name} on ${provider}${GlyphChars.Ellipsis}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} ${description}` + description: `${description}` }, Commands.OpenInRemote, [undefined, commandArgs] diff --git a/src/quickpicks/repoStatusQuickPick.ts b/src/quickpicks/repoStatusQuickPick.ts index 10feeac..2541253 100644 --- a/src/quickpicks/repoStatusQuickPick.ts +++ b/src/quickpicks/repoStatusQuickPick.ts @@ -234,9 +234,7 @@ export class RepoStatusQuickPick { const currentCommand = new CommandQuickPickItem( { label: `go back ${GlyphChars.ArrowBack}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} to ${GlyphChars.Space}$(git-branch) ${ - status.branch - } status` + description: `to status of ${GlyphChars.Space}$(git-branch) ${status.branch}` }, Commands.ShowQuickRepoStatus, [undefined, repoStatusCommandArgs] @@ -343,7 +341,7 @@ export class RepoStatusQuickPick { new CommandQuickPickItem( { label: '$(inbox) Show Stashed Changes', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} shows stashed changes in the repository` + description: 'shows stashed changes in the repository' }, Commands.ShowQuickStashList, [GitUri.fromRepoPath(status.repoPath), stashListCommandArgs] @@ -364,9 +362,7 @@ export class RepoStatusQuickPick { label: `$(cloud-upload)${GlyphChars.Space} ${status.state.ahead} Commit${ status.state.ahead > 1 ? 's' : '' } ahead of ${GlyphChars.Space}$(git-branch) ${status.upstream}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} shows commits in ${ - GlyphChars.Space - }$(git-branch) ${status.branch} but not ${GlyphChars.Space}$(git-branch) ${status.upstream}` + description: `shows commits in ${GlyphChars.Space}$(git-branch) ${status.branch} but not ${GlyphChars.Space}$(git-branch) ${status.upstream}` }, Commands.ShowQuickBranchHistory, [ @@ -391,9 +387,9 @@ export class RepoStatusQuickPick { label: `$(cloud-download)${GlyphChars.Space} ${status.state.behind} Commit${ status.state.behind > 1 ? 's' : '' } behind ${GlyphChars.Space}$(git-branch) ${status.upstream}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} shows commits in ${ + description: `shows commits in ${GlyphChars.Space}$(git-branch) ${status.upstream} but not ${ GlyphChars.Space - }$(git-branch) ${status.upstream} but not ${GlyphChars.Space}$(git-branch) ${status.branch}${ + }$(git-branch) ${status.branch}${ status.sha ? ` (since ${GlyphChars.Space}$(git-commit) ${GitService.shortenSha(status.sha)})` : '' diff --git a/src/quickpicks/repositoriesQuickPick.ts b/src/quickpicks/repositoriesQuickPick.ts index 8223d77..9d392ab 100644 --- a/src/quickpicks/repositoriesQuickPick.ts +++ b/src/quickpicks/repositoriesQuickPick.ts @@ -1,33 +1,20 @@ 'use strict'; -import { QuickPickItem, window } from 'vscode'; +import { window } from 'vscode'; import { Container } from '../container'; -import { Repository } from '../git/gitService'; import { Iterables } from '../system'; import { CommandQuickPickItem, getQuickPickIgnoreFocusOut } from './commonQuickPicks'; - -export class RepositoryQuickPickItem implements QuickPickItem { - label: string; - description: string; - detail: string | undefined; - - constructor(public readonly repository: Repository) { - this.label = repository.name; - this.description = repository.path; - } - - get repoPath(): string { - return this.repository.path; - } -} +import { RepositoryQuickPickItem } from './gitQuickPicks'; export class RepositoriesQuickPick { static async show( placeHolder: string, goBackCommand?: CommandQuickPickItem ): Promise { - const items = [ - ...Iterables.map(await Container.git.getOrderedRepositories(), r => new RepositoryQuickPickItem(r)) - ] as (RepositoryQuickPickItem | CommandQuickPickItem)[]; + const items: (RepositoryQuickPickItem | CommandQuickPickItem)[] = await Promise.all([ + ...Iterables.map(await Container.git.getOrderedRepositories(), r => + RepositoryQuickPickItem.create(r, undefined, { branch: true, status: true }) + ) + ]); if (goBackCommand !== undefined) { items.splice(0, 0, goBackCommand); diff --git a/src/quickpicks/stashListQuickPick.ts b/src/quickpicks/stashListQuickPick.ts index 7b0a3fc..9e1b434 100644 --- a/src/quickpicks/stashListQuickPick.ts +++ b/src/quickpicks/stashListQuickPick.ts @@ -5,13 +5,9 @@ import { GlyphChars } from '../constants'; import { Container } from '../container'; import { GitStash, GitStashCommit } from '../git/gitService'; import { KeyNoopCommand } from '../keyboard'; -import { Iterables, Strings } from '../system'; -import { - CommandQuickPickItem, - CommitQuickPickItem, - getQuickPickIgnoreFocusOut, - showQuickPickProgress -} from './commonQuickPicks'; +import { Iterables } from '../system'; +import { CommandQuickPickItem, getQuickPickIgnoreFocusOut, showQuickPickProgress } from './commonQuickPicks'; +import { CommitQuickPickItem } from './gitQuickPicks'; export class StashListQuickPick { static showProgress(mode: 'list' | 'apply') { @@ -34,7 +30,7 @@ export class StashListQuickPick { currentCommand?: CommandQuickPickItem ): Promise | CommandQuickPickItem | undefined> { const items = ((stash && - Array.from(Iterables.map(stash.commits.values(), c => new CommitQuickPickItem(c)))) || + Array.from(Iterables.map(stash.commits.values(), c => CommitQuickPickItem.create(c)))) || []) as (CommitQuickPickItem | CommandQuickPickItem)[]; if (mode === 'list') { @@ -47,7 +43,7 @@ export class StashListQuickPick { new CommandQuickPickItem( { label: '$(plus) Stash Changes', - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} stashes all changes` + description: 'stashes all changes' }, Commands.StashSave, [commandArgs] diff --git a/src/terminal.ts b/src/terminal.ts new file mode 100644 index 0000000..c6893d8 --- /dev/null +++ b/src/terminal.ts @@ -0,0 +1,42 @@ +'use strict'; +import { Disposable, Terminal, window } from 'vscode'; +import { extensionTerminalName } from './constants'; +import { Container } from './container'; + +let _terminal: Terminal | undefined; +let _terminalCwd: string | undefined; +let _disposable: Disposable | undefined; + +function ensureTerminal(cwd: string): Terminal { + if (_terminal === undefined) { + _terminal = window.createTerminal(extensionTerminalName); + _disposable = window.onDidCloseTerminal((e: Terminal) => { + if (e.name === extensionTerminalName) { + _terminal = undefined; + _disposable!.dispose(); + _disposable = undefined; + } + }); + + Container.context.subscriptions.push(_disposable); + _terminalCwd = undefined; + } + + if (_terminalCwd !== cwd) { + _terminal.sendText(`cd "${cwd}"`, true); + _terminalCwd = cwd; + } + + return _terminal; +} + +export function runGitCommandInTerminal(command: string, args: string, cwd: string) { + // let git = GitService.getGitPath(); + // if (git.includes(' ')) { + // git = `"${git}"`; + // } + + const terminal = ensureTerminal(cwd); + terminal.show(false); + terminal.sendText(`git ${command} ${args}`, false); +} diff --git a/src/views/nodes.ts b/src/views/nodes.ts index 3c3a941..b246bc4 100644 --- a/src/views/nodes.ts +++ b/src/views/nodes.ts @@ -1,5 +1,7 @@ 'use strict'; +export * from './nodes/common'; + export * from './nodes/viewNode'; export * from './nodes/branchesNode'; export * from './nodes/branchNode'; diff --git a/src/views/viewCommands.ts b/src/views/viewCommands.ts index 1c5ecd1..bc37585 100644 --- a/src/views/viewCommands.ts +++ b/src/views/viewCommands.ts @@ -1,6 +1,6 @@ 'use strict'; import * as paths from 'path'; -import { commands, Disposable, env, Terminal, TextDocumentShowOptions, Uri, window } from 'vscode'; +import { commands, env, TextDocumentShowOptions, Uri, window } from 'vscode'; import { Commands, DiffWithCommandArgs, @@ -13,7 +13,7 @@ import { OpenWorkingFileCommandArgs, openWorkspace } from '../commands'; -import { BuiltInCommands, CommandContext, extensionTerminalName, setCommandContext } from '../constants'; +import { BuiltInCommands, CommandContext, setCommandContext } from '../constants'; import { Container } from '../container'; import { toGitLensFSUri } from '../git/fsProvider'; import { GitService, GitUri } from '../git/gitService'; @@ -23,12 +23,14 @@ import { BranchTrackingStatusNode, CommitFileNode, CommitNode, + CompareBranchNode, CompareResultsNode, ContributorNode, FileHistoryNode, FolderNode, LineHistoryNode, nodeSupportsPaging, + PagerNode, RemoteNode, RepositoryNode, ResultsFileNode, @@ -42,8 +44,7 @@ import { viewSupportsNodeDismissal } from './nodes'; import { Strings } from '../system/string'; -import { PagerNode } from './nodes/common'; -import { CompareBranchNode } from './nodes/compareBranchNode'; +import { runGitCommandInTerminal } from '../terminal'; interface CompareSelectedInfo { ref: string; @@ -51,11 +52,7 @@ interface CompareSelectedInfo { uri?: Uri; } -export class ViewCommands implements Disposable { - private _disposable: Disposable | undefined; - private _terminal: Terminal | undefined; - private _terminalCwd: string | undefined; - +export class ViewCommands { constructor() { commands.registerCommand( 'gitlens.views.refreshNode', @@ -160,10 +157,6 @@ export class ViewCommands implements Disposable { commands.registerCommand('gitlens.views.terminalDeleteTag', this.terminalDeleteTag, this); } - dispose() { - this._disposable && this._disposable.dispose(); - } - private async contributorAddCoauthoredBy(node: ContributorNode) { if (!(node instanceof ContributorNode)) return; @@ -616,7 +609,7 @@ export class ViewCommands implements Disposable { terminalCheckoutBranch(node: BranchNode) { if (!(node instanceof BranchNode)) return; - this.sendTerminalCommand('checkout', `${node.ref}`, node.repoPath); + runGitCommandInTerminal('checkout', `${node.ref}`, node.repoPath); } async terminalCreateBranch(node: ViewRefNode) { @@ -636,59 +629,59 @@ export class ViewCommands implements Disposable { }); if (name === undefined || name.length === 0) return; - this.sendTerminalCommand('branch', `${remoteBranch ? '-t ' : ''}${name} ${node.ref}`, node.repoPath); + runGitCommandInTerminal('branch', `${remoteBranch ? '-t ' : ''}${name} ${node.ref}`, node.repoPath); } terminalDeleteBranch(node: BranchNode) { if (!(node instanceof BranchNode)) return; if (node.branch.remote) { - this.sendTerminalCommand('push', `${node.branch.getRemoteName()} :${node.branch.getName()}`, node.repoPath); + runGitCommandInTerminal('push', `${node.branch.getRemoteName()} :${node.branch.getName()}`, node.repoPath); } else { - this.sendTerminalCommand('branch', `-d ${node.ref}`, node.repoPath); + runGitCommandInTerminal('branch', `-d ${node.ref}`, node.repoPath); } } terminalMergeBranch(node: BranchNode) { if (!(node instanceof BranchNode)) return; - this.sendTerminalCommand('merge', `${node.ref}`, node.repoPath); + runGitCommandInTerminal('merge', `${node.ref}`, node.repoPath); } terminalRebaseBranch(node: BranchNode) { if (!(node instanceof BranchNode)) return; - this.sendTerminalCommand('rebase', `-i ${node.ref}`, node.repoPath); + runGitCommandInTerminal('rebase', `-i ${node.ref}`, node.repoPath); } terminalRebaseBranchToRemote(node: BranchNode | BranchTrackingStatusNode) { if (node instanceof BranchNode) { if (!node.branch.current || !node.branch.tracking) return; - this.sendTerminalCommand('rebase', `-i ${node.branch.tracking}`, node.repoPath); + runGitCommandInTerminal('rebase', `-i ${node.branch.tracking}`, node.repoPath); } else if (node instanceof BranchTrackingStatusNode) { - this.sendTerminalCommand('rebase', `-i ${node.status.upstream}`, node.status.repoPath); + runGitCommandInTerminal('rebase', `-i ${node.status.upstream}`, node.status.repoPath); } } terminalSquashBranchIntoCommit(node: BranchNode) { if (!(node instanceof BranchNode)) return; - this.sendTerminalCommand('merge', `--squash ${node.ref}`, node.repoPath); + runGitCommandInTerminal('merge', `--squash ${node.ref}`, node.repoPath); } terminalCheckoutCommit(node: CommitNode) { if (!(node instanceof CommitNode)) return; - this.sendTerminalCommand('checkout', `${node.ref}`, node.repoPath); + runGitCommandInTerminal('checkout', `${node.ref}`, node.repoPath); } terminalCherryPickCommit(node: CommitNode) { if (!(node instanceof CommitNode)) return; - this.sendTerminalCommand('cherry-pick', `-e ${node.ref}`, node.repoPath); + runGitCommandInTerminal('cherry-pick', `-e ${node.ref}`, node.repoPath); } async terminalPushCommit(node: CommitNode) { @@ -697,31 +690,31 @@ export class ViewCommands implements Disposable { const branch = node.branch || (await Container.git.getBranch(node.repoPath)); if (branch === undefined) return; - this.sendTerminalCommand('push', `${branch.getRemoteName()} ${node.ref}:${branch.getName()}`, node.repoPath); + runGitCommandInTerminal('push', `${branch.getRemoteName()} ${node.ref}:${branch.getName()}`, node.repoPath); } terminalRebaseCommit(node: CommitNode) { if (!(node instanceof CommitNode)) return; - this.sendTerminalCommand('rebase', `-i ${node.ref}^`, node.repoPath); + runGitCommandInTerminal('rebase', `-i ${node.ref}^`, node.repoPath); } terminalResetCommit(node: CommitNode) { if (!(node instanceof CommitNode)) return; - this.sendTerminalCommand('reset', `--soft ${node.ref}`, node.repoPath); + runGitCommandInTerminal('reset', `--soft ${node.ref}`, node.repoPath); } terminalRevertCommit(node: CommitNode) { if (!(node instanceof CommitNode)) return; - this.sendTerminalCommand('revert', `-e ${node.ref}`, node.repoPath); + runGitCommandInTerminal('revert', `-e ${node.ref}`, node.repoPath); } terminalRemoveRemote(node: RemoteNode) { if (!(node instanceof RemoteNode)) return; - this.sendTerminalCommand('remote', `remove ${node.remote.name}`, node.remote.repoPath); + runGitCommandInTerminal('remote', `remove ${node.remote.name}`, node.remote.repoPath); } async terminalCreateTag(node: ViewRefNode) { @@ -741,46 +734,12 @@ export class ViewCommands implements Disposable { if (message === undefined) return; const args = `${message.length !== 0 ? `-a -m "${message}" ` : ''}${name} ${node.ref}`; - this.sendTerminalCommand('tag', args, node.repoPath); + runGitCommandInTerminal('tag', args, node.repoPath); } terminalDeleteTag(node: TagNode) { if (!(node instanceof TagNode)) return; - this.sendTerminalCommand('tag', `-d ${node.ref}`, node.repoPath); - } - - private ensureTerminal(cwd: string): Terminal { - if (this._terminal === undefined) { - this._terminal = window.createTerminal(extensionTerminalName); - this._disposable = window.onDidCloseTerminal((e: Terminal) => { - if (e.name === extensionTerminalName) { - this._terminal = undefined; - this._disposable!.dispose(); - this._disposable = undefined; - } - }, this); - - Container.context.subscriptions.push(this._disposable); - this._terminalCwd = undefined; - } - - if (this._terminalCwd !== cwd) { - this._terminal.sendText(`cd "${cwd}"`, true); - this._terminalCwd = cwd; - } - - return this._terminal; - } - - private sendTerminalCommand(command: string, args: string, cwd: string) { - // let git = GitService.getGitPath(); - // if (git.includes(' ')) { - // git = `"${git}"`; - // } - - const terminal = this.ensureTerminal(cwd); - terminal.show(false); - terminal.sendText(`git ${command} ${args}`, false); + runGitCommandInTerminal('tag', `-d ${node.ref}`, node.repoPath); } }