'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'); } } }