You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

126 lines
5.0 KiB

'use strict';
import { commands, TextDocumentShowOptions, TextEditor, Uri, window } from 'vscode';
import { Container } from '../container';
import { GitCommit, GitService, GitUri } from '../git/gitService';
import { Logger } from '../logger';
import { Messages } from '../messages';
import { ActiveEditorCommand, command, CommandContext, Commands, getCommandUri } from './common';
import { DiffWithCommandArgs } from './diffWith';
import { UriComparer } from '../comparers';
export interface DiffWithWorkingCommandArgs {
commit?: GitCommit;
line?: number;
showOptions?: TextDocumentShowOptions;
}
@command()
export class DiffWithWorkingCommand extends ActiveEditorCommand {
constructor() {
super([Commands.DiffWithWorking, Commands.DiffWithWorkingInDiff]);
}
protected preExecute(context: CommandContext, args: DiffWithWorkingCommandArgs = {}) {
if (
context.command === Commands.DiffWithWorkingInDiff
// || (context.editor !== undefined && context.editor.viewColumn === undefined)
) {
// HACK: If in a diff, try to determine if we are on the right or left side
// If there is a context uri and it doesn't match the editor uri, assume we are on the left
// If on the left, use the editor uri and pretend we aren't in a diff
if (context.uri !== undefined && context.editor !== undefined && context.editor.document !== undefined) {
if (!UriComparer.equals(context.uri, context.editor.document.uri, { exact: true })) {
return this.execute(context.editor, context.editor.document.uri, args);
}
}
}
return this.execute(context.editor, context.uri, args);
}
async execute(editor?: TextEditor, uri?: Uri, args: DiffWithWorkingCommandArgs = {}): Promise<any> {
uri = getCommandUri(uri, editor);
if (uri == null) return undefined;
const gitUri = await GitUri.fromUri(uri);
args = { ...args };
if (args.line === undefined) {
args.line = editor == null ? 0 : editor.selection.active.line;
}
if (args.commit === undefined || args.commit.isUncommitted) {
// If the sha is missing, just let the user know the file matches
if (gitUri.sha === undefined) return window.showInformationMessage('File matches the working tree');
if (gitUri.sha === GitService.deletedOrMissingSha) {
return window.showWarningMessage('Unable to open compare. File has been deleted from the working tree');
}
// If we are a fake "staged" sha, check the status
let ref: string | undefined = gitUri.sha;
if (gitUri.isUncommittedStaged) {
ref = undefined;
const status = await Container.git.getStatusForFile(gitUri.repoPath!, gitUri.fsPath);
if (status !== undefined && status.indexStatus !== undefined) {
const diffArgs: DiffWithCommandArgs = {
repoPath: gitUri.repoPath,
lhs: {
sha: GitService.uncommittedStagedSha,
uri: gitUri.documentUri()
},
rhs: {
sha: '',
uri: gitUri.documentUri()
},
line: args.line,
showOptions: args.showOptions
};
return commands.executeCommand(Commands.DiffWith, diffArgs);
}
}
try {
args.commit = await Container.git.getCommitForFile(gitUri.repoPath, gitUri.fsPath, {
ref: ref,
firstIfNotFound: true
});
if (args.commit === undefined) {
return window.showWarningMessage(
"Unable to open compare. File doesn't exist in the specified revision"
);
}
}
catch (ex) {
Logger.error(
ex,
'DiffWithWorkingCommand',
`getLogCommit(${gitUri.repoPath}, ${gitUri.fsPath}, ${ref})`
);
return Messages.showGenericErrorMessage('Unable to open compare');
}
}
const workingUri = await args.commit.getWorkingUri();
if (workingUri === undefined) {
return window.showWarningMessage('Unable to open compare. File has been deleted from the working tree');
}
const diffArgs: DiffWithCommandArgs = {
repoPath: args.commit.repoPath,
lhs: {
sha: args.commit.sha,
uri: args.commit.uri
},
rhs: {
sha: '',
uri: workingUri
},
line: args.line,
showOptions: args.showOptions
};
return commands.executeCommand(Commands.DiffWith, diffArgs);
}
}