diff --git a/src/commands/addAuthors.ts b/src/commands/addAuthors.ts index 3f7112a..0138a84 100644 --- a/src/commands/addAuthors.ts +++ b/src/commands/addAuthors.ts @@ -1,9 +1,9 @@ import type { SourceControl } from 'vscode'; import { Commands } from '../constants'; import type { Container } from '../container'; +import { executeGitCommand } from '../git/actions'; import { command } from '../system/command'; import { Command } from './base'; -import { executeGitCommand } from './gitCommands.actions'; @command() export class AddAuthorsCommand extends Command { diff --git a/src/commands/copyMessageToClipboard.ts b/src/commands/copyMessageToClipboard.ts index 8049e0b..3246516 100644 --- a/src/commands/copyMessageToClipboard.ts +++ b/src/commands/copyMessageToClipboard.ts @@ -2,6 +2,7 @@ import type { TextEditor, Uri } from 'vscode'; import { env } from 'vscode'; import { Commands } from '../constants'; import type { Container } from '../container'; +import { copyMessageToClipboard } from '../git/actions/commit'; import { GitUri } from '../git/gitUri'; import { Logger } from '../logger'; import { showGenericErrorMessage } from '../messages'; @@ -15,7 +16,6 @@ import { isCommandContextViewNodeHasCommit, isCommandContextViewNodeHasTag, } from './base'; -import { GitActions } from './gitCommands.actions'; export interface CopyMessageToClipboardCommandArgs { message?: string; @@ -62,7 +62,7 @@ export class CopyMessageToClipboardCommand extends ActiveEditorCommand { try { if (!args.message) { if (args.repoPath != null && args.sha != null) { - await GitActions.Commit.copyMessageToClipboard({ ref: args.sha, repoPath: args.repoPath }); + await copyMessageToClipboard({ ref: args.sha, repoPath: args.repoPath }); return; } @@ -92,7 +92,7 @@ export class CopyMessageToClipboardCommand extends ActiveEditorCommand { const blame = await this.container.git.getBlameForLine(gitUri, blameline, editor?.document); if (blame == null || blame.commit.isUncommitted) return; - await GitActions.Commit.copyMessageToClipboard(blame.commit); + await copyMessageToClipboard(blame.commit); return; } catch (ex) { Logger.error(ex, 'CopyMessageToClipboardCommand', `getBlameForLine(${blameline})`); @@ -101,7 +101,7 @@ export class CopyMessageToClipboardCommand extends ActiveEditorCommand { return; } } else { - await GitActions.Commit.copyMessageToClipboard({ ref: args.sha, repoPath: repoPath! }); + await copyMessageToClipboard({ ref: args.sha, repoPath: repoPath! }); return; } } diff --git a/src/commands/ghpr/createWorktree.ts b/src/commands/ghpr/createWorktree.ts index 42c2ad4..a93d993 100644 --- a/src/commands/ghpr/createWorktree.ts +++ b/src/commands/ghpr/createWorktree.ts @@ -2,13 +2,14 @@ import type { Uri } from 'vscode'; import { window } from 'vscode'; import { Commands } from '../../constants'; import type { Container } from '../../container'; +import { add as addRemote } from '../../git/actions/remote'; +import { create as createWorktree } from '../../git/actions/worktree'; import { GitReference } from '../../git/models/reference'; import type { GitRemote } from '../../git/models/remote'; import { Logger } from '../../logger'; import { command } from '../../system/command'; import { waitUntilNextTick } from '../../system/promise'; import { Command } from '../base'; -import { GitActions } from '../gitCommands.actions'; interface PullRequestNode { readonly pullRequestModel: PullRequest; @@ -90,7 +91,11 @@ export class CreateWorktreeCommand extends Command { ); if (result?.title !== 'Yes') return; - await GitActions.Remote.add(repo, remoteOwner, remoteUrl, { confirm: false, fetch: true, reveal: false }); + await addRemote(repo, remoteOwner, remoteUrl, { + confirm: false, + fetch: true, + reveal: false, + }); [remote] = await repo.getRemotes({ filter: r => r.url === remoteUrl }); if (remote == null) return; } else { @@ -100,7 +105,7 @@ export class CreateWorktreeCommand extends Command { await waitUntilNextTick(); try { - await GitActions.Worktree.create( + await createWorktree( repo, undefined, GitReference.create(`${remote.name}/${ref}`, repo.path, { diff --git a/src/commands/git/log.ts b/src/commands/git/log.ts index 1d1383c..25db34a 100644 --- a/src/commands/git/log.ts +++ b/src/commands/git/log.ts @@ -1,5 +1,6 @@ import { GlyphChars, quickPickTitleMaxChars } from '../../constants'; import type { Container } from '../../container'; +import { showDetailsView } from '../../git/actions/commit'; import { GitCommit } from '../../git/models/commit'; import type { GitLog } from '../../git/models/log'; import { GitReference } from '../../git/models/reference'; @@ -7,7 +8,6 @@ import { Repository } from '../../git/models/repository'; import { formatPath } from '../../system/formatPath'; import { pad } from '../../system/string'; import type { ViewsWithRepositoryFolders } from '../../views/viewBase'; -import { GitActions } from '../gitCommands.actions'; import { getSteps } from '../gitCommands.utils'; import type { PartialStepState, StepGenerator } from '../quickCommand'; import { pickBranchOrTagStep, pickCommitStep, pickRepositoryStep, QuickCommand, StepResult } from '../quickCommand'; @@ -191,7 +191,7 @@ export class LogGitCommand extends QuickCommand { let result: StepResult>; if (state.openPickInView) { - void GitActions.Commit.showDetailsView(state.reference as GitCommit, { + void showDetailsView(state.reference as GitCommit, { pin: false, preserveFocus: false, }); diff --git a/src/commands/git/remote.ts b/src/commands/git/remote.ts index a8537a3..0cff91a 100644 --- a/src/commands/git/remote.ts +++ b/src/commands/git/remote.ts @@ -1,6 +1,7 @@ import type { QuickPickItem } from 'vscode'; import { QuickInputButtons } from 'vscode'; import type { Container } from '../../container'; +import { reveal } from '../../git/actions/remote'; import type { GitRemote } from '../../git/models/remote'; import { Repository } from '../../git/models/repository'; import { Logger } from '../../logger'; @@ -8,7 +9,6 @@ import { showGenericErrorMessage } from '../../messages'; import type { QuickPickItemOfT } from '../../quickpicks/items/common'; import { FlagsQuickPickItem } from '../../quickpicks/items/flags'; import type { ViewsWithRepositoryFolders } from '../../views/viewBase'; -import { GitActions } from '../gitCommands.actions'; import type { AsyncStepResultGenerator, PartialStepState, @@ -320,7 +320,7 @@ export class RemoteGitCommand extends QuickCommand { await state.repo.addRemote(state.name, state.url, state.flags.includes('-f') ? { fetch: true } : undefined); if (state.reveal !== false) { - void GitActions.Remote.reveal(undefined, { + void reveal(undefined, { focus: true, select: true, }); diff --git a/src/commands/git/search.ts b/src/commands/git/search.ts index 6a86cec..9342a0f 100644 --- a/src/commands/git/search.ts +++ b/src/commands/git/search.ts @@ -2,6 +2,7 @@ import { configuration } from '../../configuration'; import { ContextKeys, GlyphChars } from '../../constants'; import type { Container } from '../../container'; import { getContext } from '../../context'; +import { showDetailsView } from '../../git/actions/commit'; import type { GitCommit } from '../../git/models/commit'; import type { GitLog } from '../../git/models/log'; import type { Repository } from '../../git/models/repository'; @@ -12,7 +13,6 @@ import { ActionQuickPickItem } from '../../quickpicks/items/common'; import { pluralize } from '../../system/string'; import { SearchResultsNode } from '../../views/nodes/searchResultsNode'; import type { ViewsWithRepositoryFolders } from '../../views/viewBase'; -import { GitActions } from '../gitCommands.actions'; import { getSteps } from '../gitCommands.utils'; import type { PartialStepState, StepGenerator, StepResultGenerator, StepSelection, StepState } from '../quickCommand'; import { @@ -245,7 +245,7 @@ export class SearchGitCommand extends QuickCommand { let result: StepResult>; if (state.openPickInView) { - void GitActions.Commit.showDetailsView(context.commit, { + void showDetailsView(context.commit, { pin: false, preserveFocus: false, }); diff --git a/src/commands/git/stash.ts b/src/commands/git/stash.ts index 7c7060f..8353b37 100644 --- a/src/commands/git/stash.ts +++ b/src/commands/git/stash.ts @@ -3,6 +3,7 @@ import { QuickInputButtons, window } from 'vscode'; import { ContextKeys, GlyphChars } from '../../constants'; import type { Container } from '../../container'; import { getContext } from '../../context'; +import { reveal, showDetailsView } from '../../git/actions/stash'; import { StashApplyError, StashApplyErrorReason } from '../../git/errors'; import type { GitStashCommit } from '../../git/models/commit'; import type { GitStashReference } from '../../git/models/reference'; @@ -15,7 +16,6 @@ import { FlagsQuickPickItem } from '../../quickpicks/items/flags'; import { formatPath } from '../../system/formatPath'; import { pad } from '../../system/string'; import type { ViewsWithRepositoryFolders } from '../../views/viewBase'; -import { GitActions } from '../gitCommands.actions'; import { getSteps } from '../gitCommands.utils'; import type { AsyncStepResultGenerator, @@ -367,12 +367,12 @@ export class StashGitCommand extends QuickCommand { additionalButtons: [QuickCommandButtons.ShowDetailsView, QuickCommandButtons.RevealInSideBar], onDidClickButton: (quickpick, button) => { if (button === QuickCommandButtons.ShowDetailsView) { - void GitActions.Stash.showDetailsView(state.reference, { + void showDetailsView(state.reference, { pin: false, preserveFocus: true, }); } else if (button === QuickCommandButtons.RevealInSideBar) { - void GitActions.Stash.reveal(state.reference, { + void reveal(state.reference, { select: true, expand: true, }); @@ -431,12 +431,12 @@ export class StashGitCommand extends QuickCommand { additionalButtons: [QuickCommandButtons.ShowDetailsView, QuickCommandButtons.RevealInSideBar], onDidClickButton: (quickpick, button) => { if (button === QuickCommandButtons.ShowDetailsView) { - void GitActions.Stash.showDetailsView(state.reference, { + void showDetailsView(state.reference, { pin: false, preserveFocus: true, }); } else if (button === QuickCommandButtons.RevealInSideBar) { - void GitActions.Stash.reveal(state.reference, { + void reveal(state.reference, { select: true, expand: true, }); diff --git a/src/commands/git/worktree.ts b/src/commands/git/worktree.ts index f186591..6baf998 100644 --- a/src/commands/git/worktree.ts +++ b/src/commands/git/worktree.ts @@ -4,6 +4,7 @@ import type { Config } from '../../configuration'; import { configuration } from '../../configuration'; import type { Container } from '../../container'; import { PlusFeatures } from '../../features'; +import { open, reveal, revealInFileExplorer } from '../../git/actions/worktree'; import { WorktreeCreateError, WorktreeCreateErrorReason, @@ -22,7 +23,6 @@ import { basename, isDescendent } from '../../system/path'; import { pluralize, truncateLeft } from '../../system/string'; import { OpenWorkspaceLocation } from '../../system/utils'; import type { ViewsWithRepositoryFolders } from '../../views/viewBase'; -import { GitActions } from '../gitCommands.actions'; import type { AsyncStepResultGenerator, CustomStep, @@ -386,7 +386,7 @@ export class WorktreeGitCommand extends QuickCommand { }); if (state.reveal !== false) { - void GitActions.Worktree.reveal(undefined, { + void reveal(undefined, { select: true, focus: true, }); @@ -426,13 +426,17 @@ export class WorktreeGitCommand extends QuickCommand { switch (action) { case 'always': - GitActions.Worktree.open(worktree, { location: OpenWorkspaceLocation.CurrentWindow }); + open(worktree, { + location: OpenWorkspaceLocation.CurrentWindow, + }); break; case 'alwaysNewWindow': - GitActions.Worktree.open(worktree, { location: OpenWorkspaceLocation.NewWindow }); + open(worktree, { location: OpenWorkspaceLocation.NewWindow }); break; case 'addToWorkspace': - GitActions.Worktree.open(worktree, { location: OpenWorkspaceLocation.AddToWorkspace }); + open(worktree, { + location: OpenWorkspaceLocation.AddToWorkspace, + }); break; } }); @@ -797,9 +801,9 @@ export class WorktreeGitCommand extends QuickCommand { const worktree = context.worktrees.find(wt => wt.uri.toString() === state.uri.toString())!; if (state.flags.includes('--reveal-explorer')) { - void GitActions.Worktree.revealInFileExplorer(worktree); + void revealInFileExplorer(worktree); } else { - GitActions.Worktree.open(worktree, { + open(worktree, { location: state.flags.includes('--new-window') ? OpenWorkspaceLocation.NewWindow : OpenWorkspaceLocation.CurrentWindow, diff --git a/src/commands/gitCommands.actions.ts b/src/commands/gitCommands.actions.ts deleted file mode 100644 index fa7ffb0..0000000 --- a/src/commands/gitCommands.actions.ts +++ /dev/null @@ -1,1061 +0,0 @@ -import type { TextDocumentShowOptions } from 'vscode'; -import { env, Range, Uri, window } from 'vscode'; -import type { - BrowseRepoAtRevisionCommandArgs, - DiffWithCommandArgs, - DiffWithPreviousCommandArgs, - DiffWithWorkingCommandArgs, - GitCommandsCommandArgs, - GitCommandsCommandArgsWithCompletion, - OpenFileOnRemoteCommandArgs, - OpenWorkingFileCommandArgs, - ShowQuickCommitCommandArgs, - ShowQuickCommitFileCommandArgs, -} from '../commands'; -import type { FileAnnotationType } from '../configuration'; -import { Commands, CoreCommands } from '../constants'; -import { Container } from '../container'; -import { GitUri } from '../git/gitUri'; -import type { GitCommit, GitStashCommit } from '../git/models/commit'; -import { isCommit } from '../git/models/commit'; -import type { GitContributor } from '../git/models/contributor'; -import type { GitFile } from '../git/models/file'; -import type { - GitBranchReference, - GitRevisionReference, - GitStashReference, - GitTagReference, -} from '../git/models/reference'; -import { GitReference, GitRevision } from '../git/models/reference'; -import type { GitRemote } from '../git/models/remote'; -import type { Repository } from '../git/models/repository'; -import type { GitWorktree } from '../git/models/worktree'; -import type { ShowInCommitGraphCommandArgs } from '../plus/webviews/graph/graphWebview'; -import { ensure } from '../system/array'; -import { executeCommand, executeCoreCommand, executeEditorCommand } from '../system/command'; -import { defer } from '../system/promise'; -import type { OpenWorkspaceLocation } from '../system/utils'; -import { findOrOpenEditor, findOrOpenEditors, openWorkspace } from '../system/utils'; -import type { ViewsWithRepositoryFolders } from '../views/viewBase'; -import type { ResetGitCommandArgs } from './git/reset'; - -export async function executeGitCommand(args: GitCommandsCommandArgs): Promise { - const deferred = defer(); - void (await executeCommand(Commands.GitCommands, { - ...args, - completion: deferred, - })); - return deferred.promise; -} - -export namespace GitActions { - export async function browseAtRevision(uri: Uri, options?: { before?: boolean; openInNewWindow?: boolean }) { - void (await executeEditorCommand(Commands.BrowseRepoAtRevision, undefined, { - uri: uri, - before: options?.before, - openInNewWindow: options?.openInNewWindow, - })); - } - - export function cherryPick(repo?: string | Repository, refs?: GitRevisionReference | GitRevisionReference[]) { - return executeGitCommand({ - command: 'cherry-pick', - state: { repo: repo, references: refs }, - }); - } - - export function fetch(repos?: string | string[] | Repository | Repository[], ref?: GitBranchReference) { - return executeGitCommand({ command: 'fetch', state: { repos: repos, reference: ref } }); - } - - export function merge(repo?: string | Repository, ref?: GitReference) { - return executeGitCommand({ command: 'merge', state: { repo: repo, reference: ref } }); - } - - export function pull(repos?: string | string[] | Repository | Repository[], ref?: GitBranchReference) { - return executeGitCommand({ command: 'pull', state: { repos: repos, reference: ref } }); - } - - export function push(repos?: string | string[] | Repository | Repository[], force?: boolean, ref?: GitReference) { - return executeGitCommand({ - command: 'push', - state: { repos: repos, flags: force ? ['--force'] : [], reference: ref }, - }); - } - - export function rebase(repo?: string | Repository, ref?: GitReference, interactive: boolean = true) { - return executeGitCommand({ - command: 'rebase', - state: { repo: repo, reference: ref, flags: interactive ? ['--interactive'] : [] }, - }); - } - - export function reset( - repo?: string | Repository, - ref?: GitRevisionReference, - flags?: NonNullable['flags'], - ) { - return executeGitCommand({ - command: 'reset', - confirm: flags == null || flags.includes('--hard'), - state: { repo: repo, reference: ref, flags: flags }, - }); - } - - export function revert(repo?: string | Repository, refs?: GitRevisionReference | GitRevisionReference[]) { - return executeGitCommand({ - command: 'revert', - state: { repo: repo, references: refs }, - }); - } - - export function switchTo( - repos?: string | string[] | Repository | Repository[], - ref?: GitReference, - confirm?: boolean, - ) { - return executeGitCommand({ - command: 'switch', - state: { repos: repos, reference: ref }, - confirm: confirm, - }); - } - - export namespace Branch { - export function create(repo?: string | Repository, ref?: GitReference, name?: string) { - return executeGitCommand({ - command: 'branch', - state: { - subcommand: 'create', - repo: repo, - reference: ref, - name: name, - }, - }); - } - - export function remove(repo?: string | Repository, refs?: GitBranchReference | GitBranchReference[]) { - return executeGitCommand({ - command: 'branch', - state: { - subcommand: 'delete', - repo: repo, - references: refs, - }, - }); - } - - export function rename(repo?: string | Repository, ref?: GitBranchReference, name?: string) { - return executeGitCommand({ - command: 'branch', - state: { - subcommand: 'rename', - repo: repo, - reference: ref, - name: name, - }, - }); - } - - export async function reveal( - branch: GitBranchReference, - options?: { - select?: boolean; - focus?: boolean; - expand?: boolean | number; - }, - ) { - const view = branch.remote ? Container.instance.remotesView : Container.instance.branchesView; - const node = view.canReveal - ? await view.revealBranch(branch, options) - : await Container.instance.repositoriesView.revealBranch(branch, options); - - if (node == null) { - void view.show({ preserveFocus: !options?.focus }); - } - return node; - } - } - - export namespace Commit { - export async function applyChanges( - file: string | GitFile, - ref1: GitRevisionReference, - ref2?: GitRevisionReference, - ) { - // Open the working file to ensure undo will work - await GitActions.Commit.openFile(file, ref1, { preserveFocus: true, preview: false }); - - let ref = ref1.ref; - // If the file is `?` (untracked), then this must be a stash, so get the ^3 commit to access the untracked file - if (typeof file !== 'string' && file.status === '?') { - ref = `${ref}^3`; - } - - await Container.instance.git.applyChangesToWorkingFile( - GitUri.fromFile(file, ref1.repoPath, ref), - ref, - ref2?.ref, - ); - } - - export async function copyIdToClipboard(ref: { repoPath: string; ref: string } | GitCommit) { - await env.clipboard.writeText(ref.ref); - } - - export async function copyMessageToClipboard( - ref: { repoPath: string; ref: string } | GitCommit, - ): Promise { - let commit; - if (isCommit(ref)) { - commit = ref; - if (commit.message == null) { - await commit.ensureFullDetails(); - } - } else { - commit = await Container.instance.git.getCommit(ref.repoPath, ref.ref); - if (commit == null) return; - } - - const message = commit.message ?? commit.summary; - await env.clipboard.writeText(message); - } - - export async function openAllChanges(commit: GitCommit, options?: TextDocumentShowOptions): Promise; - export async function openAllChanges( - files: GitFile[], - refs: { repoPath: string; ref1: string; ref2: string }, - options?: TextDocumentShowOptions, - ): Promise; - export async function openAllChanges( - commitOrFiles: GitCommit | GitFile[], - refsOrOptions: { repoPath: string; ref1: string; ref2: string } | TextDocumentShowOptions | undefined, - options?: TextDocumentShowOptions, - ) { - let files; - let refs; - if (isCommit(commitOrFiles)) { - if (commitOrFiles.files == null) { - await commitOrFiles.ensureFullDetails(); - } - - files = commitOrFiles.files ?? []; - refs = { - repoPath: commitOrFiles.repoPath, - // Don't need to worry about verifying the previous sha, as the DiffWith command will - ref1: commitOrFiles.unresolvedPreviousSha, - ref2: commitOrFiles.sha, - }; - - options = refsOrOptions as TextDocumentShowOptions | undefined; - } else { - files = commitOrFiles; - refs = refsOrOptions as { repoPath: string; ref1: string; ref2: string }; - } - - if (files.length > 10) { - const result = await window.showWarningMessage( - `Are you sure you want to open the changes for all ${files.length} files?`, - { title: 'Yes' }, - { title: 'No', isCloseAffordance: true }, - ); - if (result == null || result.title === 'No') return; - } - - options = { preserveFocus: true, preview: false, ...options }; - - for (const file of files) { - await openChanges(file, refs, options); - } - } - - export async function openAllChangesWithDiffTool(commit: GitCommit): Promise; - export async function openAllChangesWithDiffTool( - files: GitFile[], - ref: { repoPath: string; ref: string }, - ): Promise; - export async function openAllChangesWithDiffTool( - commitOrFiles: GitCommit | GitFile[], - ref?: { repoPath: string; ref: string }, - ) { - let files; - if (isCommit(commitOrFiles)) { - if (commitOrFiles.files == null) { - await commitOrFiles.ensureFullDetails(); - } - - files = commitOrFiles.files ?? []; - ref = { - repoPath: commitOrFiles.repoPath, - ref: commitOrFiles.sha, - }; - } else { - files = commitOrFiles; - } - - if (files.length > 10) { - const result = await window.showWarningMessage( - `Are you sure you want to open the changes for all ${files.length} files?`, - { title: 'Yes' }, - { title: 'No', isCloseAffordance: true }, - ); - if (result == null || result.title === 'No') return; - } - - for (const file of files) { - void openChangesWithDiffTool(file, ref!); - } - } - - export async function openAllChangesWithWorking( - commit: GitCommit, - options?: TextDocumentShowOptions, - ): Promise; - export async function openAllChangesWithWorking( - files: GitFile[], - ref: { repoPath: string; ref: string }, - options?: TextDocumentShowOptions, - ): Promise; - export async function openAllChangesWithWorking( - commitOrFiles: GitCommit | GitFile[], - refOrOptions: { repoPath: string; ref: string } | TextDocumentShowOptions | undefined, - options?: TextDocumentShowOptions, - ) { - let files; - let ref; - if (isCommit(commitOrFiles)) { - if (commitOrFiles.files == null) { - await commitOrFiles.ensureFullDetails(); - } - - files = commitOrFiles.files ?? []; - ref = { - repoPath: commitOrFiles.repoPath, - ref: commitOrFiles.sha, - }; - - options = refOrOptions as TextDocumentShowOptions | undefined; - } else { - files = commitOrFiles; - ref = refOrOptions as { repoPath: string; ref: string }; - } - - if (files.length > 10) { - const result = await window.showWarningMessage( - `Are you sure you want to open the changes for all ${files.length} files?`, - { title: 'Yes' }, - { title: 'No', isCloseAffordance: true }, - ); - if (result == null || result.title === 'No') return; - } - - options = { preserveFocus: true, preview: false, ...options }; - - for (const file of files) { - await openChangesWithWorking(file, ref, options); - } - } - - export async function openChanges( - file: string | GitFile, - commit: GitCommit, - options?: TextDocumentShowOptions, - ): Promise; - export async function openChanges( - file: GitFile, - refs: { repoPath: string; ref1: string; ref2: string }, - options?: TextDocumentShowOptions, - ): Promise; - export async function openChanges( - file: string | GitFile, - commitOrRefs: GitCommit | { repoPath: string; ref1: string; ref2: string }, - options?: TextDocumentShowOptions, - ) { - if (typeof file === 'string') { - if (!isCommit(commitOrRefs)) throw new Error('Invalid arguments'); - - const f = await commitOrRefs.findFile(file); - if (f == null) throw new Error('Invalid arguments'); - - file = f; - } - - options = { preserveFocus: true, preview: false, ...options }; - - if (file.status === 'A') { - if (!isCommit(commitOrRefs)) return; - - const commit = await commitOrRefs.getCommitForFile(file); - void executeCommand(Commands.DiffWithPrevious, { - commit: commit, - showOptions: options, - }); - } - - const refs = isCommit(commitOrRefs) - ? { - repoPath: commitOrRefs.repoPath, - // Don't need to worry about verifying the previous sha, as the DiffWith command will - ref1: commitOrRefs.unresolvedPreviousSha, - ref2: commitOrRefs.sha, - } - : commitOrRefs; - - const uri1 = GitUri.fromFile(file, refs.repoPath); - const uri2 = - file.status === 'R' || file.status === 'C' - ? GitUri.fromFile(file, refs.repoPath, refs.ref2, true) - : uri1; - - void (await executeCommand(Commands.DiffWith, { - repoPath: refs.repoPath, - lhs: { uri: uri1, sha: refs.ref1 }, - rhs: { uri: uri2, sha: refs.ref2 }, - showOptions: options, - })); - } - - export function openChangesWithDiffTool( - file: string | GitFile, - commit: GitCommit, - tool?: string, - ): Promise; - export function openChangesWithDiffTool( - file: GitFile, - ref: { repoPath: string; ref: string }, - tool?: string, - ): Promise; - export async function openChangesWithDiffTool( - file: string | GitFile, - commitOrRef: GitCommit | { repoPath: string; ref: string }, - tool?: string, - ) { - if (typeof file === 'string') { - if (!isCommit(commitOrRef)) throw new Error('Invalid arguments'); - - const f = await commitOrRef.findFile(file); - if (f == null) throw new Error('Invalid arguments'); - - file = f; - } - - return Container.instance.git.openDiffTool( - commitOrRef.repoPath, - GitUri.fromFile(file, file.repoPath ?? commitOrRef.repoPath), - { - ref1: GitRevision.isUncommitted(commitOrRef.ref) ? '' : `${commitOrRef.ref}^`, - ref2: GitRevision.isUncommitted(commitOrRef.ref) ? '' : commitOrRef.ref, - staged: GitRevision.isUncommittedStaged(commitOrRef.ref) || file.indexStatus != null, - tool: tool, - }, - ); - } - - export async function openChangesWithWorking( - file: string | GitFile, - commit: GitCommit, - options?: TextDocumentShowOptions, - ): Promise; - export async function openChangesWithWorking( - file: GitFile, - ref: { repoPath: string; ref: string }, - options?: TextDocumentShowOptions, - ): Promise; - export async function openChangesWithWorking( - file: string | GitFile, - commitOrRef: GitCommit | { repoPath: string; ref: string }, - options?: TextDocumentShowOptions, - ) { - if (typeof file === 'string') { - if (!isCommit(commitOrRef)) throw new Error('Invalid arguments'); - - const f = await commitOrRef.findFile(file); - if (f == null) throw new Error('Invalid arguments'); - - file = f; - } - - if (file.status === 'D') return; - - let ref; - if (isCommit(commitOrRef)) { - ref = { - repoPath: commitOrRef.repoPath, - ref: commitOrRef.sha, - }; - } else { - ref = commitOrRef; - } - - options = { preserveFocus: true, preview: false, ...options }; - - void (await executeEditorCommand(Commands.DiffWithWorking, undefined, { - uri: GitUri.fromFile(file, ref.repoPath, ref.ref), - showOptions: options, - })); - } - - export async function openDirectoryCompare( - repoPath: string, - ref: string, - ref2: string | undefined, - tool?: string, - ): Promise { - return Container.instance.git.openDirectoryCompare(repoPath, ref, ref2, tool); - } - - export async function openDirectoryCompareWithPrevious( - ref: { repoPath: string; ref: string } | GitCommit, - ): Promise { - return openDirectoryCompare(ref.repoPath, ref.ref, `${ref.ref}^`); - } - - export async function openDirectoryCompareWithWorking( - ref: { repoPath: string; ref: string } | GitCommit, - ): Promise { - return openDirectoryCompare(ref.repoPath, ref.ref, undefined); - } - - export async function openFile(uri: Uri, options?: TextDocumentShowOptions): Promise; - export async function openFile( - file: string | GitFile, - ref: GitRevisionReference, - options?: TextDocumentShowOptions, - ): Promise; - export async function openFile( - fileOrUri: string | GitFile | Uri, - refOrOptions?: GitRevisionReference | TextDocumentShowOptions, - options?: TextDocumentShowOptions, - ) { - let uri; - if (fileOrUri instanceof Uri) { - uri = fileOrUri; - options = refOrOptions as TextDocumentShowOptions; - } else { - const ref = refOrOptions as GitRevisionReference; - - uri = GitUri.fromFile(fileOrUri, ref.repoPath, ref.ref); - // If the file is `?` (untracked), then this must be an untracked file in a stash, so just return - if (typeof fileOrUri !== 'string' && fileOrUri.status === '?') return; - } - - options = { preserveFocus: true, preview: false, ...options }; - - void (await executeEditorCommand(Commands.OpenWorkingFile, undefined, { - uri: uri, - showOptions: options, - })); - } - - export async function openFileAtRevision( - revisionUri: Uri, - options?: TextDocumentShowOptions & { annotationType?: FileAnnotationType; line?: number }, - ): Promise; - export async function openFileAtRevision( - file: string | GitFile, - commit: GitCommit, - options?: TextDocumentShowOptions & { annotationType?: FileAnnotationType; line?: number }, - ): Promise; - export async function openFileAtRevision( - fileOrRevisionUri: string | GitFile | Uri, - commitOrOptions?: GitCommit | TextDocumentShowOptions, - options?: TextDocumentShowOptions & { annotationType?: FileAnnotationType; line?: number }, - ): Promise { - let uri; - if (fileOrRevisionUri instanceof Uri) { - if (isCommit(commitOrOptions)) throw new Error('Invalid arguments'); - - uri = fileOrRevisionUri; - options = commitOrOptions; - } else { - if (!isCommit(commitOrOptions)) throw new Error('Invalid arguments'); - - const commit = commitOrOptions; - - let file; - if (typeof fileOrRevisionUri === 'string') { - const f = await commit.findFile(fileOrRevisionUri); - if (f == null) throw new Error('Invalid arguments'); - - file = f; - } else { - file = fileOrRevisionUri; - } - - uri = Container.instance.git.getRevisionUri( - file.status === 'D' ? (await commit.getPreviousSha()) ?? GitRevision.deletedOrMissing : commit.sha, - file, - commit.repoPath, - ); - } - - const { annotationType, line, ...opts }: Exclude = { - preserveFocus: true, - preview: false, - ...options, - }; - - if (line != null && line !== 0) { - opts.selection = new Range(line, 0, line, 0); - } - - const editor = await findOrOpenEditor(uri, opts); - if (annotationType != null && editor != null) { - void (await Container.instance.fileAnnotations.show(editor, annotationType, { - selection: { line: line }, - })); - } - } - - export async function openFileOnRemote(uri: Uri): Promise; - export async function openFileOnRemote(file: string | GitFile, ref: GitRevisionReference): Promise; - export async function openFileOnRemote( - fileOrUri: string | GitFile | Uri, - ref?: GitRevisionReference, - ): Promise { - let uri; - if (fileOrUri instanceof Uri) { - uri = fileOrUri; - } else { - if (ref == null) throw new Error('Invalid arguments'); - - uri = GitUri.fromFile(fileOrUri, ref.repoPath, ref.ref); - // If the file is `?` (untracked), then this must be an untracked file in a stash, so just return - if (typeof fileOrUri !== 'string' && fileOrUri.status === '?') return; - } - - void (await executeCommand<[Uri, OpenFileOnRemoteCommandArgs]>(Commands.OpenFileOnRemote, uri, { - sha: ref?.ref, - })); - } - - export async function openFiles(commit: GitCommit): Promise; - export async function openFiles(files: GitFile[], repoPath: string, ref: string): Promise; - export async function openFiles( - commitOrFiles: GitCommit | GitFile[], - repoPath?: string, - ref?: string, - ): Promise { - let files; - if (isCommit(commitOrFiles)) { - if (commitOrFiles.files == null) { - await commitOrFiles.ensureFullDetails(); - } - - files = commitOrFiles.files ?? []; - repoPath = commitOrFiles.repoPath; - ref = commitOrFiles.sha; - } else { - files = commitOrFiles; - } - - if (files.length > 10) { - const result = await window.showWarningMessage( - `Are you sure you want to open all ${files.length} files?`, - { title: 'Yes' }, - { title: 'No', isCloseAffordance: true }, - ); - if (result == null || result.title === 'No') return; - } - - const uris: Uri[] = ( - await Promise.all( - files.map(file => - Container.instance.git.getWorkingUri(repoPath!, GitUri.fromFile(file, repoPath!, ref)), - ), - ) - ).filter((u?: T): u is T => Boolean(u)); - findOrOpenEditors(uris); - } - - export async function openFilesAtRevision(commit: GitCommit): Promise; - export async function openFilesAtRevision( - files: GitFile[], - repoPath: string, - ref1: string, - ref2: string, - ): Promise; - export async function openFilesAtRevision( - commitOrFiles: GitCommit | GitFile[], - repoPath?: string, - ref1?: string, - ref2?: string, - ): Promise { - let files; - if (isCommit(commitOrFiles)) { - if (commitOrFiles.files == null) { - await commitOrFiles.ensureFullDetails(); - } - - files = commitOrFiles.files ?? []; - repoPath = commitOrFiles.repoPath; - ref1 = commitOrFiles.sha; - ref2 = await commitOrFiles.getPreviousSha(); - } else { - files = commitOrFiles; - } - - if (files.length > 10) { - const result = await window.showWarningMessage( - `Are you sure you want to open all ${files.length} file revisions?`, - { title: 'Yes' }, - { title: 'No', isCloseAffordance: true }, - ); - if (result == null || result.title === 'No') return; - } - - findOrOpenEditors( - files.map(file => - Container.instance.git.getRevisionUri(file.status === 'D' ? ref2! : ref1!, file, repoPath!), - ), - ); - } - - export async function restoreFile(file: string | GitFile, revision: GitRevisionReference) { - let path; - let ref; - if (typeof file === 'string') { - path = file; - ref = revision.ref; - } else { - path = file.path; - ref = - file.status === `?` ? `${revision.ref}^3` : file.status === 'D' ? `${revision.ref}^` : revision.ref; - } - - await Container.instance.git.checkout(revision.repoPath, ref, { path: path }); - } - - export async function reveal( - commit: GitRevisionReference, - options?: { - select?: boolean; - focus?: boolean; - expand?: boolean | number; - }, - ) { - const views = [ - Container.instance.commitsView, - Container.instance.branchesView, - Container.instance.remotesView, - ]; - - // TODO@eamodio stop duplicate notifications - - for (const view of views) { - const node = view.canReveal - ? await view.revealCommit(commit, options) - : await Container.instance.repositoriesView.revealCommit(commit, options); - if (node != null) return node; - } - - void views[0].show({ preserveFocus: !options?.focus }); - return undefined; - } - - export async function showDetailsQuickPick(commit: GitCommit, uri?: Uri): Promise; - export async function showDetailsQuickPick(commit: GitCommit, file?: string | GitFile): Promise; - export async function showDetailsQuickPick( - commit: GitCommit, - fileOrUri?: string | GitFile | Uri, - ): Promise { - if (fileOrUri == null) { - void (await executeCommand(Commands.ShowQuickCommit, { commit: commit })); - return; - } - - let uri; - if (fileOrUri instanceof Uri) { - uri = fileOrUri; - } else { - uri = GitUri.fromFile(fileOrUri, commit.repoPath, commit.ref); - } - - void (await executeCommand<[Uri, ShowQuickCommitFileCommandArgs]>(Commands.ShowQuickCommitFile, uri, { - sha: commit.sha, - })); - } - - export function showDetailsView( - commit: GitRevisionReference | GitCommit, - options?: { pin?: boolean; preserveFocus?: boolean; preserveVisibility?: boolean }, - ): Promise { - return Container.instance.commitDetailsView.show({ ...options, commit: commit }); - } - - export async function showInCommitGraph( - commit: GitRevisionReference | GitCommit, - options?: { preserveFocus?: boolean }, - ): Promise { - void (await executeCommand(Commands.ShowInCommitGraph, { - ref: GitReference.fromRevision(commit), - preserveFocus: options?.preserveFocus, - })); - } - } - - export namespace Contributor { - export function addAuthors(repo?: string | Repository, contributors?: GitContributor | GitContributor[]) { - return executeGitCommand({ - command: 'co-authors', - state: { repo: repo, contributors: contributors }, - }); - } - - export async function reveal( - contributor: GitContributor, - options?: { - select?: boolean; - focus?: boolean; - expand?: boolean | number; - }, - ) { - const view = Container.instance.contributorsView; - const node = view.canReveal - ? await view.revealContributor(contributor, options) - : await Container.instance.repositoriesView.revealContributor(contributor, options); - if (node == null) { - void view.show({ preserveFocus: !options?.focus }); - } - return node; - } - } - - export namespace Remote { - export function add( - repo?: string | Repository, - name?: string, - url?: string, - options?: { confirm?: boolean; fetch?: boolean; reveal?: boolean }, - ) { - return executeGitCommand({ - command: 'remote', - confirm: options?.confirm, - state: { - repo: repo, - subcommand: 'add', - name: name, - url: url, - flags: options?.fetch ? ['-f'] : undefined, - reveal: options?.reveal, - }, - }); - } - - export async function fetch(repo: string | Repository, remote: string) { - if (typeof repo === 'string') { - const r = Container.instance.git.getRepository(repo); - if (r == null) return; - - repo = r; - } - - await repo.fetch({ remote: remote }); - } - - export async function prune(repo: string | Repository, remote: string) { - return executeGitCommand({ - command: 'remote', - state: { repo: repo, subcommand: 'prune', remote: remote }, - }); - } - - export async function remove(repo: string | Repository, remote: string) { - return executeGitCommand({ - command: 'remote', - state: { repo: repo, subcommand: 'remove', remote: remote }, - }); - } - - export async function reveal( - remote: GitRemote | undefined, - options?: { - select?: boolean; - focus?: boolean; - expand?: boolean | number; - }, - ) { - const view = Container.instance.remotesView; - const node = - remote != null - ? view.canReveal - ? await view.revealRemote(remote, options) - : await Container.instance.repositoriesView.revealRemote(remote, options) - : undefined; - if (node == null) { - void view.show({ preserveFocus: !options?.focus }); - } - return node; - } - } - - export namespace Repo { - export async function reveal( - repoPath: string, - view?: ViewsWithRepositoryFolders, - options?: { - select?: boolean; - focus?: boolean; - expand?: boolean | number; - }, - ) { - const node = view?.canReveal - ? await view.revealRepository(repoPath, options) - : await Container.instance.repositoriesView.revealRepository(repoPath, options); - if (node == null) { - void (view ?? Container.instance.repositoriesView).show({ preserveFocus: !options?.focus }); - } - return node; - } - } - - export namespace Stash { - export function apply(repo?: string | Repository, ref?: GitStashReference) { - return executeGitCommand({ - command: 'stash', - state: { subcommand: 'apply', repo: repo, reference: ref }, - }); - } - - export function drop(repo?: string | Repository, ref?: GitStashReference) { - return executeGitCommand({ - command: 'stash', - state: { subcommand: 'drop', repo: repo, reference: ref }, - }); - } - - export function pop(repo?: string | Repository, ref?: GitStashReference) { - return executeGitCommand({ - command: 'stash', - state: { subcommand: 'pop', repo: repo, reference: ref }, - }); - } - - export function push(repo?: string | Repository, uris?: Uri[], message?: string, keepStaged: boolean = false) { - return executeGitCommand({ - command: 'stash', - state: { - subcommand: 'push', - repo: repo, - uris: uris, - message: message, - flags: keepStaged ? ['--keep-index'] : undefined, - }, - }); - } - - export async function reveal( - stash: GitStashReference, - options?: { - select?: boolean; - focus?: boolean; - expand?: boolean | number; - }, - ) { - const view = Container.instance.stashesView; - const node = view.canReveal - ? await view.revealStash(stash, options) - : await Container.instance.repositoriesView.revealStash(stash, options); - if (node == null) { - void view.show({ preserveFocus: !options?.focus }); - } - return node; - } - - export function showDetailsView( - stash: GitStashReference | GitStashCommit, - options?: { pin?: boolean; preserveFocus?: boolean }, - ): Promise { - return Container.instance.commitDetailsView.show({ ...options, commit: stash }); - } - } - - export namespace Tag { - export function create(repo?: string | Repository, ref?: GitReference, name?: string) { - return executeGitCommand({ - command: 'tag', - state: { - subcommand: 'create', - repo: repo, - reference: ref, - name: name, - }, - }); - } - - export function remove(repo?: string | Repository, refs?: GitTagReference | GitTagReference[]) { - return executeGitCommand({ - command: 'tag', - state: { - subcommand: 'delete', - repo: repo, - references: refs, - }, - }); - } - - export async function reveal( - tag: GitTagReference, - options?: { - select?: boolean; - focus?: boolean; - expand?: boolean | number; - }, - ) { - const view = Container.instance.tagsView; - const node = view.canReveal - ? await view.revealTag(tag, options) - : await Container.instance.repositoriesView.revealTag(tag, options); - if (node == null) { - void view.show({ preserveFocus: !options?.focus }); - } - return node; - } - } - - export namespace Worktree { - export function create( - repo?: string | Repository, - uri?: Uri, - ref?: GitReference, - options?: { reveal?: boolean }, - ) { - return executeGitCommand({ - command: 'worktree', - state: { subcommand: 'create', repo: repo, uri: uri, reference: ref, reveal: options?.reveal }, - }); - } - - export function open(worktree: GitWorktree, options?: { location?: OpenWorkspaceLocation }) { - return openWorkspace(worktree.uri, options); - } - - export function remove(repo?: string | Repository, uri?: Uri) { - return executeGitCommand({ - command: 'worktree', - state: { subcommand: 'delete', repo: repo, uris: ensure(uri) }, - }); - } - - export async function reveal( - worktree: GitWorktree | undefined, - options?: { select?: boolean; focus?: boolean; expand?: boolean | number }, - ) { - const view = Container.instance.worktreesView; - const node = - worktree != null - ? view.canReveal - ? await view.revealWorktree(worktree, options) - : await Container.instance.repositoriesView.revealWorktree(worktree, options) - : undefined; - if (node == null) { - void view.show({ preserveFocus: !options?.focus }); - } - return node; - } - - export async function revealInFileExplorer(worktree: GitWorktree) { - void (await executeCoreCommand(CoreCommands.RevealInFileExplorer, worktree.uri)); - } - } -} diff --git a/src/commands/openDirectoryCompare.ts b/src/commands/openDirectoryCompare.ts index 07dbd45..f167bfd 100644 --- a/src/commands/openDirectoryCompare.ts +++ b/src/commands/openDirectoryCompare.ts @@ -1,6 +1,7 @@ import type { TextEditor, Uri } from 'vscode'; import { Commands } from '../constants'; import type { Container } from '../container'; +import { openDirectoryCompare } from '../git/actions/commit'; import { Logger } from '../logger'; import { showGenericErrorMessage } from '../messages'; import { ReferencePicker } from '../quickpicks/referencePicker'; @@ -9,7 +10,6 @@ import { command } from '../system/command'; import { CompareResultsNode } from '../views/nodes/compareResultsNode'; import type { CommandContext } from './base'; import { ActiveEditorCommand, getCommandUri, isCommandContextViewNodeHasRef } from './base'; -import { GitActions } from './gitCommands.actions'; export interface OpenDirectoryCompareCommandArgs { ref1?: string; @@ -80,7 +80,7 @@ export class OpenDirectoryCompareCommand extends ActiveEditorCommand { if (args.ref1 == null) return; } - void GitActions.Commit.openDirectoryCompare(repoPath, args.ref1, args.ref2); + void openDirectoryCompare(repoPath, args.ref1, args.ref2); } catch (ex) { Logger.error(ex, 'OpenDirectoryCompareCommand'); void showGenericErrorMessage('Unable to open directory compare'); diff --git a/src/commands/openFileAtRevision.ts b/src/commands/openFileAtRevision.ts index a47f0b5..8b50cf9 100644 --- a/src/commands/openFileAtRevision.ts +++ b/src/commands/openFileAtRevision.ts @@ -3,6 +3,7 @@ import { Uri } from 'vscode'; import { FileAnnotationType } from '../configuration'; import { Commands, GlyphChars, quickPickTitleMaxChars } from '../constants'; import type { Container } from '../container'; +import { openFileAtRevision } from '../git/actions/commit'; import { GitUri } from '../git/gitUri'; import { GitRevision } from '../git/models/reference'; import { Logger } from '../logger'; @@ -13,7 +14,6 @@ import { command } from '../system/command'; import { pad } from '../system/string'; import type { CommandContext } from './base'; import { ActiveEditorCommand, getCommandUri } from './base'; -import { GitActions } from './gitCommands.actions'; import type { OpenFileAtRevisionFromCommandArgs } from './openFileAtRevisionFrom'; export interface OpenFileAtRevisionCommandArgs { @@ -135,7 +135,7 @@ export class OpenFileAtRevisionCommand extends ActiveEditorCommand { picked: gitUri.sha, keys: ['right', 'alt+right', 'ctrl+right'], onDidPressKey: async (key, item) => { - await GitActions.Commit.openFileAtRevision(item.item.file!, item.item, { + await openFileAtRevision(item.item.file!, item.item, { annotationType: args!.annotationType, line: args!.line, preserveFocus: true, @@ -157,7 +157,7 @@ export class OpenFileAtRevisionCommand extends ActiveEditorCommand { ); if (pick?.file == null) return; - await GitActions.Commit.openFileAtRevision(pick.file, pick, { + await openFileAtRevision(pick.file, pick, { annotationType: args.annotationType, line: args.line, ...args.showOptions, @@ -166,7 +166,7 @@ export class OpenFileAtRevisionCommand extends ActiveEditorCommand { return; } - await GitActions.Commit.openFileAtRevision(args.revisionUri, { + await openFileAtRevision(args.revisionUri, { annotationType: args.annotationType, line: args.line, ...args.showOptions, diff --git a/src/commands/openFileAtRevisionFrom.ts b/src/commands/openFileAtRevisionFrom.ts index 031f186..2dfedff 100644 --- a/src/commands/openFileAtRevisionFrom.ts +++ b/src/commands/openFileAtRevisionFrom.ts @@ -2,6 +2,7 @@ import type { TextDocumentShowOptions, TextEditor, Uri } from 'vscode'; import type { FileAnnotationType } from '../configuration'; import { Commands, GlyphChars, quickPickTitleMaxChars } from '../constants'; import type { Container } from '../container'; +import { openFileAtRevision } from '../git/actions/commit'; import { GitUri } from '../git/gitUri'; import type { GitReference } from '../git/models/reference'; import { showNoRepositoryWarningMessage } from '../messages'; @@ -10,7 +11,6 @@ import { ReferencePicker } from '../quickpicks/referencePicker'; import { command } from '../system/command'; import { pad } from '../system/string'; import { ActiveEditorCommand, getCommandUri } from './base'; -import { GitActions } from './gitCommands.actions'; export interface OpenFileAtRevisionFromCommandArgs { reference?: GitReference; @@ -69,7 +69,7 @@ export class OpenFileAtRevisionFromCommand extends ActiveEditorCommand { onDidPressKey: async (key, quickpick) => { const [item] = quickpick.activeItems; if (item != null) { - await GitActions.Commit.openFileAtRevision( + await openFileAtRevision( this.container.git.getRevisionUri(item.ref, gitUri.fsPath, gitUri.repoPath!), { annotationType: args!.annotationType, @@ -88,7 +88,7 @@ export class OpenFileAtRevisionFromCommand extends ActiveEditorCommand { } } - await GitActions.Commit.openFileAtRevision( + await openFileAtRevision( this.container.git.getRevisionUri(args.reference.ref, gitUri.fsPath, gitUri.repoPath), { annotationType: args.annotationType, diff --git a/src/commands/openRevisionFile.ts b/src/commands/openRevisionFile.ts index 00481cc..d139557 100644 --- a/src/commands/openRevisionFile.ts +++ b/src/commands/openRevisionFile.ts @@ -2,13 +2,13 @@ import type { TextDocumentShowOptions, TextEditor, Uri } from 'vscode'; import type { FileAnnotationType } from '../configuration'; import { Commands } from '../constants'; import type { Container } from '../container'; +import { openFileAtRevision } from '../git/actions/commit'; import { GitUri } from '../git/gitUri'; import { GitRevision } from '../git/models/reference'; import { Logger } from '../logger'; import { showGenericErrorMessage } from '../messages'; import { command } from '../system/command'; import { ActiveEditorCommand, getCommandUri } from './base'; -import { GitActions } from './gitCommands.actions'; export interface OpenRevisionFileCommandArgs { revisionUri?: Uri; @@ -53,7 +53,7 @@ export class OpenRevisionFileCommand extends ActiveEditorCommand { } } - await GitActions.Commit.openFileAtRevision(args.revisionUri, { + await openFileAtRevision(args.revisionUri, { annotationType: args.annotationType, line: args.line, ...args.showOptions, diff --git a/src/commands/quickCommand.steps.ts b/src/commands/quickCommand.steps.ts index 5b5132d..65b2e5c 100644 --- a/src/commands/quickCommand.steps.ts +++ b/src/commands/quickCommand.steps.ts @@ -3,6 +3,14 @@ import { BranchSorting, configuration, TagSorting } from '../configuration'; import { Commands, GlyphChars, quickPickTitleMaxChars } from '../constants'; import { Container } from '../container'; import type { PlusFeatures } from '../features'; +import * as BranchActions from '../git/actions/branch'; +import * as CommitActions from '../git/actions/commit'; +import * as ContributorActions from '../git/actions/contributor'; +import * as RemoteActions from '../git/actions/remote'; +import * as RepositoryActions from '../git/actions/repository'; +import * as StashActions from '../git/actions/stash'; +import * as TagActions from '../git/actions/tag'; +import * as WorktreeActions from '../git/actions/worktree'; import type { PagedResult } from '../git/gitProvider'; import type { BranchSortOptions, GitBranch } from '../git/models/branch'; import { sortBranches } from '../git/models/branch'; @@ -81,7 +89,6 @@ import { getSettledValue } from '../system/promise'; import { pad, pluralize, truncate } from '../system/string'; import { OpenWorkspaceLocation } from '../system/utils'; import type { ViewsWithRepositoryFolders } from '../views/viewBase'; -import { GitActions } from './gitCommands.actions'; import type { AsyncStepResultGenerator, PartialStepState, @@ -677,14 +684,14 @@ export async function* pickBranchStep< : branches, onDidClickItemButton: (quickpick, button, { item }) => { if (button === QuickCommandButtons.RevealInSideBar) { - void GitActions.Branch.reveal(item, { select: true, focus: false, expand: true }); + void BranchActions.reveal(item, { select: true, focus: false, expand: true }); } }, keys: ['right', 'alt+right', 'ctrl+right'], onDidPressKey: async quickpick => { if (quickpick.activeItems.length === 0) return; - await GitActions.Branch.reveal(quickpick.activeItems[0].item, { + await BranchActions.reveal(quickpick.activeItems[0].item, { select: true, focus: false, expand: true, @@ -733,14 +740,14 @@ export async function* pickBranchesStep< : branches, onDidClickItemButton: (quickpick, button, { item }) => { if (button === QuickCommandButtons.RevealInSideBar) { - void GitActions.Branch.reveal(item, { select: true, focus: false, expand: true }); + void BranchActions.reveal(item, { select: true, focus: false, expand: true }); } }, keys: ['right', 'alt+right', 'ctrl+right'], onDidPressKey: async quickpick => { if (quickpick.activeItems.length === 0) return; - await GitActions.Branch.reveal(quickpick.activeItems[0].item, { + await BranchActions.reveal(quickpick.activeItems[0].item, { select: true, focus: false, expand: true, @@ -817,11 +824,11 @@ export async function* pickBranchOrTagStep< if (button === QuickCommandButtons.RevealInSideBar) { if (GitReference.isBranch(item)) { - void GitActions.Branch.reveal(item, { select: true, focus: false, expand: true }); + void BranchActions.reveal(item, { select: true, focus: false, expand: true }); } else if (GitReference.isTag(item)) { - void GitActions.Tag.reveal(item, { select: true, focus: false, expand: true }); + void TagActions.reveal(item, { select: true, focus: false, expand: true }); } else if (GitReference.isRevision(item)) { - void GitActions.Commit.showDetailsView(item, { pin: false, preserveFocus: true }); + void CommitActions.showDetailsView(item, { pin: false, preserveFocus: true }); } } return false; @@ -853,11 +860,11 @@ export async function* pickBranchOrTagStep< const item = quickpick.activeItems[0].item; if (GitReference.isBranch(item)) { - void GitActions.Branch.reveal(item, { select: true, focus: false, expand: true }); + void BranchActions.reveal(item, { select: true, focus: false, expand: true }); } else if (GitReference.isTag(item)) { - void GitActions.Tag.reveal(item, { select: true, focus: false, expand: true }); + void TagActions.reveal(item, { select: true, focus: false, expand: true }); } else if (GitReference.isRevision(item)) { - void GitActions.Commit.showDetailsView(item, { pin: false, preserveFocus: true }); + void CommitActions.showDetailsView(item, { pin: false, preserveFocus: true }); } }, onValidateValue: getValidateGitReferenceFn(state.repo, { ranges: ranges }), @@ -925,11 +932,11 @@ export async function* pickBranchOrTagStepMultiRepo< onDidClickItemButton: (quickpick, button, { item }) => { if (button === QuickCommandButtons.RevealInSideBar) { if (GitReference.isBranch(item)) { - void GitActions.Branch.reveal(item, { select: true, focus: false, expand: true }); + void BranchActions.reveal(item, { select: true, focus: false, expand: true }); } else if (GitReference.isTag(item)) { - void GitActions.Tag.reveal(item, { select: true, focus: false, expand: true }); + void TagActions.reveal(item, { select: true, focus: false, expand: true }); } else if (GitReference.isRevision(item)) { - void GitActions.Commit.showDetailsView(item, { pin: false, preserveFocus: true }); + void CommitActions.showDetailsView(item, { pin: false, preserveFocus: true }); } } }, @@ -966,11 +973,11 @@ export async function* pickBranchOrTagStepMultiRepo< const item = quickpick.activeItems[0].item; if (GitReference.isBranch(item)) { - void GitActions.Branch.reveal(item, { select: true, focus: false, expand: true }); + void BranchActions.reveal(item, { select: true, focus: false, expand: true }); } else if (GitReference.isTag(item)) { - void GitActions.Tag.reveal(item, { select: true, focus: false, expand: true }); + void TagActions.reveal(item, { select: true, focus: false, expand: true }); } else if (GitReference.isRevision(item)) { - void GitActions.Commit.showDetailsView(item, { pin: false, preserveFocus: true }); + void CommitActions.showDetailsView(item, { pin: false, preserveFocus: true }); } }, onValidateValue: getValidateGitReferenceFn(state.repos), @@ -1056,11 +1063,11 @@ export async function* pickCommitStep< switch (button) { case QuickCommandButtons.ShowDetailsView: - void GitActions.Commit.showDetailsView(item.item, { pin: false, preserveFocus: true }); + void CommitActions.showDetailsView(item.item, { pin: false, preserveFocus: true }); break; case QuickCommandButtons.RevealInSideBar: - void GitActions.Commit.reveal(item.item, { + void CommitActions.reveal(item.item, { select: true, focus: false, expand: true, @@ -1088,9 +1095,9 @@ export async function* pickCommitStep< ); if (key === 'ctrl+right') { - void GitActions.Commit.showDetailsView(items[0].item, { pin: false, preserveFocus: true }); + void CommitActions.showDetailsView(items[0].item, { pin: false, preserveFocus: true }); } else { - await GitActions.Commit.reveal(items[0].item, { + await CommitActions.reveal(items[0].item, { select: true, focus: false, expand: true, @@ -1175,11 +1182,11 @@ export function* pickCommitsStep< onDidClickItemButton: (quickpick, button, { item }) => { switch (button) { case QuickCommandButtons.ShowDetailsView: - void GitActions.Commit.showDetailsView(item, { pin: false, preserveFocus: true }); + void CommitActions.showDetailsView(item, { pin: false, preserveFocus: true }); break; case QuickCommandButtons.RevealInSideBar: - void GitActions.Commit.reveal(item, { + void CommitActions.reveal(item, { select: true, focus: false, expand: true, @@ -1192,12 +1199,12 @@ export function* pickCommitsStep< if (quickpick.activeItems.length === 0) return; if (key === 'ctrl+right') { - void GitActions.Commit.showDetailsView(quickpick.activeItems[0].item, { + void CommitActions.showDetailsView(quickpick.activeItems[0].item, { pin: false, preserveFocus: true, }); } else { - await GitActions.Commit.reveal(quickpick.activeItems[0].item, { + await CommitActions.reveal(quickpick.activeItems[0].item, { select: true, focus: false, expand: true, @@ -1232,14 +1239,14 @@ export async function* pickContributorsStep< ), onDidClickItemButton: (quickpick, button, { item }) => { if (button === QuickCommandButtons.RevealInSideBar) { - void GitActions.Contributor.reveal(item, { select: true, focus: false, expand: true }); + void ContributorActions.reveal(item, { select: true, focus: false, expand: true }); } }, keys: ['right', 'alt+right', 'ctrl+right'], onDidPressKey: quickpick => { if (quickpick.activeItems.length === 0) return; - void GitActions.Contributor.reveal(quickpick.activeItems[0].item, { + void ContributorActions.reveal(quickpick.activeItems[0].item, { select: true, focus: false, expand: true, @@ -1284,14 +1291,14 @@ export async function* pickRemoteStep< : remotes, onDidClickItemButton: (quickpick, button, { item }) => { if (button === QuickCommandButtons.RevealInSideBar) { - void GitActions.Remote.reveal(item, { select: true, focus: false, expand: true }); + void RemoteActions.reveal(item, { select: true, focus: false, expand: true }); } }, keys: ['right', 'alt+right', 'ctrl+right'], onDidPressKey: async quickpick => { if (quickpick.activeItems.length === 0) return; - await GitActions.Remote.reveal(quickpick.activeItems[0].item, { + await RemoteActions.reveal(quickpick.activeItems[0].item, { select: true, focus: false, expand: true, @@ -1337,14 +1344,14 @@ export async function* pickRemotesStep< : remotes, onDidClickItemButton: (quickpick, button, { item }) => { if (button === QuickCommandButtons.RevealInSideBar) { - void GitActions.Remote.reveal(item, { select: true, focus: false, expand: true }); + void RemoteActions.reveal(item, { select: true, focus: false, expand: true }); } }, keys: ['right', 'alt+right', 'ctrl+right'], onDidPressKey: async quickpick => { if (quickpick.activeItems.length === 0) return; - await GitActions.Remote.reveal(quickpick.activeItems[0].item, { + await RemoteActions.reveal(quickpick.activeItems[0].item, { select: true, focus: false, expand: true, @@ -1383,7 +1390,7 @@ export async function* pickRepositoryStep< ), onDidClickItemButton: (quickpick, button, { item }) => { if (button === QuickCommandButtons.RevealInSideBar) { - void GitActions.Repo.reveal(item.path, context.associatedView, { + void RepositoryActions.reveal(item.path, context.associatedView, { select: true, focus: false, expand: true, @@ -1394,7 +1401,7 @@ export async function* pickRepositoryStep< onDidPressKey: quickpick => { if (quickpick.activeItems.length === 0) return; - void GitActions.Repo.reveal(quickpick.activeItems[0].item.path, context.associatedView, { + void RepositoryActions.reveal(quickpick.activeItems[0].item.path, context.associatedView, { select: true, focus: false, expand: true, @@ -1453,7 +1460,7 @@ export async function* pickRepositoriesStep< ), onDidClickItemButton: (quickpick, button, { item }) => { if (button === QuickCommandButtons.RevealInSideBar) { - void GitActions.Repo.reveal(item.path, context.associatedView, { + void RepositoryActions.reveal(item.path, context.associatedView, { select: true, focus: false, expand: true, @@ -1464,7 +1471,7 @@ export async function* pickRepositoriesStep< onDidPressKey: quickpick => { if (quickpick.activeItems.length === 0) return; - void GitActions.Repo.reveal(quickpick.activeItems[0].item.path, context.associatedView, { + void RepositoryActions.reveal(quickpick.activeItems[0].item.path, context.associatedView, { select: true, focus: false, expand: true, @@ -1520,14 +1527,14 @@ export function* pickStashStep< ], onDidClickItemButton: (_quickpick, button, { item }) => { if (button === QuickCommandButtons.ShowDetailsView) { - void GitActions.Stash.showDetailsView(item, { pin: false, preserveFocus: true }); + void StashActions.showDetailsView(item, { pin: false, preserveFocus: true }); } }, keys: ['right', 'alt+right', 'ctrl+right'], onDidPressKey: async quickpick => { if (quickpick.activeItems.length === 0) return; - await GitActions.Stash.showDetailsView(quickpick.activeItems[0].item, { pin: false, preserveFocus: true }); + await StashActions.showDetailsView(quickpick.activeItems[0].item, { pin: false, preserveFocus: true }); }, }); const selection: StepSelection = yield step; @@ -1569,7 +1576,7 @@ export async function* pickTagsStep< : tags, onDidClickItemButton: (quickpick, button, { item }) => { if (button === QuickCommandButtons.RevealInSideBar) { - void GitActions.Tag.reveal(item, { + void TagActions.reveal(item, { select: true, focus: false, expand: true, @@ -1580,7 +1587,7 @@ export async function* pickTagsStep< onDidPressKey: async quickpick => { if (quickpick.activeItems.length === 0) return; - await GitActions.Tag.reveal(quickpick.activeItems[0].item, { + await TagActions.reveal(quickpick.activeItems[0].item, { select: true, focus: false, expand: true, @@ -1629,10 +1636,10 @@ export async function* pickWorktreeStep< onDidClickItemButton: (quickpick, button, { item }) => { switch (button) { case QuickCommandButtons.OpenInNewWindow: - GitActions.Worktree.open(item, { location: OpenWorkspaceLocation.NewWindow }); + WorktreeActions.open(item, { location: OpenWorkspaceLocation.NewWindow }); break; case QuickCommandButtons.RevealInSideBar: - void GitActions.Worktree.reveal(item, { select: true, focus: false, expand: true }); + void WorktreeActions.reveal(item, { select: true, focus: false, expand: true }); break; } }, @@ -1640,7 +1647,7 @@ export async function* pickWorktreeStep< onDidPressKey: async quickpick => { if (quickpick.activeItems.length === 0) return; - await GitActions.Worktree.reveal(quickpick.activeItems[0].item, { + await WorktreeActions.reveal(quickpick.activeItems[0].item, { select: true, focus: false, expand: true, @@ -1690,10 +1697,10 @@ export async function* pickWorktreesStep< onDidClickItemButton: (quickpick, button, { item }) => { switch (button) { case QuickCommandButtons.OpenInNewWindow: - GitActions.Worktree.open(item, { location: OpenWorkspaceLocation.NewWindow }); + WorktreeActions.open(item, { location: OpenWorkspaceLocation.NewWindow }); break; case QuickCommandButtons.RevealInSideBar: - void GitActions.Worktree.reveal(item, { select: true, focus: false, expand: true }); + void WorktreeActions.reveal(item, { select: true, focus: false, expand: true }); break; } }, @@ -1701,7 +1708,7 @@ export async function* pickWorktreesStep< onDidPressKey: async quickpick => { if (quickpick.activeItems.length === 0) return; - await GitActions.Worktree.reveal(quickpick.activeItems[0].item, { + await WorktreeActions.reveal(quickpick.activeItems[0].item, { select: true, focus: false, expand: true, @@ -1737,9 +1744,9 @@ export async function* showCommitOrStashStep< switch (button) { case QuickCommandButtons.ShowDetailsView: if (GitReference.isStash(state.reference)) { - void GitActions.Stash.showDetailsView(state.reference, { pin: false, preserveFocus: true }); + void StashActions.showDetailsView(state.reference, { pin: false, preserveFocus: true }); } else { - void GitActions.Commit.showDetailsView(state.reference, { + void CommitActions.showDetailsView(state.reference, { pin: false, preserveFocus: true, }); @@ -1747,13 +1754,13 @@ export async function* showCommitOrStashStep< break; case QuickCommandButtons.RevealInSideBar: if (GitReference.isStash(state.reference)) { - void GitActions.Stash.reveal(state.reference, { + void StashActions.reveal(state.reference, { select: true, focus: false, expand: true, }); } else { - void GitActions.Commit.reveal(state.reference, { + void CommitActions.reveal(state.reference, { select: true, focus: false, expand: true, @@ -2021,20 +2028,23 @@ export function* showCommitOrStashFilesStep< switch (button) { case QuickCommandButtons.ShowDetailsView: if (GitReference.isStash(state.reference)) { - void GitActions.Stash.showDetailsView(state.reference, { pin: false, preserveFocus: true }); + void StashActions.showDetailsView(state.reference, { pin: false, preserveFocus: true }); } else { - void GitActions.Commit.showDetailsView(state.reference, { pin: false, preserveFocus: true }); + void CommitActions.showDetailsView(state.reference, { + pin: false, + preserveFocus: true, + }); } break; case QuickCommandButtons.RevealInSideBar: if (GitReference.isStash(state.reference)) { - void GitActions.Stash.reveal(state.reference, { + void StashActions.reveal(state.reference, { select: true, focus: false, expand: true, }); } else { - void GitActions.Commit.reveal(state.reference, { + void CommitActions.reveal(state.reference, { select: true, focus: false, expand: true, @@ -2085,20 +2095,23 @@ export async function* showCommitOrStashFileStep< switch (button) { case QuickCommandButtons.ShowDetailsView: if (GitReference.isStash(state.reference)) { - void GitActions.Stash.showDetailsView(state.reference, { pin: false, preserveFocus: true }); + void StashActions.showDetailsView(state.reference, { pin: false, preserveFocus: true }); } else { - void GitActions.Commit.showDetailsView(state.reference, { pin: false, preserveFocus: true }); + void CommitActions.showDetailsView(state.reference, { + pin: false, + preserveFocus: true, + }); } break; case QuickCommandButtons.RevealInSideBar: if (GitReference.isStash(state.reference)) { - void GitActions.Stash.reveal(state.reference, { + void StashActions.reveal(state.reference, { select: true, focus: false, expand: true, }); } else { - void GitActions.Commit.reveal(state.reference, { + void CommitActions.reveal(state.reference, { select: true, focus: false, expand: true, diff --git a/src/commands/repositories.ts b/src/commands/repositories.ts index 756d670..f98b0b2 100644 --- a/src/commands/repositories.ts +++ b/src/commands/repositories.ts @@ -1,8 +1,8 @@ import { Commands } from '../constants'; import type { Container } from '../container'; +import { executeGitCommand } from '../git/actions'; import { command } from '../system/command'; import { Command } from './base'; -import { executeGitCommand } from './gitCommands.actions'; @command() export class FetchRepositoriesCommand extends Command { diff --git a/src/commands/searchCommits.ts b/src/commands/searchCommits.ts index 4873db3..093f379 100644 --- a/src/commands/searchCommits.ts +++ b/src/commands/searchCommits.ts @@ -1,12 +1,12 @@ import { configuration } from '../configuration'; import { Commands } from '../constants'; import type { Container } from '../container'; +import { executeGitCommand } from '../git/actions'; import type { SearchQuery } from '../git/search'; import { command } from '../system/command'; import { SearchResultsNode } from '../views/nodes/searchResultsNode'; import type { CommandContext } from './base'; import { Command, isCommandContextViewNodeHasRepository } from './base'; -import { executeGitCommand } from './gitCommands.actions'; export interface SearchCommitsCommandArgs { search?: Partial; diff --git a/src/commands/showCommitsInView.ts b/src/commands/showCommitsInView.ts index 695bc05..ff87c71 100644 --- a/src/commands/showCommitsInView.ts +++ b/src/commands/showCommitsInView.ts @@ -1,6 +1,8 @@ import type { TextEditor, Uri } from 'vscode'; import { Commands } from '../constants'; import type { Container } from '../container'; +import { executeGitCommand } from '../git/actions'; +import { showDetailsView } from '../git/actions/commit'; import { GitUri } from '../git/gitUri'; import { GitReference } from '../git/models/reference'; import { createSearchQueryForCommits } from '../git/search'; @@ -10,7 +12,6 @@ import { command } from '../system/command'; import { filterMap } from '../system/iterable'; import type { CommandContext } from './base'; import { ActiveEditorCommand, getCommandUri, isCommandContextViewNodeHasCommit } from './base'; -import { executeGitCommand, GitActions } from './gitCommands.actions'; export interface ShowCommitsInViewCommandArgs { refs?: string[]; @@ -80,9 +81,7 @@ export class ShowCommitsInViewCommand extends ActiveEditorCommand { } if (args.refs.length === 1) { - return GitActions.Commit.showDetailsView( - GitReference.create(args.refs[0], args.repoPath!, { refType: 'revision' }), - ); + return showDetailsView(GitReference.create(args.refs[0], args.repoPath!, { refType: 'revision' })); } return executeGitCommand({ diff --git a/src/commands/showQuickBranchHistory.ts b/src/commands/showQuickBranchHistory.ts index 3256424..4eb1350 100644 --- a/src/commands/showQuickBranchHistory.ts +++ b/src/commands/showQuickBranchHistory.ts @@ -1,12 +1,12 @@ import type { TextEditor, Uri } from 'vscode'; import { Commands } from '../constants'; import type { Container } from '../container'; +import { executeGitCommand } from '../git/actions'; import { GitUri } from '../git/gitUri'; import { GitReference } from '../git/models/reference'; import { command } from '../system/command'; import type { CommandContext } from './base'; import { ActiveEditorCachedCommand, getCommandUri } from './base'; -import { executeGitCommand } from './gitCommands.actions'; export interface ShowQuickBranchHistoryCommandArgs { repoPath?: string; diff --git a/src/commands/showQuickCommit.ts b/src/commands/showQuickCommit.ts index 52bc787..330f436 100644 --- a/src/commands/showQuickCommit.ts +++ b/src/commands/showQuickCommit.ts @@ -1,6 +1,8 @@ import type { TextEditor, Uri } from 'vscode'; import { Commands } from '../constants'; import type { Container } from '../container'; +import { executeGitCommand } from '../git/actions'; +import { reveal } from '../git/actions/commit'; import { GitUri } from '../git/gitUri'; import type { GitCommit, GitStashCommit } from '../git/models/commit'; import type { GitLog } from '../git/models/log'; @@ -14,7 +16,6 @@ import { import { command } from '../system/command'; import type { CommandContext } from './base'; import { ActiveEditorCachedCommand, getCommandUri, isCommandContextViewNodeHasCommit } from './base'; -import { executeGitCommand, GitActions } from './gitCommands.actions'; export interface ShowQuickCommitCommandArgs { repoPath?: string; @@ -138,7 +139,7 @@ export class ShowQuickCommitCommand extends ActiveEditorCachedCommand { } if (args.revealInView) { - void (await GitActions.Commit.reveal(args.commit, { + void (await reveal(args.commit, { select: true, focus: true, expand: true, diff --git a/src/commands/showQuickCommitFile.ts b/src/commands/showQuickCommitFile.ts index fbf3def..9b8a765 100644 --- a/src/commands/showQuickCommitFile.ts +++ b/src/commands/showQuickCommitFile.ts @@ -2,6 +2,7 @@ import type { TextEditor } from 'vscode'; import { Uri } from 'vscode'; import { Commands } from '../constants'; import type { Container } from '../container'; +import { executeGitCommand } from '../git/actions'; import { GitUri } from '../git/gitUri'; import type { GitCommit, GitStashCommit } from '../git/models/commit'; import { isCommit } from '../git/models/commit'; @@ -16,7 +17,6 @@ import { import { command } from '../system/command'; import type { CommandContext } from './base'; import { ActiveEditorCachedCommand, getCommandUri, isCommandContextViewNodeHasCommit } from './base'; -import { executeGitCommand } from './gitCommands.actions'; export interface ShowQuickCommitFileCommandArgs { sha?: string; diff --git a/src/commands/showQuickFileHistory.ts b/src/commands/showQuickFileHistory.ts index ceb3c78..9e487c8 100644 --- a/src/commands/showQuickFileHistory.ts +++ b/src/commands/showQuickFileHistory.ts @@ -1,6 +1,7 @@ import type { Range, TextEditor, Uri } from 'vscode'; import { Commands } from '../constants'; import type { Container } from '../container'; +import { executeGitCommand } from '../git/actions'; import { GitUri } from '../git/gitUri'; import type { GitBranch } from '../git/models/branch'; import type { GitLog } from '../git/models/log'; @@ -10,7 +11,6 @@ import type { CommandQuickPickItem } from '../quickpicks/items/common'; import { command } from '../system/command'; import type { CommandContext } from './base'; import { ActiveEditorCachedCommand, getCommandUri } from './base'; -import { executeGitCommand } from './gitCommands.actions'; export interface ShowQuickFileHistoryCommandArgs { reference?: GitBranch | GitTag | GitReference; diff --git a/src/commands/showQuickRepoStatus.ts b/src/commands/showQuickRepoStatus.ts index ce2485b..57f5308 100644 --- a/src/commands/showQuickRepoStatus.ts +++ b/src/commands/showQuickRepoStatus.ts @@ -1,8 +1,8 @@ import { Commands } from '../constants'; import type { Container } from '../container'; +import { executeGitCommand } from '../git/actions'; import { command } from '../system/command'; import { Command } from './base'; -import { executeGitCommand } from './gitCommands.actions'; export interface ShowQuickRepoStatusCommandArgs { repoPath?: string; diff --git a/src/commands/showQuickStashList.ts b/src/commands/showQuickStashList.ts index 76b7069..6a96bc1 100644 --- a/src/commands/showQuickStashList.ts +++ b/src/commands/showQuickStashList.ts @@ -1,8 +1,8 @@ import { Commands } from '../constants'; import type { Container } from '../container'; +import { executeGitCommand } from '../git/actions'; import { command } from '../system/command'; import { Command } from './base'; -import { executeGitCommand } from './gitCommands.actions'; export interface ShowQuickStashListCommandArgs { repoPath?: string; diff --git a/src/commands/stashApply.ts b/src/commands/stashApply.ts index b12553a..a681a42 100644 --- a/src/commands/stashApply.ts +++ b/src/commands/stashApply.ts @@ -1,12 +1,12 @@ import { Commands } from '../constants'; import type { Container } from '../container'; +import { apply, pop } from '../git/actions/stash'; import type { GitStashCommit } from '../git/models/commit'; import type { GitStashReference } from '../git/models/reference'; import type { CommandQuickPickItem } from '../quickpicks/items/common'; import { command } from '../system/command'; import type { CommandContext } from './base'; import { Command, isCommandContextViewNodeHasCommit, isCommandContextViewNodeHasRepository } from './base'; -import { GitActions } from './gitCommands.actions'; export interface StashApplyCommandArgs { deleteAfter?: boolean; @@ -37,9 +37,9 @@ export class StashApplyCommand extends Command { async execute(args?: StashApplyCommandArgs) { if (args?.deleteAfter) { - return GitActions.Stash.pop(args?.repoPath ?? args?.stashItem?.repoPath, args?.stashItem); + return pop(args?.repoPath ?? args?.stashItem?.repoPath, args?.stashItem); } - return GitActions.Stash.apply(args?.repoPath ?? args?.stashItem?.repoPath, args?.stashItem); + return apply(args?.repoPath ?? args?.stashItem?.repoPath, args?.stashItem); } } diff --git a/src/commands/stashSave.ts b/src/commands/stashSave.ts index cc68d8f..9bd0bfd 100644 --- a/src/commands/stashSave.ts +++ b/src/commands/stashSave.ts @@ -3,6 +3,7 @@ import type { ScmResource } from '../@types/vscode.git.resources'; import { ScmResourceGroupType } from '../@types/vscode.git.resources.enums'; import { Commands } from '../constants'; import type { Container } from '../container'; +import { push } from '../git/actions/stash'; import { GitUri } from '../git/gitUri'; import { command } from '../system/command'; import type { CommandContext } from './base'; @@ -12,7 +13,6 @@ import { isCommandContextViewNodeHasRepoPath, isCommandContextViewNodeHasRepository, } from './base'; -import { GitActions } from './gitCommands.actions'; export interface StashSaveCommandArgs { message?: string; @@ -73,6 +73,6 @@ export class StashSaveCommand extends Command { } execute(args?: StashSaveCommandArgs) { - return GitActions.Stash.push(args?.repoPath, args?.uris, args?.message, args?.keepStaged); + return push(args?.repoPath, args?.uris, args?.message, args?.keepStaged); } } diff --git a/src/git/actions.ts b/src/git/actions.ts new file mode 100644 index 0000000..e3052e1 --- /dev/null +++ b/src/git/actions.ts @@ -0,0 +1,26 @@ +import type { Uri } from 'vscode'; +import type { + BrowseRepoAtRevisionCommandArgs, + GitCommandsCommandArgs, + GitCommandsCommandArgsWithCompletion, +} from '../commands'; +import { Commands } from '../constants'; +import { executeCommand, executeEditorCommand } from '../system/command'; +import { defer } from '../system/promise'; + +export async function executeGitCommand(args: GitCommandsCommandArgs): Promise { + const deferred = defer(); + void (await executeCommand(Commands.GitCommands, { + ...args, + completion: deferred, + })); + return deferred.promise; +} + +export async function browseAtRevision(uri: Uri, options?: { before?: boolean; openInNewWindow?: boolean }) { + void (await executeEditorCommand(Commands.BrowseRepoAtRevision, undefined, { + uri: uri, + before: options?.before, + openInNewWindow: options?.openInNewWindow, + })); +} diff --git a/src/git/actions/branch.ts b/src/git/actions/branch.ts new file mode 100644 index 0000000..3ac5d67 --- /dev/null +++ b/src/git/actions/branch.ts @@ -0,0 +1,58 @@ +import { Container } from '../../container'; +import { executeGitCommand } from '../actions'; +import type { GitBranchReference, GitReference } from '../models/reference'; +import type { Repository } from '../models/repository'; + +export function create(repo?: string | Repository, ref?: GitReference, name?: string) { + return executeGitCommand({ + command: 'branch', + state: { + subcommand: 'create', + repo: repo, + reference: ref, + name: name, + }, + }); +} + +export function remove(repo?: string | Repository, refs?: GitBranchReference | GitBranchReference[]) { + return executeGitCommand({ + command: 'branch', + state: { + subcommand: 'delete', + repo: repo, + references: refs, + }, + }); +} + +export function rename(repo?: string | Repository, ref?: GitBranchReference, name?: string) { + return executeGitCommand({ + command: 'branch', + state: { + subcommand: 'rename', + repo: repo, + reference: ref, + name: name, + }, + }); +} + +export async function reveal( + branch: GitBranchReference, + options?: { + select?: boolean; + focus?: boolean; + expand?: boolean | number; + }, +) { + const view = branch.remote ? Container.instance.remotesView : Container.instance.branchesView; + const node = view.canReveal + ? await view.revealBranch(branch, options) + : await Container.instance.repositoriesView.revealBranch(branch, options); + + if (node == null) { + void view.show({ preserveFocus: !options?.focus }); + } + return node; +} diff --git a/src/git/actions/commit.ts b/src/git/actions/commit.ts new file mode 100644 index 0000000..b53abc9 --- /dev/null +++ b/src/git/actions/commit.ts @@ -0,0 +1,600 @@ +import type { TextDocumentShowOptions } from 'vscode'; +import { env, Range, Uri, window } from 'vscode'; +import type { + DiffWithCommandArgs, + DiffWithPreviousCommandArgs, + DiffWithWorkingCommandArgs, + OpenFileOnRemoteCommandArgs, + OpenWorkingFileCommandArgs, + ShowQuickCommitCommandArgs, + ShowQuickCommitFileCommandArgs, +} from '../../commands'; +import type { FileAnnotationType } from '../../config'; +import { Commands } from '../../constants'; +import { Container } from '../../container'; +import type { ShowInCommitGraphCommandArgs } from '../../plus/webviews/graph/graphWebview'; +import { executeCommand, executeEditorCommand } from '../../system/command'; +import { findOrOpenEditor, findOrOpenEditors } from '../../system/utils'; +import { GitUri } from '../gitUri'; +import type { GitCommit } from '../models/commit'; +import { isCommit } from '../models/commit'; +import type { GitFile } from '../models/file'; +import type { GitRevisionReference } from '../models/reference'; +import { GitReference, GitRevision } from '../models/reference'; + +export async function applyChanges(file: string | GitFile, ref1: GitRevisionReference, ref2?: GitRevisionReference) { + // Open the working file to ensure undo will work + await openFile(file, ref1, { preserveFocus: true, preview: false }); + + let ref = ref1.ref; + // If the file is `?` (untracked), then this must be a stash, so get the ^3 commit to access the untracked file + if (typeof file !== 'string' && file.status === '?') { + ref = `${ref}^3`; + } + + await Container.instance.git.applyChangesToWorkingFile(GitUri.fromFile(file, ref1.repoPath, ref), ref, ref2?.ref); +} + +export async function copyIdToClipboard(ref: { repoPath: string; ref: string } | GitCommit) { + await env.clipboard.writeText(ref.ref); +} + +export async function copyMessageToClipboard(ref: { repoPath: string; ref: string } | GitCommit): Promise { + let commit; + if (isCommit(ref)) { + commit = ref; + if (commit.message == null) { + await commit.ensureFullDetails(); + } + } else { + commit = await Container.instance.git.getCommit(ref.repoPath, ref.ref); + if (commit == null) return; + } + + const message = commit.message ?? commit.summary; + await env.clipboard.writeText(message); +} + +export async function openAllChanges(commit: GitCommit, options?: TextDocumentShowOptions): Promise; +export async function openAllChanges( + files: GitFile[], + refs: { repoPath: string; ref1: string; ref2: string }, + options?: TextDocumentShowOptions, +): Promise; +export async function openAllChanges( + commitOrFiles: GitCommit | GitFile[], + refsOrOptions: { repoPath: string; ref1: string; ref2: string } | TextDocumentShowOptions | undefined, + options?: TextDocumentShowOptions, +) { + let files; + let refs; + if (isCommit(commitOrFiles)) { + if (commitOrFiles.files == null) { + await commitOrFiles.ensureFullDetails(); + } + + files = commitOrFiles.files ?? []; + refs = { + repoPath: commitOrFiles.repoPath, + // Don't need to worry about verifying the previous sha, as the DiffWith command will + ref1: commitOrFiles.unresolvedPreviousSha, + ref2: commitOrFiles.sha, + }; + + options = refsOrOptions as TextDocumentShowOptions | undefined; + } else { + files = commitOrFiles; + refs = refsOrOptions as { repoPath: string; ref1: string; ref2: string }; + } + + if (files.length > 10) { + const result = await window.showWarningMessage( + `Are you sure you want to open the changes for all ${files.length} files?`, + { title: 'Yes' }, + { title: 'No', isCloseAffordance: true }, + ); + if (result == null || result.title === 'No') return; + } + + options = { preserveFocus: true, preview: false, ...options }; + + for (const file of files) { + await openChanges(file, refs, options); + } +} + +export async function openAllChangesWithDiffTool(commit: GitCommit): Promise; +export async function openAllChangesWithDiffTool( + files: GitFile[], + ref: { repoPath: string; ref: string }, +): Promise; +export async function openAllChangesWithDiffTool( + commitOrFiles: GitCommit | GitFile[], + ref?: { repoPath: string; ref: string }, +) { + let files; + if (isCommit(commitOrFiles)) { + if (commitOrFiles.files == null) { + await commitOrFiles.ensureFullDetails(); + } + + files = commitOrFiles.files ?? []; + ref = { + repoPath: commitOrFiles.repoPath, + ref: commitOrFiles.sha, + }; + } else { + files = commitOrFiles; + } + + if (files.length > 10) { + const result = await window.showWarningMessage( + `Are you sure you want to open the changes for all ${files.length} files?`, + { title: 'Yes' }, + { title: 'No', isCloseAffordance: true }, + ); + if (result == null || result.title === 'No') return; + } + + for (const file of files) { + void openChangesWithDiffTool(file, ref!); + } +} + +export async function openAllChangesWithWorking(commit: GitCommit, options?: TextDocumentShowOptions): Promise; +export async function openAllChangesWithWorking( + files: GitFile[], + ref: { repoPath: string; ref: string }, + options?: TextDocumentShowOptions, +): Promise; +export async function openAllChangesWithWorking( + commitOrFiles: GitCommit | GitFile[], + refOrOptions: { repoPath: string; ref: string } | TextDocumentShowOptions | undefined, + options?: TextDocumentShowOptions, +) { + let files; + let ref; + if (isCommit(commitOrFiles)) { + if (commitOrFiles.files == null) { + await commitOrFiles.ensureFullDetails(); + } + + files = commitOrFiles.files ?? []; + ref = { + repoPath: commitOrFiles.repoPath, + ref: commitOrFiles.sha, + }; + + options = refOrOptions as TextDocumentShowOptions | undefined; + } else { + files = commitOrFiles; + ref = refOrOptions as { repoPath: string; ref: string }; + } + + if (files.length > 10) { + const result = await window.showWarningMessage( + `Are you sure you want to open the changes for all ${files.length} files?`, + { title: 'Yes' }, + { title: 'No', isCloseAffordance: true }, + ); + if (result == null || result.title === 'No') return; + } + + options = { preserveFocus: true, preview: false, ...options }; + + for (const file of files) { + await openChangesWithWorking(file, ref, options); + } +} + +export async function openChanges( + file: string | GitFile, + commit: GitCommit, + options?: TextDocumentShowOptions, +): Promise; +export async function openChanges( + file: GitFile, + refs: { repoPath: string; ref1: string; ref2: string }, + options?: TextDocumentShowOptions, +): Promise; +export async function openChanges( + file: string | GitFile, + commitOrRefs: GitCommit | { repoPath: string; ref1: string; ref2: string }, + options?: TextDocumentShowOptions, +) { + if (typeof file === 'string') { + if (!isCommit(commitOrRefs)) throw new Error('Invalid arguments'); + + const f = await commitOrRefs.findFile(file); + if (f == null) throw new Error('Invalid arguments'); + + file = f; + } + + options = { preserveFocus: true, preview: false, ...options }; + + if (file.status === 'A') { + if (!isCommit(commitOrRefs)) return; + + const commit = await commitOrRefs.getCommitForFile(file); + void executeCommand(Commands.DiffWithPrevious, { + commit: commit, + showOptions: options, + }); + } + + const refs = isCommit(commitOrRefs) + ? { + repoPath: commitOrRefs.repoPath, + // Don't need to worry about verifying the previous sha, as the DiffWith command will + ref1: commitOrRefs.unresolvedPreviousSha, + ref2: commitOrRefs.sha, + } + : commitOrRefs; + + const uri1 = GitUri.fromFile(file, refs.repoPath); + const uri2 = + file.status === 'R' || file.status === 'C' ? GitUri.fromFile(file, refs.repoPath, refs.ref2, true) : uri1; + + void (await executeCommand(Commands.DiffWith, { + repoPath: refs.repoPath, + lhs: { uri: uri1, sha: refs.ref1 }, + rhs: { uri: uri2, sha: refs.ref2 }, + showOptions: options, + })); +} + +export function openChangesWithDiffTool(file: string | GitFile, commit: GitCommit, tool?: string): Promise; +export function openChangesWithDiffTool( + file: GitFile, + ref: { repoPath: string; ref: string }, + tool?: string, +): Promise; +export async function openChangesWithDiffTool( + file: string | GitFile, + commitOrRef: GitCommit | { repoPath: string; ref: string }, + tool?: string, +) { + if (typeof file === 'string') { + if (!isCommit(commitOrRef)) throw new Error('Invalid arguments'); + + const f = await commitOrRef.findFile(file); + if (f == null) throw new Error('Invalid arguments'); + + file = f; + } + + return Container.instance.git.openDiffTool( + commitOrRef.repoPath, + GitUri.fromFile(file, file.repoPath ?? commitOrRef.repoPath), + { + ref1: GitRevision.isUncommitted(commitOrRef.ref) ? '' : `${commitOrRef.ref}^`, + ref2: GitRevision.isUncommitted(commitOrRef.ref) ? '' : commitOrRef.ref, + staged: GitRevision.isUncommittedStaged(commitOrRef.ref) || file.indexStatus != null, + tool: tool, + }, + ); +} + +export async function openChangesWithWorking( + file: string | GitFile, + commit: GitCommit, + options?: TextDocumentShowOptions, +): Promise; +export async function openChangesWithWorking( + file: GitFile, + ref: { repoPath: string; ref: string }, + options?: TextDocumentShowOptions, +): Promise; +export async function openChangesWithWorking( + file: string | GitFile, + commitOrRef: GitCommit | { repoPath: string; ref: string }, + options?: TextDocumentShowOptions, +) { + if (typeof file === 'string') { + if (!isCommit(commitOrRef)) throw new Error('Invalid arguments'); + + const f = await commitOrRef.findFile(file); + if (f == null) throw new Error('Invalid arguments'); + + file = f; + } + + if (file.status === 'D') return; + + let ref; + if (isCommit(commitOrRef)) { + ref = { + repoPath: commitOrRef.repoPath, + ref: commitOrRef.sha, + }; + } else { + ref = commitOrRef; + } + + options = { preserveFocus: true, preview: false, ...options }; + + void (await executeEditorCommand(Commands.DiffWithWorking, undefined, { + uri: GitUri.fromFile(file, ref.repoPath, ref.ref), + showOptions: options, + })); +} + +export async function openDirectoryCompare( + repoPath: string, + ref: string, + ref2: string | undefined, + tool?: string, +): Promise { + return Container.instance.git.openDirectoryCompare(repoPath, ref, ref2, tool); +} + +export async function openDirectoryCompareWithPrevious( + ref: { repoPath: string; ref: string } | GitCommit, +): Promise { + return openDirectoryCompare(ref.repoPath, ref.ref, `${ref.ref}^`); +} + +export async function openDirectoryCompareWithWorking( + ref: { repoPath: string; ref: string } | GitCommit, +): Promise { + return openDirectoryCompare(ref.repoPath, ref.ref, undefined); +} + +export async function openFile(uri: Uri, options?: TextDocumentShowOptions): Promise; +export async function openFile( + file: string | GitFile, + ref: GitRevisionReference, + options?: TextDocumentShowOptions, +): Promise; +export async function openFile( + fileOrUri: string | GitFile | Uri, + refOrOptions?: GitRevisionReference | TextDocumentShowOptions, + options?: TextDocumentShowOptions, +) { + let uri; + if (fileOrUri instanceof Uri) { + uri = fileOrUri; + options = refOrOptions as TextDocumentShowOptions; + } else { + const ref = refOrOptions as GitRevisionReference; + + uri = GitUri.fromFile(fileOrUri, ref.repoPath, ref.ref); + // If the file is `?` (untracked), then this must be an untracked file in a stash, so just return + if (typeof fileOrUri !== 'string' && fileOrUri.status === '?') return; + } + + options = { preserveFocus: true, preview: false, ...options }; + + void (await executeEditorCommand(Commands.OpenWorkingFile, undefined, { + uri: uri, + showOptions: options, + })); +} + +export async function openFileAtRevision( + revisionUri: Uri, + options?: TextDocumentShowOptions & { annotationType?: FileAnnotationType; line?: number }, +): Promise; +export async function openFileAtRevision( + file: string | GitFile, + commit: GitCommit, + options?: TextDocumentShowOptions & { annotationType?: FileAnnotationType; line?: number }, +): Promise; +export async function openFileAtRevision( + fileOrRevisionUri: string | GitFile | Uri, + commitOrOptions?: GitCommit | TextDocumentShowOptions, + options?: TextDocumentShowOptions & { annotationType?: FileAnnotationType; line?: number }, +): Promise { + let uri; + if (fileOrRevisionUri instanceof Uri) { + if (isCommit(commitOrOptions)) throw new Error('Invalid arguments'); + + uri = fileOrRevisionUri; + options = commitOrOptions; + } else { + if (!isCommit(commitOrOptions)) throw new Error('Invalid arguments'); + + const commit = commitOrOptions; + + let file; + if (typeof fileOrRevisionUri === 'string') { + const f = await commit.findFile(fileOrRevisionUri); + if (f == null) throw new Error('Invalid arguments'); + + file = f; + } else { + file = fileOrRevisionUri; + } + + uri = Container.instance.git.getRevisionUri( + file.status === 'D' ? (await commit.getPreviousSha()) ?? GitRevision.deletedOrMissing : commit.sha, + file, + commit.repoPath, + ); + } + + const { annotationType, line, ...opts }: Exclude = { + preserveFocus: true, + preview: false, + ...options, + }; + + if (line != null && line !== 0) { + opts.selection = new Range(line, 0, line, 0); + } + + const editor = await findOrOpenEditor(uri, opts); + if (annotationType != null && editor != null) { + void (await Container.instance.fileAnnotations.show(editor, annotationType, { + selection: { line: line }, + })); + } +} + +export async function openFileOnRemote(uri: Uri): Promise; +export async function openFileOnRemote(file: string | GitFile, ref: GitRevisionReference): Promise; +export async function openFileOnRemote(fileOrUri: string | GitFile | Uri, ref?: GitRevisionReference): Promise { + let uri; + if (fileOrUri instanceof Uri) { + uri = fileOrUri; + } else { + if (ref == null) throw new Error('Invalid arguments'); + + uri = GitUri.fromFile(fileOrUri, ref.repoPath, ref.ref); + // If the file is `?` (untracked), then this must be an untracked file in a stash, so just return + if (typeof fileOrUri !== 'string' && fileOrUri.status === '?') return; + } + + void (await executeCommand<[Uri, OpenFileOnRemoteCommandArgs]>(Commands.OpenFileOnRemote, uri, { + sha: ref?.ref, + })); +} + +export async function openFiles(commit: GitCommit): Promise; +export async function openFiles(files: GitFile[], repoPath: string, ref: string): Promise; +export async function openFiles(commitOrFiles: GitCommit | GitFile[], repoPath?: string, ref?: string): Promise { + let files; + if (isCommit(commitOrFiles)) { + if (commitOrFiles.files == null) { + await commitOrFiles.ensureFullDetails(); + } + + files = commitOrFiles.files ?? []; + repoPath = commitOrFiles.repoPath; + ref = commitOrFiles.sha; + } else { + files = commitOrFiles; + } + + if (files.length > 10) { + const result = await window.showWarningMessage( + `Are you sure you want to open all ${files.length} files?`, + { title: 'Yes' }, + { title: 'No', isCloseAffordance: true }, + ); + if (result == null || result.title === 'No') return; + } + + const uris: Uri[] = ( + await Promise.all( + files.map(file => Container.instance.git.getWorkingUri(repoPath!, GitUri.fromFile(file, repoPath!, ref))), + ) + ).filter((u?: T): u is T => Boolean(u)); + findOrOpenEditors(uris); +} + +export async function openFilesAtRevision(commit: GitCommit): Promise; +export async function openFilesAtRevision( + files: GitFile[], + repoPath: string, + ref1: string, + ref2: string, +): Promise; +export async function openFilesAtRevision( + commitOrFiles: GitCommit | GitFile[], + repoPath?: string, + ref1?: string, + ref2?: string, +): Promise { + let files; + if (isCommit(commitOrFiles)) { + if (commitOrFiles.files == null) { + await commitOrFiles.ensureFullDetails(); + } + + files = commitOrFiles.files ?? []; + repoPath = commitOrFiles.repoPath; + ref1 = commitOrFiles.sha; + ref2 = await commitOrFiles.getPreviousSha(); + } else { + files = commitOrFiles; + } + + if (files.length > 10) { + const result = await window.showWarningMessage( + `Are you sure you want to open all ${files.length} file revisions?`, + { title: 'Yes' }, + { title: 'No', isCloseAffordance: true }, + ); + if (result == null || result.title === 'No') return; + } + + findOrOpenEditors( + files.map(file => Container.instance.git.getRevisionUri(file.status === 'D' ? ref2! : ref1!, file, repoPath!)), + ); +} + +export async function restoreFile(file: string | GitFile, revision: GitRevisionReference) { + let path; + let ref; + if (typeof file === 'string') { + path = file; + ref = revision.ref; + } else { + path = file.path; + ref = file.status === `?` ? `${revision.ref}^3` : file.status === 'D' ? `${revision.ref}^` : revision.ref; + } + + await Container.instance.git.checkout(revision.repoPath, ref, { path: path }); +} + +export async function reveal( + commit: GitRevisionReference, + options?: { + select?: boolean; + focus?: boolean; + expand?: boolean | number; + }, +) { + const views = [Container.instance.commitsView, Container.instance.branchesView, Container.instance.remotesView]; + + // TODO@eamodio stop duplicate notifications + + for (const view of views) { + const node = view.canReveal + ? await view.revealCommit(commit, options) + : await Container.instance.repositoriesView.revealCommit(commit, options); + if (node != null) return node; + } + + void views[0].show({ preserveFocus: !options?.focus }); + return undefined; +} + +export async function showDetailsQuickPick(commit: GitCommit, uri?: Uri): Promise; +export async function showDetailsQuickPick(commit: GitCommit, file?: string | GitFile): Promise; +export async function showDetailsQuickPick(commit: GitCommit, fileOrUri?: string | GitFile | Uri): Promise { + if (fileOrUri == null) { + void (await executeCommand(Commands.ShowQuickCommit, { commit: commit })); + return; + } + + let uri; + if (fileOrUri instanceof Uri) { + uri = fileOrUri; + } else { + uri = GitUri.fromFile(fileOrUri, commit.repoPath, commit.ref); + } + + void (await executeCommand<[Uri, ShowQuickCommitFileCommandArgs]>(Commands.ShowQuickCommitFile, uri, { + sha: commit.sha, + })); +} + +export function showDetailsView( + commit: GitRevisionReference | GitCommit, + options?: { pin?: boolean; preserveFocus?: boolean; preserveVisibility?: boolean }, +): Promise { + return Container.instance.commitDetailsView.show({ ...options, commit: commit }); +} + +export async function showInCommitGraph( + commit: GitRevisionReference | GitCommit, + options?: { preserveFocus?: boolean }, +): Promise { + void (await executeCommand(Commands.ShowInCommitGraph, { + ref: GitReference.fromRevision(commit), + preserveFocus: options?.preserveFocus, + })); +} diff --git a/src/git/actions/contributor.ts b/src/git/actions/contributor.ts new file mode 100644 index 0000000..f335b58 --- /dev/null +++ b/src/git/actions/contributor.ts @@ -0,0 +1,29 @@ +import { Container } from '../../container'; +import { executeGitCommand } from '../actions'; +import type { GitContributor } from '../models/contributor'; +import type { Repository } from '../models/repository'; + +export function addAuthors(repo?: string | Repository, contributors?: GitContributor | GitContributor[]) { + return executeGitCommand({ + command: 'co-authors', + state: { repo: repo, contributors: contributors }, + }); +} + +export async function reveal( + contributor: GitContributor, + options?: { + select?: boolean; + focus?: boolean; + expand?: boolean | number; + }, +) { + const view = Container.instance.contributorsView; + const node = view.canReveal + ? await view.revealContributor(contributor, options) + : await Container.instance.repositoriesView.revealContributor(contributor, options); + if (node == null) { + void view.show({ preserveFocus: !options?.focus }); + } + return node; +} diff --git a/src/git/actions/remote.ts b/src/git/actions/remote.ts new file mode 100644 index 0000000..1dcc223 --- /dev/null +++ b/src/git/actions/remote.ts @@ -0,0 +1,70 @@ +import { Container } from '../../container'; +import { executeGitCommand } from '../actions'; +import type { GitRemote } from '../models/remote'; +import type { Repository } from '../models/repository'; + +export function add( + repo?: string | Repository, + name?: string, + url?: string, + options?: { confirm?: boolean; fetch?: boolean; reveal?: boolean }, +) { + return executeGitCommand({ + command: 'remote', + confirm: options?.confirm, + state: { + repo: repo, + subcommand: 'add', + name: name, + url: url, + flags: options?.fetch ? ['-f'] : undefined, + reveal: options?.reveal, + }, + }); +} + +export async function fetch(repo: string | Repository, remote: string) { + if (typeof repo === 'string') { + const r = Container.instance.git.getRepository(repo); + if (r == null) return; + + repo = r; + } + + await repo.fetch({ remote: remote }); +} + +export async function prune(repo: string | Repository, remote: string) { + return executeGitCommand({ + command: 'remote', + state: { repo: repo, subcommand: 'prune', remote: remote }, + }); +} + +export async function remove(repo: string | Repository, remote: string) { + return executeGitCommand({ + command: 'remote', + state: { repo: repo, subcommand: 'remove', remote: remote }, + }); +} + +export async function reveal( + remote: GitRemote | undefined, + options?: { + select?: boolean; + focus?: boolean; + expand?: boolean | number; + }, +) { + const view = Container.instance.remotesView; + const node = + remote != null + ? view.canReveal + ? await view.revealRemote(remote, options) + : await Container.instance.repositoriesView.revealRemote(remote, options) + : undefined; + if (node == null) { + void view.show({ preserveFocus: !options?.focus }); + } + return node; +} diff --git a/src/git/actions/repository.ts b/src/git/actions/repository.ts new file mode 100644 index 0000000..680b7cb --- /dev/null +++ b/src/git/actions/repository.ts @@ -0,0 +1,84 @@ +import type { ResetGitCommandArgs } from '../../commands/git/reset'; +import { Container } from '../../container'; +import type { ViewsWithRepositoryFolders } from '../../views/viewBase'; +import { executeGitCommand } from '../actions'; +import type { GitBranchReference, GitReference, GitRevisionReference } from '../models/reference'; +import type { Repository } from '../models/repository'; + +export function cherryPick(repo?: string | Repository, refs?: GitRevisionReference | GitRevisionReference[]) { + return executeGitCommand({ + command: 'cherry-pick', + state: { repo: repo, references: refs }, + }); +} + +export function fetch(repos?: string | string[] | Repository | Repository[], ref?: GitBranchReference) { + return executeGitCommand({ command: 'fetch', state: { repos: repos, reference: ref } }); +} + +export function merge(repo?: string | Repository, ref?: GitReference) { + return executeGitCommand({ command: 'merge', state: { repo: repo, reference: ref } }); +} + +export function pull(repos?: string | string[] | Repository | Repository[], ref?: GitBranchReference) { + return executeGitCommand({ command: 'pull', state: { repos: repos, reference: ref } }); +} + +export function push(repos?: string | string[] | Repository | Repository[], force?: boolean, ref?: GitReference) { + return executeGitCommand({ + command: 'push', + state: { repos: repos, flags: force ? ['--force'] : [], reference: ref }, + }); +} + +export function rebase(repo?: string | Repository, ref?: GitReference, interactive: boolean = true) { + return executeGitCommand({ + command: 'rebase', + state: { repo: repo, reference: ref, flags: interactive ? ['--interactive'] : [] }, + }); +} + +export function reset( + repo?: string | Repository, + ref?: GitRevisionReference, + flags?: NonNullable['flags'], +) { + return executeGitCommand({ + command: 'reset', + confirm: flags == null || flags.includes('--hard'), + state: { repo: repo, reference: ref, flags: flags }, + }); +} + +export function revert(repo?: string | Repository, refs?: GitRevisionReference | GitRevisionReference[]) { + return executeGitCommand({ + command: 'revert', + state: { repo: repo, references: refs }, + }); +} + +export function switchTo(repos?: string | string[] | Repository | Repository[], ref?: GitReference, confirm?: boolean) { + return executeGitCommand({ + command: 'switch', + state: { repos: repos, reference: ref }, + confirm: confirm, + }); +} + +export async function reveal( + repoPath: string, + view?: ViewsWithRepositoryFolders, + options?: { + select?: boolean; + focus?: boolean; + expand?: boolean | number; + }, +) { + const node = view?.canReveal + ? await view.revealRepository(repoPath, options) + : await Container.instance.repositoriesView.revealRepository(repoPath, options); + if (node == null) { + void (view ?? Container.instance.repositoriesView).show({ preserveFocus: !options?.focus }); + } + return node; +} diff --git a/src/git/actions/stash.ts b/src/git/actions/stash.ts new file mode 100644 index 0000000..75aa77c --- /dev/null +++ b/src/git/actions/stash.ts @@ -0,0 +1,65 @@ +import type { Uri } from 'vscode'; +import { Container } from '../../container'; +import { executeGitCommand } from '../actions'; +import type { GitStashCommit } from '../models/commit'; +import type { GitStashReference } from '../models/reference'; +import type { Repository } from '../models/repository'; + +export function apply(repo?: string | Repository, ref?: GitStashReference) { + return executeGitCommand({ + command: 'stash', + state: { subcommand: 'apply', repo: repo, reference: ref }, + }); +} + +export function drop(repo?: string | Repository, ref?: GitStashReference) { + return executeGitCommand({ + command: 'stash', + state: { subcommand: 'drop', repo: repo, reference: ref }, + }); +} + +export function pop(repo?: string | Repository, ref?: GitStashReference) { + return executeGitCommand({ + command: 'stash', + state: { subcommand: 'pop', repo: repo, reference: ref }, + }); +} + +export function push(repo?: string | Repository, uris?: Uri[], message?: string, keepStaged: boolean = false) { + return executeGitCommand({ + command: 'stash', + state: { + subcommand: 'push', + repo: repo, + uris: uris, + message: message, + flags: keepStaged ? ['--keep-index'] : undefined, + }, + }); +} + +export async function reveal( + stash: GitStashReference, + options?: { + select?: boolean; + focus?: boolean; + expand?: boolean | number; + }, +) { + const view = Container.instance.stashesView; + const node = view.canReveal + ? await view.revealStash(stash, options) + : await Container.instance.repositoriesView.revealStash(stash, options); + if (node == null) { + void view.show({ preserveFocus: !options?.focus }); + } + return node; +} + +export function showDetailsView( + stash: GitStashReference | GitStashCommit, + options?: { pin?: boolean; preserveFocus?: boolean }, +): Promise { + return Container.instance.commitDetailsView.show({ ...options, commit: stash }); +} diff --git a/src/git/actions/tag.ts b/src/git/actions/tag.ts new file mode 100644 index 0000000..adfbc47 --- /dev/null +++ b/src/git/actions/tag.ts @@ -0,0 +1,45 @@ +import { Container } from '../../container'; +import { executeGitCommand } from '../actions'; +import type { GitReference, GitTagReference } from '../models/reference'; +import type { Repository } from '../models/repository'; + +export function create(repo?: string | Repository, ref?: GitReference, name?: string) { + return executeGitCommand({ + command: 'tag', + state: { + subcommand: 'create', + repo: repo, + reference: ref, + name: name, + }, + }); +} + +export function remove(repo?: string | Repository, refs?: GitTagReference | GitTagReference[]) { + return executeGitCommand({ + command: 'tag', + state: { + subcommand: 'delete', + repo: repo, + references: refs, + }, + }); +} + +export async function reveal( + tag: GitTagReference, + options?: { + select?: boolean; + focus?: boolean; + expand?: boolean | number; + }, +) { + const view = Container.instance.tagsView; + const node = view.canReveal + ? await view.revealTag(tag, options) + : await Container.instance.repositoriesView.revealTag(tag, options); + if (node == null) { + void view.show({ preserveFocus: !options?.focus }); + } + return node; +} diff --git a/src/git/actions/worktree.ts b/src/git/actions/worktree.ts new file mode 100644 index 0000000..fcfffbe --- /dev/null +++ b/src/git/actions/worktree.ts @@ -0,0 +1,50 @@ +import type { Uri } from 'vscode'; +import { CoreCommands } from '../../constants'; +import { Container } from '../../container'; +import { ensure } from '../../system/array'; +import { executeCoreCommand } from '../../system/command'; +import type { OpenWorkspaceLocation} from '../../system/utils'; +import { openWorkspace } from '../../system/utils'; +import { executeGitCommand } from '../actions'; +import type { GitReference } from '../models/reference'; +import type { Repository } from '../models/repository'; +import type { GitWorktree } from '../models/worktree'; + +export function create(repo?: string | Repository, uri?: Uri, ref?: GitReference, options?: { reveal?: boolean }) { + return executeGitCommand({ + command: 'worktree', + state: { subcommand: 'create', repo: repo, uri: uri, reference: ref, reveal: options?.reveal }, + }); +} + +export function open(worktree: GitWorktree, options?: { location?: OpenWorkspaceLocation }) { + return openWorkspace(worktree.uri, options); +} + +export function remove(repo?: string | Repository, uri?: Uri) { + return executeGitCommand({ + command: 'worktree', + state: { subcommand: 'delete', repo: repo, uris: ensure(uri) }, + }); +} + +export async function reveal( + worktree: GitWorktree | undefined, + options?: { select?: boolean; focus?: boolean; expand?: boolean | number }, +) { + const view = Container.instance.worktreesView; + const node = + worktree != null + ? view.canReveal + ? await view.revealWorktree(worktree, options) + : await Container.instance.repositoriesView.revealWorktree(worktree, options) + : undefined; + if (node == null) { + void view.show({ preserveFocus: !options?.focus }); + } + return node; +} + +export async function revealInFileExplorer(worktree: GitWorktree) { + void (await executeCoreCommand(CoreCommands.RevealInFileExplorer, worktree.uri)); +} diff --git a/src/plus/webviews/graph/graphWebview.ts b/src/plus/webviews/graph/graphWebview.ts index 0eb41cb..0b8870e 100644 --- a/src/plus/webviews/graph/graphWebview.ts +++ b/src/plus/webviews/graph/graphWebview.ts @@ -27,13 +27,18 @@ import type { ShowCommitsInViewCommandArgs, } from '../../../commands'; import { parseCommandContext } from '../../../commands/base'; -import { GitActions } from '../../../commands/gitCommands.actions'; import type { Config } from '../../../configuration'; import { configuration } from '../../../configuration'; import { Commands, ContextKeys, CoreCommands, CoreGitCommands, GlyphChars } from '../../../constants'; import type { Container } from '../../../container'; import { getContext, onDidChangeContext } from '../../../context'; import { PlusFeatures } from '../../../features'; +import * as BranchActions from '../../../git/actions/branch'; +import * as ContributorActions from '../../../git/actions/contributor'; +import * as RepoActions from '../../../git/actions/repository'; +import * as StashActions from '../../../git/actions/stash'; +import * as TagActions from '../../../git/actions/tag'; +import * as WorktreeActions from '../../../git/actions/worktree'; import { GitSearchError } from '../../../git/errors'; import { getBranchId, getBranchNameWithoutRemote, getRemoteNameFromBranchName } from '../../../git/models/branch'; import { GitContributor } from '../../../git/models/contributor'; @@ -698,11 +703,11 @@ export class GraphWebview extends WebviewBase { if (isGraphItemRefContext(item)) { const { ref } = item.webviewItemValue; if (e.ref.refType === 'head' && e.ref.isCurrentHead) { - return GitActions.switchTo(ref.repoPath); + return RepoActions.switchTo(ref.repoPath); } // Override the default confirmation if the setting is unset - return GitActions.switchTo( + return RepoActions.switchTo( ref.repoPath, ref, configuration.isUnset('gitCommands.skipConfirmations') ? true : undefined, @@ -1926,17 +1931,17 @@ export class GraphWebview extends WebviewBase { @debug() private fetch() { - void GitActions.fetch(this.repository); + void RepoActions.fetch(this.repository); } @debug() private pull() { - void GitActions.pull(this.repository); + void RepoActions.pull(this.repository); } @debug() private push() { - void GitActions.push(this.repository); + void RepoActions.push(this.repository); } @debug() @@ -1944,14 +1949,14 @@ export class GraphWebview extends WebviewBase { const ref = this.getGraphItemRef(item); if (ref == null) return Promise.resolve(); - return GitActions.Branch.create(ref.repoPath, ref); + return BranchActions.create(ref.repoPath, ref); } @debug() private deleteBranch(item?: GraphItemContext) { if (isGraphItemRefContext(item, 'branch')) { const { ref } = item.webviewItemValue; - return GitActions.Branch.remove(ref.repoPath, ref); + return BranchActions.remove(ref.repoPath, ref); } return Promise.resolve(); @@ -1961,7 +1966,7 @@ export class GraphWebview extends WebviewBase { private mergeBranchInto(item?: GraphItemContext) { if (isGraphItemRefContext(item, 'branch')) { const { ref } = item.webviewItemValue; - return GitActions.merge(ref.repoPath, ref); + return RepoActions.merge(ref.repoPath, ref); } return Promise.resolve(); @@ -1986,7 +1991,7 @@ export class GraphWebview extends WebviewBase { const ref = this.getGraphItemRef(item); if (ref == null) return Promise.resolve(); - return GitActions.rebase(ref.repoPath, ref); + return RepoActions.rebase(ref.repoPath, ref); } @debug() @@ -1994,7 +1999,7 @@ export class GraphWebview extends WebviewBase { if (isGraphItemRefContext(item, 'branch')) { const { ref } = item.webviewItemValue; if (ref.upstream != null) { - return GitActions.rebase( + return RepoActions.rebase( ref.repoPath, GitReference.create(ref.upstream.name, ref.repoPath, { refType: 'branch', @@ -2012,7 +2017,7 @@ export class GraphWebview extends WebviewBase { private renameBranch(item?: GraphItemContext) { if (isGraphItemRefContext(item, 'branch')) { const { ref } = item.webviewItemValue; - return GitActions.Branch.rename(ref.repoPath, ref); + return BranchActions.rename(ref.repoPath, ref); } return Promise.resolve(); @@ -2023,7 +2028,7 @@ export class GraphWebview extends WebviewBase { const ref = this.getGraphItemRef(item, 'revision'); if (ref == null) return Promise.resolve(); - return GitActions.cherryPick(ref.repoPath, ref); + return RepoActions.cherryPick(ref.repoPath, ref); } @debug() @@ -2106,7 +2111,7 @@ export class GraphWebview extends WebviewBase { const ref = this.getGraphItemRef(item, 'revision'); if (ref == null) return Promise.resolve(); - return GitActions.reset( + return RepoActions.reset( ref.repoPath, GitReference.create(`${ref.ref}^`, ref.repoPath, { refType: 'revision', @@ -2121,7 +2126,7 @@ export class GraphWebview extends WebviewBase { const ref = this.getGraphItemRef(item, 'revision'); if (ref == null) return Promise.resolve(); - return GitActions.reset(ref.repoPath, ref); + return RepoActions.reset(ref.repoPath, ref); } @debug() @@ -2129,7 +2134,7 @@ export class GraphWebview extends WebviewBase { const ref = this.getGraphItemRef(item, 'revision'); if (ref == null) return Promise.resolve(); - return GitActions.revert(ref.repoPath, ref); + return RepoActions.revert(ref.repoPath, ref); } @debug() @@ -2137,7 +2142,7 @@ export class GraphWebview extends WebviewBase { const ref = this.getGraphItemRef(item); if (ref == null) return Promise.resolve(); - return GitActions.switchTo(ref.repoPath, ref); + return RepoActions.switchTo(ref.repoPath, ref); } @debug() @@ -2174,9 +2179,9 @@ export class GraphWebview extends WebviewBase { @debug() private switchToAnother(item?: GraphItemContext | unknown) { const ref = this.getGraphItemRef(item); - if (ref == null) return GitActions.switchTo(this.repository?.path); + if (ref == null) return RepoActions.switchTo(this.repository?.path); - return GitActions.switchTo(ref.repoPath); + return RepoActions.switchTo(ref.repoPath); } @debug() @@ -2206,7 +2211,7 @@ export class GraphWebview extends WebviewBase { const ref = this.getGraphItemRef(item); if (ref == null) return Promise.resolve(); - return GitActions.Stash.push(ref.repoPath); + return StashActions.push(ref.repoPath); } @debug() @@ -2214,7 +2219,7 @@ export class GraphWebview extends WebviewBase { const ref = this.getGraphItemRef(item, 'stash'); if (ref == null) return Promise.resolve(); - return GitActions.Stash.apply(ref.repoPath, ref); + return StashActions.apply(ref.repoPath, ref); } @debug() @@ -2222,7 +2227,7 @@ export class GraphWebview extends WebviewBase { const ref = this.getGraphItemRef(item, 'stash'); if (ref == null) return Promise.resolve(); - return GitActions.Stash.drop(ref.repoPath, ref); + return StashActions.drop(ref.repoPath, ref); } @debug() @@ -2230,14 +2235,14 @@ export class GraphWebview extends WebviewBase { const ref = this.getGraphItemRef(item); if (ref == null) return Promise.resolve(); - return GitActions.Tag.create(ref.repoPath, ref); + return TagActions.create(ref.repoPath, ref); } @debug() private deleteTag(item?: GraphItemContext) { if (isGraphItemRefContext(item, 'tag')) { const { ref } = item.webviewItemValue; - return GitActions.Tag.remove(ref.repoPath, ref); + return TagActions.remove(ref.repoPath, ref); } return Promise.resolve(); @@ -2248,7 +2253,7 @@ export class GraphWebview extends WebviewBase { const ref = this.getGraphItemRef(item); if (ref == null) return Promise.resolve(); - return GitActions.Worktree.create(ref.repoPath, undefined, ref); + return WorktreeActions.create(ref.repoPath, undefined, ref); } @debug() @@ -2355,7 +2360,7 @@ export class GraphWebview extends WebviewBase { private addAuthor(item?: GraphItemContext) { if (isGraphItemTypedContext(item, 'contributor')) { const { repoPath, name, email, current } = item.webviewItemValue; - return GitActions.Contributor.addAuthors( + return ContributorActions.addAuthors( repoPath, new GitContributor(repoPath, name, email, 0, undefined, current), ); diff --git a/src/plus/webviews/timeline/timelineWebview.ts b/src/plus/webviews/timeline/timelineWebview.ts index bd77ea6..f5cfc2a 100644 --- a/src/plus/webviews/timeline/timelineWebview.ts +++ b/src/plus/webviews/timeline/timelineWebview.ts @@ -1,11 +1,11 @@ 'use strict'; import type { Disposable, TextEditor, ViewColumn } from 'vscode'; import { Uri, window } from 'vscode'; -import { GitActions } from '../../../commands/gitCommands.actions'; import { configuration } from '../../../configuration'; import { Commands, ContextKeys } from '../../../constants'; import type { Container } from '../../../container'; import { PlusFeatures } from '../../../features'; +import { showDetailsView } from '../../../git/actions/commit'; import { GitUri } from '../../../git/gitUri'; import { getChangedFilesCount } from '../../../git/models/commit'; import type { RepositoryChangeEvent } from '../../../git/models/repository'; @@ -139,7 +139,7 @@ export class TimelineWebview extends WebviewBase { const commit = await repository.getCommit(params.data.id); if (commit == null) return; - void GitActions.Commit.showDetailsView(commit, { pin: false, preserveFocus: true }); + void showDetailsView(commit, { pin: false, preserveFocus: true }); }); break; diff --git a/src/quickpicks/items/commits.ts b/src/quickpicks/items/commits.ts index 9b7c476..642168c 100644 --- a/src/quickpicks/items/commits.ts +++ b/src/quickpicks/items/commits.ts @@ -1,10 +1,11 @@ import type { QuickPickItem } from 'vscode'; import { window } from 'vscode'; -import { GitActions } from '../../commands/gitCommands.actions'; import type { OpenChangedFilesCommandArgs } from '../../commands/openChangedFiles'; import { QuickCommandButtons } from '../../commands/quickCommand.buttons'; import { Commands, GlyphChars } from '../../constants'; import { Container } from '../../container'; +import { browseAtRevision } from '../../git/actions'; +import * as CommitActions from '../../git/actions/commit'; import { CommitFormatter } from '../../git/formatters/commitFormatter'; import type { GitCommit } from '../../git/models/commit'; import type { GitFileChange } from '../../git/models/file'; @@ -76,7 +77,7 @@ export class CommitFileQuickPickItem extends CommandQuickPickItem { } override execute(options?: { preserveFocus?: boolean; preview?: boolean }): Promise { - return GitActions.Commit.openChanges(this.file, this.commit, options); + return CommitActions.openChanges(this.file, this.commit, options); // const fileCommit = await this.commit.getCommitForFile(this.file)!; // if (fileCommit.previousSha === undefined) { @@ -114,7 +115,7 @@ export class CommitBrowseRepositoryFromHereCommandQuickPickItem extends CommandQ } override execute(_options: { preserveFocus?: boolean; preview?: boolean }): Promise { - return GitActions.browseAtRevision(this.commit.getGitUri(), { + return browseAtRevision(this.commit.getGitUri(), { before: this.executeOptions?.before, openInNewWindow: this.executeOptions?.openInNewWindow, }); @@ -147,7 +148,7 @@ export class CommitCopyIdQuickPickItem extends CommandQuickPickItem { } override execute(): Promise { - return GitActions.Commit.copyIdToClipboard(this.commit); + return CommitActions.copyIdToClipboard(this.commit); } override async onDidPressKey(key: Keys): Promise { @@ -162,7 +163,7 @@ export class CommitCopyMessageQuickPickItem extends CommandQuickPickItem { } override execute(): Promise { - return GitActions.Commit.copyMessageToClipboard(this.commit); + return CommitActions.copyMessageToClipboard(this.commit); } override async onDidPressKey(key: Keys): Promise { @@ -179,7 +180,7 @@ export class CommitOpenAllChangesCommandQuickPickItem extends CommandQuickPickIt } override execute(options: { preserveFocus?: boolean; preview?: boolean }): Promise { - return GitActions.Commit.openAllChanges(this.commit, options); + return CommitActions.openAllChanges(this.commit, options); } } @@ -189,7 +190,7 @@ export class CommitOpenAllChangesWithDiffToolCommandQuickPickItem extends Comman } override execute(): Promise { - return GitActions.Commit.openAllChangesWithDiffTool(this.commit); + return CommitActions.openAllChangesWithDiffTool(this.commit); } } @@ -199,7 +200,7 @@ export class CommitOpenAllChangesWithWorkingCommandQuickPickItem extends Command } override execute(options: { preserveFocus?: boolean; preview?: boolean }): Promise { - return GitActions.Commit.openAllChangesWithWorking(this.commit, options); + return CommitActions.openAllChangesWithWorking(this.commit, options); } } @@ -209,7 +210,7 @@ export class CommitOpenChangesCommandQuickPickItem extends CommandQuickPickItem } override execute(options: { preserveFocus?: boolean; preview?: boolean }): Promise { - return GitActions.Commit.openChanges(this.file, this.commit, options); + return CommitActions.openChanges(this.file, this.commit, options); } } @@ -219,7 +220,7 @@ export class CommitOpenChangesWithDiffToolCommandQuickPickItem extends CommandQu } override execute(): Promise { - return GitActions.Commit.openChangesWithDiffTool(this.file, this.commit); + return CommitActions.openChangesWithDiffTool(this.file, this.commit); } } @@ -229,7 +230,7 @@ export class CommitOpenChangesWithWorkingCommandQuickPickItem extends CommandQui } override execute(options: { preserveFocus?: boolean; preview?: boolean }): Promise { - return GitActions.Commit.openChangesWithWorking(this.file, this.commit, options); + return CommitActions.openChangesWithWorking(this.file, this.commit, options); } } @@ -239,7 +240,7 @@ export class CommitOpenDirectoryCompareCommandQuickPickItem extends CommandQuick } override execute(): Promise { - return GitActions.Commit.openDirectoryCompareWithPrevious(this.commit); + return CommitActions.openDirectoryCompareWithPrevious(this.commit); } } @@ -249,7 +250,7 @@ export class CommitOpenDirectoryCompareWithWorkingCommandQuickPickItem extends C } override execute(): Promise { - return GitActions.Commit.openDirectoryCompareWithWorking(this.commit); + return CommitActions.openDirectoryCompareWithWorking(this.commit); } } @@ -259,7 +260,7 @@ export class CommitOpenDetailsCommandQuickPickItem extends CommandQuickPickItem } override execute(options: { preserveFocus?: boolean; preview?: boolean }): Promise { - return GitActions.Commit.showDetailsView(this.commit, { preserveFocus: options?.preserveFocus }); + return CommitActions.showDetailsView(this.commit, { preserveFocus: options?.preserveFocus }); } } @@ -269,7 +270,7 @@ export class CommitOpenInGraphCommandQuickPickItem extends CommandQuickPickItem } override execute(options: { preserveFocus?: boolean; preview?: boolean }): Promise { - return GitActions.Commit.showInCommitGraph(this.commit, { preserveFocus: options?.preserveFocus }); + return CommitActions.showInCommitGraph(this.commit, { preserveFocus: options?.preserveFocus }); } } @@ -279,7 +280,7 @@ export class CommitOpenFilesCommandQuickPickItem extends CommandQuickPickItem { } override execute(_options: { preserveFocus?: boolean; preview?: boolean }): Promise { - return GitActions.Commit.openFiles(this.commit); + return CommitActions.openFiles(this.commit); } } @@ -289,7 +290,7 @@ export class CommitOpenFileCommandQuickPickItem extends CommandQuickPickItem { } override execute(options?: { preserveFocus?: boolean; preview?: boolean }): Promise { - return GitActions.Commit.openFile(this.file, this.commit, options); + return CommitActions.openFile(this.file, this.commit, options); } } @@ -299,7 +300,7 @@ export class CommitOpenRevisionsCommandQuickPickItem extends CommandQuickPickIte } override execute(_options: { preserveFocus?: boolean; preview?: boolean }): Promise { - return GitActions.Commit.openFilesAtRevision(this.commit); + return CommitActions.openFilesAtRevision(this.commit); } } @@ -309,7 +310,7 @@ export class CommitOpenRevisionCommandQuickPickItem extends CommandQuickPickItem } override execute(options?: { preserveFocus?: boolean; preview?: boolean }): Promise { - return GitActions.Commit.openFileAtRevision(this.file, this.commit, options); + return CommitActions.openFileAtRevision(this.file, this.commit, options); } } @@ -319,7 +320,7 @@ export class CommitApplyFileChangesCommandQuickPickItem extends CommandQuickPick } override async execute(): Promise { - return GitActions.Commit.applyChanges(this.file, this.commit); + return CommitActions.applyChanges(this.file, this.commit); } } @@ -334,7 +335,7 @@ export class CommitRestoreFileChangesCommandQuickPickItem extends CommandQuickPi } override execute(): Promise { - return GitActions.Commit.restoreFile(this.file, this.commit); + return CommitActions.restoreFile(this.file, this.commit); } } diff --git a/src/quickpicks/referencePicker.ts b/src/quickpicks/referencePicker.ts index 9ab1148..0938b85 100644 --- a/src/quickpicks/referencePicker.ts +++ b/src/quickpicks/referencePicker.ts @@ -1,9 +1,11 @@ import type { Disposable, QuickPick } from 'vscode'; import { CancellationTokenSource, window } from 'vscode'; -import { GitActions } from '../commands/gitCommands.actions'; import { getBranchesAndOrTags, getValidateGitReferenceFn, QuickCommandButtons } from '../commands/quickCommand'; import { GlyphChars } from '../constants'; import { Container } from '../container'; +import { reveal as revealBranch } from '../git/actions/branch'; +import { showDetailsView } from '../git/actions/commit'; +import { reveal as revealTag } from '../git/actions/tag'; import type { BranchSortOptions, GitBranch } from '../git/models/branch'; import { GitReference } from '../git/models/reference'; import type { GitTag, TagSortOptions } from '../git/models/tag'; @@ -133,11 +135,11 @@ export namespace ReferencePicker { quickpick.onDidTriggerItemButton(({ button, item: { item } }) => { if (button === QuickCommandButtons.RevealInSideBar) { if (GitReference.isBranch(item)) { - void GitActions.Branch.reveal(item, { select: true, expand: true }); + void revealBranch(item, { select: true, expand: true }); } else if (GitReference.isTag(item)) { - void GitActions.Tag.reveal(item, { select: true, expand: true }); + void revealTag(item, { select: true, expand: true }); } else if (GitReference.isRevision(item)) { - void GitActions.Commit.showDetailsView(item, { + void showDetailsView(item, { pin: false, preserveFocus: true, }); diff --git a/src/views/nodes/searchResultsNode.ts b/src/views/nodes/searchResultsNode.ts index 5b809e1..c34b646 100644 --- a/src/views/nodes/searchResultsNode.ts +++ b/src/views/nodes/searchResultsNode.ts @@ -1,6 +1,6 @@ import type { TreeItem } from 'vscode'; import { ThemeIcon } from 'vscode'; -import { executeGitCommand } from '../../commands/gitCommands.actions'; +import { executeGitCommand } from '../../git/actions'; import { GitUri } from '../../git/gitUri'; import type { GitLog } from '../../git/models/log'; import type { SearchQuery, StoredSearchQuery } from '../../git/search'; diff --git a/src/views/viewCommands.ts b/src/views/viewCommands.ts index 7cae2b0..03016f1 100644 --- a/src/views/viewCommands.ts +++ b/src/views/viewCommands.ts @@ -7,11 +7,19 @@ import type { DiffWithWorkingCommandArgs, OpenFileAtRevisionCommandArgs, } from '../commands'; -import { GitActions } from '../commands/gitCommands.actions'; import { configuration, FileAnnotationType, ViewShowBranchComparison } from '../configuration'; import { Commands, ContextKeys, CoreCommands, CoreGitCommands } from '../constants'; import type { Container } from '../container'; import { setContext } from '../context'; +import { browseAtRevision } from '../git/actions'; +import * as BranchActions from '../git/actions/branch'; +import * as CommitActions from '../git/actions/commit'; +import * as ContributorActions from '../git/actions/contributor'; +import * as RemoteActions from '../git/actions/remote'; +import * as RepoActions from '../git/actions/repository'; +import * as StashActions from '../git/actions/stash'; +import * as TagActions from '../git/actions/tag'; +import * as WorktreeActions from '../git/actions/worktree'; import { GitUri } from '../git/gitUri'; import type { GitStashReference } from '../git/models/reference'; import { GitReference, GitRevision } from '../git/models/reference'; @@ -288,13 +296,13 @@ export class ViewCommands { @debug() private addAuthors(node?: ViewNode) { - return GitActions.Contributor.addAuthors(getNodeRepoPath(node)); + return ContributorActions.addAuthors(getNodeRepoPath(node)); } @debug() private addAuthor(node?: ContributorNode) { if (node instanceof ContributorNode) { - return GitActions.Contributor.addAuthors( + return ContributorActions.addAuthors( node.repoPath, node.contributor.current ? undefined : node.contributor, ); @@ -305,7 +313,7 @@ export class ViewCommands { @debug() private addRemote(node?: ViewNode) { - return GitActions.Remote.add(getNodeRepoPath(node)); + return RemoteActions.add(getNodeRepoPath(node)); } @debug() @@ -313,7 +321,7 @@ export class ViewCommands { if (!(node instanceof ViewRefFileNode)) return Promise.resolve(); if (node instanceof ResultsFileNode) { - return GitActions.Commit.applyChanges( + return CommitActions.applyChanges( node.file, GitReference.create(node.ref1, node.repoPath), GitReference.create(node.ref2, node.repoPath), @@ -322,19 +330,19 @@ export class ViewCommands { if (node.ref == null || node.ref.ref === 'HEAD') return Promise.resolve(); - return GitActions.Commit.applyChanges(node.file, node.ref); + return CommitActions.applyChanges(node.file, node.ref); } @debug() private applyStash() { - return GitActions.Stash.apply(); + return StashActions.apply(); } @debug() private browseRepoAtRevision(node: ViewRefNode, options?: { before?: boolean; openInNewWindow?: boolean }) { if (!(node instanceof ViewRefNode)) return Promise.resolve(); - return GitActions.browseAtRevision(node.uri, { + return browseAtRevision(node.uri, { before: options?.before, openInNewWindow: options?.openInNewWindow, }); @@ -345,13 +353,13 @@ export class ViewCommands { if (!(node instanceof CommitNode)) return Promise.resolve(); if (nodes != null && nodes.length !== 0) { - return GitActions.cherryPick( + return RepoActions.cherryPick( node.repoPath, nodes.map(n => n.ref), ); } - return GitActions.cherryPick(node.repoPath, node.ref); + return RepoActions.cherryPick(node.repoPath, node.ref); } @debug() @@ -375,7 +383,7 @@ export class ViewCommands { ); from = branch; } - return GitActions.Branch.create(node?.repoPath, from); + return BranchActions.create(node?.repoPath, from); } @debug() @@ -425,7 +433,7 @@ export class ViewCommands { ); from = branch; } - return GitActions.Tag.create(node?.repoPath, from); + return TagActions.create(node?.repoPath, from); } @debug() @@ -435,14 +443,14 @@ export class ViewCommands { } if (node != null && !(node instanceof BranchNode)) return undefined; - return GitActions.Worktree.create(node?.repoPath, undefined, node?.ref); + return WorktreeActions.create(node?.repoPath, undefined, node?.ref); } @debug() private deleteBranch(node: BranchNode) { if (!(node instanceof BranchNode)) return Promise.resolve(); - return GitActions.Branch.remove(node.repoPath, node.branch); + return BranchActions.remove(node.repoPath, node.branch); } @debug() @@ -453,34 +461,34 @@ export class ViewCommands { const sorted = nodes.sort((a, b) => parseInt(b.commit.number, 10) - parseInt(a.commit.number, 10)); return sequentialize( - GitActions.Stash.drop, + StashActions.drop, sorted.map<[string, GitStashReference]>(n => [n.repoPath, n.commit]), this, ); } - return GitActions.Stash.drop(node.repoPath, node.commit); + return StashActions.drop(node.repoPath, node.commit); } @debug() private deleteTag(node: TagNode) { if (!(node instanceof TagNode)) return Promise.resolve(); - return GitActions.Tag.remove(node.repoPath, node.tag); + return TagActions.remove(node.repoPath, node.tag); } @debug() private async deleteWorktree(node: WorktreeNode) { if (!(node instanceof WorktreeNode)) return undefined; - return GitActions.Worktree.remove(node.repoPath, node.worktree.uri); + return WorktreeActions.remove(node.repoPath, node.worktree.uri); } @debug() private fetch(node: RemoteNode | RepositoryNode | RepositoryFolderNode | BranchNode | BranchTrackingStatusNode) { - if (node instanceof RepositoryNode || node instanceof RepositoryFolderNode) return GitActions.fetch(node.repo); - if (node instanceof RemoteNode) return GitActions.Remote.fetch(node.remote.repoPath, node.remote.name); + if (node instanceof RepositoryNode || node instanceof RepositoryFolderNode) return RepoActions.fetch(node.repo); + if (node instanceof RemoteNode) return RemoteActions.fetch(node.remote.repoPath, node.remote.name); if (node instanceof BranchNode || node instanceof BranchTrackingStatusNode) { - return GitActions.fetch(node.repoPath, node.root ? undefined : node.branch); + return RepoActions.fetch(node.repoPath, node.root ? undefined : node.branch); } return Promise.resolve(); @@ -532,7 +540,7 @@ export class ViewCommands { private merge(node: BranchNode | TagNode) { if (!(node instanceof BranchNode) && !(node instanceof TagNode)) return Promise.resolve(); - return GitActions.merge(node.repoPath, node instanceof BranchNode ? node.branch : node.tag); + return RepoActions.merge(node.repoPath, node instanceof BranchNode ? node.branch : node.tag); } @debug() @@ -564,27 +572,27 @@ export class ViewCommands { private openWorktree(node: WorktreeNode, options?: { location?: OpenWorkspaceLocation }) { if (!(node instanceof WorktreeNode)) return undefined; - return GitActions.Worktree.open(node.worktree, options); + return WorktreeActions.open(node.worktree, options); } @debug() private pruneRemote(node: RemoteNode) { if (!(node instanceof RemoteNode)) return Promise.resolve(); - return GitActions.Remote.prune(node.repo, node.remote.name); + return RemoteActions.prune(node.repo, node.remote.name); } @debug() private async removeRemote(node: RemoteNode) { if (!(node instanceof RemoteNode)) return Promise.resolve(); - return GitActions.Remote.remove(node.repo, node.remote.name); + return RemoteActions.remove(node.repo, node.remote.name); } @debug() private publishBranch(node: BranchNode | BranchTrackingStatusNode) { if (node instanceof BranchNode || node instanceof BranchTrackingStatusNode) { - return GitActions.push(node.repoPath, undefined, node.branch); + return RepoActions.push(node.repoPath, undefined, node.branch); } return Promise.resolve(); } @@ -599,9 +607,9 @@ export class ViewCommands { @debug() private pull(node: RepositoryNode | RepositoryFolderNode | BranchNode | BranchTrackingStatusNode) { - if (node instanceof RepositoryNode || node instanceof RepositoryFolderNode) return GitActions.pull(node.repo); + if (node instanceof RepositoryNode || node instanceof RepositoryFolderNode) return RepoActions.pull(node.repo); if (node instanceof BranchNode || node instanceof BranchTrackingStatusNode) { - return GitActions.pull(node.repoPath, node.root ? undefined : node.branch); + return RepoActions.pull(node.repoPath, node.root ? undefined : node.branch); } return Promise.resolve(); @@ -619,16 +627,16 @@ export class ViewCommands { force?: boolean, ) { if (node instanceof RepositoryNode || node instanceof RepositoryFolderNode) { - return GitActions.push(node.repo, force); + return RepoActions.push(node.repo, force); } if (node instanceof BranchNode || node instanceof BranchTrackingStatusNode) { - return GitActions.push(node.repoPath, force, node.root ? undefined : node.branch); + return RepoActions.push(node.repoPath, force, node.root ? undefined : node.branch); } if (node instanceof CommitNode || node instanceof FileRevisionAsCommitNode) { if (node.isTip) { - return GitActions.push(node.repoPath, force); + return RepoActions.push(node.repoPath, force); } return this.pushToCommit(node); @@ -641,7 +649,7 @@ export class ViewCommands { private pushToCommit(node: CommitNode | FileRevisionAsCommitNode) { if (!(node instanceof CommitNode) && !(node instanceof FileRevisionAsCommitNode)) return Promise.resolve(); - return GitActions.push(node.repoPath, false, node.commit); + return RepoActions.push(node.repoPath, false, node.commit); } @debug() @@ -655,7 +663,7 @@ export class ViewCommands { return Promise.resolve(); } - return GitActions.rebase(node.repoPath, node.ref); + return RepoActions.rebase(node.repoPath, node.ref); } @debug() @@ -665,7 +673,7 @@ export class ViewCommands { const upstream = node instanceof BranchNode ? node.branch.upstream?.name : node.status.upstream; if (upstream == null) return Promise.resolve(); - return GitActions.rebase( + return RepoActions.rebase( node.repoPath, GitReference.create(upstream, node.repoPath, { refType: 'branch', @@ -679,14 +687,14 @@ export class ViewCommands { private renameBranch(node: BranchNode) { if (!(node instanceof BranchNode)) return Promise.resolve(); - return GitActions.Branch.rename(node.repoPath, node.branch); + return BranchActions.rename(node.repoPath, node.branch); } @debug() private resetCommit(node: CommitNode | FileRevisionAsCommitNode) { if (!(node instanceof CommitNode) && !(node instanceof FileRevisionAsCommitNode)) return Promise.resolve(); - return GitActions.reset( + return RepoActions.reset( node.repoPath, GitReference.create(`${node.ref.ref}^`, node.ref.repoPath, { refType: 'revision', @@ -700,28 +708,28 @@ export class ViewCommands { private resetToCommit(node: CommitNode | FileRevisionAsCommitNode) { if (!(node instanceof CommitNode) && !(node instanceof FileRevisionAsCommitNode)) return Promise.resolve(); - return GitActions.reset(node.repoPath, node.ref); + return RepoActions.reset(node.repoPath, node.ref); } @debug() private restore(node: ViewRefFileNode) { if (!(node instanceof ViewRefFileNode)) return Promise.resolve(); - return GitActions.Commit.restoreFile(node.file, node.ref); + return CommitActions.restoreFile(node.file, node.ref); } @debug() private revealWorktreeInExplorer(node: WorktreeNode) { if (!(node instanceof WorktreeNode)) return undefined; - return GitActions.Worktree.revealInFileExplorer(node.worktree); + return WorktreeActions.revealInFileExplorer(node.worktree); } @debug() private revert(node: CommitNode | FileRevisionAsCommitNode) { if (!(node instanceof CommitNode) && !(node instanceof FileRevisionAsCommitNode)) return Promise.resolve(); - return GitActions.revert(node.repoPath, node.ref); + return RepoActions.revert(node.repoPath, node.ref); } @debug() @@ -780,19 +788,19 @@ export class ViewCommands { @debug() private switch(node?: ViewNode) { - return GitActions.switchTo(getNodeRepoPath(node)); + return RepoActions.switchTo(getNodeRepoPath(node)); } @debug() private switchTo(node?: ViewNode) { if (node instanceof ViewRefNode) { - return GitActions.switchTo( + return RepoActions.switchTo( node.repoPath, node instanceof BranchNode && node.branch.current ? undefined : node.ref, ); } - return GitActions.switchTo(getNodeRepoPath(node)); + return RepoActions.switchTo(getNodeRepoPath(node)); } @debug() @@ -964,7 +972,7 @@ export class ViewCommands { const { files: diff } = await node.getFilesQueryResults(); if (diff == null || diff.length === 0) return undefined; - return GitActions.Commit.openAllChanges( + return CommitActions.openAllChanges( diff, { repoPath: node.repoPath, @@ -975,7 +983,7 @@ export class ViewCommands { ); } - return GitActions.Commit.openAllChanges(node.commit, options); + return CommitActions.openAllChanges(node.commit, options); } @debug() @@ -1030,7 +1038,7 @@ export class ViewCommands { } // TODO@eamodio Revisit this - // return GitActions.Commit.openChanges(node.file, node instanceof ViewRefFileNode ? node.ref : node.commit, { + // return CommitActions.openChanges(node.file, node instanceof ViewRefFileNode ? node.ref : node.commit, { // preserveFocus: true, // preview: false, // }); @@ -1049,7 +1057,7 @@ export class ViewCommands { const { files: diff } = await node.getFilesQueryResults(); if (diff == null || diff.length === 0) return undefined; - return GitActions.Commit.openAllChangesWithWorking( + return CommitActions.openAllChangesWithWorking( diff, { repoPath: node.repoPath, @@ -1059,7 +1067,7 @@ export class ViewCommands { ); } - return GitActions.Commit.openAllChangesWithWorking(node.commit, options); + return CommitActions.openAllChangesWithWorking(node.commit, options); // options = { preserveFocus: false, preview: false, ...options }; @@ -1140,14 +1148,17 @@ export class ViewCommands { } } - return GitActions.Commit.openChangesWithWorking(node.file, { repoPath: node.repoPath, ref: node.ref.ref }); + return CommitActions.openChangesWithWorking(node.file, { + repoPath: node.repoPath, + ref: node.ref.ref, + }); } @debug() private async openPreviousChangesWithWorking(node: ViewRefFileNode) { if (!(node instanceof ViewRefFileNode)) return Promise.resolve(); - return GitActions.Commit.openChangesWithWorking(node.file, { + return CommitActions.openChangesWithWorking(node.file, { repoPath: node.repoPath, ref: `${node.ref.ref}^`, }); @@ -1168,7 +1179,7 @@ export class ViewCommands { return Promise.resolve(); } - return GitActions.Commit.openFile(node.uri, { + return CommitActions.openFile(node.uri, { preserveFocus: true, preview: false, ...options, @@ -1185,10 +1196,10 @@ export class ViewCommands { const { files: diff } = await node.getFilesQueryResults(); if (diff == null || diff.length === 0) return undefined; - return GitActions.Commit.openFiles(diff, node.repoPath, node.ref1 || node.ref2); + return CommitActions.openFiles(diff, node.repoPath, node.ref1 || node.ref2); } - return GitActions.Commit.openFiles(node.commit); + return CommitActions.openFiles(node.commit); } @debug() @@ -1231,10 +1242,7 @@ export class ViewCommands { } } - return GitActions.Commit.openFileAtRevision( - uri, - options.showOptions ?? { preserveFocus: true, preview: false }, - ); + return CommitActions.openFileAtRevision(uri, options.showOptions ?? { preserveFocus: true, preview: false }); } @debug() @@ -1247,9 +1255,9 @@ export class ViewCommands { const { files: diff } = await node.getFilesQueryResults(); if (diff == null || diff.length === 0) return undefined; - return GitActions.Commit.openFilesAtRevision(diff, node.repoPath, node.ref1, node.ref2); + return CommitActions.openFilesAtRevision(diff, node.repoPath, node.ref1, node.ref2); } - return GitActions.Commit.openFilesAtRevision(node.commit); + return CommitActions.openFilesAtRevision(node.commit); } } diff --git a/src/webviews/commitDetails/commitDetailsWebviewView.ts b/src/webviews/commitDetails/commitDetailsWebviewView.ts index 29eaade..3ee01a0 100644 --- a/src/webviews/commitDetails/commitDetailsWebviewView.ts +++ b/src/webviews/commitDetails/commitDetailsWebviewView.ts @@ -2,12 +2,19 @@ import type { CancellationToken, ConfigurationChangeEvent, TextDocumentShowOptio import { CancellationTokenSource, Disposable, Uri, ViewColumn, window } from 'vscode'; import { serializeAutolink } from '../../annotations/autolinks'; import type { CopyShaToClipboardCommandArgs } from '../../commands'; -import { executeGitCommand, GitActions } from '../../commands/gitCommands.actions'; import { configuration } from '../../configuration'; import { Commands, ContextKeys, CoreCommands } from '../../constants'; import type { Container } from '../../container'; import { getContext } from '../../context'; import type { CommitSelectedEvent } from '../../eventBus'; +import { executeGitCommand } from '../../git/actions'; +import { + openChanges, + openChangesWithWorking, + openFile, + openFileOnRemote, + showDetailsQuickPick, +} from '../../git/actions/commit'; import { CommitFormatter } from '../../git/formatters/commitFormatter'; import type { GitCommit } from '../../git/models/commit'; import { isCommit } from '../../git/models/commit'; @@ -787,7 +794,7 @@ export class CommitDetailsWebviewView extends WebviewViewBase