diff --git a/CHANGELOG.md b/CHANGELOG.md index a5f507b..72e596b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Added +- Adds `Open All Changes (with difftool)` command (`gitlens.externalDiffAll`) - opens all working changes with the configured git difftool -- closes [#164](https://github.com/eamodio/vscode-gitlens/issues/164) + - Also adds the command to the Source Control group context menu + +### Changed +- Renames `Directory Compare` command (`gitlens.diffDirectory`) to `Compare Directory with Branch...` +- Renames `Directory Compare with Previous Commit` in quick pick menus to `Compare Directory with Previous Commit` +- Renames `Directory Compare with Working Tree` in quick pick menus to `Compare Directory with Working Tree` +- Changes the marketplace keywords for better discoverability + +### Fixed +- Fixes [#163](https://github.com/eamodio/vscode-gitlens/issues/163) - GitLens can cause git locking in the background ## [5.6.5] - 2017-10-16 ### Removed diff --git a/README.md b/README.md index 55d5c19..298756c 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,7 @@ GitLens provides an unobtrusive blame annotation at the end of the current line, - Provides easy access to the following comparison commands via the `Command Palette` as well as in context via the many provided quick pick menus -- Adds a `Directory Compare` command (`gitlens.diffDirectory`) to open the configured Git difftool to compare directories between branches +- Adds a `Compare Directory with Branch...` command (`gitlens.diffDirectory`) to open the configured Git difftool to compare directories between branches - Adds a `Compare File with Branch...` command (`gitlens.diffWithBranch`) to compare the active file with the same file on the selected branch @@ -224,7 +224,7 @@ GitLens provides an unobtrusive blame annotation at the end of the current line,  - Quickly see the set of files changed in the commit, complete with status indicators for adds, changes, renames, and deletes - - Provides entries to `Copy to Clipboard`, `Directory Compare`, `Open Changed Files`, `Open File in <remote-service>` when available, and more + - Provides entries to `Copy to Clipboard`, `Compare Directory with...`, `Open Changed Files`, `Open File in <remote-service>` when available, and more - Navigate back to the previous quick pick menu via `alt+left arrow`, if available - Use the `alt+right arrow` shortcut on an entry to execute it without closing the quick pick menu, if possible — commands that open windows outside of VS Code will still close the quick pick menu unless [`"gitlens.advanced.quickPick.closeOnFocusOut": false`](#extension-settings) is set - Use the `alt+right arrow` shortcut on a file entry in the `Changed Files` section to preview the comparison of the current revision with the previous one @@ -261,20 +261,25 @@ GitLens provides an unobtrusive blame annotation at the end of the current line,  - Quickly see the set of files changed in the stash, complete with status indicators for adds, changes, renames, and deletes - - Provides entries to `Copy Message to Clipboard`, `Directory Compare`, and `Open Changed Files` + - Provides entries to `Copy Message to Clipboard`, `Compare Directory with...`, and `Open Changed Files` - Provides entries to `Apply Stashed Changes` and `Delete Stashed Changes` — both require a confirmation - Navigate back to the previous quick pick menu via `alt+left arrow`, if available - Use the `alt+right arrow` shortcut on an entry to execute it without closing the quick pick menu, if possible — commands that open windows outside of VS Code will still close the quick pick menu unless [`"gitlens.advanced.quickPick.closeOnFocusOut": false`](#extension-settings) is set - Use the `alt+right arrow` shortcut on a file entry in the `Changed Files` section to preview the comparison of the current revision with the previous one - Adds a `Show Last Opened Quick Pick` command (`gitlens.showLastQuickPick`) with a shortcut of `alt+-` to quickly get back to where you were when the last GitLens quick pick menu closed - +7 ### And More - Adds a `Copy Commit ID to Clipboard` command (`gitlens.copyShaToClipboard`) to copy the commit id (sha) of the active line to the clipboard or from the most recent commit to the current branch, if there is no active editor - Adds a `Copy Commit Message to Clipboard` command (`gitlens.copyMessageToClipboard`) to copy the commit message of the active line to the clipboard or from the most recent commit to the current branch, if there is no active editor +- Adds a `Open Changes (with difftool)` command (`gitlens.externalDiff`) to the source control group and source control resource context menus to open the changes of a file or set of files with the configured git difftool + +- Adds a `Open All Changes (with difftool)` command (`gitlens.externalDiffAll`) to open all working changes with the configured git difftool + - Also adds the command to the Source Control group context menu + - Adds a `Open Changed Files` command (`gitlens.openChangedFiles`) to open any files with working tree changes - Adds a `Close Unchanged Files` command (`gitlens.closeUnchangedFiles`) to close any files without working tree changes diff --git a/package.json b/package.json index e8aed1a..93c1e4b 100644 --- a/package.json +++ b/package.json @@ -896,7 +896,7 @@ "commands": [ { "command": "gitlens.diffDirectory", - "title": "Directory Compare", + "title": "Compare Directory with Branch...", "category": "GitLens" }, { @@ -1114,6 +1114,11 @@ "category": "GitLens" }, { + "command": "gitlens.externalDiffAll", + "title": "Open All Changes (with difftool)", + "category": "GitLens" + }, + { "command": "gitlens.resetSuppressedWarnings", "title": "Reset Suppressed Warnings", "category": "GitLens" @@ -1235,6 +1240,10 @@ "when": "gitlens:isBlameable" }, { + "command": "gitlens.externalDiffAll", + "when": "gitlens:enabled" + }, + { "command": "gitlens.showFileBlame", "when": "gitlens:isBlameable" }, @@ -1570,6 +1579,11 @@ "group": "2_gitlens@3" }, { + "command": "gitlens.externalDiffAll", + "when": "gitlens:enabled", + "group": "2_gitlens@4" + }, + { "command": "gitlens.stashSave", "when": "gitlens:enabled", "group": "3_gitlens@1" diff --git a/src/commands/common.ts b/src/commands/common.ts index 3a76153..b41f99a 100644 --- a/src/commands/common.ts +++ b/src/commands/common.ts @@ -11,6 +11,7 @@ export enum Commands { CopyMessageToClipboard = 'gitlens.copyMessageToClipboard', CopyShaToClipboard = 'gitlens.copyShaToClipboard', DiffDirectory = 'gitlens.diffDirectory', + ExternalDiffAll = 'gitlens.externalDiffAll', DiffWith = 'gitlens.diffWith', DiffWithBranch = 'gitlens.diffWithBranch', DiffWithNext = 'gitlens.diffWithNext', @@ -61,6 +62,7 @@ export interface CommandContextParsingOptions { } export interface CommandBaseContext { + command: string; editor?: TextEditor; uri?: Uri; } @@ -134,10 +136,18 @@ export abstract class Command extends Disposable { private _disposable: Disposable; - constructor(protected command: Commands) { + constructor(command: Commands | Commands[]) { super(() => this.dispose()); - this._disposable = commands.registerCommand(command, this._execute, this); + if (!Array.isArray(command)) { + command = [command]; + } + + const subscriptions = []; + for (const cmd of command) { + subscriptions.push(commands.registerCommand(cmd, (...args: any[]) => this._execute(cmd, ...args), this)); + } + this._disposable = Disposable.from(...subscriptions); } dispose() { @@ -150,14 +160,14 @@ export abstract class Command extends Disposable { abstract execute(...args: any[]): any; - protected _execute(...args: any[]): any { - Telemetry.trackEvent(this.command); + protected _execute(command: string, ...args: any[]): any { + Telemetry.trackEvent(command); - const [context, rest] = Command._parseContext(this.contextParsingOptions, ...args); + const [context, rest] = Command._parseContext(command, this.contextParsingOptions, ...args); return this.preExecute(context, ...rest); } - private static _parseContext(options: CommandContextParsingOptions, ...args: any[]): [CommandContext, any[]] { + private static _parseContext(command: string, options: CommandContextParsingOptions, ...args: any[]): [CommandContext, any[]] { let editor: TextEditor | undefined = undefined; let firstArg = args[0]; @@ -169,12 +179,12 @@ export abstract class Command extends Disposable { if (options.uri && (firstArg === undefined || firstArg instanceof Uri)) { const [uri, ...rest] = args as [Uri, any]; - return [{ type: 'uri', editor: editor, uri: uri }, rest]; + return [{ command: command, type: 'uri', editor: editor, uri: uri }, rest]; } if (firstArg instanceof ExplorerNode) { const [node, ...rest] = args as [ExplorerNode, any]; - return [{ type: 'view', node: node, uri: node.uri }, rest]; + return [{ command: command, type: 'view', node: node, uri: node.uri }, rest]; } if (isScmResourceState(firstArg)) { @@ -187,7 +197,7 @@ export abstract class Command extends Disposable { states.push(arg); } - return [{ type: 'scm-states', scmResourceStates: states, uri: states[0].resourceUri }, args.slice(count)]; + return [{ command: command, type: 'scm-states', scmResourceStates: states, uri: states[0].resourceUri }, args.slice(count)]; } if (isScmResourceGroup(firstArg)) { @@ -200,10 +210,10 @@ export abstract class Command extends Disposable { groups.push(arg); } - return [{ type: 'scm-groups', scmResourceGroups: groups }, args.slice(count)]; + return [{ command: command, type: 'scm-groups', scmResourceGroups: groups }, args.slice(count)]; } - return [{ type: 'unknown', editor: editor }, args]; + return [{ command: command, type: 'unknown', editor: editor }, args]; } } @@ -211,7 +221,7 @@ export abstract class ActiveEditorCommand extends Command { protected readonly contextParsingOptions: CommandContextParsingOptions = { editor: true, uri: true }; - constructor(public readonly command: Commands) { + constructor(command: Commands | Commands[]) { super(command); } @@ -219,8 +229,8 @@ export abstract class ActiveEditorCommand extends Command { return this.execute(context.editor, context.uri, ...args); } - protected _execute(...args: any[]): any { - return super._execute(window.activeTextEditor, ...args); + protected _execute(command: string, ...args: any[]): any { + return super._execute(command, window.activeTextEditor, ...args); } abstract execute(editor?: TextEditor, ...args: any[]): any; @@ -233,16 +243,16 @@ export function getLastCommand() { export abstract class ActiveEditorCachedCommand extends ActiveEditorCommand { - constructor(public readonly command: Commands) { + constructor(command: Commands | Commands[]) { super(command); } - protected _execute(...args: any[]): any { + protected _execute(command: string, ...args: any[]): any { lastCommand = { - command: this.command, + command: command, args: args }; - return super._execute(...args); + return super._execute(command, ...args); } abstract execute(editor: TextEditor, ...args: any[]): any; @@ -252,17 +262,26 @@ export abstract class EditorCommand extends Disposable { private _disposable: Disposable; - constructor(public readonly command: Commands) { + constructor(command: Commands | Commands[]) { super(() => this.dispose()); - this._disposable = commands.registerTextEditorCommand(command, this._execute, this); + + if (!Array.isArray(command)) { + command = [command]; + } + + const subscriptions = []; + for (const cmd of command) { + subscriptions.push(commands.registerCommand(cmd, (editor: TextEditor, edit: TextEditorEdit, ...args: any[]) => this._execute(cmd, editor, edit, ...args), this)); + } + this._disposable = Disposable.from(...subscriptions); } dispose() { this._disposable && this._disposable.dispose(); } - private _execute(editor: TextEditor, edit: TextEditorEdit, ...args: any[]): any { - Telemetry.trackEvent(this.command); + private _execute(command: string, editor: TextEditor, edit: TextEditorEdit, ...args: any[]): any { + Telemetry.trackEvent(command); return this.execute(editor, edit, ...args); } diff --git a/src/commands/diffDirectory.ts b/src/commands/diffDirectory.ts index cff4e4a..9910006 100644 --- a/src/commands/diffDirectory.ts +++ b/src/commands/diffDirectory.ts @@ -2,6 +2,7 @@ import { Iterables } from '../system'; import { commands, TextEditor, Uri, window } from 'vscode'; import { ActiveEditorCommand, Commands, getCommandUri } from './common'; +import { CommandContext } from '../commands'; import { BuiltInCommands, GlyphChars } from '../constants'; import { GitService } from '../gitService'; import { Logger } from '../logger'; @@ -16,7 +17,16 @@ export interface DiffDirectoryCommandCommandArgs { export class DiffDirectoryCommand extends ActiveEditorCommand { constructor(private git: GitService) { - super(Commands.DiffDirectory); + super([Commands.DiffDirectory, Commands.ExternalDiffAll]); + } + + protected async preExecute(context: CommandContext, args: DiffDirectoryCommandCommandArgs = {}): Promise<any> { + if (context.command === Commands.ExternalDiffAll) { + args.shaOrBranch1 = 'HEAD'; + args.shaOrBranch2 = undefined; + } + + return this.execute(context.editor, context.uri, args); } async execute(editor?: TextEditor, uri?: Uri, args: DiffDirectoryCommandCommandArgs = {}): Promise<any> { diff --git a/src/quickPicks/commitDetails.ts b/src/quickPicks/commitDetails.ts index 60d3621..f5d79a3 100644 --- a/src/quickPicks/commitDetails.ts +++ b/src/quickPicks/commitDetails.ts @@ -161,7 +161,7 @@ export class CommitDetailsQuickPick { } items.splice(index++, 0, new CommandQuickPickItem({ - label: `$(git-compare) Directory Compare with Previous Commit`, + label: `$(git-compare) Compare Directory with Previous Commit`, description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(git-commit) ${commit.previousShortSha || `${commit.shortSha}^`} ${GlyphChars.Space} $(git-compare) ${GlyphChars.Space} $(git-commit) ${commit.shortSha}` }, Commands.DiffDirectory, [ commit.uri, @@ -173,7 +173,7 @@ export class CommitDetailsQuickPick { } items.splice(index++, 0, new CommandQuickPickItem({ - label: `$(git-compare) Directory Compare with Working Tree`, + label: `$(git-compare) Compare Directory with Working Tree`, description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(git-commit) ${commit.shortSha} ${GlyphChars.Space} $(git-compare) ${GlyphChars.Space} $(file-directory) Working Tree` }, Commands.DiffDirectory, [ uri,