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.
 

104 lines
3.2 KiB

'use strict';
import { env, TextEditor, Uri } from 'vscode';
import {
ActiveEditorCommand,
command,
CommandContext,
Commands,
getCommandUri,
isCommandContextViewNodeHasBranch,
isCommandContextViewNodeHasCommit,
isCommandContextViewNodeHasTag,
} from './common';
import { Container } from '../container';
import { GitUri } from '../git/gitUri';
import { Logger } from '../logger';
import { Messages } from '../messages';
import { Iterables } from '../system';
export interface CopyMessageToClipboardCommandArgs {
message?: string;
sha?: string;
}
@command()
export class CopyMessageToClipboardCommand extends ActiveEditorCommand {
constructor() {
super(Commands.CopyMessageToClipboard);
}
protected preExecute(context: CommandContext, args?: CopyMessageToClipboardCommandArgs) {
if (isCommandContextViewNodeHasCommit(context)) {
args = { ...args };
args.sha = context.node.commit.sha;
return this.execute(context.editor, context.node.commit.uri, args);
} else if (isCommandContextViewNodeHasBranch(context)) {
args = { ...args };
args.sha = context.node.branch.sha;
return this.execute(context.editor, context.node.uri, args);
} else if (isCommandContextViewNodeHasTag(context)) {
args = { ...args };
args.sha = context.node.tag.sha;
return this.execute(context.editor, context.node.uri, args);
}
return this.execute(context.editor, context.uri, args);
}
async execute(editor?: TextEditor, uri?: Uri, args?: CopyMessageToClipboardCommandArgs) {
uri = getCommandUri(uri, editor);
args = { ...args };
try {
let repoPath;
// If we don't have an editor then get the message of the last commit to the branch
if (uri == null) {
repoPath = await Container.git.getActiveRepoPath(editor);
if (!repoPath) return;
const log = await Container.git.getLog(repoPath, { limit: 1 });
if (log == null) return;
args.message = Iterables.first(log.commits.values()).message;
} else if (args.message == null) {
const gitUri = await GitUri.fromUri(uri);
repoPath = gitUri.repoPath;
if (args.sha == null) {
const blameline = editor?.selection.active.line ?? 0;
if (blameline < 0) return;
try {
const blame = editor?.document.isDirty
? await Container.git.getBlameForLineContents(gitUri, blameline, editor.document.getText())
: await Container.git.getBlameForLine(gitUri, blameline);
if (blame == null) return;
if (blame.commit.isUncommitted) return;
args.sha = blame.commit.sha;
if (!repoPath) {
repoPath = blame.commit.repoPath;
}
} catch (ex) {
Logger.error(ex, 'CopyMessageToClipboardCommand', `getBlameForLine(${blameline})`);
void Messages.showGenericErrorMessage('Unable to copy message');
return;
}
}
// Get the full commit message -- since blame only returns the summary
const commit = await Container.git.getCommit(repoPath!, args.sha);
if (commit == null) return;
args.message = commit.message;
}
void (await env.clipboard.writeText(args.message));
} catch (ex) {
Logger.error(ex, 'CopyMessageToClipboardCommand');
void Messages.showGenericErrorMessage('Unable to copy message');
}
}
}