mirror of
https://github.com/ckaczor/vscode-gitlens.git
synced 2026-01-14 01:25:43 -05:00
Refactors commands to use typed args objects
This commit is contained in:
@@ -1,31 +1,33 @@
|
||||
'use strict';
|
||||
import { TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorTracker } from '../activeEditorTracker';
|
||||
import { ActiveEditorCommand, Commands } from './common';
|
||||
import { ActiveEditorCommand, Commands, getCommandUri } from './common';
|
||||
import { TextEditorComparer, UriComparer } from '../comparers';
|
||||
import { GitService } from '../gitService';
|
||||
import { Logger } from '../logger';
|
||||
|
||||
export interface CloseUnchangedFilesCommandArgs {
|
||||
uris?: Uri[];
|
||||
}
|
||||
|
||||
export class CloseUnchangedFilesCommand extends ActiveEditorCommand {
|
||||
|
||||
constructor(private git: GitService) {
|
||||
super(Commands.CloseUnchangedFiles);
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor, uri?: Uri, uris?: Uri[]) {
|
||||
if (!(uri instanceof Uri)) {
|
||||
uri = editor && editor.document && editor.document.uri;
|
||||
}
|
||||
async execute(editor: TextEditor, uri?: Uri, args: CloseUnchangedFilesCommandArgs = {}) {
|
||||
uri = getCommandUri(uri, editor);
|
||||
|
||||
try {
|
||||
if (!uris) {
|
||||
if (args.uris === undefined) {
|
||||
const repoPath = await this.git.getRepoPathFromUri(uri);
|
||||
if (!repoPath) return window.showWarningMessage(`Unable to close unchanged files`);
|
||||
if (repoPath === undefined) return window.showWarningMessage(`Unable to close unchanged files`);
|
||||
|
||||
const status = await this.git.getStatusForRepo(repoPath);
|
||||
if (!status) return window.showWarningMessage(`Unable to close unchanged files`);
|
||||
if (status === undefined) return window.showWarningMessage(`Unable to close unchanged files`);
|
||||
|
||||
uris = status.files.map(_ => _.Uri);
|
||||
args.uris = status.files.map(_ => _.Uri);
|
||||
}
|
||||
|
||||
const editorTracker = new ActiveEditorTracker();
|
||||
@@ -35,7 +37,7 @@ export class CloseUnchangedFilesCommand extends ActiveEditorCommand {
|
||||
do {
|
||||
if (editor !== undefined) {
|
||||
if ((editor.document !== undefined && editor.document.isDirty) ||
|
||||
uris.some(_ => UriComparer.equals(_, editor!.document && editor!.document.uri))) {
|
||||
args.uris.some(_ => UriComparer.equals(_, editor!.document && editor!.document.uri))) {
|
||||
// If we didn't start with a valid editor, set one once we find it
|
||||
if (active === undefined) {
|
||||
active = editor;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
'use strict';
|
||||
import { commands, Disposable, TextEditor, TextEditorEdit, Uri, window, workspace } from 'vscode';
|
||||
import { commands, Disposable, TextDocumentShowOptions, TextEditor, TextEditorEdit, Uri, window, workspace } from 'vscode';
|
||||
import { BuiltInCommands } from '../constants';
|
||||
import { Logger } from '../logger';
|
||||
import { Telemetry } from '../telemetry';
|
||||
@@ -48,6 +48,12 @@ export const Commands = {
|
||||
ToggleCodeLens: 'gitlens.toggleCodeLens' as Commands
|
||||
};
|
||||
|
||||
export function getCommandUri(uri?: Uri, editor?: TextEditor): Uri | undefined {
|
||||
if (uri instanceof Uri) return uri;
|
||||
if (editor === undefined || editor.document === undefined) return undefined;
|
||||
return editor.document.uri;
|
||||
}
|
||||
|
||||
export type CommandContext = 'gitlens:canToggleCodeLens' | 'gitlens:enabled' | 'gitlens:hasRemotes' | 'gitlens:isBlameable' | 'gitlens:isRepository' | 'gitlens:isTracked' | 'gitlens:key';
|
||||
export const CommandContext = {
|
||||
CanToggleCodeLens: 'gitlens:canToggleCodeLens' as CommandContext,
|
||||
@@ -140,12 +146,16 @@ export abstract class ActiveEditorCachedCommand extends ActiveEditorCommand {
|
||||
abstract execute(editor: TextEditor, ...args: any[]): any;
|
||||
}
|
||||
|
||||
export async function openEditor(uri: Uri, pinned: boolean = false) {
|
||||
export async function openEditor(uri: Uri, options?: TextDocumentShowOptions): Promise<TextEditor | undefined> {
|
||||
try {
|
||||
if (!pinned) return await commands.executeCommand(BuiltInCommands.Open, uri);
|
||||
const defaults: TextDocumentShowOptions = {
|
||||
preserveFocus: false,
|
||||
preview: true,
|
||||
viewColumn: (window.activeTextEditor && window.activeTextEditor.viewColumn) || 1
|
||||
};
|
||||
|
||||
const document = await workspace.openTextDocument(uri);
|
||||
return window.showTextDocument(document, (window.activeTextEditor && window.activeTextEditor.viewColumn) || 1, true);
|
||||
return window.showTextDocument(document, { ...defaults, ...(options || {}) });
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'openEditor');
|
||||
|
||||
@@ -1,40 +1,43 @@
|
||||
'use strict';
|
||||
import { Iterables } from '../system';
|
||||
import { TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCommand, Commands } from './common';
|
||||
import { ActiveEditorCommand, Commands, getCommandUri } from './common';
|
||||
import { GitService, GitUri } from '../gitService';
|
||||
import { Logger } from '../logger';
|
||||
import { copy } from 'copy-paste';
|
||||
|
||||
export interface CopyMessageToClipboardCommandArgs {
|
||||
message?: string;
|
||||
sha?: string;
|
||||
}
|
||||
|
||||
export class CopyMessageToClipboardCommand extends ActiveEditorCommand {
|
||||
|
||||
constructor(private git: GitService) {
|
||||
super(Commands.CopyMessageToClipboard);
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor, uri?: Uri, sha?: string, message?: string): Promise<any> {
|
||||
if (!(uri instanceof Uri)) {
|
||||
uri = editor && editor.document && editor.document.uri;
|
||||
}
|
||||
async execute(editor: TextEditor, uri?: Uri, args: CopyMessageToClipboardCommandArgs = {}): Promise<any> {
|
||||
uri = getCommandUri(uri, editor);
|
||||
|
||||
try {
|
||||
// If we don't have an editor then get the message of the last commit to the branch
|
||||
if (!uri) {
|
||||
if (uri === undefined) {
|
||||
if (!this.git.repoPath) return undefined;
|
||||
|
||||
const log = await this.git.getLogForRepo(this.git.repoPath, undefined, 1);
|
||||
if (!log) return undefined;
|
||||
|
||||
message = Iterables.first(log.commits.values()).message;
|
||||
copy(message);
|
||||
args.message = Iterables.first(log.commits.values()).message;
|
||||
copy(args.message);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const gitUri = await GitUri.fromUri(uri, this.git);
|
||||
|
||||
if (!message) {
|
||||
if (!sha) {
|
||||
if (editor && editor.document && editor.document.isDirty) return undefined;
|
||||
if (args.message === undefined) {
|
||||
if (args.sha === undefined) {
|
||||
if (editor !== undefined && editor.document !== undefined && editor.document.isDirty) return undefined;
|
||||
|
||||
const line = (editor && editor.selection.active.line) || gitUri.offset;
|
||||
const blameline = line - gitUri.offset;
|
||||
@@ -46,7 +49,7 @@ export class CopyMessageToClipboardCommand extends ActiveEditorCommand {
|
||||
|
||||
if (blame.commit.isUncommitted) return undefined;
|
||||
|
||||
sha = blame.commit.sha;
|
||||
args.sha = blame.commit.sha;
|
||||
if (!gitUri.repoPath) {
|
||||
gitUri.repoPath = blame.commit.repoPath;
|
||||
}
|
||||
@@ -58,13 +61,13 @@ export class CopyMessageToClipboardCommand extends ActiveEditorCommand {
|
||||
}
|
||||
|
||||
// Get the full commit message -- since blame only returns the summary
|
||||
const commit = await this.git.getLogCommit(gitUri.repoPath, gitUri.fsPath, sha);
|
||||
const commit = await this.git.getLogCommit(gitUri.repoPath, gitUri.fsPath, args.sha);
|
||||
if (!commit) return undefined;
|
||||
|
||||
message = commit.message;
|
||||
args.message = commit.message;
|
||||
}
|
||||
|
||||
copy(message);
|
||||
copy(args.message);
|
||||
return undefined;
|
||||
}
|
||||
catch (ex) {
|
||||
|
||||
@@ -1,39 +1,41 @@
|
||||
'use strict';
|
||||
import { Iterables } from '../system';
|
||||
import { TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCommand, Commands } from './common';
|
||||
import { ActiveEditorCommand, Commands, getCommandUri } from './common';
|
||||
import { GitService, GitUri } from '../gitService';
|
||||
import { Logger } from '../logger';
|
||||
import { copy } from 'copy-paste';
|
||||
|
||||
export interface CopyShaToClipboardCommandArgs {
|
||||
sha?: string;
|
||||
}
|
||||
|
||||
export class CopyShaToClipboardCommand extends ActiveEditorCommand {
|
||||
|
||||
constructor(private git: GitService) {
|
||||
super(Commands.CopyShaToClipboard);
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor, uri?: Uri, sha?: string): Promise<any> {
|
||||
if (!(uri instanceof Uri)) {
|
||||
uri = editor && editor.document && editor.document.uri;
|
||||
}
|
||||
async execute(editor: TextEditor, uri?: Uri, args: CopyShaToClipboardCommandArgs = {}): Promise<any> {
|
||||
uri = getCommandUri(uri, editor);
|
||||
|
||||
try {
|
||||
// If we don't have an editor then get the sha of the last commit to the branch
|
||||
if (!uri) {
|
||||
if (uri === undefined) {
|
||||
if (!this.git.repoPath) return undefined;
|
||||
|
||||
const log = await this.git.getLogForRepo(this.git.repoPath, undefined, 1);
|
||||
if (!log) return undefined;
|
||||
|
||||
sha = Iterables.first(log.commits.values()).sha;
|
||||
copy(sha);
|
||||
args.sha = Iterables.first(log.commits.values()).sha;
|
||||
copy(args.sha);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const gitUri = await GitUri.fromUri(uri, this.git);
|
||||
|
||||
if (!sha) {
|
||||
if (editor && editor.document && editor.document.isDirty) return undefined;
|
||||
if (args.sha === undefined) {
|
||||
if (editor !== undefined && editor.document !== undefined && editor.document.isDirty) return undefined;
|
||||
|
||||
const line = (editor && editor.selection.active.line) || gitUri.offset;
|
||||
const blameline = line - gitUri.offset;
|
||||
@@ -43,7 +45,7 @@ export class CopyShaToClipboardCommand extends ActiveEditorCommand {
|
||||
const blame = await this.git.getBlameForLine(gitUri, blameline);
|
||||
if (!blame) return undefined;
|
||||
|
||||
sha = blame.commit.sha;
|
||||
args.sha = blame.commit.sha;
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'CopyShaToClipboardCommand', `getBlameForLine(${blameline})`);
|
||||
@@ -51,7 +53,7 @@ export class CopyShaToClipboardCommand extends ActiveEditorCommand {
|
||||
}
|
||||
}
|
||||
|
||||
copy(sha);
|
||||
copy(args.sha);
|
||||
return undefined;
|
||||
}
|
||||
catch (ex) {
|
||||
|
||||
@@ -1,51 +1,53 @@
|
||||
'use strict';
|
||||
import { Iterables } from '../system';
|
||||
import { commands, TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCommand, Commands } from './common';
|
||||
import { ActiveEditorCommand, Commands, getCommandUri } from './common';
|
||||
import { BuiltInCommands } from '../constants';
|
||||
import { GitService } from '../gitService';
|
||||
import { Logger } from '../logger';
|
||||
import { CommandQuickPickItem, BranchesQuickPick } from '../quickPicks';
|
||||
|
||||
export interface DiffDirectoryCommandCommandArgs {
|
||||
shaOrBranch1?: string;
|
||||
shaOrBranch2?: string;
|
||||
}
|
||||
|
||||
export class DiffDirectoryCommand extends ActiveEditorCommand {
|
||||
|
||||
constructor(private git: GitService) {
|
||||
super(Commands.DiffDirectory);
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor, uri?: Uri, shaOrBranch1?: string, shaOrBranch2?: string): Promise<any> {
|
||||
async execute(editor: TextEditor, uri?: Uri, args: DiffDirectoryCommandCommandArgs = {}): Promise<any> {
|
||||
const diffTool = await this.git.getConfig('diff.tool');
|
||||
if (!diffTool) {
|
||||
const result = await window.showWarningMessage(`Unable to open directory compare because there is no Git diff tool configured`, 'View Git Docs');
|
||||
if (!result) return undefined;
|
||||
|
||||
return commands.executeCommand(BuiltInCommands.Open, Uri.parse('https://git-scm.com/docs/git-config#git-config-difftool'));
|
||||
}
|
||||
|
||||
if (!(uri instanceof Uri)) {
|
||||
uri = editor && editor.document && editor.document.uri;
|
||||
}
|
||||
uri = getCommandUri(uri, editor);
|
||||
|
||||
try {
|
||||
const repoPath = await this.git.getRepoPathFromUri(uri);
|
||||
if (!repoPath) return window.showWarningMessage(`Unable to open directory compare`);
|
||||
|
||||
if (!shaOrBranch1) {
|
||||
if (!args.shaOrBranch1) {
|
||||
const branches = await this.git.getBranches(repoPath);
|
||||
const current = Iterables.find(branches, _ => _.current);
|
||||
if (current == null) return window.showWarningMessage(`Unable to open directory compare`);
|
||||
|
||||
const pick = await BranchesQuickPick.show(branches, `Compare ${current.name} to \u2026`);
|
||||
if (!pick) return undefined;
|
||||
if (pick === undefined) return undefined;
|
||||
|
||||
if (pick instanceof CommandQuickPickItem) {
|
||||
return pick.execute();
|
||||
}
|
||||
if (pick instanceof CommandQuickPickItem) return pick.execute();
|
||||
|
||||
shaOrBranch1 = pick.branch.name;
|
||||
if (!shaOrBranch1) return undefined;
|
||||
args.shaOrBranch1 = pick.branch.name;
|
||||
if (args.shaOrBranch1 === undefined) return undefined;
|
||||
}
|
||||
|
||||
this.git.openDirectoryDiff(repoPath, shaOrBranch1, shaOrBranch2);
|
||||
this.git.openDirectoryDiff(repoPath, args.shaOrBranch1, args.shaOrBranch2);
|
||||
return undefined;
|
||||
}
|
||||
catch (ex) {
|
||||
|
||||
@@ -1,51 +1,63 @@
|
||||
'use strict';
|
||||
import { commands, TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCommand, Commands } from './common';
|
||||
import { commands, TextDocumentShowOptions, TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCommand, Commands, getCommandUri } from './common';
|
||||
import { BuiltInCommands } from '../constants';
|
||||
import { DiffWithPreviousCommandArgs } from './diffWithPrevious';
|
||||
import { DiffWithWorkingCommandArgs } from './diffWithWorking';
|
||||
import { GitCommit, GitService, GitUri } from '../gitService';
|
||||
import { Logger } from '../logger';
|
||||
import * as path from 'path';
|
||||
|
||||
export interface DiffLineWithPreviousCommandArgs {
|
||||
commit?: GitCommit;
|
||||
line?: number;
|
||||
showOptions?: TextDocumentShowOptions;
|
||||
}
|
||||
|
||||
export class DiffLineWithPreviousCommand extends ActiveEditorCommand {
|
||||
|
||||
constructor(private git: GitService) {
|
||||
super(Commands.DiffLineWithPrevious);
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor): Promise<any>;
|
||||
async execute(editor: TextEditor, uri: Uri): Promise<any>;
|
||||
async execute(editor: TextEditor, uri?: Uri, commit?: GitCommit, line?: number): Promise<any> {
|
||||
if (!(uri instanceof Uri)) {
|
||||
if (!editor || !editor.document) return undefined;
|
||||
uri = editor.document.uri;
|
||||
}
|
||||
async execute(editor: TextEditor, uri?: Uri, args: DiffLineWithPreviousCommandArgs = {}): Promise<any> {
|
||||
uri = getCommandUri(uri, editor);
|
||||
if (uri === undefined) return undefined;
|
||||
|
||||
const gitUri = await GitUri.fromUri(uri, this.git);
|
||||
line = line || (editor && editor.selection.active.line) || gitUri.offset;
|
||||
args.line = args.line || (editor === undefined ? gitUri.offset : editor.selection.active.line);
|
||||
|
||||
if (!commit || GitService.isUncommitted(commit.sha)) {
|
||||
if (editor && editor.document && editor.document.isDirty) return undefined;
|
||||
if (args.commit === undefined || GitService.isUncommitted(args.commit.sha)) {
|
||||
if (editor !== undefined && editor.document !== undefined && editor.document.isDirty) return undefined;
|
||||
|
||||
const blameline = line - gitUri.offset;
|
||||
const blameline = args.line - gitUri.offset;
|
||||
if (blameline < 0) return undefined;
|
||||
|
||||
try {
|
||||
const blame = await this.git.getBlameForLine(gitUri, blameline);
|
||||
if (!blame) return window.showWarningMessage(`Unable to open compare. File is probably not under source control`);
|
||||
if (blame === undefined) return window.showWarningMessage(`Unable to open compare. File is probably not under source control`);
|
||||
|
||||
commit = blame.commit;
|
||||
args.commit = blame.commit;
|
||||
|
||||
// If we don't have a sha or the current commit matches the blame, show the previous
|
||||
if (!gitUri.sha || gitUri.sha === commit.sha) {
|
||||
return commands.executeCommand(Commands.DiffWithPrevious, new GitUri(uri, commit), undefined, line);
|
||||
if (gitUri.sha === undefined || gitUri.sha === args.commit.sha) {
|
||||
return commands.executeCommand(Commands.DiffWithPrevious, new GitUri(uri, args.commit), {
|
||||
line: args.line,
|
||||
showOptions: args.showOptions
|
||||
} as DiffWithPreviousCommandArgs);
|
||||
}
|
||||
|
||||
// If the line is uncommitted, find the previous commit and treat it as a DiffWithWorking
|
||||
if (commit.isUncommitted) {
|
||||
uri = commit.uri;
|
||||
commit = new GitCommit(commit.type, commit.repoPath, commit.previousSha!, commit.previousFileName!, commit.author, commit.date, commit.message);
|
||||
line = (blame.line.line + 1) + gitUri.offset;
|
||||
return commands.executeCommand(Commands.DiffWithWorking, uri, commit, line);
|
||||
if (args.commit.isUncommitted) {
|
||||
uri = args.commit.uri;
|
||||
args.commit = new GitCommit(args.commit.type, args.commit.repoPath, args.commit.previousSha!, args.commit.previousFileName!, args.commit.author, args.commit.date, args.commit.message);
|
||||
args.line = (blame.line.line + 1) + gitUri.offset;
|
||||
|
||||
return commands.executeCommand(Commands.DiffWithWorking, uri, {
|
||||
commit: args.commit,
|
||||
line: args.line,
|
||||
showOptions: args.showOptions
|
||||
} as DiffWithWorkingCommandArgs);
|
||||
}
|
||||
}
|
||||
catch (ex) {
|
||||
@@ -57,11 +69,17 @@ export class DiffLineWithPreviousCommand extends ActiveEditorCommand {
|
||||
try {
|
||||
const [rhs, lhs] = await Promise.all([
|
||||
this.git.getVersionedFile(gitUri.repoPath, gitUri.fsPath, gitUri.sha!),
|
||||
this.git.getVersionedFile(commit.repoPath, commit.uri.fsPath, commit.sha)
|
||||
this.git.getVersionedFile(args.commit.repoPath, args.commit.uri.fsPath, args.commit.sha)
|
||||
]);
|
||||
await commands.executeCommand(BuiltInCommands.Diff, Uri.file(lhs), Uri.file(rhs), `${path.basename(commit.uri.fsPath)} (${commit.shortSha}) \u2194 ${path.basename(gitUri.fsPath)} (${gitUri.shortSha})`);
|
||||
|
||||
await commands.executeCommand(BuiltInCommands.Diff,
|
||||
Uri.file(lhs),
|
||||
Uri.file(rhs),
|
||||
`${path.basename(args.commit.uri.fsPath)} (${args.commit.shortSha}) \u2194 ${path.basename(gitUri.fsPath)} (${gitUri.shortSha})`,
|
||||
args.showOptions);
|
||||
|
||||
// TODO: Figure out how to focus the left pane
|
||||
return await commands.executeCommand(BuiltInCommands.RevealLine, { lineNumber: line, at: 'center' });
|
||||
return await commands.executeCommand(BuiltInCommands.RevealLine, { lineNumber: args.line, at: 'center' });
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'DiffWithPreviousLineCommand', 'getVersionedFile');
|
||||
|
||||
@@ -1,41 +1,44 @@
|
||||
'use strict';
|
||||
import { commands, TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCommand, Commands } from './common';
|
||||
import { commands, TextDocumentShowOptions, TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCommand, Commands, getCommandUri } from './common';
|
||||
import { DiffWithWorkingCommandArgs } from './diffWithWorking';
|
||||
import { GitCommit, GitService, GitUri } from '../gitService';
|
||||
import { Logger } from '../logger';
|
||||
|
||||
export interface DiffLineWithWorkingCommandArgs {
|
||||
commit?: GitCommit;
|
||||
line?: number;
|
||||
showOptions?: TextDocumentShowOptions;
|
||||
}
|
||||
|
||||
export class DiffLineWithWorkingCommand extends ActiveEditorCommand {
|
||||
|
||||
constructor(private git: GitService) {
|
||||
super(Commands.DiffLineWithWorking);
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor): Promise<any>;
|
||||
async execute(editor: TextEditor, uri: Uri): Promise<any>;
|
||||
async execute(editor: TextEditor, uri?: Uri, commit?: GitCommit, line?: number): Promise<any> {
|
||||
if (!(uri instanceof Uri)) {
|
||||
if (!editor || !editor.document) return undefined;
|
||||
uri = editor.document.uri;
|
||||
}
|
||||
async execute(editor: TextEditor, uri?: Uri, args: DiffLineWithWorkingCommandArgs = {}): Promise<any> {
|
||||
uri = getCommandUri(uri, editor);
|
||||
if (uri === undefined) return undefined;
|
||||
|
||||
const gitUri = await GitUri.fromUri(uri, this.git);
|
||||
line = line || (editor && editor.selection.active.line) || gitUri.offset;
|
||||
args.line = args.line || (editor === undefined ? gitUri.offset : editor.selection.active.line);
|
||||
|
||||
if (!commit || GitService.isUncommitted(commit.sha)) {
|
||||
if (editor && editor.document && editor.document.isDirty) return undefined;
|
||||
if (args.commit === undefined || GitService.isUncommitted(args.commit.sha)) {
|
||||
if (editor !== undefined && editor.document !== undefined && editor.document.isDirty) return undefined;
|
||||
|
||||
const blameline = line - gitUri.offset;
|
||||
const blameline = args.line - gitUri.offset;
|
||||
if (blameline < 0) return undefined;
|
||||
|
||||
try {
|
||||
const blame = await this.git.getBlameForLine(gitUri, blameline);
|
||||
if (!blame) return window.showWarningMessage(`Unable to open compare. File is probably not under source control`);
|
||||
if (blame === undefined) return window.showWarningMessage(`Unable to open compare. File is probably not under source control`);
|
||||
|
||||
commit = blame.commit;
|
||||
args.commit = blame.commit;
|
||||
// If the line is uncommitted, find the previous commit
|
||||
if (commit.isUncommitted) {
|
||||
commit = new GitCommit(commit.type, commit.repoPath, commit.previousSha!, commit.previousFileName!, commit.author, commit.date, commit.message);
|
||||
line = blame.line.line + 1 + gitUri.offset;
|
||||
if (args.commit.isUncommitted) {
|
||||
args.commit = new GitCommit(args.commit.type, args.commit.repoPath, args.commit.previousSha!, args.commit.previousFileName!, args.commit.author, args.commit.date, args.commit.message);
|
||||
args.line = blame.line.line + 1 + gitUri.offset;
|
||||
}
|
||||
}
|
||||
catch (ex) {
|
||||
@@ -44,6 +47,6 @@ export class DiffLineWithWorkingCommand extends ActiveEditorCommand {
|
||||
}
|
||||
}
|
||||
|
||||
return commands.executeCommand(Commands.DiffWithWorking, uri, commit, line);
|
||||
return commands.executeCommand(Commands.DiffWithWorking, uri, args as DiffWithWorkingCommandArgs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,44 +1,54 @@
|
||||
'use strict';
|
||||
import { commands, TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCommand, Commands } from './common';
|
||||
import { commands, TextDocumentShowOptions, TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCommand, Commands, getCommandUri } from './common';
|
||||
import { BuiltInCommands } from '../constants';
|
||||
import { GitService, GitUri } from '../gitService';
|
||||
import { Logger } from '../logger';
|
||||
import { CommandQuickPickItem, BranchesQuickPick } from '../quickPicks';
|
||||
import * as path from 'path';
|
||||
|
||||
export interface DiffWithBranchCommandArgs {
|
||||
line?: number;
|
||||
showOptions?: TextDocumentShowOptions;
|
||||
|
||||
goBackCommand?: CommandQuickPickItem;
|
||||
}
|
||||
|
||||
export class DiffWithBranchCommand extends ActiveEditorCommand {
|
||||
|
||||
constructor(private git: GitService) {
|
||||
super(Commands.DiffWithBranch);
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor, uri?: Uri, goBackCommand?: CommandQuickPickItem): Promise<any> {
|
||||
if (!(uri instanceof Uri)) {
|
||||
if (!editor || !editor.document) return undefined;
|
||||
uri = editor.document.uri;
|
||||
}
|
||||
async execute(editor: TextEditor, uri?: Uri, args: DiffWithBranchCommandArgs = {}): Promise<any> {
|
||||
uri = getCommandUri(uri, editor);
|
||||
if (uri === undefined) return undefined;
|
||||
|
||||
const line = (editor && editor.selection.active.line) || 0;
|
||||
args.line = args.line || (editor === undefined ? 0 : editor.selection.active.line);
|
||||
|
||||
const gitUri = await GitUri.fromUri(uri, this.git);
|
||||
if (gitUri.repoPath === undefined) return undefined;
|
||||
|
||||
const branches = await this.git.getBranches(gitUri.repoPath);
|
||||
const pick = await BranchesQuickPick.show(branches, `Compare ${path.basename(gitUri.fsPath)} to \u2026`, goBackCommand);
|
||||
if (!pick) return undefined;
|
||||
const pick = await BranchesQuickPick.show(branches, `Compare ${path.basename(gitUri.fsPath)} to \u2026`, args.goBackCommand);
|
||||
if (pick === undefined) return undefined;
|
||||
|
||||
if (pick instanceof CommandQuickPickItem) {
|
||||
return pick.execute();
|
||||
}
|
||||
if (pick instanceof CommandQuickPickItem) return pick.execute();
|
||||
|
||||
const branch = pick.branch.name;
|
||||
if (!branch) return undefined;
|
||||
if (branch === undefined) return undefined;
|
||||
|
||||
try {
|
||||
const compare = await this.git.getVersionedFile(gitUri.repoPath, gitUri.fsPath, branch);
|
||||
await commands.executeCommand(BuiltInCommands.Diff, Uri.file(compare), gitUri.fileUri(), `${path.basename(gitUri.fsPath)} (${branch}) \u2194 ${path.basename(gitUri.fsPath)}`);
|
||||
return await commands.executeCommand(BuiltInCommands.RevealLine, { lineNumber: line, at: 'center' });
|
||||
|
||||
await commands.executeCommand(BuiltInCommands.Diff,
|
||||
Uri.file(compare),
|
||||
gitUri.fileUri(),
|
||||
`${path.basename(gitUri.fsPath)} (${branch}) \u2194 ${path.basename(gitUri.fsPath)}`,
|
||||
args.showOptions);
|
||||
|
||||
// TODO: Figure out how to focus the left pane
|
||||
return await commands.executeCommand(BuiltInCommands.RevealLine, { lineNumber: args.line, at: 'center' });
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'DiffWithBranchCommand', 'getVersionedFile');
|
||||
|
||||
@@ -1,51 +1,46 @@
|
||||
'use strict';
|
||||
import { Iterables } from '../system';
|
||||
import { commands, Range, TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCommand, Commands } from './common';
|
||||
import { commands, Range, TextDocumentShowOptions, TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCommand, Commands, getCommandUri } from './common';
|
||||
import { BuiltInCommands } from '../constants';
|
||||
import { GitLogCommit, GitService, GitUri } from '../gitService';
|
||||
import { Logger } from '../logger';
|
||||
import * as path from 'path';
|
||||
|
||||
export interface DiffWithNextCommandArgs {
|
||||
commit?: GitLogCommit;
|
||||
line?: number;
|
||||
range?: Range;
|
||||
showOptions?: TextDocumentShowOptions;
|
||||
}
|
||||
|
||||
export class DiffWithNextCommand extends ActiveEditorCommand {
|
||||
|
||||
constructor(private git: GitService) {
|
||||
super(Commands.DiffWithNext);
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor): Promise<any>;
|
||||
async execute(editor: TextEditor, uri: Uri): Promise<any>;
|
||||
async execute(editor: TextEditor, uri: Uri, commit: GitLogCommit, range?: Range): Promise<any>;
|
||||
async execute(editor: TextEditor, uri: Uri, commit: GitLogCommit, line?: number): Promise<any>;
|
||||
async execute(editor: TextEditor, uri?: Uri, commit?: GitLogCommit, rangeOrLine?: Range | number): Promise<any> {
|
||||
if (!(uri instanceof Uri)) {
|
||||
if (!editor || !editor.document) return undefined;
|
||||
uri = editor.document.uri;
|
||||
}
|
||||
async execute(editor: TextEditor, uri?: Uri, args: DiffWithNextCommandArgs = {}): Promise<any> {
|
||||
uri = getCommandUri(uri, editor);
|
||||
if (uri === undefined) return undefined;
|
||||
|
||||
let line = (editor && editor.selection.active.line) || 0;
|
||||
if (typeof rangeOrLine === 'number') {
|
||||
line = rangeOrLine || line;
|
||||
rangeOrLine = undefined;
|
||||
}
|
||||
args.line = args.line || (editor === undefined ? 0 : editor.selection.active.line);
|
||||
|
||||
if (!commit || !(commit instanceof GitLogCommit) || rangeOrLine instanceof Range) {
|
||||
if (args.commit === undefined || !(args.commit instanceof GitLogCommit) || args.range !== undefined) {
|
||||
const gitUri = await GitUri.fromUri(uri, this.git);
|
||||
|
||||
try {
|
||||
if (!gitUri.sha) {
|
||||
// If the file is uncommitted, treat it as a DiffWithWorking
|
||||
if (await this.git.isFileUncommitted(gitUri)) {
|
||||
return commands.executeCommand(Commands.DiffWithWorking, uri);
|
||||
}
|
||||
// If the sha is missing or the file is uncommitted, treat it as a DiffWithWorking
|
||||
if (gitUri.sha === undefined && await this.git.isFileUncommitted(gitUri)) {
|
||||
return commands.executeCommand(Commands.DiffWithWorking, uri);
|
||||
}
|
||||
|
||||
const sha = (commit && commit.sha) || gitUri.sha;
|
||||
const sha = args.commit === undefined ? gitUri.sha : args.commit.sha;
|
||||
|
||||
const log = await this.git.getLogForFile(gitUri.repoPath, gitUri.fsPath, undefined, sha ? undefined : 2, rangeOrLine!);
|
||||
if (!log) return window.showWarningMessage(`Unable to open compare. File is probably not under source control`);
|
||||
const log = await this.git.getLogForFile(gitUri.repoPath, gitUri.fsPath, undefined, sha ? undefined : 2, args.range!);
|
||||
if (log === undefined) return window.showWarningMessage(`Unable to open compare. File is probably not under source control`);
|
||||
|
||||
commit = (sha && log.commits.get(sha)) || Iterables.first(log.commits.values());
|
||||
args.commit = (sha && log.commits.get(sha)) || Iterables.first(log.commits.values());
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'DiffWithNextCommand', `getLogForFile(${gitUri.repoPath}, ${gitUri.fsPath})`);
|
||||
@@ -53,17 +48,22 @@ export class DiffWithNextCommand extends ActiveEditorCommand {
|
||||
}
|
||||
}
|
||||
|
||||
if (!commit.nextSha) {
|
||||
return commands.executeCommand(Commands.DiffWithWorking, uri);
|
||||
}
|
||||
if (args.commit.nextSha === undefined) return commands.executeCommand(Commands.DiffWithWorking, uri);
|
||||
|
||||
try {
|
||||
const [rhs, lhs] = await Promise.all([
|
||||
this.git.getVersionedFile(commit.repoPath, commit.nextUri.fsPath, commit.nextSha),
|
||||
this.git.getVersionedFile(commit.repoPath, commit.uri.fsPath, commit.sha)
|
||||
this.git.getVersionedFile(args.commit.repoPath, args.commit.nextUri.fsPath, args.commit.nextSha),
|
||||
this.git.getVersionedFile(args.commit.repoPath, args.commit.uri.fsPath, args.commit.sha)
|
||||
]);
|
||||
await commands.executeCommand(BuiltInCommands.Diff, Uri.file(lhs), Uri.file(rhs), `${path.basename(commit.uri.fsPath)} (${commit.shortSha}) \u2194 ${path.basename(commit.nextUri.fsPath)} (${commit.nextShortSha})`);
|
||||
return await commands.executeCommand(BuiltInCommands.RevealLine, { lineNumber: line, at: 'center' });
|
||||
|
||||
await commands.executeCommand(BuiltInCommands.Diff,
|
||||
Uri.file(lhs),
|
||||
Uri.file(rhs),
|
||||
`${path.basename(args.commit.uri.fsPath)} (${args.commit.shortSha}) \u2194 ${path.basename(args.commit.nextUri.fsPath)} (${args.commit.nextShortSha})`,
|
||||
args.showOptions);
|
||||
|
||||
// TODO: Figure out how to focus the left pane
|
||||
return await commands.executeCommand(BuiltInCommands.RevealLine, { lineNumber: args.line, at: 'center' });
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'DiffWithNextCommand', 'getVersionedFile');
|
||||
|
||||
@@ -1,52 +1,47 @@
|
||||
'use strict';
|
||||
import { Iterables } from '../system';
|
||||
import { commands, Range, TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCommand, Commands } from './common';
|
||||
import { commands, Range, TextDocumentShowOptions, TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCommand, Commands, getCommandUri } from './common';
|
||||
import { BuiltInCommands } from '../constants';
|
||||
import { GitCommit, GitService, GitUri } from '../gitService';
|
||||
import { Logger } from '../logger';
|
||||
import * as moment from 'moment';
|
||||
import * as path from 'path';
|
||||
|
||||
export interface DiffWithPreviousCommandArgs {
|
||||
commit?: GitCommit;
|
||||
line?: number;
|
||||
range?: Range;
|
||||
showOptions?: TextDocumentShowOptions;
|
||||
}
|
||||
|
||||
export class DiffWithPreviousCommand extends ActiveEditorCommand {
|
||||
|
||||
constructor(private git: GitService) {
|
||||
super(Commands.DiffWithPrevious);
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor): Promise<any>;
|
||||
async execute(editor: TextEditor, uri: Uri): Promise<any>;
|
||||
async execute(editor: TextEditor, uri: Uri, commit: GitCommit, range?: Range): Promise<any>;
|
||||
async execute(editor: TextEditor, uri: Uri, commit: GitCommit, line?: number): Promise<any>;
|
||||
async execute(editor: TextEditor, uri?: Uri, commit?: GitCommit, rangeOrLine?: Range | number): Promise<any> {
|
||||
if (!(uri instanceof Uri)) {
|
||||
if (!editor || !editor.document) return undefined;
|
||||
uri = editor.document.uri;
|
||||
}
|
||||
async execute(editor: TextEditor, uri?: Uri, args: DiffWithPreviousCommandArgs = {}): Promise<any> {
|
||||
uri = getCommandUri(uri, editor);
|
||||
if (uri === undefined) return undefined;
|
||||
|
||||
let line = (editor && editor.selection.active.line) || 0;
|
||||
if (typeof rangeOrLine === 'number') {
|
||||
line = rangeOrLine || line;
|
||||
rangeOrLine = undefined;
|
||||
}
|
||||
args.line = args.line || (editor === undefined ? 0 : editor.selection.active.line);
|
||||
|
||||
if (!commit || rangeOrLine instanceof Range) {
|
||||
if (args.commit === undefined || args.range !== undefined) {
|
||||
const gitUri = await GitUri.fromUri(uri, this.git);
|
||||
|
||||
try {
|
||||
if (!gitUri.sha) {
|
||||
// If the file is uncommitted, treat it as a DiffWithWorking
|
||||
if (await this.git.isFileUncommitted(gitUri)) {
|
||||
return commands.executeCommand(Commands.DiffWithWorking, uri);
|
||||
}
|
||||
// If the sha is missing or the file is uncommitted, treat it as a DiffWithWorking
|
||||
if (gitUri.sha === undefined && await this.git.isFileUncommitted(gitUri)) {
|
||||
return commands.executeCommand(Commands.DiffWithWorking, uri);
|
||||
}
|
||||
|
||||
const sha = (commit && commit.sha) || gitUri.sha;
|
||||
const sha = args.commit === undefined ? gitUri.sha : args.commit.sha;
|
||||
|
||||
const log = await this.git.getLogForFile(gitUri.repoPath, gitUri.fsPath, undefined, sha ? undefined : 2, rangeOrLine!);
|
||||
if (!log) return window.showWarningMessage(`Unable to open compare. File is probably not under source control`);
|
||||
const log = await this.git.getLogForFile(gitUri.repoPath, gitUri.fsPath, undefined, sha ? undefined : 2, args.range!);
|
||||
if (log === undefined) return window.showWarningMessage(`Unable to open compare. File is probably not under source control`);
|
||||
|
||||
commit = (sha && log.commits.get(sha)) || Iterables.first(log.commits.values());
|
||||
args.commit = (sha && log.commits.get(sha)) || Iterables.first(log.commits.values());
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'DiffWithPreviousCommand', `getLogForFile(${gitUri.repoPath}, ${gitUri.fsPath})`);
|
||||
@@ -54,18 +49,22 @@ export class DiffWithPreviousCommand extends ActiveEditorCommand {
|
||||
}
|
||||
}
|
||||
|
||||
if (!commit.previousSha) {
|
||||
return window.showInformationMessage(`Commit ${commit.shortSha} (${commit.author}, ${moment(commit.date).fromNow()}) has no previous commit`);
|
||||
}
|
||||
if (args.commit.previousSha === undefined) return window.showInformationMessage(`Commit ${args.commit.shortSha} (${args.commit.author}, ${moment(args.commit.date).fromNow()}) has no previous commit`);
|
||||
|
||||
try {
|
||||
const [rhs, lhs] = await Promise.all([
|
||||
this.git.getVersionedFile(commit.repoPath, commit.uri.fsPath, commit.sha),
|
||||
this.git.getVersionedFile(commit.repoPath, commit.previousUri.fsPath, commit.previousSha)
|
||||
this.git.getVersionedFile(args.commit.repoPath, args.commit.uri.fsPath, args.commit.sha),
|
||||
this.git.getVersionedFile(args.commit.repoPath, args.commit.previousUri.fsPath, args.commit.previousSha)
|
||||
]);
|
||||
await commands.executeCommand(BuiltInCommands.Diff, Uri.file(lhs), Uri.file(rhs), `${path.basename(commit.previousUri.fsPath)} (${commit.previousShortSha}) \u2194 ${path.basename(commit.uri.fsPath)} (${commit.shortSha})`);
|
||||
|
||||
await commands.executeCommand(BuiltInCommands.Diff,
|
||||
Uri.file(lhs),
|
||||
Uri.file(rhs),
|
||||
`${path.basename(args.commit.previousUri.fsPath)} (${args.commit.previousShortSha}) \u2194 ${path.basename(args.commit.uri.fsPath)} (${args.commit.shortSha})`,
|
||||
args.showOptions);
|
||||
|
||||
// TODO: Figure out how to focus the left pane
|
||||
return await commands.executeCommand(BuiltInCommands.RevealLine, { lineNumber: line, at: 'center' });
|
||||
return await commands.executeCommand(BuiltInCommands.RevealLine, { lineNumber: args.line, at: 'center' });
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'DiffWithPreviousCommand', 'getVersionedFile');
|
||||
|
||||
@@ -1,34 +1,35 @@
|
||||
'use strict';
|
||||
// import { Iterables } from '../system';
|
||||
import { commands, TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCommand, Commands } from './common';
|
||||
import { commands, TextDocumentShowOptions, TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCommand, Commands, getCommandUri } from './common';
|
||||
import { BuiltInCommands } from '../constants';
|
||||
import { GitCommit, GitService, GitUri } from '../gitService';
|
||||
import { Logger } from '../logger';
|
||||
import * as path from 'path';
|
||||
|
||||
export interface DiffWithWorkingCommandArgs {
|
||||
commit?: GitCommit;
|
||||
line?: number;
|
||||
showOptions?: TextDocumentShowOptions;
|
||||
}
|
||||
|
||||
export class DiffWithWorkingCommand extends ActiveEditorCommand {
|
||||
|
||||
constructor(private git: GitService) {
|
||||
super(Commands.DiffWithWorking);
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor): Promise<any>;
|
||||
async execute(editor: TextEditor, uri: Uri): Promise<any>;
|
||||
async execute(editor: TextEditor, uri?: Uri, commit?: GitCommit, line?: number): Promise<any> {
|
||||
if (!(uri instanceof Uri)) {
|
||||
if (!editor || !editor.document) return undefined;
|
||||
uri = editor.document.uri;
|
||||
}
|
||||
async execute(editor: TextEditor, uri?: Uri, args: DiffWithWorkingCommandArgs = {}): Promise<any> {
|
||||
uri = getCommandUri(uri, editor);
|
||||
if (uri === undefined) return undefined;
|
||||
|
||||
line = line || (editor && editor.selection.active.line) || 0;
|
||||
args.line = args.line || (editor === undefined ? 0 : editor.selection.active.line);
|
||||
|
||||
if (!commit || GitService.isUncommitted(commit.sha)) {
|
||||
if (args.commit === undefined || GitService.isUncommitted(args.commit.sha)) {
|
||||
const gitUri = await GitUri.fromUri(uri, this.git);
|
||||
|
||||
try {
|
||||
commit = await this.git.getLogCommit(gitUri.repoPath, gitUri.fsPath, gitUri.sha, { firstIfMissing: true });
|
||||
if (!commit) return window.showWarningMessage(`Unable to open compare. File is probably not under source control`);
|
||||
args.commit = await this.git.getLogCommit(gitUri.repoPath, gitUri.fsPath, gitUri.sha, { firstIfMissing: true });
|
||||
if (args.commit === undefined) return window.showWarningMessage(`Unable to open compare. File is probably not under source control`);
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'DiffWithWorkingCommand', `getLogCommit(${gitUri.repoPath}, ${gitUri.fsPath}, ${gitUri.sha})`);
|
||||
@@ -42,9 +43,16 @@ export class DiffWithWorkingCommand extends ActiveEditorCommand {
|
||||
if (workingFileName === undefined) return undefined;
|
||||
|
||||
try {
|
||||
const compare = await this.git.getVersionedFile(commit.repoPath, commit.uri.fsPath, commit.sha);
|
||||
await commands.executeCommand(BuiltInCommands.Diff, Uri.file(compare), Uri.file(path.resolve(gitUri.repoPath, workingFileName)), `${path.basename(commit.uri.fsPath)} (${commit.shortSha}) \u2194 ${path.basename(workingFileName)}`);
|
||||
return await commands.executeCommand(BuiltInCommands.RevealLine, { lineNumber: line, at: 'center' });
|
||||
const compare = await this.git.getVersionedFile(args.commit.repoPath, args.commit.uri.fsPath, args.commit.sha);
|
||||
|
||||
await commands.executeCommand(BuiltInCommands.Diff,
|
||||
Uri.file(compare),
|
||||
Uri.file(path.resolve(gitUri.repoPath, workingFileName)),
|
||||
`${path.basename(args.commit.uri.fsPath)} (${args.commit.shortSha}) \u2194 ${path.basename(workingFileName)}`,
|
||||
args.showOptions);
|
||||
|
||||
// TODO: Figure out how to focus the left pane
|
||||
return await commands.executeCommand(BuiltInCommands.RevealLine, { lineNumber: args.line, at: 'center' });
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'DiffWithWorkingCommand', 'getVersionedFile');
|
||||
|
||||
@@ -1,142 +1,137 @@
|
||||
'use strict';
|
||||
import { commands, Disposable, QuickPickItem } from 'vscode';
|
||||
import { CommandContext, setCommandContext } from './common';
|
||||
import { ExtensionKey } from '../constants';
|
||||
import { CommandQuickPickItem, OpenFileCommandQuickPickItem } from '../quickPicks';
|
||||
import { Logger } from '../logger';
|
||||
|
||||
const keyNoopCommand = Object.create(null) as QuickPickItem;
|
||||
export { keyNoopCommand as KeyNoopCommand };
|
||||
|
||||
export declare type Keys = 'left' | 'right' | ',' | '.';
|
||||
export const keys: Keys[] = [
|
||||
'left',
|
||||
'right',
|
||||
',',
|
||||
'.'
|
||||
];
|
||||
|
||||
'use strict';
|
||||
import { commands, Disposable } from 'vscode';
|
||||
import { CommandContext, setCommandContext } from './common';
|
||||
import { ExtensionKey } from '../constants';
|
||||
import { QuickPickItem } from '../quickPicks';
|
||||
import { Logger } from '../logger';
|
||||
|
||||
const keyNoopCommand = Object.create(null) as QuickPickItem;
|
||||
export { keyNoopCommand as KeyNoopCommand };
|
||||
|
||||
export declare type Keys = 'left' | 'right' | ',' | '.';
|
||||
export const keys: Keys[] = [
|
||||
'left',
|
||||
'right',
|
||||
',',
|
||||
'.'
|
||||
];
|
||||
|
||||
export declare type KeyMapping = { [id: string]: (QuickPickItem | (() => Promise<QuickPickItem>) | undefined) };
|
||||
let mappings: KeyMapping[] = [];
|
||||
|
||||
let _instance: Keyboard;
|
||||
|
||||
export class KeyboardScope extends Disposable {
|
||||
|
||||
constructor(private mapping: KeyMapping) {
|
||||
super(() => this.dispose());
|
||||
|
||||
for (const key in mapping) {
|
||||
mapping[key] = mapping[key] || keyNoopCommand;
|
||||
}
|
||||
}
|
||||
|
||||
async dispose() {
|
||||
const index = mappings.indexOf(this.mapping);
|
||||
Logger.log('KeyboardScope.dispose', mappings.length, index);
|
||||
if (index === (mappings.length - 1)) {
|
||||
mappings.pop();
|
||||
await this.updateKeyCommandsContext(mappings[mappings.length - 1]);
|
||||
}
|
||||
else {
|
||||
mappings.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
async begin() {
|
||||
mappings.push(this.mapping);
|
||||
await this.updateKeyCommandsContext(this.mapping);
|
||||
return this;
|
||||
}
|
||||
|
||||
async clearKeyCommand(key: Keys) {
|
||||
const mapping = mappings[mappings.length - 1];
|
||||
if (mapping !== this.mapping || !mapping[key]) return;
|
||||
|
||||
Logger.log('KeyboardScope.clearKeyCommand', mappings.length, key);
|
||||
mapping[key] = undefined;
|
||||
await setCommandContext(`${CommandContext.Key}:${key}`, false);
|
||||
}
|
||||
|
||||
async setKeyCommand(key: Keys, command: QuickPickItem | (() => Promise<QuickPickItem>)) {
|
||||
const mapping = mappings[mappings.length - 1];
|
||||
if (mapping !== this.mapping) return;
|
||||
|
||||
Logger.log('KeyboardScope.setKeyCommand', mappings.length, key, !!mapping[key]);
|
||||
|
||||
if (!mapping[key]) {
|
||||
mapping[key] = command;
|
||||
await setCommandContext(`${CommandContext.Key}:${key}`, true);
|
||||
}
|
||||
else {
|
||||
mapping[key] = command;
|
||||
}
|
||||
}
|
||||
|
||||
private async updateKeyCommandsContext(mapping: KeyMapping) {
|
||||
const promises = [];
|
||||
for (const key of keys) {
|
||||
promises.push(setCommandContext(`${CommandContext.Key}:${key}`, !!(mapping && mapping[key])));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
}
|
||||
}
|
||||
|
||||
export class Keyboard extends Disposable {
|
||||
|
||||
static get instance(): Keyboard {
|
||||
return _instance;
|
||||
}
|
||||
|
||||
private _disposable: Disposable;
|
||||
|
||||
constructor() {
|
||||
super(() => this.dispose());
|
||||
|
||||
const subscriptions: Disposable[] = [];
|
||||
|
||||
for (const key of keys) {
|
||||
subscriptions.push(commands.registerCommand(`${ExtensionKey}.key.${key}`, () => this.execute(key), this));
|
||||
}
|
||||
|
||||
this._disposable = Disposable.from(...subscriptions);
|
||||
|
||||
_instance = this;
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this._disposable && this._disposable.dispose();
|
||||
}
|
||||
|
||||
async beginScope(mapping?: KeyMapping): Promise<KeyboardScope> {
|
||||
Logger.log('Keyboard.beginScope', mappings.length);
|
||||
return await new KeyboardScope(mapping ? Object.assign(Object.create(null), mapping) : Object.create(null)).begin();
|
||||
}
|
||||
|
||||
async execute(key: Keys): Promise<{} | undefined> {
|
||||
if (!mappings.length) return undefined;
|
||||
|
||||
try {
|
||||
const mapping = mappings[mappings.length - 1];
|
||||
|
||||
let command = mapping[key] as CommandQuickPickItem | (() => Promise<CommandQuickPickItem>);
|
||||
if (typeof command === 'function') {
|
||||
command = await command();
|
||||
}
|
||||
if (!command || !(command instanceof CommandQuickPickItem)) return undefined;
|
||||
|
||||
Logger.log('Keyboard.execute', key);
|
||||
|
||||
if (command instanceof OpenFileCommandQuickPickItem) {
|
||||
// Have to open this pinned right now, because vscode doesn't have a way to open a unpinned, but unfocused editor
|
||||
return await command.execute(true);
|
||||
}
|
||||
|
||||
return await command.execute();
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'Keyboard.execute');
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
let mappings: KeyMapping[] = [];
|
||||
|
||||
let _instance: Keyboard;
|
||||
|
||||
export class KeyboardScope extends Disposable {
|
||||
|
||||
constructor(private mapping: KeyMapping) {
|
||||
super(() => this.dispose());
|
||||
|
||||
for (const key in mapping) {
|
||||
mapping[key] = mapping[key] || keyNoopCommand;
|
||||
}
|
||||
}
|
||||
|
||||
async dispose() {
|
||||
const index = mappings.indexOf(this.mapping);
|
||||
Logger.log('KeyboardScope.dispose', mappings.length, index);
|
||||
if (index === (mappings.length - 1)) {
|
||||
mappings.pop();
|
||||
await this.updateKeyCommandsContext(mappings[mappings.length - 1]);
|
||||
}
|
||||
else {
|
||||
mappings.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
async begin() {
|
||||
mappings.push(this.mapping);
|
||||
await this.updateKeyCommandsContext(this.mapping);
|
||||
return this;
|
||||
}
|
||||
|
||||
async clearKeyCommand(key: Keys) {
|
||||
const mapping = mappings[mappings.length - 1];
|
||||
if (mapping !== this.mapping || !mapping[key]) return;
|
||||
|
||||
Logger.log('KeyboardScope.clearKeyCommand', mappings.length, key);
|
||||
mapping[key] = undefined;
|
||||
await setCommandContext(`${CommandContext.Key}:${key}`, false);
|
||||
}
|
||||
|
||||
async setKeyCommand(key: Keys, command: QuickPickItem | (() => Promise<QuickPickItem>)) {
|
||||
const mapping = mappings[mappings.length - 1];
|
||||
if (mapping !== this.mapping) return;
|
||||
|
||||
Logger.log('KeyboardScope.setKeyCommand', mappings.length, key, !!mapping[key]);
|
||||
|
||||
if (!mapping[key]) {
|
||||
mapping[key] = command;
|
||||
await setCommandContext(`${CommandContext.Key}:${key}`, true);
|
||||
}
|
||||
else {
|
||||
mapping[key] = command;
|
||||
}
|
||||
}
|
||||
|
||||
private async updateKeyCommandsContext(mapping: KeyMapping) {
|
||||
const promises = [];
|
||||
for (const key of keys) {
|
||||
promises.push(setCommandContext(`${CommandContext.Key}:${key}`, !!(mapping && mapping[key])));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
}
|
||||
}
|
||||
|
||||
export class Keyboard extends Disposable {
|
||||
|
||||
static get instance(): Keyboard {
|
||||
return _instance;
|
||||
}
|
||||
|
||||
private _disposable: Disposable;
|
||||
|
||||
constructor() {
|
||||
super(() => this.dispose());
|
||||
|
||||
const subscriptions: Disposable[] = [];
|
||||
|
||||
for (const key of keys) {
|
||||
subscriptions.push(commands.registerCommand(`${ExtensionKey}.key.${key}`, () => this.execute(key), this));
|
||||
}
|
||||
|
||||
this._disposable = Disposable.from(...subscriptions);
|
||||
|
||||
_instance = this;
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this._disposable && this._disposable.dispose();
|
||||
}
|
||||
|
||||
async beginScope(mapping?: KeyMapping): Promise<KeyboardScope> {
|
||||
Logger.log('Keyboard.beginScope', mappings.length);
|
||||
return await new KeyboardScope(mapping ? Object.assign(Object.create(null), mapping) : Object.create(null)).begin();
|
||||
}
|
||||
|
||||
async execute(key: Keys): Promise<{} | undefined> {
|
||||
if (!mappings.length) return undefined;
|
||||
|
||||
try {
|
||||
const mapping = mappings[mappings.length - 1];
|
||||
|
||||
let command = mapping[key] as QuickPickItem | (() => Promise<QuickPickItem>);
|
||||
if (typeof command === 'function') {
|
||||
command = await command();
|
||||
}
|
||||
if (!command || typeof command.onDidPressKey !== 'function') return undefined;
|
||||
|
||||
Logger.log('Keyboard.execute', key);
|
||||
|
||||
return await command.onDidPressKey(key);
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'Keyboard.execute');
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,33 +1,35 @@
|
||||
'use strict';
|
||||
import { TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCommand, Commands, openEditor } from './common';
|
||||
import { TextDocumentShowOptions, TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCommand, Commands, getCommandUri, openEditor } from './common';
|
||||
import { GitService } from '../gitService';
|
||||
import { Logger } from '../logger';
|
||||
|
||||
export interface OpenChangedFilesCommandArgs {
|
||||
uris?: Uri[];
|
||||
}
|
||||
|
||||
export class OpenChangedFilesCommand extends ActiveEditorCommand {
|
||||
|
||||
constructor(private git: GitService) {
|
||||
super(Commands.OpenChangedFiles);
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor, uri?: Uri, uris?: Uri[]) {
|
||||
if (!(uri instanceof Uri)) {
|
||||
uri = editor && editor.document && editor.document.uri;
|
||||
}
|
||||
async execute(editor: TextEditor, uri?: Uri, args: OpenChangedFilesCommandArgs = {}) {
|
||||
uri = getCommandUri(uri, editor);
|
||||
|
||||
try {
|
||||
if (!uris) {
|
||||
if (args.uris === undefined) {
|
||||
const repoPath = await this.git.getRepoPathFromUri(uri);
|
||||
if (!repoPath) return window.showWarningMessage(`Unable to open changed files`);
|
||||
if (repoPath === undefined) return window.showWarningMessage(`Unable to open changed files`);
|
||||
|
||||
const status = await this.git.getStatusForRepo(repoPath);
|
||||
if (!status) return window.showWarningMessage(`Unable to open changed files`);
|
||||
if (status === undefined) return window.showWarningMessage(`Unable to open changed files`);
|
||||
|
||||
uris = status.files.filter(_ => _.status !== 'D').map(_ => _.Uri);
|
||||
args.uris = status.files.filter(_ => _.status !== 'D').map(_ => _.Uri);
|
||||
}
|
||||
|
||||
for (const uri of uris) {
|
||||
await openEditor(uri, true);
|
||||
for (const uri of args.uris) {
|
||||
await openEditor(uri, { preserveFocus: true, preview: false } as TextDocumentShowOptions);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
'use strict';
|
||||
import { Arrays } from '../system';
|
||||
import { commands, TextEditor, TextEditorEdit, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCommand, Commands } from './common';
|
||||
import { ActiveEditorCommand, Commands, getCommandUri } from './common';
|
||||
import { GitCommit, GitService, GitUri } from '../gitService';
|
||||
import { Logger } from '../logger';
|
||||
import { OpenInRemoteCommandArgs } from './openInRemote';
|
||||
|
||||
export class OpenCommitInRemoteCommand extends ActiveEditorCommand {
|
||||
|
||||
@@ -12,24 +13,21 @@ export class OpenCommitInRemoteCommand extends ActiveEditorCommand {
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor, edit: TextEditorEdit, uri?: Uri) {
|
||||
if (!(uri instanceof Uri)) {
|
||||
if (!editor || !editor.document) return undefined;
|
||||
uri = editor.document.uri;
|
||||
}
|
||||
|
||||
if ((editor && editor.document && editor.document.isDirty) || !uri) return undefined;
|
||||
uri = getCommandUri(uri, editor);
|
||||
if (uri === undefined) return undefined;
|
||||
if (editor !== undefined && editor.document !== undefined && editor.document.isDirty) return undefined;
|
||||
|
||||
const gitUri = await GitUri.fromUri(uri, this.git);
|
||||
if (!gitUri.repoPath) return undefined;
|
||||
|
||||
const line = (editor && editor.selection.active.line) || gitUri.offset;
|
||||
const line = editor === undefined ? gitUri.offset : editor.selection.active.line;
|
||||
|
||||
try {
|
||||
const blameline = line - gitUri.offset;
|
||||
if (blameline < 0) return undefined;
|
||||
|
||||
const blame = await this.git.getBlameForLine(gitUri, blameline);
|
||||
if (!blame) return window.showWarningMessage(`Unable to open commit in remote provider. File is probably not under source control`);
|
||||
if (blame === undefined) return window.showWarningMessage(`Unable to open commit in remote provider. File is probably not under source control`);
|
||||
|
||||
let commit = blame.commit;
|
||||
// If the line is uncommitted, find the previous commit
|
||||
@@ -38,7 +36,13 @@ export class OpenCommitInRemoteCommand extends ActiveEditorCommand {
|
||||
}
|
||||
|
||||
const remotes = Arrays.uniqueBy(await this.git.getRemotes(gitUri.repoPath), _ => _.url, _ => !!_.provider);
|
||||
return commands.executeCommand(Commands.OpenInRemote, uri, remotes, 'commit', [commit.sha]);
|
||||
return commands.executeCommand(Commands.OpenInRemote, uri, {
|
||||
resource: {
|
||||
type: 'commit',
|
||||
sha: commit.sha
|
||||
},
|
||||
remotes
|
||||
} as OpenInRemoteCommandArgs);
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'OpenCommitInRemoteCommand');
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
'use strict';
|
||||
import { Arrays } from '../system';
|
||||
import { commands, Range, TextEditor, TextEditorEdit, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCommand, Commands } from './common';
|
||||
import { ActiveEditorCommand, Commands, getCommandUri } from './common';
|
||||
import { GitService, GitUri } from '../gitService';
|
||||
import { Logger } from '../logger';
|
||||
import { OpenInRemoteCommandArgs } from './openInRemote';
|
||||
|
||||
export class OpenFileInRemoteCommand extends ActiveEditorCommand {
|
||||
|
||||
@@ -12,12 +13,8 @@ export class OpenFileInRemoteCommand extends ActiveEditorCommand {
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor, edit: TextEditorEdit, uri?: Uri) {
|
||||
if (!(uri instanceof Uri)) {
|
||||
if (!editor || !editor.document) return undefined;
|
||||
uri = editor.document.uri;
|
||||
}
|
||||
|
||||
if (!uri) return undefined;
|
||||
uri = getCommandUri(uri, editor);
|
||||
if (uri === undefined) return undefined;
|
||||
|
||||
const gitUri = await GitUri.fromUri(uri, this.git);
|
||||
if (!gitUri.repoPath) return undefined;
|
||||
@@ -26,8 +23,18 @@ export class OpenFileInRemoteCommand extends ActiveEditorCommand {
|
||||
|
||||
try {
|
||||
const remotes = Arrays.uniqueBy(await this.git.getRemotes(gitUri.repoPath), _ => _.url, _ => !!_.provider);
|
||||
const range = editor && new Range(editor.selection.start.with({ line: editor.selection.start.line + 1 }), editor.selection.end.with({ line: editor.selection.end.line + 1 }));
|
||||
return commands.executeCommand(Commands.OpenInRemote, uri, remotes, 'file', [gitUri.getRelativePath(), branch === undefined ? 'Current' : branch.name, gitUri.sha, range]);
|
||||
const range = editor === undefined ? undefined : new Range(editor.selection.start.with({ line: editor.selection.start.line + 1 }), editor.selection.end.with({ line: editor.selection.end.line + 1 }));
|
||||
|
||||
return commands.executeCommand(Commands.OpenInRemote, uri, {
|
||||
resource: {
|
||||
type: 'file',
|
||||
branch: branch === undefined ? 'Current' : branch.name,
|
||||
fileName: gitUri.getRelativePath(),
|
||||
range: range,
|
||||
sha: gitUri.sha
|
||||
},
|
||||
remotes
|
||||
} as OpenInRemoteCommandArgs);
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'OpenFileInRemoteCommand');
|
||||
|
||||
@@ -1,50 +1,73 @@
|
||||
'use strict';
|
||||
import { TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCommand, Commands } from './common';
|
||||
import { GitRemote, RemoteOpenType } from '../gitService';
|
||||
import { ActiveEditorCommand, Commands, getCommandUri } from './common';
|
||||
import { GitLogCommit, GitRemote, RemoteResource } from '../gitService';
|
||||
import { Logger } from '../logger';
|
||||
import { CommandQuickPickItem, OpenRemoteCommandQuickPickItem, RemotesQuickPick } from '../quickPicks';
|
||||
|
||||
export interface OpenInRemoteCommandArgs {
|
||||
remotes?: GitRemote[];
|
||||
resource?: RemoteResource;
|
||||
|
||||
goBackCommand?: CommandQuickPickItem;
|
||||
}
|
||||
|
||||
export class OpenInRemoteCommand extends ActiveEditorCommand {
|
||||
|
||||
constructor() {
|
||||
super(Commands.OpenInRemote);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
async execute(editor: TextEditor, uri?: Uri, args: OpenInRemoteCommandArgs = {}) {
|
||||
uri = getCommandUri(uri, editor);
|
||||
|
||||
try {
|
||||
if (remotes === undefined) return undefined;
|
||||
if (type === undefined) throw new Error(`Invalid type ${type}`);
|
||||
if (args.remotes === undefined || args.resource === undefined) return undefined;
|
||||
|
||||
if (remotes.length === 1) {
|
||||
const command = new OpenRemoteCommandQuickPickItem(remotes[0], type, ...args);
|
||||
if (args.remotes.length === 1) {
|
||||
const command = new OpenRemoteCommandQuickPickItem(args.remotes[0], args.resource);
|
||||
return command.execute();
|
||||
}
|
||||
|
||||
let placeHolder: string = '';
|
||||
switch (type) {
|
||||
switch (args.resource.type) {
|
||||
case 'branch':
|
||||
placeHolder = `open ${args[0]} branch in\u2026`;
|
||||
placeHolder = `open ${args.resource.branch} branch in\u2026`;
|
||||
break;
|
||||
|
||||
case 'commit':
|
||||
const shortSha = args[0].substring(0, 8);
|
||||
const shortSha = args.resource.sha.substring(0, 8);
|
||||
placeHolder = `open commit ${shortSha} in\u2026`;
|
||||
break;
|
||||
case 'file':
|
||||
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`;
|
||||
case 'file':
|
||||
if (args.resource.commit !== undefined && args.resource.commit instanceof GitLogCommit) {
|
||||
if (args.resource.commit.status === 'D') {
|
||||
args.resource.sha = args.resource.commit.previousSha;
|
||||
placeHolder = `open ${args.resource.fileName} \u00a0\u2022\u00a0 ${args.resource.commit.previousShortSha} in\u2026`;
|
||||
}
|
||||
else {
|
||||
args.resource.sha = args.resource.commit.sha;
|
||||
placeHolder = `open ${args.resource.fileName} \u00a0\u2022\u00a0 ${args.resource.commit.shortSha} in\u2026`;
|
||||
}
|
||||
}
|
||||
else {
|
||||
const shortFileSha = args.resource.sha === undefined ? '' : args.resource.sha.substring(0, 8);
|
||||
const shaSuffix = shortFileSha ? ` \u00a0\u2022\u00a0 ${shortFileSha}` : '';
|
||||
|
||||
placeHolder = `open ${args.resource.fileName}${shaSuffix} in\u2026`;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'working-file':
|
||||
placeHolder = `open ${args.resource.fileName} in\u2026`;
|
||||
break;
|
||||
}
|
||||
|
||||
const pick = await RemotesQuickPick.show(remotes, placeHolder, type, args, goBackCommand);
|
||||
return pick && pick.execute();
|
||||
const pick = await RemotesQuickPick.show(args.remotes, placeHolder, args.resource, args.goBackCommand);
|
||||
if (pick === undefined) return undefined;
|
||||
|
||||
return pick.execute();
|
||||
|
||||
}
|
||||
catch (ex) {
|
||||
|
||||
@@ -4,19 +4,21 @@ import { BlameAnnotationController } from '../blameAnnotationController';
|
||||
import { Commands, EditorCommand } from './common';
|
||||
import { Logger } from '../logger';
|
||||
|
||||
export interface ShowBlameCommandArgs {
|
||||
sha?: string;
|
||||
}
|
||||
|
||||
export class ShowBlameCommand extends EditorCommand {
|
||||
|
||||
constructor(private annotationController: BlameAnnotationController) {
|
||||
super(Commands.ShowBlame);
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor, edit: TextEditorEdit, uri?: Uri, sha?: string): Promise<any> {
|
||||
try {
|
||||
if (sha) {
|
||||
return this.annotationController.showBlameAnnotation(editor, sha);
|
||||
}
|
||||
async execute(editor: TextEditor, edit: TextEditorEdit, uri?: Uri, args: ShowBlameCommandArgs = {}): Promise<any> {
|
||||
if (editor !== undefined && editor.document !== undefined && editor.document.isDirty) return undefined;
|
||||
|
||||
return this.annotationController.showBlameAnnotation(editor, editor.selection.active.line);
|
||||
try {
|
||||
return this.annotationController.showBlameAnnotation(editor, args.sha !== undefined ? args.sha : editor.selection.active.line);
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'ShowBlameCommand');
|
||||
|
||||
@@ -1,35 +1,40 @@
|
||||
'use strict';
|
||||
import { commands, Position, Range, TextEditor, TextEditorEdit, Uri, window } from 'vscode';
|
||||
import { Commands, EditorCommand } from './common';
|
||||
import { Commands, EditorCommand, getCommandUri } from './common';
|
||||
import { BuiltInCommands } from '../constants';
|
||||
import { GitService, GitUri } from '../gitService';
|
||||
import { Logger } from '../logger';
|
||||
|
||||
export interface ShowBlameHistoryCommandArgs {
|
||||
line?: number;
|
||||
position?: Position;
|
||||
range?: Range;
|
||||
sha?: string;
|
||||
}
|
||||
|
||||
export class ShowBlameHistoryCommand extends EditorCommand {
|
||||
|
||||
constructor(private git: GitService) {
|
||||
super(Commands.ShowBlameHistory);
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor, edit: TextEditorEdit, uri?: Uri, range?: Range, position?: Position, sha?: string, line?: number) {
|
||||
if (!(uri instanceof Uri)) {
|
||||
if (!editor.document) return undefined;
|
||||
uri = editor.document.uri;
|
||||
}
|
||||
async execute(editor: TextEditor, edit: TextEditorEdit, uri?: Uri, args: ShowBlameHistoryCommandArgs = {}) {
|
||||
uri = getCommandUri(uri, editor);
|
||||
if (uri === undefined) return undefined;
|
||||
|
||||
if (range == null || position == null) {
|
||||
if (args.range == null || args.position == null) {
|
||||
// If the command is executed manually -- treat it as a click on the root lens (i.e. show blame for the whole file)
|
||||
range = editor.document.validateRange(new Range(0, 0, 1000000, 1000000));
|
||||
position = editor.document.validateRange(new Range(0, 0, 0, 1000000)).start;
|
||||
args.range = editor.document.validateRange(new Range(0, 0, 1000000, 1000000));
|
||||
args.position = editor.document.validateRange(new Range(0, 0, 0, 1000000)).start;
|
||||
}
|
||||
|
||||
const gitUri = await GitUri.fromUri(uri, this.git);
|
||||
|
||||
try {
|
||||
const locations = await this.git.getBlameLocations(gitUri, range, sha, line);
|
||||
if (!locations) return window.showWarningMessage(`Unable to show blame history. File is probably not under source control`);
|
||||
const locations = await this.git.getBlameLocations(gitUri, args.range, args.sha, args.line);
|
||||
if (locations === undefined) return window.showWarningMessage(`Unable to show blame history. File is probably not under source control`);
|
||||
|
||||
return commands.executeCommand(BuiltInCommands.ShowReferences, uri, position, locations);
|
||||
return commands.executeCommand(BuiltInCommands.ShowReferences, uri, args.position, locations);
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'ShowBlameHistoryCommand', 'getBlameLocations');
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
'use strict';
|
||||
import { commands, InputBoxOptions, TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCachedCommand, Commands } from './common';
|
||||
import { ActiveEditorCachedCommand, Commands, getCommandUri } from './common';
|
||||
import { GitRepoSearchBy, GitService, GitUri } from '../gitService';
|
||||
import { Logger } from '../logger';
|
||||
import { CommandQuickPickItem, CommitsQuickPick } from '../quickPicks';
|
||||
import { ShowQuickCommitDetailsCommandArgs } from './showQuickCommitDetails';
|
||||
|
||||
const searchByRegex = /^([@:#])/;
|
||||
const searchByMap = new Map<string, GitRepoSearchBy>([
|
||||
@@ -12,68 +13,73 @@ const searchByMap = new Map<string, GitRepoSearchBy>([
|
||||
['#', GitRepoSearchBy.Sha]
|
||||
]);
|
||||
|
||||
export interface ShowCommitSearchCommandArgs {
|
||||
search?: string;
|
||||
searchBy?: GitRepoSearchBy;
|
||||
|
||||
goBackCommand?: CommandQuickPickItem;
|
||||
}
|
||||
|
||||
export class ShowCommitSearchCommand extends ActiveEditorCachedCommand {
|
||||
|
||||
constructor(private git: GitService) {
|
||||
super(Commands.ShowCommitSearch);
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor, uri?: Uri, search?: string, searchBy?: GitRepoSearchBy, goBackCommand?: CommandQuickPickItem) {
|
||||
if (!(uri instanceof Uri)) {
|
||||
if (!editor || !editor.document) return undefined;
|
||||
uri = editor.document.uri;
|
||||
}
|
||||
async execute(editor: TextEditor, uri?: Uri, args: ShowCommitSearchCommandArgs = {}) {
|
||||
uri = getCommandUri(uri, editor);
|
||||
if (uri === undefined) return undefined;
|
||||
|
||||
const gitUri = await GitUri.fromUri(uri, this.git);
|
||||
if (gitUri.repoPath === undefined) return undefined;
|
||||
|
||||
if (!search || searchBy == null) {
|
||||
search = await window.showInputBox({
|
||||
value: search,
|
||||
if (!args.search || args.searchBy == null) {
|
||||
args.search = await window.showInputBox({
|
||||
value: args.search,
|
||||
prompt: `Please enter a search string`,
|
||||
placeHolder: `search by message, author (use @<name>), files (use :<pattern>), or commit id (use #<sha>)`
|
||||
} as InputBoxOptions);
|
||||
if (search === undefined) return goBackCommand && goBackCommand.execute();
|
||||
if (args.search === undefined) return args.goBackCommand === undefined ? undefined : args.goBackCommand.execute();
|
||||
|
||||
const match = searchByRegex.exec(search);
|
||||
const match = searchByRegex.exec(args.search);
|
||||
if (match && match[1]) {
|
||||
searchBy = searchByMap.get(match[1]);
|
||||
search = search.substring((search[1] === ' ') ? 2 : 1);
|
||||
args.searchBy = searchByMap.get(match[1]);
|
||||
args.search = args.search.substring((args.search[1] === ' ') ? 2 : 1);
|
||||
}
|
||||
else if (GitService.isSha(search)) {
|
||||
searchBy = GitRepoSearchBy.Sha;
|
||||
else if (GitService.isSha(args.search)) {
|
||||
args.searchBy = GitRepoSearchBy.Sha;
|
||||
}
|
||||
else {
|
||||
searchBy = GitRepoSearchBy.Message;
|
||||
args.searchBy = GitRepoSearchBy.Message;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (searchBy === undefined) {
|
||||
searchBy = GitRepoSearchBy.Message;
|
||||
if (args.searchBy === undefined) {
|
||||
args.searchBy = GitRepoSearchBy.Message;
|
||||
}
|
||||
|
||||
const log = await this.git.getLogForRepoSearch(gitUri.repoPath, search, searchBy);
|
||||
const log = await this.git.getLogForRepoSearch(gitUri.repoPath, args.search, args.searchBy);
|
||||
if (log === undefined) return undefined;
|
||||
|
||||
let originalSearch: string | undefined = undefined;
|
||||
let placeHolder: string | undefined = undefined;
|
||||
switch (searchBy) {
|
||||
switch (args.searchBy) {
|
||||
case GitRepoSearchBy.Author:
|
||||
originalSearch = `@${search}`;
|
||||
placeHolder = `commits with author matching '${search}'`;
|
||||
originalSearch = `@${args.search}`;
|
||||
placeHolder = `commits with author matching '${args.search}'`;
|
||||
break;
|
||||
case GitRepoSearchBy.Files:
|
||||
originalSearch = `:${search}`;
|
||||
placeHolder = `commits with files matching '${search}'`;
|
||||
originalSearch = `:${args.search}`;
|
||||
placeHolder = `commits with files matching '${args.search}'`;
|
||||
break;
|
||||
case GitRepoSearchBy.Message:
|
||||
originalSearch = search;
|
||||
placeHolder = `commits with message matching '${search}'`;
|
||||
originalSearch = args.search;
|
||||
placeHolder = `commits with message matching '${args.search}'`;
|
||||
break;
|
||||
case GitRepoSearchBy.Sha:
|
||||
originalSearch = `#${search}`;
|
||||
placeHolder = `commits with id matching '${search}'`;
|
||||
originalSearch = `#${args.search}`;
|
||||
placeHolder = `commits with id matching '${args.search}'`;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -81,20 +87,32 @@ export class ShowCommitSearchCommand extends ActiveEditorCachedCommand {
|
||||
const currentCommand = new CommandQuickPickItem({
|
||||
label: `go back \u21A9`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 to commit search`
|
||||
}, Commands.ShowCommitSearch, [gitUri, originalSearch, undefined, goBackCommand]);
|
||||
}, Commands.ShowCommitSearch, [
|
||||
gitUri,
|
||||
{
|
||||
search: originalSearch,
|
||||
goBackCommand: args.goBackCommand
|
||||
} as ShowCommitSearchCommandArgs
|
||||
]);
|
||||
|
||||
const pick = await CommitsQuickPick.show(this.git, log, placeHolder!, currentCommand);
|
||||
if (!pick) return undefined;
|
||||
if (pick === undefined) return undefined;
|
||||
|
||||
if (pick instanceof CommandQuickPickItem) {
|
||||
return pick.execute();
|
||||
}
|
||||
if (pick instanceof CommandQuickPickItem) return pick.execute();
|
||||
|
||||
return commands.executeCommand(Commands.ShowQuickCommitDetails, new GitUri(pick.commit.uri, pick.commit), pick.commit.sha, pick.commit,
|
||||
new CommandQuickPickItem({
|
||||
label: `go back \u21A9`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 to search for ${placeHolder}`
|
||||
}, Commands.ShowCommitSearch, [gitUri, search, searchBy, goBackCommand]));
|
||||
return commands.executeCommand(Commands.ShowQuickCommitDetails,
|
||||
new GitUri(pick.commit.uri, pick.commit),
|
||||
{
|
||||
sha: pick.commit.sha,
|
||||
commit: pick.commit,
|
||||
goBackCommand: new CommandQuickPickItem({
|
||||
label: `go back \u21A9`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 to search for ${placeHolder}`
|
||||
}, Commands.ShowCommitSearch, [
|
||||
gitUri,
|
||||
args
|
||||
])
|
||||
} as ShowQuickCommitDetailsCommandArgs);
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'ShowCommitSearchCommand');
|
||||
|
||||
@@ -1,34 +1,38 @@
|
||||
'use strict';
|
||||
import { commands, Position, Range, TextEditor, TextEditorEdit, Uri, window } from 'vscode';
|
||||
import { Commands, EditorCommand } from './common';
|
||||
import { Commands, EditorCommand, getCommandUri } from './common';
|
||||
import { BuiltInCommands } from '../constants';
|
||||
import { GitService, GitUri } from '../gitService';
|
||||
import { Logger } from '../logger';
|
||||
|
||||
export interface ShowFileHistoryCommandArgs {
|
||||
line?: number;
|
||||
position?: Position;
|
||||
sha?: string;
|
||||
}
|
||||
|
||||
export class ShowFileHistoryCommand extends EditorCommand {
|
||||
|
||||
constructor(private git: GitService) {
|
||||
super(Commands.ShowFileHistory);
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor, edit: TextEditorEdit, uri?: Uri, position?: Position, sha?: string, line?: number) {
|
||||
if (!(uri instanceof Uri)) {
|
||||
if (!editor.document) return undefined;
|
||||
uri = editor.document.uri;
|
||||
}
|
||||
async execute(editor: TextEditor, edit: TextEditorEdit, uri?: Uri, args: ShowFileHistoryCommandArgs = {}) {
|
||||
uri = getCommandUri(uri, editor);
|
||||
if (uri === undefined) return undefined;
|
||||
|
||||
if (position == null) {
|
||||
if (args.position == null) {
|
||||
// If the command is executed manually -- treat it as a click on the root lens (i.e. show blame for the whole file)
|
||||
position = editor.document.validateRange(new Range(0, 0, 0, 1000000)).start;
|
||||
args.position = editor.document.validateRange(new Range(0, 0, 0, 1000000)).start;
|
||||
}
|
||||
|
||||
const gitUri = await GitUri.fromUri(uri, this.git);
|
||||
|
||||
try {
|
||||
const locations = await this.git.getLogLocations(gitUri, sha, line);
|
||||
if (!locations) return window.showWarningMessage(`Unable to show file history. File is probably not under source control`);
|
||||
const locations = await this.git.getLogLocations(gitUri, args.sha, args.line);
|
||||
if (locations === undefined) return window.showWarningMessage(`Unable to show file history. File is probably not under source control`);
|
||||
|
||||
return commands.executeCommand(BuiltInCommands.ShowReferences, uri, position, locations);
|
||||
return commands.executeCommand(BuiltInCommands.ShowReferences, uri, args.position, locations);
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'ShowFileHistoryCommand', 'getLogLocations');
|
||||
|
||||
@@ -1,9 +1,19 @@
|
||||
'use strict';
|
||||
import { commands, TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCachedCommand, Commands } from './common';
|
||||
import { ActiveEditorCachedCommand, Commands, getCommandUri } from './common';
|
||||
import { GitService, GitUri, IGitLog } from '../gitService';
|
||||
import { Logger } from '../logger';
|
||||
import { BranchesQuickPick, BranchHistoryQuickPick, CommandQuickPickItem } from '../quickPicks';
|
||||
import { ShowQuickCommitDetailsCommandArgs } from './showQuickCommitDetails';
|
||||
|
||||
export interface ShowQuickBranchHistoryCommandArgs {
|
||||
branch?: string;
|
||||
log?: IGitLog;
|
||||
maxCount?: number;
|
||||
|
||||
goBackCommand?: CommandQuickPickItem;
|
||||
nextPageCommand?: CommandQuickPickItem;
|
||||
}
|
||||
|
||||
export class ShowQuickBranchHistoryCommand extends ActiveEditorCachedCommand {
|
||||
|
||||
@@ -11,58 +21,63 @@ export class ShowQuickBranchHistoryCommand extends ActiveEditorCachedCommand {
|
||||
super(Commands.ShowQuickBranchHistory);
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor, uri?: Uri, branch?: string, maxCount?: number, goBackCommand?: CommandQuickPickItem, log?: IGitLog, nextPageCommand?: CommandQuickPickItem) {
|
||||
if (!(uri instanceof Uri)) {
|
||||
uri = editor && editor.document && editor.document.uri;
|
||||
}
|
||||
async execute(editor: TextEditor, uri?: Uri, args: ShowQuickBranchHistoryCommandArgs = {}) {
|
||||
uri = getCommandUri(uri, editor);
|
||||
|
||||
const gitUri = uri && await GitUri.fromUri(uri, this.git);
|
||||
|
||||
if (maxCount == null) {
|
||||
maxCount = this.git.config.advanced.maxQuickHistory;
|
||||
if (args.maxCount == null) {
|
||||
args.maxCount = this.git.config.advanced.maxQuickHistory;
|
||||
}
|
||||
|
||||
let progressCancellation = branch === undefined ? undefined : BranchHistoryQuickPick.showProgress(branch);
|
||||
let progressCancellation = args.branch === undefined ? undefined : BranchHistoryQuickPick.showProgress(args.branch);
|
||||
try {
|
||||
const repoPath = (gitUri && gitUri.repoPath) || this.git.repoPath;
|
||||
if (repoPath === undefined) return window.showWarningMessage(`Unable to show branch history`);
|
||||
|
||||
if (branch === undefined) {
|
||||
if (args.branch === undefined) {
|
||||
const branches = await this.git.getBranches(repoPath);
|
||||
|
||||
const pick = await BranchesQuickPick.show(branches, `Show history for branch\u2026`);
|
||||
if (!pick) return undefined;
|
||||
if (pick === undefined) return undefined;
|
||||
|
||||
if (pick instanceof CommandQuickPickItem) {
|
||||
return pick.execute();
|
||||
}
|
||||
if (pick instanceof CommandQuickPickItem) return pick.execute();
|
||||
|
||||
branch = pick.branch.name;
|
||||
if (branch === undefined) return undefined;
|
||||
args.branch = pick.branch.name;
|
||||
if (args.branch === undefined) return undefined;
|
||||
|
||||
progressCancellation = BranchHistoryQuickPick.showProgress(branch);
|
||||
progressCancellation = BranchHistoryQuickPick.showProgress(args.branch);
|
||||
}
|
||||
|
||||
if (!log) {
|
||||
log = await this.git.getLogForRepo(repoPath, (gitUri && gitUri.sha) || branch, maxCount);
|
||||
if (!log) return window.showWarningMessage(`Unable to show branch history`);
|
||||
if (args.log === undefined) {
|
||||
args.log = await this.git.getLogForRepo(repoPath, (gitUri && gitUri.sha) || args.branch, args.maxCount);
|
||||
if (args.log === undefined) return window.showWarningMessage(`Unable to show branch history`);
|
||||
}
|
||||
|
||||
if (progressCancellation !== undefined && progressCancellation.token.isCancellationRequested) return undefined;
|
||||
|
||||
const pick = await BranchHistoryQuickPick.show(this.git, log, gitUri, branch, progressCancellation!, goBackCommand, nextPageCommand);
|
||||
if (!pick) return undefined;
|
||||
const pick = await BranchHistoryQuickPick.show(this.git, args.log, gitUri, args.branch, progressCancellation!, args.goBackCommand, args.nextPageCommand);
|
||||
if (pick === undefined) return undefined;
|
||||
|
||||
if (pick instanceof CommandQuickPickItem) {
|
||||
return pick.execute();
|
||||
}
|
||||
if (pick instanceof CommandQuickPickItem) return pick.execute();
|
||||
|
||||
return commands.executeCommand(Commands.ShowQuickCommitDetails, new GitUri(pick.commit.uri, pick.commit), pick.commit.sha, pick.commit,
|
||||
new CommandQuickPickItem({
|
||||
label: `go back \u21A9`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 to \u00a0$(git-branch) ${branch} history`
|
||||
}, Commands.ShowQuickBranchHistory, [uri, branch, maxCount, goBackCommand, log]),
|
||||
log);
|
||||
// Create a command to get back to here
|
||||
const currentCommand = new CommandQuickPickItem({
|
||||
label: `go back \u21A9`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 to \u00a0$(git-branch) ${args.branch} history`
|
||||
}, Commands.ShowQuickBranchHistory, [
|
||||
uri,
|
||||
args
|
||||
]);
|
||||
|
||||
return commands.executeCommand(Commands.ShowQuickCommitDetails,
|
||||
new GitUri(pick.commit.uri, pick.commit),
|
||||
{
|
||||
sha: pick.commit.sha,
|
||||
commit: pick.commit,
|
||||
repoLog: args.log,
|
||||
goBackCommand: currentCommand
|
||||
} as ShowQuickCommitDetailsCommandArgs);
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'ShowQuickBranchHistoryCommand');
|
||||
|
||||
@@ -1,43 +1,50 @@
|
||||
'use strict';
|
||||
import { commands, TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCachedCommand, Commands } from './common';
|
||||
import { ActiveEditorCachedCommand, Commands, getCommandUri } from './common';
|
||||
import { GitCommit, GitLogCommit, GitService, GitUri, IGitLog } from '../gitService';
|
||||
import { Logger } from '../logger';
|
||||
import { CommandQuickPickItem, CommitDetailsQuickPick, CommitWithFileStatusQuickPickItem } from '../quickPicks';
|
||||
import { ShowQuickCommitFileDetailsCommandArgs } from './showQuickCommitFileDetails';
|
||||
import * as path from 'path';
|
||||
|
||||
export interface ShowQuickCommitDetailsCommandArgs {
|
||||
sha?: string;
|
||||
commit?: GitCommit | GitLogCommit;
|
||||
repoLog?: IGitLog;
|
||||
|
||||
goBackCommand?: CommandQuickPickItem;
|
||||
}
|
||||
|
||||
export class ShowQuickCommitDetailsCommand extends ActiveEditorCachedCommand {
|
||||
|
||||
constructor(private git: GitService) {
|
||||
super(Commands.ShowQuickCommitDetails);
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor, uri?: Uri, sha?: string, commit?: GitCommit | GitLogCommit, goBackCommand?: CommandQuickPickItem, repoLog?: IGitLog) {
|
||||
if (!(uri instanceof Uri)) {
|
||||
if (!editor || !editor.document) return undefined;
|
||||
uri = editor.document.uri;
|
||||
}
|
||||
async execute(editor: TextEditor, uri?: Uri, args: ShowQuickCommitDetailsCommandArgs = {}) {
|
||||
uri = getCommandUri(uri, editor);
|
||||
if (uri === undefined) return undefined;
|
||||
|
||||
const gitUri = await GitUri.fromUri(uri, this.git);
|
||||
|
||||
let repoPath = gitUri.repoPath;
|
||||
let workingFileName = path.relative(repoPath || '', gitUri.fsPath);
|
||||
|
||||
if (!sha) {
|
||||
if (!editor) return undefined;
|
||||
if (args.sha === undefined) {
|
||||
if (editor === undefined) return undefined;
|
||||
|
||||
const blameline = editor.selection.active.line - gitUri.offset;
|
||||
if (blameline < 0) return undefined;
|
||||
|
||||
try {
|
||||
const blame = await this.git.getBlameForLine(gitUri, blameline);
|
||||
if (!blame) return window.showWarningMessage(`Unable to show commit details. File is probably not under source control`);
|
||||
if (blame === undefined) return window.showWarningMessage(`Unable to show commit details. File is probably not under source control`);
|
||||
|
||||
sha = blame.commit.isUncommitted ? blame.commit.previousSha : blame.commit.sha;
|
||||
args.sha = blame.commit.isUncommitted ? blame.commit.previousSha : blame.commit.sha;
|
||||
repoPath = blame.commit.repoPath;
|
||||
workingFileName = blame.commit.fileName;
|
||||
|
||||
commit = blame.commit;
|
||||
args.commit = blame.commit;
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'ShowQuickCommitDetailsCommand', `getBlameForLine(${blameline})`);
|
||||
@@ -46,51 +53,60 @@ export class ShowQuickCommitDetailsCommand extends ActiveEditorCachedCommand {
|
||||
}
|
||||
|
||||
try {
|
||||
if (!commit || (commit.type !== 'branch' && commit.type !== 'stash')) {
|
||||
if (repoLog) {
|
||||
commit = repoLog.commits.get(sha!);
|
||||
if (args.commit === undefined || (args.commit.type !== 'branch' && args.commit.type !== 'stash')) {
|
||||
if (args.repoLog !== undefined) {
|
||||
args.commit = args.repoLog.commits.get(args.sha!);
|
||||
// If we can't find the commit, kill the repoLog
|
||||
if (commit === undefined) {
|
||||
repoLog = undefined;
|
||||
if (args.commit === undefined) {
|
||||
args.repoLog = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
if (repoLog === undefined) {
|
||||
const log = await this.git.getLogForRepo(repoPath!, sha, 2);
|
||||
if (args.repoLog === undefined) {
|
||||
const log = await this.git.getLogForRepo(repoPath!, args.sha, 2);
|
||||
if (log === undefined) return window.showWarningMessage(`Unable to show commit details`);
|
||||
|
||||
commit = log.commits.get(sha!);
|
||||
args.commit = log.commits.get(args.sha!);
|
||||
}
|
||||
}
|
||||
|
||||
if (commit === undefined) return window.showWarningMessage(`Unable to show commit details`);
|
||||
if (args.commit === undefined) return window.showWarningMessage(`Unable to show commit details`);
|
||||
|
||||
if (!commit.workingFileName) {
|
||||
commit.workingFileName = workingFileName;
|
||||
if (args.commit.workingFileName === undefined) {
|
||||
args.commit.workingFileName = workingFileName;
|
||||
}
|
||||
|
||||
if (!goBackCommand) {
|
||||
if (args.goBackCommand === undefined) {
|
||||
// Create a command to get back to the branch history
|
||||
goBackCommand = new CommandQuickPickItem({
|
||||
args.goBackCommand = new CommandQuickPickItem({
|
||||
label: `go back \u21A9`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 to branch history`
|
||||
}, Commands.ShowQuickCurrentBranchHistory, [new GitUri(commit.uri, commit)]);
|
||||
}, Commands.ShowQuickCurrentBranchHistory, [
|
||||
new GitUri(args.commit.uri, args.commit)
|
||||
]);
|
||||
}
|
||||
|
||||
// Create a command to get back to where we are right now
|
||||
const currentCommand = new CommandQuickPickItem({
|
||||
label: `go back \u21A9`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 to details of \u00a0$(git-commit) ${commit.shortSha}`
|
||||
}, Commands.ShowQuickCommitDetails, [new GitUri(commit.uri, commit), sha, commit, goBackCommand, repoLog]);
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 to details of \u00a0$(git-commit) ${args.commit.shortSha}`
|
||||
}, Commands.ShowQuickCommitDetails, [
|
||||
new GitUri(args.commit.uri, args.commit),
|
||||
args
|
||||
]);
|
||||
|
||||
const pick = await CommitDetailsQuickPick.show(this.git, commit as GitLogCommit, uri, goBackCommand, currentCommand, repoLog);
|
||||
if (!pick) return undefined;
|
||||
const pick = await CommitDetailsQuickPick.show(this.git, args.commit as GitLogCommit, uri, args.goBackCommand, currentCommand, args.repoLog);
|
||||
if (pick === undefined) return undefined;
|
||||
|
||||
if (!(pick instanceof CommitWithFileStatusQuickPickItem)) {
|
||||
return pick.execute();
|
||||
}
|
||||
if (!(pick instanceof CommitWithFileStatusQuickPickItem)) return pick.execute();
|
||||
|
||||
return commands.executeCommand(Commands.ShowQuickCommitFileDetails, pick.gitUri, pick.sha, commit, currentCommand);
|
||||
return commands.executeCommand(Commands.ShowQuickCommitFileDetails,
|
||||
pick.gitUri,
|
||||
{
|
||||
commit: args.commit,
|
||||
sha: pick.sha,
|
||||
goBackCommand: currentCommand
|
||||
} as ShowQuickCommitFileDetailsCommandArgs);
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'ShowQuickCommitDetailsCommand');
|
||||
|
||||
@@ -1,41 +1,48 @@
|
||||
'use strict';
|
||||
import { TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCachedCommand, Commands } from './common';
|
||||
import { ActiveEditorCachedCommand, Commands, getCommandUri } from './common';
|
||||
import { GitCommit, GitLogCommit, GitService, GitUri, IGitLog } from '../gitService';
|
||||
import { Logger } from '../logger';
|
||||
import { CommandQuickPickItem, CommitFileDetailsQuickPick } from '../quickPicks';
|
||||
import { ShowQuickCommitDetailsCommandArgs } from './showQuickCommitDetails';
|
||||
import * as path from 'path';
|
||||
|
||||
export interface ShowQuickCommitFileDetailsCommandArgs {
|
||||
sha?: string;
|
||||
commit?: GitCommit | GitLogCommit;
|
||||
fileLog?: IGitLog;
|
||||
|
||||
goBackCommand?: CommandQuickPickItem;
|
||||
}
|
||||
|
||||
export class ShowQuickCommitFileDetailsCommand extends ActiveEditorCachedCommand {
|
||||
|
||||
constructor(private git: GitService) {
|
||||
super(Commands.ShowQuickCommitFileDetails);
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor, uri?: Uri, sha?: string, commit?: GitCommit | GitLogCommit, goBackCommand?: CommandQuickPickItem, fileLog?: IGitLog) {
|
||||
if (!(uri instanceof Uri)) {
|
||||
if (!editor || !editor.document) return undefined;
|
||||
uri = editor.document.uri;
|
||||
}
|
||||
async execute(editor: TextEditor, uri?: Uri, args: ShowQuickCommitFileDetailsCommandArgs = {}) {
|
||||
uri = getCommandUri(uri, editor);
|
||||
if (uri === undefined) return undefined;
|
||||
|
||||
let workingFileName = commit && commit.workingFileName;
|
||||
let workingFileName = args.commit && args.commit.workingFileName;
|
||||
|
||||
const gitUri = await GitUri.fromUri(uri, this.git);
|
||||
|
||||
if (!sha) {
|
||||
if (!editor) return undefined;
|
||||
if (args.sha === undefined) {
|
||||
if (editor === undefined) return undefined;
|
||||
|
||||
const blameline = editor.selection.active.line - gitUri.offset;
|
||||
if (blameline < 0) return undefined;
|
||||
|
||||
try {
|
||||
const blame = await this.git.getBlameForLine(gitUri, blameline);
|
||||
if (!blame) return window.showWarningMessage(`Unable to show commit file details. File is probably not under source control`);
|
||||
if (blame === undefined) return window.showWarningMessage(`Unable to show commit file details. File is probably not under source control`);
|
||||
|
||||
sha = blame.commit.isUncommitted ? blame.commit.previousSha : blame.commit.sha;
|
||||
args.sha = blame.commit.isUncommitted ? blame.commit.previousSha : blame.commit.sha;
|
||||
|
||||
commit = blame.commit;
|
||||
workingFileName = path.relative(commit.repoPath, gitUri.fsPath);
|
||||
args.commit = blame.commit;
|
||||
workingFileName = path.relative(args.commit.repoPath, gitUri.fsPath);
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'ShowQuickCommitFileDetailsCommand', `getBlameForLine(${blameline})`);
|
||||
@@ -44,50 +51,56 @@ export class ShowQuickCommitFileDetailsCommand extends ActiveEditorCachedCommand
|
||||
}
|
||||
|
||||
try {
|
||||
if (!commit || (commit.type !== 'file' && commit.type !== 'stash')) {
|
||||
if (fileLog) {
|
||||
commit = fileLog.commits.get(sha!);
|
||||
if (args.commit === undefined || (args.commit.type !== 'file' && args.commit.type !== 'stash')) {
|
||||
if (args.fileLog !== undefined) {
|
||||
args.commit = args.fileLog.commits.get(args.sha!);
|
||||
// If we can't find the commit, kill the fileLog
|
||||
if (commit === undefined) {
|
||||
fileLog = undefined;
|
||||
if (args.commit === undefined) {
|
||||
args.fileLog = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
if (fileLog === undefined) {
|
||||
commit = await this.git.getLogCommit(commit ? commit.repoPath : gitUri.repoPath, gitUri.fsPath, sha, { previous: true });
|
||||
if (commit === undefined) return window.showWarningMessage(`Unable to show commit file details`);
|
||||
if (args.fileLog === undefined) {
|
||||
args.commit = await this.git.getLogCommit(args.commit ? args.commit.repoPath : gitUri.repoPath, gitUri.fsPath, args.sha, { previous: true });
|
||||
if (args.commit === undefined) return window.showWarningMessage(`Unable to show commit file details`);
|
||||
}
|
||||
}
|
||||
|
||||
if (commit === undefined) return window.showWarningMessage(`Unable to show commit file details`);
|
||||
if (args.commit === undefined) return window.showWarningMessage(`Unable to show commit file details`);
|
||||
|
||||
// Attempt to the most recent commit -- so that we can find the real working filename if there was a rename
|
||||
commit.workingFileName = workingFileName;
|
||||
commit.workingFileName = await this.git.findWorkingFileName(commit);
|
||||
args.commit.workingFileName = workingFileName;
|
||||
args.commit.workingFileName = await this.git.findWorkingFileName(args.commit);
|
||||
|
||||
const shortSha = sha!.substring(0, 8);
|
||||
const shortSha = args.sha!.substring(0, 8);
|
||||
|
||||
if (!goBackCommand) {
|
||||
if (args.goBackCommand === undefined) {
|
||||
// Create a command to get back to the commit details
|
||||
goBackCommand = new CommandQuickPickItem({
|
||||
args.goBackCommand = new CommandQuickPickItem({
|
||||
label: `go back \u21A9`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 to details of \u00a0$(git-commit) ${shortSha}`
|
||||
}, Commands.ShowQuickCommitDetails, [new GitUri(commit.uri, commit), sha, commit]);
|
||||
}, Commands.ShowQuickCommitDetails, [
|
||||
new GitUri(args.commit.uri, args.commit),
|
||||
{
|
||||
commit: args.commit,
|
||||
sha: args.sha
|
||||
} as ShowQuickCommitDetailsCommandArgs
|
||||
]);
|
||||
}
|
||||
|
||||
const pick = await CommitFileDetailsQuickPick.show(this.git, commit as GitLogCommit, uri, goBackCommand,
|
||||
// Create a command to get back to where we are right now
|
||||
new CommandQuickPickItem({
|
||||
label: `go back \u21A9`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 to details of \u00a0$(file-text) ${path.basename(commit.fileName)} in \u00a0$(git-commit) ${shortSha}`
|
||||
}, Commands.ShowQuickCommitFileDetails, [new GitUri(commit.uri, commit), sha, commit, goBackCommand]),
|
||||
fileLog);
|
||||
// Create a command to get back to where we are right now
|
||||
const currentCommand = new CommandQuickPickItem({
|
||||
label: `go back \u21A9`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 to details of \u00a0$(file-text) ${path.basename(args.commit.fileName)} in \u00a0$(git-commit) ${shortSha}`
|
||||
}, Commands.ShowQuickCommitFileDetails, [
|
||||
new GitUri(args.commit.uri, args.commit),
|
||||
args
|
||||
]);
|
||||
|
||||
if (!pick) return undefined;
|
||||
const pick = await CommitFileDetailsQuickPick.show(this.git, args.commit as GitLogCommit, uri, args.goBackCommand, currentCommand, args.fileLog);
|
||||
if (pick === undefined) return undefined;
|
||||
|
||||
if (pick instanceof CommandQuickPickItem) {
|
||||
return pick.execute();
|
||||
}
|
||||
if (pick instanceof CommandQuickPickItem) return pick.execute();
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -1,29 +1,37 @@
|
||||
'use strict';
|
||||
import { commands, TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCachedCommand, Commands } from './common';
|
||||
import { ActiveEditorCachedCommand, Commands, getCommandUri } from './common';
|
||||
import { ShowQuickBranchHistoryCommandArgs } from './showQuickBranchHistory';
|
||||
import { GitService } from '../gitService';
|
||||
import { Logger } from '../logger';
|
||||
import { CommandQuickPickItem } from '../quickPicks';
|
||||
|
||||
export interface ShowQuickCurrentBranchHistoryCommandArgs {
|
||||
goBackCommand?: CommandQuickPickItem;
|
||||
}
|
||||
|
||||
export class ShowQuickCurrentBranchHistoryCommand extends ActiveEditorCachedCommand {
|
||||
|
||||
constructor(private git: GitService) {
|
||||
super(Commands.ShowQuickCurrentBranchHistory);
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor, uri?: Uri, goBackCommand?: CommandQuickPickItem) {
|
||||
if (!(uri instanceof Uri)) {
|
||||
uri = editor && editor.document && editor.document.uri;
|
||||
}
|
||||
async execute(editor: TextEditor, uri?: Uri, args: ShowQuickCurrentBranchHistoryCommandArgs = {}) {
|
||||
uri = getCommandUri(uri, editor);
|
||||
|
||||
try {
|
||||
const repoPath = await this.git.getRepoPathFromUri(uri);
|
||||
if (!repoPath) return window.showWarningMessage(`Unable to show branch history`);
|
||||
|
||||
const branch = await this.git.getBranch(repoPath);
|
||||
if (!branch) return undefined;
|
||||
if (branch === undefined) return undefined;
|
||||
|
||||
return commands.executeCommand(Commands.ShowQuickBranchHistory, uri, branch.name, undefined, goBackCommand);
|
||||
return commands.executeCommand(Commands.ShowQuickBranchHistory,
|
||||
uri,
|
||||
{
|
||||
branch: branch.name,
|
||||
goBackCommand: args.goBackCommand
|
||||
} as ShowQuickBranchHistoryCommandArgs);
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'ShowQuickCurrentBranchHistoryCommand');
|
||||
|
||||
@@ -1,52 +1,68 @@
|
||||
'use strict';
|
||||
import { commands, Range, TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCachedCommand, Commands } from './common';
|
||||
import { ActiveEditorCachedCommand, Commands, getCommandUri } from './common';
|
||||
import { GitService, GitUri, IGitLog } from '../gitService';
|
||||
import { Logger } from '../logger';
|
||||
import { CommandQuickPickItem, FileHistoryQuickPick } from '../quickPicks';
|
||||
import { ShowQuickCommitFileDetailsCommandArgs } from './showQuickCommitFileDetails';
|
||||
import * as path from 'path';
|
||||
|
||||
export interface ShowQuickFileHistoryCommandArgs {
|
||||
log?: IGitLog;
|
||||
maxCount?: number;
|
||||
range?: Range;
|
||||
|
||||
goBackCommand?: CommandQuickPickItem;
|
||||
nextPageCommand?: CommandQuickPickItem;
|
||||
}
|
||||
|
||||
export class ShowQuickFileHistoryCommand extends ActiveEditorCachedCommand {
|
||||
|
||||
constructor(private git: GitService) {
|
||||
super(Commands.ShowQuickFileHistory);
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor, uri?: Uri, range?: Range, maxCount?: number, goBackCommand?: CommandQuickPickItem, log?: IGitLog, nextPageCommand?: CommandQuickPickItem) {
|
||||
if (!(uri instanceof Uri)) {
|
||||
uri = editor && editor.document && editor.document.uri;
|
||||
}
|
||||
|
||||
if (!uri) return commands.executeCommand(Commands.ShowQuickCurrentBranchHistory);
|
||||
async execute(editor: TextEditor, uri?: Uri, args: ShowQuickFileHistoryCommandArgs = {}) {
|
||||
uri = getCommandUri(uri, editor);
|
||||
if (uri === undefined) return commands.executeCommand(Commands.ShowQuickCurrentBranchHistory);
|
||||
|
||||
const gitUri = await GitUri.fromUri(uri, this.git);
|
||||
|
||||
if (maxCount == null) {
|
||||
maxCount = this.git.config.advanced.maxQuickHistory;
|
||||
if (args.maxCount == null) {
|
||||
args.maxCount = this.git.config.advanced.maxQuickHistory;
|
||||
}
|
||||
|
||||
const progressCancellation = FileHistoryQuickPick.showProgress(gitUri);
|
||||
try {
|
||||
if (!log) {
|
||||
log = await this.git.getLogForFile(gitUri.repoPath, gitUri.fsPath, gitUri.sha, maxCount, range);
|
||||
if (!log) return window.showWarningMessage(`Unable to show file history. File is probably not under source control`);
|
||||
if (args.log === undefined) {
|
||||
args.log = await this.git.getLogForFile(gitUri.repoPath, gitUri.fsPath, gitUri.sha, args.maxCount, args.range);
|
||||
if (args.log === undefined) return window.showWarningMessage(`Unable to show file history. File is probably not under source control`);
|
||||
}
|
||||
|
||||
if (progressCancellation.token.isCancellationRequested) return undefined;
|
||||
|
||||
const pick = await FileHistoryQuickPick.show(this.git, log, gitUri, progressCancellation, goBackCommand, nextPageCommand);
|
||||
if (!pick) return undefined;
|
||||
const pick = await FileHistoryQuickPick.show(this.git, args.log, gitUri, progressCancellation, args.goBackCommand, args.nextPageCommand);
|
||||
if (pick === undefined) return undefined;
|
||||
|
||||
if (pick instanceof CommandQuickPickItem) {
|
||||
return pick.execute();
|
||||
}
|
||||
if (pick instanceof CommandQuickPickItem) return pick.execute();
|
||||
|
||||
return commands.executeCommand(Commands.ShowQuickCommitFileDetails, new GitUri(pick.commit.uri, pick.commit), pick.commit.sha, pick.commit,
|
||||
new CommandQuickPickItem({
|
||||
label: `go back \u21A9`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 to history of \u00a0$(file-text) ${path.basename(pick.commit.fileName)}${gitUri.sha ? ` from \u00a0$(git-commit) ${gitUri.shortSha}` : ''}`
|
||||
}, Commands.ShowQuickFileHistory, [uri, range, maxCount, goBackCommand, log]),
|
||||
log);
|
||||
// Create a command to get back to where we are right now
|
||||
const currentCommand = new CommandQuickPickItem({
|
||||
label: `go back \u21A9`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 to history of \u00a0$(file-text) ${path.basename(pick.commit.fileName)}${gitUri.sha ? ` from \u00a0$(git-commit) ${gitUri.shortSha}` : ''}`
|
||||
}, Commands.ShowQuickFileHistory, [
|
||||
uri,
|
||||
args
|
||||
]);
|
||||
|
||||
return commands.executeCommand(Commands.ShowQuickCommitFileDetails,
|
||||
new GitUri(pick.commit.uri, pick.commit),
|
||||
{
|
||||
commit: pick.commit,
|
||||
fileLog: args.log,
|
||||
sha: pick.commit.sha,
|
||||
goBackCommand: currentCommand
|
||||
} as ShowQuickCommitFileDetailsCommandArgs);
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'ShowQuickFileHistoryCommand');
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
'use strict';
|
||||
import { TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCachedCommand, Commands } from './common';
|
||||
import { ActiveEditorCachedCommand, Commands, getCommandUri } from './common';
|
||||
import { GitService } from '../gitService';
|
||||
import { Logger } from '../logger';
|
||||
import { CommandQuickPickItem, RepoStatusQuickPick } from '../quickPicks';
|
||||
|
||||
export interface ShowQuickRepoStatusCommandArgs {
|
||||
goBackCommand?: CommandQuickPickItem;
|
||||
}
|
||||
|
||||
export class ShowQuickRepoStatusCommand extends ActiveEditorCachedCommand {
|
||||
|
||||
constructor(private git: GitService) {
|
||||
super(Commands.ShowQuickRepoStatus);
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor, uri?: Uri, goBackCommand?: CommandQuickPickItem) {
|
||||
if (!(uri instanceof Uri)) {
|
||||
uri = editor && editor.document && editor.document.uri;
|
||||
}
|
||||
async execute(editor: TextEditor, uri?: Uri, args: ShowQuickRepoStatusCommandArgs = {}) {
|
||||
uri = getCommandUri(uri, editor);
|
||||
|
||||
try {
|
||||
const repoPath = await this.git.getRepoPathFromUri(uri);
|
||||
if (!repoPath) return window.showWarningMessage(`Unable to show repository status`);
|
||||
|
||||
const status = await this.git.getStatusForRepo(repoPath);
|
||||
if (!status) return window.showWarningMessage(`Unable to show repository status`);
|
||||
if (status === undefined) return window.showWarningMessage(`Unable to show repository status`);
|
||||
|
||||
const pick = await RepoStatusQuickPick.show(status, goBackCommand);
|
||||
if (!pick) return undefined;
|
||||
const pick = await RepoStatusQuickPick.show(status, args.goBackCommand);
|
||||
if (pick === undefined) return undefined;
|
||||
|
||||
if (pick instanceof CommandQuickPickItem) {
|
||||
return pick.execute();
|
||||
}
|
||||
if (pick instanceof CommandQuickPickItem) return pick.execute();
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
'use strict';
|
||||
import { commands, TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCachedCommand, Commands } from './common';
|
||||
import { ActiveEditorCachedCommand, Commands, getCommandUri } from './common';
|
||||
import { GitService, GitUri } from '../gitService';
|
||||
import { Logger } from '../logger';
|
||||
import { CommandQuickPickItem, StashListQuickPick } from '../quickPicks';
|
||||
import { ShowQuickCommitDetailsCommandArgs } from './showQuickCommitDetails';
|
||||
|
||||
export interface ShowQuickStashListCommandArgs {
|
||||
goBackCommand?: CommandQuickPickItem;
|
||||
}
|
||||
|
||||
export class ShowQuickStashListCommand extends ActiveEditorCachedCommand {
|
||||
|
||||
@@ -11,14 +16,12 @@ export class ShowQuickStashListCommand extends ActiveEditorCachedCommand {
|
||||
super(Commands.ShowQuickStashList);
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor, uri?: Uri, goBackCommand?: CommandQuickPickItem) {
|
||||
if (!(uri instanceof Uri)) {
|
||||
uri = editor && editor.document && editor.document.uri;
|
||||
}
|
||||
async execute(editor: TextEditor, uri?: Uri, args: ShowQuickStashListCommandArgs = {}) {
|
||||
uri = getCommandUri(uri, editor);
|
||||
|
||||
try {
|
||||
const repoPath = await this.git.getRepoPathFromUri(uri);
|
||||
if (repoPath === undefined) return window.showWarningMessage(`Unable to show stashed changes`);
|
||||
if (!repoPath) return window.showWarningMessage(`Unable to show stashed changes`);
|
||||
|
||||
const stash = await this.git.getStashList(repoPath);
|
||||
if (stash === undefined) return window.showWarningMessage(`Unable to show stashed changes`);
|
||||
@@ -27,16 +30,25 @@ export class ShowQuickStashListCommand extends ActiveEditorCachedCommand {
|
||||
const currentCommand = new CommandQuickPickItem({
|
||||
label: `go back \u21A9`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 to stashed changes`
|
||||
}, Commands.ShowQuickStashList, [uri, goBackCommand]);
|
||||
}, Commands.ShowQuickStashList, [
|
||||
uri,
|
||||
{
|
||||
goBackCommand: args.goBackCommand
|
||||
} as ShowQuickStashListCommandArgs
|
||||
]);
|
||||
|
||||
const pick = await StashListQuickPick.show(this.git, stash, 'list', goBackCommand, currentCommand);
|
||||
if (!pick) return undefined;
|
||||
const pick = await StashListQuickPick.show(this.git, stash, 'list', args.goBackCommand, currentCommand);
|
||||
if (pick === undefined) return undefined;
|
||||
|
||||
if (pick instanceof CommandQuickPickItem) {
|
||||
return pick.execute();
|
||||
}
|
||||
if (pick instanceof CommandQuickPickItem) return pick.execute();
|
||||
|
||||
return commands.executeCommand(Commands.ShowQuickCommitDetails, new GitUri(pick.commit.uri, pick.commit), pick.commit.sha, pick.commit, currentCommand);
|
||||
return commands.executeCommand(Commands.ShowQuickCommitDetails,
|
||||
new GitUri(pick.commit.uri, pick.commit),
|
||||
{
|
||||
commit: pick.commit,
|
||||
sha: pick.commit.sha,
|
||||
goBackCommand: currentCommand
|
||||
} as ShowQuickCommitDetailsCommandArgs);
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'ShowQuickStashListCommand');
|
||||
|
||||
@@ -6,42 +6,50 @@ import { CommitQuickPickItem, StashListQuickPick } from '../quickPicks';
|
||||
import { Logger } from '../logger';
|
||||
import { CommandQuickPickItem } from '../quickPicks';
|
||||
|
||||
export interface StashApplyCommandArgs {
|
||||
confirm?: boolean;
|
||||
deleteAfter?: boolean;
|
||||
stashItem?: { stashName: string, message: string };
|
||||
|
||||
goBackCommand?: CommandQuickPickItem;
|
||||
}
|
||||
|
||||
export class StashApplyCommand extends Command {
|
||||
|
||||
constructor(private git: GitService) {
|
||||
super(Commands.StashApply);
|
||||
}
|
||||
|
||||
async execute(stashItem: { stashName: string, message: string }, confirm: boolean = true, deleteAfter: boolean = false, goBackCommand?: CommandQuickPickItem) {
|
||||
async execute(args: StashApplyCommandArgs = { confirm: true, deleteAfter: false }) {
|
||||
if (!this.git.config.insiders) return undefined;
|
||||
if (!this.git.repoPath) return undefined;
|
||||
|
||||
if (!stashItem || !stashItem.stashName) {
|
||||
if (args.stashItem === undefined || args.stashItem.stashName === undefined) {
|
||||
const stash = await this.git.getStashList(this.git.repoPath);
|
||||
if (!stash) return window.showInformationMessage(`There are no stashed changes`);
|
||||
if (stash === undefined) return window.showInformationMessage(`There are no stashed changes`);
|
||||
|
||||
const currentCommand = new CommandQuickPickItem({
|
||||
label: `go back \u21A9`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 to apply stashed changes`
|
||||
}, Commands.StashApply, [stashItem, confirm, deleteAfter, goBackCommand]);
|
||||
}, Commands.StashApply, [args]);
|
||||
|
||||
const pick = await StashListQuickPick.show(this.git, stash, 'apply', goBackCommand, currentCommand);
|
||||
if (!pick || !(pick instanceof CommitQuickPickItem)) return goBackCommand && goBackCommand.execute();
|
||||
const pick = await StashListQuickPick.show(this.git, stash, 'apply', args.goBackCommand, currentCommand);
|
||||
if (pick === undefined || !(pick instanceof CommitQuickPickItem)) return args.goBackCommand === undefined ? undefined : args.goBackCommand.execute();
|
||||
|
||||
goBackCommand = currentCommand;
|
||||
stashItem = pick.commit as GitStashCommit;
|
||||
args.goBackCommand = currentCommand;
|
||||
args.stashItem = pick.commit as GitStashCommit;
|
||||
}
|
||||
|
||||
try {
|
||||
if (confirm) {
|
||||
const message = stashItem.message.length > 80 ? `${stashItem.message.substring(0, 80)}\u2026` : stashItem.message;
|
||||
if (args.confirm) {
|
||||
const message = args.stashItem.message.length > 80 ? `${args.stashItem.message.substring(0, 80)}\u2026` : args.stashItem.message;
|
||||
const result = await window.showWarningMessage(`Apply stashed changes '${message}' to your working tree?`, { title: 'Yes, delete after applying' } as MessageItem, { title: 'Yes' } as MessageItem, { title: 'No', isCloseAffordance: true } as MessageItem);
|
||||
if (!result || result.title === 'No') return goBackCommand && goBackCommand.execute();
|
||||
if (result === undefined || result.title === 'No') return args.goBackCommand === undefined ? undefined : args.goBackCommand.execute();
|
||||
|
||||
deleteAfter = result.title !== 'Yes';
|
||||
args.deleteAfter = result.title !== 'Yes';
|
||||
}
|
||||
|
||||
return await this.git.stashApply(this.git.repoPath, stashItem.stashName, deleteAfter);
|
||||
return await this.git.stashApply(this.git.repoPath, args.stashItem.stashName, args.deleteAfter);
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'StashApplyCommand');
|
||||
|
||||
@@ -5,25 +5,37 @@ import { Command, Commands } from './common';
|
||||
import { Logger } from '../logger';
|
||||
import { CommandQuickPickItem } from '../quickPicks';
|
||||
|
||||
export interface StashDeleteCommandArgs {
|
||||
confirm?: boolean;
|
||||
stashItem?: { stashName: string, message: string };
|
||||
|
||||
goBackCommand?: CommandQuickPickItem;
|
||||
}
|
||||
|
||||
export class StashDeleteCommand extends Command {
|
||||
|
||||
constructor(private git: GitService) {
|
||||
super(Commands.StashDelete);
|
||||
}
|
||||
|
||||
async execute(stashItem: { stashName: string, message: string }, confirm: boolean = true, goBackCommand?: CommandQuickPickItem) {
|
||||
async execute(args: StashDeleteCommandArgs = { confirm: true }) {
|
||||
if (!this.git.config.insiders) return undefined;
|
||||
if (!this.git.repoPath) return undefined;
|
||||
if (!stashItem || !stashItem.stashName) return undefined;
|
||||
|
||||
if (args.stashItem === undefined || args.stashItem.stashName === undefined) return undefined;
|
||||
|
||||
if (args.confirm === undefined) {
|
||||
args.confirm = true;
|
||||
}
|
||||
|
||||
try {
|
||||
if (confirm) {
|
||||
const message = stashItem.message.length > 80 ? `${stashItem.message.substring(0, 80)}\u2026` : stashItem.message;
|
||||
if (args.confirm) {
|
||||
const message = args.stashItem.message.length > 80 ? `${args.stashItem.message.substring(0, 80)}\u2026` : args.stashItem.message;
|
||||
const result = await window.showWarningMessage(`Delete stashed changes '${message}'?`, { title: 'Yes' } as MessageItem, { title: 'No', isCloseAffordance: true } as MessageItem);
|
||||
if (!result || result.title !== 'Yes') return goBackCommand && goBackCommand.execute();
|
||||
if (result === undefined || result.title !== 'Yes') return args.goBackCommand === undefined ? undefined : args.goBackCommand.execute();
|
||||
}
|
||||
|
||||
return await this.git.stashDelete(this.git.repoPath, stashItem.stashName);
|
||||
return await this.git.stashDelete(this.git.repoPath, args.stashItem.stashName);
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'StashDeleteCommand');
|
||||
|
||||
@@ -5,26 +5,37 @@ import { Command, Commands } from './common';
|
||||
import { Logger } from '../logger';
|
||||
import { CommandQuickPickItem } from '../quickPicks';
|
||||
|
||||
export interface StashSaveCommandArgs {
|
||||
message?: string;
|
||||
unstagedOnly?: boolean;
|
||||
|
||||
goBackCommand?: CommandQuickPickItem;
|
||||
}
|
||||
|
||||
export class StashSaveCommand extends Command {
|
||||
|
||||
constructor(private git: GitService) {
|
||||
super(Commands.StashSave);
|
||||
}
|
||||
|
||||
async execute(message?: string, unstagedOnly: boolean = false, goBackCommand?: CommandQuickPickItem) {
|
||||
async execute(args: StashSaveCommandArgs = { unstagedOnly : false }) {
|
||||
if (!this.git.config.insiders) return undefined;
|
||||
if (!this.git.repoPath) return undefined;
|
||||
|
||||
if (args.unstagedOnly === undefined) {
|
||||
args.unstagedOnly = false;
|
||||
}
|
||||
|
||||
try {
|
||||
if (message == null) {
|
||||
message = await window.showInputBox({
|
||||
if (args.message == null) {
|
||||
args.message = await window.showInputBox({
|
||||
prompt: `Please provide a stash message`,
|
||||
placeHolder: `Stash message`
|
||||
} as InputBoxOptions);
|
||||
if (message === undefined) return goBackCommand && goBackCommand.execute();
|
||||
if (args.message === undefined) return args.goBackCommand === undefined ? undefined : args.goBackCommand.execute();
|
||||
}
|
||||
|
||||
return await this.git.stashSave(this.git.repoPath, message, unstagedOnly);
|
||||
return await this.git.stashSave(this.git.repoPath, args.message, args.unstagedOnly);
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'StashSaveCommand');
|
||||
|
||||
@@ -4,21 +4,21 @@ import { BlameAnnotationController } from '../blameAnnotationController';
|
||||
import { Commands, EditorCommand } from './common';
|
||||
import { Logger } from '../logger';
|
||||
|
||||
export interface ToggleBlameCommandArgs {
|
||||
sha?: string;
|
||||
}
|
||||
|
||||
export class ToggleBlameCommand extends EditorCommand {
|
||||
|
||||
constructor(private annotationController: BlameAnnotationController) {
|
||||
super(Commands.ToggleBlame);
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor, edit: TextEditorEdit, uri?: Uri, sha?: string): Promise<any> {
|
||||
if (editor && editor.document && editor.document.isDirty) return undefined;
|
||||
async execute(editor: TextEditor, edit: TextEditorEdit, uri?: Uri, args: ToggleBlameCommandArgs = {}): Promise<any> {
|
||||
if (editor !== undefined && editor.document !== undefined && editor.document.isDirty) return undefined;
|
||||
|
||||
try {
|
||||
if (sha) {
|
||||
return this.annotationController.toggleBlameAnnotation(editor, sha);
|
||||
}
|
||||
|
||||
return this.annotationController.toggleBlameAnnotation(editor, editor.selection.active.line);
|
||||
return this.annotationController.toggleBlameAnnotation(editor, args.sha !== undefined ? args.sha : editor.selection.active.line);
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex, 'ToggleBlameCommand');
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
'use strict';
|
||||
import { commands, Range, Uri } from 'vscode';
|
||||
import { BuiltInCommands } from '../../constants';
|
||||
import { GitLogCommit } from '../../gitService';
|
||||
|
||||
export type RemoteOpenType = 'branch' | 'commit' | 'file' | 'working-file';
|
||||
export type RemoteResourceType = 'branch' | 'commit' | 'file' | 'working-file';
|
||||
export type RemoteResource = { type: 'branch', branch: string } |
|
||||
{ type: 'commit', sha: string } |
|
||||
{ type: 'file', branch?: string, commit?: GitLogCommit, fileName: string, range?: Range, sha?: string } |
|
||||
{ type: 'working-file', branch?: string, fileName: string, range?: Range };
|
||||
|
||||
export function getNameFromRemoteOpenType(type: RemoteOpenType) {
|
||||
switch (type) {
|
||||
export function getNameFromRemoteResource(resource: RemoteResource) {
|
||||
switch (resource.type) {
|
||||
case 'branch': return 'Branch';
|
||||
case 'commit': return 'Commit';
|
||||
case 'file': return 'File';
|
||||
@@ -34,19 +39,16 @@ export abstract class RemoteProvider {
|
||||
return commands.executeCommand(BuiltInCommands.Open, Uri.parse(url));
|
||||
}
|
||||
|
||||
open(type: 'branch', branch: string): Promise<{}>;
|
||||
open(type: 'commit', sha: string): Promise<{}>;
|
||||
open(type: 'file', fileName: string, branch?: string, sha?: string, range?: Range): Promise<{}>;
|
||||
open(type: RemoteOpenType, ...args: any[]): Promise<{}>;
|
||||
open(type: RemoteOpenType, branchOrShaOrFileName: string, fileBranch?: string, fileSha?: string, fileRange?: Range): Promise<{}> {
|
||||
switch (type) {
|
||||
open(resource: RemoteResource): Promise<{}> {
|
||||
switch (resource.type) {
|
||||
case 'branch':
|
||||
return this.openBranch(branchOrShaOrFileName);
|
||||
return this.openBranch(resource.branch);
|
||||
case 'commit':
|
||||
return this.openCommit(branchOrShaOrFileName);
|
||||
return this.openCommit(resource.sha);
|
||||
case 'file':
|
||||
return this.openFile(resource.fileName, resource.branch, resource.sha, resource.range);
|
||||
case 'working-file':
|
||||
return this.openFile(branchOrShaOrFileName, fileBranch, fileSha, fileRange);
|
||||
return this.openFile(resource.fileName, resource.branch, undefined, resource.range);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
import { Functions, Iterables, Strings } from './system';
|
||||
import { CancellationToken, CodeLens, CodeLensProvider, Command, commands, DocumentSelector, Event, EventEmitter, ExtensionContext, Position, Range, SymbolInformation, SymbolKind, TextDocument, Uri, workspace } from 'vscode';
|
||||
import { Commands } from './commands';
|
||||
import { Commands, DiffWithPreviousCommandArgs, ShowBlameHistoryCommandArgs, ShowFileHistoryCommandArgs, ShowQuickCommitDetailsCommandArgs, ShowQuickCommitFileDetailsCommandArgs, ShowQuickFileHistoryCommandArgs } from './commands';
|
||||
import { BuiltInCommands, DocumentSchemes, ExtensionKey } from './constants';
|
||||
import { CodeLensCommand, CodeLensLocation, IConfig, ICodeLensLanguageLocation } from './configuration';
|
||||
import { GitCommit, GitService, GitUri, IGitBlame, IGitBlameLines } from './gitService';
|
||||
@@ -321,7 +321,15 @@ export class GitCodeLensProvider implements CodeLensProvider {
|
||||
lens.command = {
|
||||
title: title,
|
||||
command: Commands.ShowBlameHistory,
|
||||
arguments: [Uri.file(lens.uri.fsPath), lens.blameRange, position, commit && commit.sha, line]
|
||||
arguments: [
|
||||
Uri.file(lens.uri.fsPath),
|
||||
{
|
||||
line,
|
||||
position,
|
||||
range: lens.blameRange,
|
||||
sha: commit && commit.sha
|
||||
} as ShowBlameHistoryCommandArgs
|
||||
]
|
||||
};
|
||||
return lens;
|
||||
}
|
||||
@@ -339,7 +347,14 @@ export class GitCodeLensProvider implements CodeLensProvider {
|
||||
lens.command = {
|
||||
title: title,
|
||||
command: Commands.ShowFileHistory,
|
||||
arguments: [Uri.file(lens.uri.fsPath), position, commit && commit.sha, line]
|
||||
arguments: [
|
||||
Uri.file(lens.uri.fsPath),
|
||||
{
|
||||
line,
|
||||
position,
|
||||
sha: commit && commit.sha
|
||||
} as ShowFileHistoryCommandArgs
|
||||
]
|
||||
};
|
||||
return lens;
|
||||
}
|
||||
@@ -355,8 +370,10 @@ export class GitCodeLensProvider implements CodeLensProvider {
|
||||
command: Commands.DiffWithPrevious,
|
||||
arguments: [
|
||||
Uri.file(lens.uri.fsPath),
|
||||
commit,
|
||||
lens.isFullRange ? undefined : lens.blameRange
|
||||
{
|
||||
commit: commit,
|
||||
range: lens.isFullRange ? undefined : lens.blameRange
|
||||
} as DiffWithPreviousCommandArgs
|
||||
]
|
||||
};
|
||||
return lens;
|
||||
@@ -366,7 +383,12 @@ export class GitCodeLensProvider implements CodeLensProvider {
|
||||
lens.command = {
|
||||
title: title,
|
||||
command: CodeLensCommand.ShowQuickCommitDetails,
|
||||
arguments: [Uri.file(lens.uri.fsPath), commit === undefined ? undefined : commit.sha, commit]
|
||||
arguments: [
|
||||
Uri.file(lens.uri.fsPath),
|
||||
{
|
||||
commit,
|
||||
sha: commit === undefined ? undefined : commit.sha
|
||||
} as ShowQuickCommitDetailsCommandArgs]
|
||||
};
|
||||
return lens;
|
||||
}
|
||||
@@ -375,7 +397,12 @@ export class GitCodeLensProvider implements CodeLensProvider {
|
||||
lens.command = {
|
||||
title: title,
|
||||
command: CodeLensCommand.ShowQuickCommitFileDetails,
|
||||
arguments: [Uri.file(lens.uri.fsPath), commit === undefined ? undefined : commit.sha, commit]
|
||||
arguments: [
|
||||
Uri.file(lens.uri.fsPath),
|
||||
{
|
||||
commit,
|
||||
sha: commit === undefined ? undefined : commit.sha
|
||||
} as ShowQuickCommitFileDetailsCommandArgs]
|
||||
};
|
||||
return lens;
|
||||
}
|
||||
@@ -384,7 +411,12 @@ export class GitCodeLensProvider implements CodeLensProvider {
|
||||
lens.command = {
|
||||
title: title,
|
||||
command: CodeLensCommand.ShowQuickFileHistory,
|
||||
arguments: [Uri.file(lens.uri.fsPath), lens.isFullRange ? undefined : lens.blameRange]
|
||||
arguments: [
|
||||
Uri.file(lens.uri.fsPath),
|
||||
{
|
||||
range: lens.isFullRange ? undefined : lens.blameRange
|
||||
} as ShowQuickFileHistoryCommandArgs
|
||||
]
|
||||
};
|
||||
return lens;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
// import { Iterables } from './system';
|
||||
import { CancellationToken, CodeLens, CodeLensProvider, DocumentSelector, ExtensionContext, Range, TextDocument, Uri } from 'vscode';
|
||||
import { Commands } from './commands';
|
||||
import { Commands, DiffWithPreviousCommandArgs, DiffWithWorkingCommandArgs } from './commands';
|
||||
import { DocumentSchemes } from './constants';
|
||||
import { GitCommit, GitService, GitUri } from './gitService';
|
||||
|
||||
@@ -55,8 +55,10 @@ export class GitRevisionCodeLensProvider implements CodeLensProvider {
|
||||
command: Commands.DiffWithWorking,
|
||||
arguments: [
|
||||
Uri.file(lens.fileName),
|
||||
lens.commit,
|
||||
lens.range.start.line
|
||||
{
|
||||
commit: lens.commit,
|
||||
line: lens.range.start.line
|
||||
} as DiffWithWorkingCommandArgs
|
||||
]
|
||||
};
|
||||
return Promise.resolve(lens);
|
||||
@@ -68,8 +70,10 @@ export class GitRevisionCodeLensProvider implements CodeLensProvider {
|
||||
command: Commands.DiffWithPrevious,
|
||||
arguments: [
|
||||
Uri.file(lens.fileName),
|
||||
lens.commit,
|
||||
lens.range.start.line
|
||||
{
|
||||
commit: lens.commit,
|
||||
line: lens.range.start.line
|
||||
} as DiffWithPreviousCommandArgs
|
||||
]
|
||||
};
|
||||
return Promise.resolve(lens);
|
||||
|
||||
1874
src/gitService.ts
1874
src/gitService.ts
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
import { Arrays, Iterables } from '../system';
|
||||
import { CancellationTokenSource, QuickPickOptions, Uri, window } from 'vscode';
|
||||
import { Commands, Keyboard, KeyNoopCommand } from '../commands';
|
||||
import { Commands, Keyboard, KeyNoopCommand, ShowCommitSearchCommandArgs, ShowQuickBranchHistoryCommandArgs } from '../commands';
|
||||
import { CommandQuickPickItem, CommitQuickPickItem, getQuickPickIgnoreFocusOut, showQuickPickProgress } from './common';
|
||||
import { GitService, GitUri, IGitLog } from '../gitService';
|
||||
import { GitService, GitUri, IGitLog, RemoteResource } from '../gitService';
|
||||
import { OpenRemotesCommandQuickPickItem } from './remotes';
|
||||
|
||||
export class BranchHistoryQuickPick {
|
||||
@@ -23,17 +23,33 @@ export class BranchHistoryQuickPick {
|
||||
const currentCommand = new CommandQuickPickItem({
|
||||
label: `go back \u21A9`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 to \u00a0$(git-branch) ${branch} history`
|
||||
}, Commands.ShowQuickBranchHistory, [uri, branch, log.maxCount, goBackCommand, log]);
|
||||
}, Commands.ShowQuickBranchHistory, [
|
||||
uri,
|
||||
{
|
||||
branch,
|
||||
log,
|
||||
maxCount: log.maxCount,
|
||||
goBackCommand
|
||||
} as ShowQuickBranchHistoryCommandArgs
|
||||
]);
|
||||
|
||||
const remotes = Arrays.uniqueBy(await git.getRemotes((uri && uri.repoPath) || git.repoPath), _ => _.url, _ => !!_.provider);
|
||||
if (remotes.length) {
|
||||
items.splice(0, 0, new OpenRemotesCommandQuickPickItem(remotes, 'branch', branch, currentCommand));
|
||||
items.splice(0, 0, new OpenRemotesCommandQuickPickItem(remotes, {
|
||||
type: 'branch',
|
||||
branch
|
||||
} as RemoteResource, currentCommand));
|
||||
}
|
||||
|
||||
items.splice(0, 0, new CommandQuickPickItem({
|
||||
label: `$(search) Show Commit Search`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 search for commits by message, author, files, or commit id`
|
||||
}, Commands.ShowCommitSearch, [new GitUri(Uri.file(log.repoPath), { fileName: '', repoPath: log.repoPath }), undefined, undefined, currentCommand]));
|
||||
}, Commands.ShowCommitSearch, [
|
||||
new GitUri(Uri.file(log.repoPath), { fileName: '', repoPath: log.repoPath }),
|
||||
{
|
||||
goBackCommand: currentCommand
|
||||
} as ShowCommitSearchCommandArgs
|
||||
]));
|
||||
|
||||
let previousPageCommand: CommandQuickPickItem | undefined = undefined;
|
||||
|
||||
@@ -44,9 +60,11 @@ export class BranchHistoryQuickPick {
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 this may take a while`
|
||||
}, Commands.ShowQuickBranchHistory, [
|
||||
new GitUri(Uri.file(log.repoPath), { fileName: '', repoPath: log.repoPath }),
|
||||
branch,
|
||||
0,
|
||||
goBackCommand
|
||||
{
|
||||
branch,
|
||||
maxCount: 0,
|
||||
goBackCommand
|
||||
} as ShowQuickBranchHistoryCommandArgs
|
||||
]));
|
||||
}
|
||||
else {
|
||||
@@ -55,9 +73,10 @@ export class BranchHistoryQuickPick {
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 shows \u00a0$(git-branch) ${branch} history`
|
||||
}, Commands.ShowQuickBranchHistory, [
|
||||
new GitUri(Uri.file(log.repoPath), { fileName: '', repoPath: log.repoPath }),
|
||||
branch,
|
||||
undefined,
|
||||
currentCommand
|
||||
{
|
||||
branch,
|
||||
goBackCommand: currentCommand
|
||||
} as ShowQuickBranchHistoryCommandArgs
|
||||
]));
|
||||
}
|
||||
|
||||
@@ -69,14 +88,29 @@ export class BranchHistoryQuickPick {
|
||||
const npc = new CommandQuickPickItem({
|
||||
label: `$(arrow-right) Show Next Commits`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 shows ${log.maxCount} newer commits`
|
||||
}, Commands.ShowQuickBranchHistory, [uri, branch, log.maxCount, goBackCommand, undefined, nextPageCommand]);
|
||||
}, Commands.ShowQuickBranchHistory, [
|
||||
uri,
|
||||
{
|
||||
branch,
|
||||
maxCount: log.maxCount,
|
||||
nextPageCommand
|
||||
} as ShowQuickBranchHistoryCommandArgs
|
||||
]);
|
||||
|
||||
const last = Iterables.last(log.commits.values());
|
||||
if (last != null) {
|
||||
previousPageCommand = new CommandQuickPickItem({
|
||||
label: `$(arrow-left) Show Previous Commits`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 shows ${log.maxCount} older commits`
|
||||
}, Commands.ShowQuickBranchHistory, [new GitUri(uri ? uri : last.uri, last), branch, log.maxCount, goBackCommand, undefined, npc]);
|
||||
}, Commands.ShowQuickBranchHistory, [
|
||||
new GitUri(uri ? uri : last.uri, last),
|
||||
{
|
||||
branch,
|
||||
maxCount: log.maxCount,
|
||||
goBackCommand,
|
||||
nextPageCommand: npc
|
||||
} as ShowQuickBranchHistoryCommandArgs
|
||||
]);
|
||||
|
||||
items.splice(0, 0, previousPageCommand);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
import { Arrays, Iterables } from '../system';
|
||||
import { QuickPickItem, QuickPickOptions, Uri, window } from 'vscode';
|
||||
import { Commands, Keyboard, KeyNoopCommand } from '../commands';
|
||||
import { Commands, CopyMessageToClipboardCommandArgs, CopyShaToClipboardCommandArgs, DiffDirectoryCommandCommandArgs, Keyboard, KeyNoopCommand, ShowQuickCommitDetailsCommandArgs, StashApplyCommandArgs, StashDeleteCommandArgs } from '../commands';
|
||||
import { CommandQuickPickItem, getQuickPickIgnoreFocusOut, KeyCommandQuickPickItem, OpenFileCommandQuickPickItem, OpenFilesCommandQuickPickItem } from './common';
|
||||
import { getGitStatusIcon, GitCommit, GitLogCommit, GitService, GitStashCommit, GitStatusFileStatus, GitUri, IGitLog, IGitStatusFile } from '../gitService';
|
||||
import { getGitStatusIcon, GitCommit, GitLogCommit, GitService, GitStashCommit, GitStatusFileStatus, GitUri, IGitLog, IGitStatusFile, RemoteResource } from '../gitService';
|
||||
import { OpenRemotesCommandQuickPickItem } from './remotes';
|
||||
import * as moment from 'moment';
|
||||
import * as path from 'path';
|
||||
@@ -93,47 +93,93 @@ export class CommitDetailsQuickPick {
|
||||
items.splice(index++, 0, new CommandQuickPickItem({
|
||||
label: `$(git-pull-request) Apply Stashed Changes`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 ${commit.message}`
|
||||
}, Commands.StashApply, [commit as GitStashCommit, true, false, currentCommand]));
|
||||
}, Commands.StashApply, [
|
||||
{
|
||||
confirm: true,
|
||||
deleteAfter: false,
|
||||
stashItem: commit as GitStashCommit,
|
||||
goBackCommand: currentCommand
|
||||
} as StashApplyCommandArgs
|
||||
]));
|
||||
|
||||
items.splice(index++, 0, new CommandQuickPickItem({
|
||||
label: `$(x) Delete Stashed Changes`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 ${commit.message}`
|
||||
}, Commands.StashDelete, [commit as GitStashCommit, true, currentCommand]));
|
||||
}, Commands.StashDelete, [
|
||||
{
|
||||
confirm: true,
|
||||
stashItem: commit as GitStashCommit,
|
||||
goBackCommand: currentCommand
|
||||
} as StashDeleteCommandArgs
|
||||
]));
|
||||
}
|
||||
|
||||
if (!stash) {
|
||||
items.splice(index++, 0, new CommandQuickPickItem({
|
||||
label: `$(clippy) Copy Commit ID to Clipboard`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 ${commit.shortSha}`
|
||||
}, Commands.CopyShaToClipboard, [uri, commit.sha]));
|
||||
}, Commands.CopyShaToClipboard, [
|
||||
uri,
|
||||
{
|
||||
sha: commit.sha
|
||||
} as CopyShaToClipboardCommandArgs
|
||||
]));
|
||||
}
|
||||
|
||||
items.splice(index++, 0, new CommandQuickPickItem({
|
||||
label: `$(clippy) Copy Message to Clipboard`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 ${commit.message}`
|
||||
}, Commands.CopyMessageToClipboard, [uri, commit.sha, commit.message]));
|
||||
}, Commands.CopyMessageToClipboard, [
|
||||
uri,
|
||||
{
|
||||
message: commit.message,
|
||||
sha: commit.sha
|
||||
} as CopyMessageToClipboardCommandArgs
|
||||
]));
|
||||
|
||||
if (!stash) {
|
||||
const remotes = Arrays.uniqueBy(await git.getRemotes(commit.repoPath), _ => _.url, _ => !!_.provider);
|
||||
if (remotes.length) {
|
||||
items.splice(index++, 0, new OpenRemotesCommandQuickPickItem(remotes, 'commit', commit.sha, currentCommand));
|
||||
items.splice(index++, 0, new OpenRemotesCommandQuickPickItem(remotes, {
|
||||
type: 'commit',
|
||||
sha: commit.sha
|
||||
} as RemoteResource, currentCommand));
|
||||
}
|
||||
|
||||
items.splice(index++, 0, new CommandQuickPickItem({
|
||||
label: `$(git-compare) Directory Compare with Previous Commit`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 $(git-commit) ${commit.previousShortSha || `${commit.shortSha}^`} \u00a0 $(git-compare) \u00a0 $(git-commit) ${commit.shortSha}`
|
||||
}, Commands.DiffDirectory, [commit.uri, commit.previousSha || `${commit.sha}^`, commit.sha]));
|
||||
}, Commands.DiffDirectory, [
|
||||
commit.uri,
|
||||
{
|
||||
shaOrBranch1: commit.previousSha || `${commit.sha}^`,
|
||||
shaOrBranch2: commit.sha
|
||||
} as DiffDirectoryCommandCommandArgs
|
||||
]));
|
||||
}
|
||||
|
||||
items.splice(index++, 0, new CommandQuickPickItem({
|
||||
label: `$(git-compare) Directory Compare with Working Tree`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 $(git-commit) ${commit.shortSha} \u00a0 $(git-compare) \u00a0 $(file-directory) Working Tree`
|
||||
}, Commands.DiffDirectory, [uri, commit.sha]));
|
||||
}, Commands.DiffDirectory, [
|
||||
uri,
|
||||
{
|
||||
shaOrBranch1: commit.sha
|
||||
} as DiffDirectoryCommandCommandArgs
|
||||
]));
|
||||
|
||||
items.splice(index++, 0, new CommandQuickPickItem({
|
||||
label: `Changed Files`,
|
||||
description: commit.getDiffStatus()
|
||||
}, Commands.ShowQuickCommitDetails, [uri, commit.sha, commit, goBackCommand, repoLog]));
|
||||
}, Commands.ShowQuickCommitDetails, [
|
||||
uri,
|
||||
{
|
||||
commit,
|
||||
repoLog,
|
||||
sha: commit.sha,
|
||||
goBackCommand
|
||||
} as ShowQuickCommitDetailsCommandArgs
|
||||
]));
|
||||
|
||||
items.push(new OpenCommitFilesCommandQuickPickItem(commit));
|
||||
items.push(new OpenCommitWorkingTreeFilesCommandQuickPickItem(commit));
|
||||
@@ -146,9 +192,28 @@ export class CommitDetailsQuickPick {
|
||||
let nextCommand: CommandQuickPickItem | (() => Promise<CommandQuickPickItem>) | undefined = undefined;
|
||||
if (!stash) {
|
||||
// If we have the full history, we are good
|
||||
if (repoLog && !repoLog.truncated && !repoLog.sha) {
|
||||
previousCommand = commit.previousSha === undefined ? undefined : new KeyCommandQuickPickItem(Commands.ShowQuickCommitDetails, [commit.previousUri, commit.previousSha, undefined, goBackCommand, repoLog]);
|
||||
nextCommand = commit.nextSha === undefined ? undefined : new KeyCommandQuickPickItem(Commands.ShowQuickCommitDetails, [commit.nextUri, commit.nextSha, undefined, goBackCommand, repoLog]);
|
||||
if (repoLog !== undefined && !repoLog.truncated && repoLog.sha === undefined) {
|
||||
previousCommand = commit.previousSha === undefined
|
||||
? undefined
|
||||
: new KeyCommandQuickPickItem(Commands.ShowQuickCommitDetails, [
|
||||
commit.previousUri,
|
||||
{
|
||||
repoLog,
|
||||
sha: commit.previousSha,
|
||||
goBackCommand
|
||||
} as ShowQuickCommitDetailsCommandArgs
|
||||
]);
|
||||
|
||||
nextCommand = commit.nextSha === undefined
|
||||
? undefined
|
||||
: new KeyCommandQuickPickItem(Commands.ShowQuickCommitDetails, [
|
||||
commit.nextUri,
|
||||
{
|
||||
repoLog,
|
||||
sha: commit.nextSha,
|
||||
goBackCommand
|
||||
} as ShowQuickCommitDetailsCommandArgs
|
||||
]);
|
||||
}
|
||||
else {
|
||||
previousCommand = async () => {
|
||||
@@ -156,7 +221,7 @@ export class CommitDetailsQuickPick {
|
||||
let c = log && log.commits.get(commit.sha);
|
||||
|
||||
// If we can't find the commit or the previous commit isn't available (since it isn't trustworthy)
|
||||
if (!c || !c.previousSha) {
|
||||
if (c === undefined || c.previousSha === undefined) {
|
||||
log = await git.getLogForRepo(commit.repoPath, commit.sha, git.config.advanced.maxQuickHistory);
|
||||
c = log && log.commits.get(commit.sha);
|
||||
|
||||
@@ -165,8 +230,17 @@ export class CommitDetailsQuickPick {
|
||||
c.nextSha = commit.nextSha;
|
||||
}
|
||||
}
|
||||
if (!c || !c.previousSha) return KeyNoopCommand;
|
||||
return new KeyCommandQuickPickItem(Commands.ShowQuickCommitDetails, [c.previousUri, c.previousSha, undefined, goBackCommand, log]);
|
||||
|
||||
if (c === undefined || c.previousSha === undefined) return KeyNoopCommand;
|
||||
|
||||
return new KeyCommandQuickPickItem(Commands.ShowQuickCommitDetails, [
|
||||
c.previousUri,
|
||||
{
|
||||
repoLog: log,
|
||||
sha: c.previousSha,
|
||||
goBackCommand
|
||||
} as ShowQuickCommitDetailsCommandArgs
|
||||
]);
|
||||
};
|
||||
|
||||
nextCommand = async () => {
|
||||
@@ -174,20 +248,29 @@ export class CommitDetailsQuickPick {
|
||||
let c = log && log.commits.get(commit.sha);
|
||||
|
||||
// If we can't find the commit or the next commit isn't available (since it isn't trustworthy)
|
||||
if (!c || !c.nextSha) {
|
||||
if (c === undefined || c.nextSha === undefined) {
|
||||
log = undefined;
|
||||
c = undefined;
|
||||
|
||||
// Try to find the next commit
|
||||
const nextLog = await git.getLogForRepo(commit.repoPath, commit.sha, 1, true);
|
||||
const next = nextLog && Iterables.first(nextLog.commits.values());
|
||||
if (next && next.sha !== commit.sha) {
|
||||
if (next !== undefined && next.sha !== commit.sha) {
|
||||
c = commit;
|
||||
c.nextSha = next.sha;
|
||||
}
|
||||
}
|
||||
if (!c || !c.nextSha) return KeyNoopCommand;
|
||||
return new KeyCommandQuickPickItem(Commands.ShowQuickCommitDetails, [c.nextUri, c.nextSha, undefined, goBackCommand, log]);
|
||||
|
||||
if (c === undefined || c.nextSha === undefined) return KeyNoopCommand;
|
||||
|
||||
return new KeyCommandQuickPickItem(Commands.ShowQuickCommitDetails, [
|
||||
c.nextUri,
|
||||
{
|
||||
repoLog: log,
|
||||
sha: c.nextSha,
|
||||
goBackCommand
|
||||
} as ShowQuickCommitDetailsCommandArgs
|
||||
]);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
import { Arrays, Iterables } from '../system';
|
||||
import { QuickPickItem, QuickPickOptions, Uri, window } from 'vscode';
|
||||
import { Commands, Keyboard, KeyNoopCommand } from '../commands';
|
||||
import { Commands, CopyMessageToClipboardCommandArgs, CopyShaToClipboardCommandArgs, DiffWithPreviousCommandArgs, DiffWithWorkingCommandArgs, Keyboard, KeyNoopCommand, ShowQuickCommitDetailsCommandArgs, ShowQuickCommitFileDetailsCommandArgs, ShowQuickFileHistoryCommandArgs } from '../commands';
|
||||
import { CommandQuickPickItem, getQuickPickIgnoreFocusOut, KeyCommandQuickPickItem, OpenFileCommandQuickPickItem } from './common';
|
||||
import { GitBranch, GitLogCommit, GitService, GitUri, IGitLog } from '../gitService';
|
||||
import { GitBranch, GitLogCommit, GitService, GitUri, IGitLog, RemoteResource } from '../gitService';
|
||||
import { OpenRemotesCommandQuickPickItem } from './remotes';
|
||||
import * as moment from 'moment';
|
||||
import * as path from 'path';
|
||||
@@ -61,13 +61,25 @@ export class CommitFileDetailsQuickPick {
|
||||
items.push(new CommandQuickPickItem({
|
||||
label: `$(git-commit) Show Commit Details`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 $(git-commit) ${commit.shortSha}`
|
||||
}, Commands.ShowQuickCommitDetails, [new GitUri(commit.uri, commit), commit.sha, commit, currentCommand]));
|
||||
}, Commands.ShowQuickCommitDetails, [
|
||||
new GitUri(commit.uri, commit),
|
||||
{
|
||||
commit,
|
||||
sha: commit.sha,
|
||||
goBackCommand: currentCommand
|
||||
} as ShowQuickCommitDetailsCommandArgs
|
||||
]));
|
||||
|
||||
if (commit.previousSha) {
|
||||
items.push(new CommandQuickPickItem({
|
||||
label: `$(git-compare) Compare with Previous Commit`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 $(git-commit) ${commit.previousShortSha} \u00a0 $(git-compare) \u00a0 $(git-commit) ${commit.shortSha}`
|
||||
}, Commands.DiffWithPrevious, [commit.uri, commit]));
|
||||
}, Commands.DiffWithPrevious, [
|
||||
commit.uri,
|
||||
{
|
||||
commit
|
||||
} as DiffWithPreviousCommandArgs
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,19 +87,35 @@ export class CommitFileDetailsQuickPick {
|
||||
items.push(new CommandQuickPickItem({
|
||||
label: `$(git-compare) Compare with Working Tree`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 $(git-commit) ${commit.shortSha} \u00a0 $(git-compare) \u00a0 $(file-text) ${workingName}`
|
||||
}, Commands.DiffWithWorking, [Uri.file(path.resolve(commit.repoPath, commit.workingFileName)), commit]));
|
||||
}, Commands.DiffWithWorking, [
|
||||
Uri.file(path.resolve(commit.repoPath, commit.workingFileName)),
|
||||
{
|
||||
commit
|
||||
} as DiffWithWorkingCommandArgs
|
||||
]));
|
||||
}
|
||||
|
||||
if (!stash) {
|
||||
items.push(new CommandQuickPickItem({
|
||||
label: `$(clippy) Copy Commit ID to Clipboard`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 ${commit.shortSha}`
|
||||
}, Commands.CopyShaToClipboard, [uri, commit.sha]));
|
||||
}, Commands.CopyShaToClipboard, [
|
||||
uri,
|
||||
{
|
||||
sha: commit.sha
|
||||
} as CopyShaToClipboardCommandArgs
|
||||
]));
|
||||
|
||||
items.push(new CommandQuickPickItem({
|
||||
label: `$(clippy) Copy Message to Clipboard`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 ${commit.message}`
|
||||
}, Commands.CopyMessageToClipboard, [uri, commit.sha, commit.message]));
|
||||
}, Commands.CopyMessageToClipboard, [
|
||||
uri,
|
||||
{
|
||||
message: commit.message,
|
||||
sha: commit.sha
|
||||
} as CopyMessageToClipboardCommandArgs
|
||||
]));
|
||||
}
|
||||
|
||||
items.push(new OpenCommitFileCommandQuickPickItem(commit));
|
||||
@@ -98,11 +126,19 @@ export class CommitFileDetailsQuickPick {
|
||||
const remotes = Arrays.uniqueBy(await git.getRemotes(commit.repoPath), _ => _.url, _ => !!_.provider);
|
||||
if (remotes.length) {
|
||||
if (!stash) {
|
||||
items.push(new OpenRemotesCommandQuickPickItem(remotes, 'file', commit.fileName, undefined, commit, currentCommand));
|
||||
items.push(new OpenRemotesCommandQuickPickItem(remotes, {
|
||||
type: 'file',
|
||||
fileName: commit.fileName,
|
||||
commit
|
||||
} as RemoteResource, currentCommand));
|
||||
}
|
||||
if (commit.workingFileName && commit.status !== 'D') {
|
||||
const branch = await git.getBranch(commit.repoPath || git.repoPath) as GitBranch;
|
||||
items.push(new OpenRemotesCommandQuickPickItem(remotes, 'working-file', commit.workingFileName, branch.name, undefined, currentCommand));
|
||||
items.push(new OpenRemotesCommandQuickPickItem(remotes, {
|
||||
type: 'working-file',
|
||||
fileName: commit.workingFileName,
|
||||
branch: branch.name
|
||||
} as RemoteResource, currentCommand));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,14 +146,25 @@ export class CommitFileDetailsQuickPick {
|
||||
items.push(new CommandQuickPickItem({
|
||||
label: `$(history) Show File History`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 of ${path.basename(commit.fileName)}`
|
||||
}, Commands.ShowQuickFileHistory, [Uri.file(path.resolve(commit.repoPath, commit.workingFileName)), undefined, undefined, currentCommand, fileLog]));
|
||||
}, Commands.ShowQuickFileHistory, [
|
||||
Uri.file(path.resolve(commit.repoPath, commit.workingFileName)),
|
||||
{
|
||||
fileLog,
|
||||
goBackCommand: currentCommand
|
||||
} as ShowQuickFileHistoryCommandArgs
|
||||
]));
|
||||
}
|
||||
|
||||
if (!stash) {
|
||||
items.push(new CommandQuickPickItem({
|
||||
label: `$(history) Show ${commit.workingFileName ? 'Previous ' : ''}File History`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 of ${path.basename(commit.fileName)} \u00a0\u2022\u00a0 from \u00a0$(git-commit) ${commit.shortSha}`
|
||||
}, Commands.ShowQuickFileHistory, [new GitUri(commit.uri, commit), undefined, undefined, currentCommand]));
|
||||
}, Commands.ShowQuickFileHistory, [
|
||||
new GitUri(commit.uri, commit),
|
||||
{
|
||||
goBackCommand: currentCommand
|
||||
} as ShowQuickFileHistoryCommandArgs
|
||||
]));
|
||||
}
|
||||
|
||||
if (goBackCommand) {
|
||||
@@ -128,9 +175,28 @@ export class CommitFileDetailsQuickPick {
|
||||
let nextCommand: CommandQuickPickItem | (() => Promise<CommandQuickPickItem>) | undefined = undefined;
|
||||
if (!stash) {
|
||||
// If we have the full history, we are good
|
||||
if (fileLog && !fileLog.truncated && !fileLog.sha) {
|
||||
previousCommand = commit.previousSha === undefined ? undefined : new KeyCommandQuickPickItem(Commands.ShowQuickCommitFileDetails, [commit.previousUri, commit.previousSha, undefined, goBackCommand, fileLog]);
|
||||
nextCommand = commit.nextSha === undefined ? undefined : new KeyCommandQuickPickItem(Commands.ShowQuickCommitFileDetails, [commit.nextUri, commit.nextSha, undefined, goBackCommand, fileLog]);
|
||||
if (fileLog !== undefined && !fileLog.truncated && fileLog.sha === undefined) {
|
||||
previousCommand = commit.previousSha === undefined
|
||||
? undefined
|
||||
: new KeyCommandQuickPickItem(Commands.ShowQuickCommitFileDetails, [
|
||||
commit.previousUri,
|
||||
{
|
||||
fileLog,
|
||||
sha: commit.previousSha,
|
||||
goBackCommand
|
||||
} as ShowQuickCommitFileDetailsCommandArgs
|
||||
]);
|
||||
|
||||
nextCommand = commit.nextSha === undefined
|
||||
? undefined
|
||||
: new KeyCommandQuickPickItem(Commands.ShowQuickCommitFileDetails, [
|
||||
commit.nextUri,
|
||||
{
|
||||
fileLog,
|
||||
sha: commit.nextSha,
|
||||
goBackCommand
|
||||
} as ShowQuickCommitFileDetailsCommandArgs
|
||||
]);
|
||||
}
|
||||
else {
|
||||
previousCommand = async () => {
|
||||
@@ -138,13 +204,13 @@ export class CommitFileDetailsQuickPick {
|
||||
let c = log && log.commits.get(commit.sha);
|
||||
|
||||
// If we can't find the commit or the previous commit isn't available (since it isn't trustworthy)
|
||||
if (!c || !c.previousSha) {
|
||||
if (c === undefined || c.previousSha === undefined) {
|
||||
log = await git.getLogForFile(commit.repoPath, uri.fsPath, commit.sha, git.config.advanced.maxQuickHistory);
|
||||
if (log === undefined) return KeyNoopCommand;
|
||||
|
||||
c = log && log.commits.get(commit.sha);
|
||||
// Since we exclude merge commits in file log, just grab the first returned commit
|
||||
if (!c && commit.isMerge) {
|
||||
if (c === undefined && commit.isMerge) {
|
||||
c = Iterables.first(log.commits.values());
|
||||
}
|
||||
|
||||
@@ -154,8 +220,17 @@ export class CommitFileDetailsQuickPick {
|
||||
c.nextFileName = commit.nextFileName;
|
||||
}
|
||||
}
|
||||
if (!c || !c.previousSha) return KeyNoopCommand;
|
||||
return new KeyCommandQuickPickItem(Commands.ShowQuickCommitFileDetails, [c.previousUri, c.previousSha, undefined, goBackCommand, log]);
|
||||
|
||||
if (c === undefined || c.previousSha === undefined) return KeyNoopCommand;
|
||||
|
||||
return new KeyCommandQuickPickItem(Commands.ShowQuickCommitFileDetails, [
|
||||
c.previousUri,
|
||||
{
|
||||
fileLog: log,
|
||||
sha: c.previousSha,
|
||||
goBackCommand
|
||||
} as ShowQuickCommitFileDetailsCommandArgs
|
||||
]);
|
||||
};
|
||||
|
||||
nextCommand = async () => {
|
||||
@@ -163,20 +238,29 @@ export class CommitFileDetailsQuickPick {
|
||||
let c = log && log.commits.get(commit.sha);
|
||||
|
||||
// If we can't find the commit or the next commit isn't available (since it isn't trustworthy)
|
||||
if (!c || !c.nextSha) {
|
||||
if (c === undefined || c.nextSha === undefined) {
|
||||
log = undefined;
|
||||
c = undefined;
|
||||
|
||||
// Try to find the next commit
|
||||
const next = await git.findNextCommit(commit.repoPath, uri.fsPath, commit.sha);
|
||||
if (next && next.sha !== commit.sha) {
|
||||
if (next !== undefined && next.sha !== commit.sha) {
|
||||
c = commit;
|
||||
c.nextSha = next.sha;
|
||||
c.nextFileName = next.originalFileName || next.fileName;
|
||||
}
|
||||
}
|
||||
if (!c || !c.nextSha) return KeyNoopCommand;
|
||||
return new KeyCommandQuickPickItem(Commands.ShowQuickCommitFileDetails, [c.nextUri, c.nextSha, undefined, goBackCommand, log]);
|
||||
|
||||
if (c === undefined || c.nextSha === undefined) return KeyNoopCommand;
|
||||
|
||||
return new KeyCommandQuickPickItem(Commands.ShowQuickCommitFileDetails, [
|
||||
c.nextUri,
|
||||
{
|
||||
fileLog: log,
|
||||
sha: c.nextSha,
|
||||
goBackCommand
|
||||
} as ShowQuickCommitFileDetailsCommandArgs
|
||||
]);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use strict';
|
||||
import { CancellationTokenSource, commands, Disposable, QuickPickItem, QuickPickOptions, Uri, window, workspace } from 'vscode';
|
||||
import { Commands, Keyboard, KeyboardScope, KeyMapping, openEditor } from '../commands';
|
||||
import { CancellationTokenSource, commands, Disposable, QuickPickItem, QuickPickOptions, TextDocumentShowOptions, TextEditor, Uri, window, workspace } from 'vscode';
|
||||
import { Commands, Keyboard, Keys, KeyboardScope, KeyMapping, openEditor } from '../commands';
|
||||
import { IAdvancedConfig } from '../configuration';
|
||||
import { ExtensionKey } from '../constants';
|
||||
import { GitCommit, GitLogCommit, GitStashCommit } from '../gitService';
|
||||
@@ -61,20 +61,45 @@ function _getInfiniteCancellablePromise(cancellation: CancellationTokenSource) {
|
||||
});
|
||||
}
|
||||
|
||||
export interface QuickPickItem extends QuickPickItem {
|
||||
onDidSelect?(): void;
|
||||
onDidPressKey?(key: Keys): Promise<{} | undefined>;
|
||||
}
|
||||
|
||||
export class CommandQuickPickItem implements QuickPickItem {
|
||||
|
||||
label: string;
|
||||
description: string;
|
||||
detail?: string | undefined;
|
||||
protected command: Commands | undefined;
|
||||
protected args: any[] | undefined;
|
||||
|
||||
constructor(item: QuickPickItem, protected command: Commands | undefined, protected args?: any[]) {
|
||||
constructor(item: QuickPickItem, args?: [Commands, any[]]);
|
||||
constructor(item: QuickPickItem, command?: Commands, args?: any[]);
|
||||
constructor(item: QuickPickItem, commandOrArgs?: Commands | [Commands, any[]], args?: any[]) {
|
||||
if (commandOrArgs === undefined) {
|
||||
this.command = undefined;
|
||||
this.args = args;
|
||||
}
|
||||
else if (typeof commandOrArgs === 'string') {
|
||||
this.command = commandOrArgs;
|
||||
this.args = args;
|
||||
}
|
||||
else {
|
||||
this.command = commandOrArgs[0];
|
||||
this.args = commandOrArgs.slice(1);
|
||||
}
|
||||
Object.assign(this, item);
|
||||
}
|
||||
|
||||
execute(): Thenable<{} | undefined> {
|
||||
execute(): Promise<{} | undefined> {
|
||||
if (this.command === undefined) return Promise.resolve(undefined);
|
||||
|
||||
return commands.executeCommand(this.command, ...(this.args || []));
|
||||
return commands.executeCommand(this.command, ...(this.args || [])) as Promise<{} | undefined>;
|
||||
}
|
||||
|
||||
onDidPressKey(key: Keys): Promise<{} | undefined> {
|
||||
return this.execute();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,12 +116,22 @@ export class OpenFileCommandQuickPickItem extends CommandQuickPickItem {
|
||||
super(item, undefined, undefined);
|
||||
}
|
||||
|
||||
async execute(pinned: boolean = false): Promise<{} | undefined> {
|
||||
return this.open(pinned);
|
||||
async execute(options?: TextDocumentShowOptions): Promise<TextEditor | undefined> {
|
||||
return openEditor(this.uri, options);
|
||||
}
|
||||
|
||||
async open(pinned: boolean = false): Promise<{} | undefined> {
|
||||
return openEditor(this.uri, pinned);
|
||||
onDidSelect(): Promise<{} | undefined> {
|
||||
return this.execute({
|
||||
preserveFocus: true,
|
||||
preview: true
|
||||
});
|
||||
}
|
||||
|
||||
onDidPressKey(key: Keys): Promise<{} | undefined> {
|
||||
return this.execute({
|
||||
preserveFocus: true,
|
||||
preview: false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,12 +141,19 @@ export class OpenFilesCommandQuickPickItem extends CommandQuickPickItem {
|
||||
super(item, undefined, undefined);
|
||||
}
|
||||
|
||||
async execute(): Promise<{} | undefined> {
|
||||
async execute(options: TextDocumentShowOptions = { preserveFocus: false, preview: false }): Promise<{} | undefined> {
|
||||
for (const uri of this.uris) {
|
||||
await openEditor(uri, true);
|
||||
await openEditor(uri, options);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async onDidPressKey(key: Keys): Promise<{} | undefined> {
|
||||
return this.execute({
|
||||
preserveFocus: true,
|
||||
preview: false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class CommitQuickPickItem implements QuickPickItem {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
import { Arrays, Iterables } from '../system';
|
||||
import { CancellationTokenSource, QuickPickOptions, Uri, window } from 'vscode';
|
||||
import { Commands, Keyboard, KeyNoopCommand } from '../commands';
|
||||
import { Commands, Keyboard, KeyNoopCommand, ShowQuickCurrentBranchHistoryCommandArgs, ShowQuickFileHistoryCommandArgs } from '../commands';
|
||||
import { CommandQuickPickItem, CommitQuickPickItem, getQuickPickIgnoreFocusOut, showQuickPickProgress } from './common';
|
||||
import { GitService, GitUri, IGitLog } from '../gitService';
|
||||
import { GitService, GitUri, IGitLog, RemoteResource } from '../gitService';
|
||||
import { OpenRemotesCommandQuickPickItem } from './remotes';
|
||||
import * as path from 'path';
|
||||
|
||||
@@ -30,7 +30,13 @@ export class FileHistoryQuickPick {
|
||||
items.splice(0, 0, new CommandQuickPickItem({
|
||||
label: `$(sync) Show All Commits`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 this may take a while`
|
||||
}, Commands.ShowQuickFileHistory, [Uri.file(uri.fsPath), undefined, 0, goBackCommand]));
|
||||
}, Commands.ShowQuickFileHistory, [
|
||||
Uri.file(uri.fsPath),
|
||||
{
|
||||
maxCount: 0,
|
||||
goBackCommand
|
||||
} as ShowQuickFileHistoryCommandArgs
|
||||
]));
|
||||
}
|
||||
else {
|
||||
const workingFileName = await git.findWorkingFileName(log.repoPath, path.relative(log.repoPath, uri.fsPath));
|
||||
@@ -40,14 +46,22 @@ export class FileHistoryQuickPick {
|
||||
label: `$(history) Show File History`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 of ${path.basename(workingFileName)}`
|
||||
}, Commands.ShowQuickFileHistory, [
|
||||
Uri.file(path.resolve(log.repoPath, workingFileName)),
|
||||
undefined,
|
||||
undefined,
|
||||
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}` : ''}`
|
||||
}, Commands.ShowQuickFileHistory, [uri, log.range, log.maxCount, goBackCommand, log])
|
||||
]));
|
||||
Uri.file(path.resolve(log.repoPath, workingFileName)),
|
||||
{
|
||||
goBackCommand: 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}` : ''}`
|
||||
}, Commands.ShowQuickFileHistory, [
|
||||
uri,
|
||||
{
|
||||
log: log,
|
||||
maxCount: log.maxCount,
|
||||
range: log.range,
|
||||
goBackCommand
|
||||
} as ShowQuickFileHistoryCommandArgs
|
||||
])
|
||||
} as ShowQuickFileHistoryCommandArgs
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,14 +74,28 @@ export class FileHistoryQuickPick {
|
||||
const npc = new CommandQuickPickItem({
|
||||
label: `$(arrow-right) Show Next Commits`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 shows ${log.maxCount} newer commits`
|
||||
}, Commands.ShowQuickFileHistory, [uri, undefined, log.maxCount, goBackCommand, undefined, nextPageCommand]);
|
||||
}, Commands.ShowQuickFileHistory, [
|
||||
uri,
|
||||
{
|
||||
maxCount: log.maxCount,
|
||||
goBackCommand,
|
||||
nextPageCommand
|
||||
} as ShowQuickFileHistoryCommandArgs
|
||||
]);
|
||||
|
||||
const last = Iterables.last(log.commits.values());
|
||||
if (last != null) {
|
||||
previousPageCommand = new CommandQuickPickItem({
|
||||
label: `$(arrow-left) Show Previous Commits`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 shows ${log.maxCount} older commits`
|
||||
}, Commands.ShowQuickFileHistory, [new GitUri(uri, last), undefined, log.maxCount, goBackCommand, undefined, npc]);
|
||||
}, Commands.ShowQuickFileHistory, [
|
||||
new GitUri(uri, last),
|
||||
{
|
||||
maxCount: log.maxCount,
|
||||
goBackCommand,
|
||||
nextPageCommand: npc
|
||||
} as ShowQuickFileHistoryCommandArgs
|
||||
]);
|
||||
|
||||
index++;
|
||||
items.splice(0, 0, previousPageCommand);
|
||||
@@ -80,23 +108,37 @@ export class FileHistoryQuickPick {
|
||||
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}` : ''}`
|
||||
}, Commands.ShowQuickFileHistory, [uri, log.range, log.maxCount, undefined, log]);
|
||||
}, Commands.ShowQuickFileHistory, [
|
||||
uri,
|
||||
{
|
||||
log,
|
||||
maxCount: log.maxCount,
|
||||
range: log.range
|
||||
} as ShowQuickFileHistoryCommandArgs
|
||||
]);
|
||||
|
||||
// Only show the full repo option if we are the root
|
||||
if (!goBackCommand) {
|
||||
if (goBackCommand === undefined) {
|
||||
items.splice(index++, 0, new CommandQuickPickItem({
|
||||
label: `$(history) Show Branch History`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 shows \u00a0$(git-branch) ${branch!.name} history`
|
||||
}, Commands.ShowQuickCurrentBranchHistory,
|
||||
[
|
||||
undefined,
|
||||
currentCommand
|
||||
{
|
||||
goBackCommand: currentCommand
|
||||
} as ShowQuickCurrentBranchHistoryCommandArgs
|
||||
]));
|
||||
}
|
||||
|
||||
const remotes = Arrays.uniqueBy(await git.getRemotes(uri.repoPath!), _ => _.url, _ => !!_.provider);
|
||||
if (remotes.length) {
|
||||
items.splice(index++, 0, new OpenRemotesCommandQuickPickItem(remotes, 'file', uri.getRelativePath(), branch!.name, uri.sha, currentCommand));
|
||||
items.splice(index++, 0, new OpenRemotesCommandQuickPickItem(remotes, {
|
||||
type: 'file',
|
||||
branch: branch!.name,
|
||||
fileName: uri.getRelativePath(),
|
||||
sha: uri.sha
|
||||
} as RemoteResource, currentCommand));
|
||||
}
|
||||
|
||||
if (goBackCommand) {
|
||||
|
||||
@@ -1,88 +1,66 @@
|
||||
'use strict';
|
||||
import { QuickPickOptions, window } from 'vscode';
|
||||
import { Commands } from '../commands';
|
||||
import { Commands, OpenInRemoteCommandArgs } from '../commands';
|
||||
import { CommandQuickPickItem, getQuickPickIgnoreFocusOut } from './common';
|
||||
import { getNameFromRemoteOpenType, GitLogCommit, GitRemote, RemoteOpenType } from '../gitService';
|
||||
import { getNameFromRemoteResource, GitLogCommit, GitRemote, RemoteResource } from '../gitService';
|
||||
import * as path from 'path';
|
||||
|
||||
export class OpenRemoteCommandQuickPickItem extends CommandQuickPickItem {
|
||||
|
||||
private remote: GitRemote;
|
||||
private type: RemoteOpenType;
|
||||
private resource: RemoteResource;
|
||||
|
||||
constructor(remote: GitRemote, type: RemoteOpenType, ...args: string[]) {
|
||||
constructor(remote: GitRemote, resource: RemoteResource) {
|
||||
super({
|
||||
label: `$(link-external) Open ${getNameFromRemoteOpenType(type)} in ${remote.provider!.name}`,
|
||||
label: `$(link-external) Open ${getNameFromRemoteResource(resource)} in ${remote.provider!.name}`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 $(repo) ${remote.provider!.path}`
|
||||
}, undefined, undefined);
|
||||
|
||||
this.remote = remote;
|
||||
this.type = type;
|
||||
this.args = args;
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
async execute(): Promise<{}> {
|
||||
return this.remote.provider!.open(this.type, ...this.args!);
|
||||
return this.remote.provider!.open(this.resource);
|
||||
}
|
||||
}
|
||||
|
||||
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, branch?: string, commit?: GitLogCommit, goBackCommand?: CommandQuickPickItem);
|
||||
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, fileShaOrCommit?: string | GitLogCommit, goBackCommand?: CommandQuickPickItem) {
|
||||
let fileBranch: string | undefined = undefined;
|
||||
if (typeof goBackCommandOrFileBranch === 'string') {
|
||||
fileBranch = goBackCommandOrFileBranch;
|
||||
}
|
||||
else if (!goBackCommand) {
|
||||
goBackCommand = goBackCommandOrFileBranch;
|
||||
}
|
||||
constructor(remotes: GitRemote[], resource: RemoteResource, goBackCommand?: CommandQuickPickItem) {
|
||||
const name = getNameFromRemoteResource(resource);
|
||||
|
||||
const name = getNameFromRemoteOpenType(type);
|
||||
|
||||
let fileSha: string | undefined = undefined;
|
||||
let description: string | undefined = undefined;
|
||||
let placeHolder: string | undefined = undefined;
|
||||
switch (type) {
|
||||
let description: string = '';
|
||||
switch (resource.type) {
|
||||
case 'branch':
|
||||
description = `$(git-branch) ${branchOrShaOrFileName}`;
|
||||
placeHolder = `open ${branchOrShaOrFileName} ${name.toLowerCase()} in\u2026`;
|
||||
description = `$(git-branch) ${resource.branch}`;
|
||||
break;
|
||||
|
||||
case 'commit':
|
||||
const shortSha = branchOrShaOrFileName.substring(0, 8);
|
||||
|
||||
const shortSha = resource.sha.substring(0, 8);
|
||||
description = `$(git-commit) ${shortSha}`;
|
||||
placeHolder = `open ${name.toLowerCase()} ${shortSha} in\u2026`;
|
||||
break;
|
||||
case 'file':
|
||||
case 'working-file':
|
||||
const fileName = path.basename(branchOrShaOrFileName);
|
||||
if (fileShaOrCommit instanceof GitLogCommit) {
|
||||
if (fileShaOrCommit.status === 'D') {
|
||||
fileSha = fileShaOrCommit.previousSha;
|
||||
|
||||
description = `$(file-text) ${fileName} in \u00a0$(git-commit) ${fileShaOrCommit.previousShortSha} (deleted in \u00a0$(git-commit) ${fileShaOrCommit.shortSha})`;
|
||||
placeHolder = `open ${branchOrShaOrFileName} \u00a0\u2022\u00a0 ${fileShaOrCommit.previousShortSha} in\u2026`;
|
||||
case 'file':
|
||||
if (resource.commit !== undefined && resource.commit instanceof GitLogCommit) {
|
||||
if (resource.commit.status === 'D') {
|
||||
resource.sha = resource.commit.previousSha;
|
||||
description = `$(file-text) ${path.basename(resource.fileName)} in \u00a0$(git-commit) ${resource.commit.previousShortSha} (deleted in \u00a0$(git-commit) ${resource.commit.shortSha})`;
|
||||
}
|
||||
else {
|
||||
fileSha = fileShaOrCommit.sha;
|
||||
|
||||
description = `$(file-text) ${fileName} in \u00a0$(git-commit) ${fileShaOrCommit.shortSha}`;
|
||||
placeHolder = `open ${branchOrShaOrFileName} \u00a0\u2022\u00a0 ${fileShaOrCommit.shortSha} in\u2026`;
|
||||
resource.sha = resource.commit.sha;
|
||||
description = `$(file-text) ${path.basename(resource.fileName)} in \u00a0$(git-commit) ${resource.commit.shortSha}`;
|
||||
}
|
||||
}
|
||||
else {
|
||||
fileSha = fileShaOrCommit;
|
||||
const shortFileSha = (fileSha && fileSha.substring(0, 8)) || '';
|
||||
const shaSuffix = shortFileSha ? ` \u00a0\u2022\u00a0 ${shortFileSha}` : '';
|
||||
|
||||
description = `$(file-text) ${fileName}${shortFileSha ? ` in \u00a0$(git-commit) ${shortFileSha}` : ''}`;
|
||||
placeHolder = `open ${branchOrShaOrFileName}${shaSuffix} in\u2026`;
|
||||
const shortFileSha = resource.sha === undefined ? '' : resource.sha.substring(0, 8);
|
||||
description = `$(file-text) ${path.basename(resource.fileName)}${shortFileSha ? ` in \u00a0$(git-commit) ${shortFileSha}` : ''}`;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'working-file':
|
||||
description = `$(file-text) ${path.basename(resource.fileName)}`;
|
||||
break;
|
||||
}
|
||||
|
||||
const remote = remotes[0];
|
||||
@@ -90,7 +68,14 @@ 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, fileBranch, fileSha], goBackCommand]);
|
||||
}, Commands.OpenInRemote, [
|
||||
undefined,
|
||||
{
|
||||
remotes,
|
||||
resource,
|
||||
goBackCommand
|
||||
} as OpenInRemoteCommandArgs
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -102,15 +87,21 @@ 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, fileBranch, fileSha], goBackCommand]);
|
||||
}, Commands.OpenInRemote, [
|
||||
undefined,
|
||||
{
|
||||
remotes,
|
||||
resource,
|
||||
goBackCommand
|
||||
} as OpenInRemoteCommandArgs
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
export class RemotesQuickPick {
|
||||
|
||||
static async show(remotes: GitRemote[], placeHolder: string, type: RemoteOpenType, args: string[], goBackCommand?: CommandQuickPickItem): Promise<OpenRemoteCommandQuickPickItem | CommandQuickPickItem | undefined> {
|
||||
|
||||
const items = remotes.map(_ => new OpenRemoteCommandQuickPickItem(_, type, ...args)) as (OpenRemoteCommandQuickPickItem | CommandQuickPickItem)[];
|
||||
static async show(remotes: GitRemote[], placeHolder: string, resource: RemoteResource, goBackCommand?: CommandQuickPickItem): Promise<OpenRemoteCommandQuickPickItem | CommandQuickPickItem | undefined> {
|
||||
const items = remotes.map(_ => new OpenRemoteCommandQuickPickItem(_, resource)) as (OpenRemoteCommandQuickPickItem | CommandQuickPickItem)[];
|
||||
|
||||
if (goBackCommand) {
|
||||
items.splice(0, 0, goBackCommand);
|
||||
@@ -118,12 +109,11 @@ export class RemotesQuickPick {
|
||||
|
||||
// const scope = await Keyboard.instance.beginScope({ left: goBackCommand });
|
||||
|
||||
const pick = await window.showQuickPick(items,
|
||||
{
|
||||
placeHolder: placeHolder,
|
||||
ignoreFocusOut: getQuickPickIgnoreFocusOut()
|
||||
} as QuickPickOptions);
|
||||
if (!pick) return undefined;
|
||||
const pick = await window.showQuickPick(items, {
|
||||
placeHolder: placeHolder,
|
||||
ignoreFocusOut: getQuickPickIgnoreFocusOut()
|
||||
} as QuickPickOptions);
|
||||
if (pick === undefined) return undefined;
|
||||
|
||||
// await scope.dispose();
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
import { Iterables } from '../system';
|
||||
import { QuickPickItem, QuickPickOptions, Uri, window } from 'vscode';
|
||||
import { Commands, Keyboard } from '../commands';
|
||||
import { Commands, Keyboard, OpenChangedFilesCommandArgs, ShowQuickBranchHistoryCommandArgs, ShowQuickRepoStatusCommandArgs, ShowQuickStashListCommandArgs } from '../commands';
|
||||
import { CommandQuickPickItem, getQuickPickIgnoreFocusOut, OpenFileCommandQuickPickItem } from './common';
|
||||
import { GitService, GitStatusFile, GitUri, IGitStatus } from '../gitService';
|
||||
import * as path from 'path';
|
||||
@@ -36,7 +36,12 @@ export class OpenStatusFilesCommandQuickPickItem extends CommandQuickPickItem {
|
||||
label: `$(file-symlink-file) Open Changed Files`,
|
||||
description: ''
|
||||
//detail: `Opens all of the changed files in the repository`
|
||||
}, Commands.OpenChangedFiles, [undefined, uris]);
|
||||
}, Commands.OpenChangedFiles, [
|
||||
undefined,
|
||||
{
|
||||
uris
|
||||
} as OpenChangedFilesCommandArgs
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +77,12 @@ export class RepoStatusQuickPick {
|
||||
const currentCommand = new CommandQuickPickItem({
|
||||
label: `go back \u21A9`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 to \u00a0$(git-branch) ${status.branch} status`
|
||||
}, Commands.ShowQuickRepoStatus, [undefined, goBackCommand]);
|
||||
}, Commands.ShowQuickRepoStatus, [
|
||||
undefined,
|
||||
{
|
||||
goBackCommand
|
||||
} as ShowQuickRepoStatusCommandArgs
|
||||
]);
|
||||
|
||||
if (hasStaged) {
|
||||
let index = 0;
|
||||
@@ -81,7 +91,12 @@ export class RepoStatusQuickPick {
|
||||
items.splice(unstagedIndex, 0, new CommandQuickPickItem({
|
||||
label: `Unstaged Files`,
|
||||
description: unstagedStatus
|
||||
}, Commands.ShowQuickRepoStatus, [undefined, goBackCommand]));
|
||||
}, Commands.ShowQuickRepoStatus, [
|
||||
undefined,
|
||||
{
|
||||
goBackCommand
|
||||
} as ShowQuickRepoStatusCommandArgs
|
||||
]));
|
||||
|
||||
items.splice(unstagedIndex, 0, new OpenStatusFilesCommandQuickPickItem(files.filter(_ => _.status !== 'D' && _.staged), {
|
||||
label: `\u00a0\u00a0\u00a0\u00a0 $(file-symlink-file) Open Staged Files`,
|
||||
@@ -97,13 +112,23 @@ export class RepoStatusQuickPick {
|
||||
items.splice(index++, 0, new CommandQuickPickItem({
|
||||
label: `Staged Files`,
|
||||
description: stagedStatus
|
||||
}, Commands.ShowQuickRepoStatus, [undefined, goBackCommand]));
|
||||
}, Commands.ShowQuickRepoStatus, [
|
||||
undefined,
|
||||
{
|
||||
goBackCommand
|
||||
} as ShowQuickRepoStatusCommandArgs
|
||||
]));
|
||||
}
|
||||
else if (files.some(_ => !_.staged)) {
|
||||
items.splice(0, 0, new CommandQuickPickItem({
|
||||
label: `Unstaged Files`,
|
||||
description: unstagedStatus
|
||||
}, Commands.ShowQuickRepoStatus, [undefined, goBackCommand]));
|
||||
}, Commands.ShowQuickRepoStatus, [
|
||||
undefined,
|
||||
{
|
||||
goBackCommand
|
||||
} as ShowQuickRepoStatusCommandArgs
|
||||
]));
|
||||
}
|
||||
|
||||
if (files.length) {
|
||||
@@ -117,13 +142,23 @@ export class RepoStatusQuickPick {
|
||||
items.push(new CommandQuickPickItem({
|
||||
label: `No changes in the working tree`,
|
||||
description: ''
|
||||
}, Commands.ShowQuickRepoStatus, [undefined, goBackCommand]));
|
||||
}, Commands.ShowQuickRepoStatus, [
|
||||
undefined,
|
||||
{
|
||||
goBackCommand
|
||||
} as ShowQuickRepoStatusCommandArgs
|
||||
]));
|
||||
}
|
||||
|
||||
items.splice(0, 0, new CommandQuickPickItem({
|
||||
label: `$(repo-push) Show Stashed Changes`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 shows stashed changes in the repository`
|
||||
}, Commands.ShowQuickStashList, [new GitUri(Uri.file(status.repoPath), { fileName: '', repoPath: status.repoPath }), currentCommand]));
|
||||
}, Commands.ShowQuickStashList, [
|
||||
new GitUri(Uri.file(status.repoPath), { fileName: '', repoPath: status.repoPath }),
|
||||
{
|
||||
goBackCommand: currentCommand
|
||||
} as ShowQuickStashListCommandArgs
|
||||
]));
|
||||
|
||||
if (status.upstream && status.state.ahead) {
|
||||
items.splice(0, 0, new CommandQuickPickItem({
|
||||
@@ -131,9 +166,12 @@ export class RepoStatusQuickPick {
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 shows commits in \u00a0$(git-branch) ${status.branch} but not \u00a0$(git-branch) ${status.upstream}`
|
||||
}, Commands.ShowQuickBranchHistory, [
|
||||
new GitUri(Uri.file(status.repoPath), { fileName: '', repoPath: status.repoPath, sha: `${status.upstream}..${status.branch}` }),
|
||||
status.branch, 0, currentCommand
|
||||
])
|
||||
);
|
||||
{
|
||||
branch: status.branch,
|
||||
maxCount: 0,
|
||||
goBackCommand: currentCommand
|
||||
} as ShowQuickBranchHistoryCommandArgs
|
||||
]));
|
||||
}
|
||||
|
||||
if (status.upstream && status.state.behind) {
|
||||
@@ -142,16 +180,24 @@ export class RepoStatusQuickPick {
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 shows commits in \u00a0$(git-branch) ${status.upstream} but not \u00a0$(git-branch) ${status.branch}${status.sha ? ` (since \u00a0$(git-commit) ${status.sha.substring(0, 8)})` : ''}`
|
||||
}, Commands.ShowQuickBranchHistory, [
|
||||
new GitUri(Uri.file(status.repoPath), { fileName: '', repoPath: status.repoPath, sha: `${status.branch}..${status.upstream}` }),
|
||||
status.upstream, 0, currentCommand
|
||||
])
|
||||
);
|
||||
{
|
||||
branch: status.upstream,
|
||||
maxCount: 0,
|
||||
goBackCommand: currentCommand
|
||||
} as ShowQuickBranchHistoryCommandArgs
|
||||
]));
|
||||
}
|
||||
|
||||
if (status.upstream && !status.state.ahead && !status.state.behind) {
|
||||
items.splice(0, 0, new CommandQuickPickItem({
|
||||
label: `$(git-branch) ${status.branch} is up-to-date with \u00a0$(git-branch) ${status.upstream}`,
|
||||
description: ''
|
||||
}, Commands.ShowQuickRepoStatus, [undefined, goBackCommand]));
|
||||
}, Commands.ShowQuickRepoStatus, [
|
||||
undefined,
|
||||
{
|
||||
goBackCommand
|
||||
} as ShowQuickRepoStatusCommandArgs
|
||||
]));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
import { Iterables } from '../system';
|
||||
import { QuickPickOptions, window } from 'vscode';
|
||||
import { Commands, Keyboard } from '../commands';
|
||||
import { Commands, Keyboard, StashSaveCommandArgs } from '../commands';
|
||||
import { GitService, IGitStash } from '../gitService';
|
||||
import { CommandQuickPickItem, CommitQuickPickItem, getQuickPickIgnoreFocusOut } from '../quickPicks';
|
||||
|
||||
@@ -14,12 +14,22 @@ export class StashListQuickPick {
|
||||
items.splice(0, 0, new CommandQuickPickItem({
|
||||
label: `$(repo-push) Stash Unstaged Changes`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 stashes only unstaged changes`
|
||||
}, Commands.StashSave, [undefined, true, currentCommand]));
|
||||
}, Commands.StashSave, [
|
||||
{
|
||||
unstagedOnly: true,
|
||||
goBackCommand: currentCommand
|
||||
} as StashSaveCommandArgs
|
||||
]));
|
||||
|
||||
items.splice(0, 0, new CommandQuickPickItem({
|
||||
label: `$(repo-push) Stash Changes`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 stashes all changes`
|
||||
}, Commands.StashSave, [undefined, undefined, currentCommand]));
|
||||
}, Commands.StashSave, [
|
||||
{
|
||||
unstagedOnly: false,
|
||||
goBackCommand: currentCommand
|
||||
} as StashSaveCommandArgs
|
||||
]));
|
||||
}
|
||||
|
||||
if (goBackCommand) {
|
||||
|
||||
Reference in New Issue
Block a user