Browse Source

Changes `getDiff` to use to/from args for clarity

Changes `PatchRevisionRange` to use to/from args for clarity
Changes `openChanges`/`openAllChanges`  to use lhs/rhs args for clarity
Ensures comparisons -> patch works properly
main
Eric Amodio 1 year ago
parent
commit
685340b13c
14 changed files with 193 additions and 300 deletions
  1. +78
    -162
      src/commands/patches.ts
  2. +18
    -18
      src/env/node/git/localGitProvider.ts
  3. +31
    -46
      src/git/actions/commit.ts
  4. +2
    -2
      src/git/gitProvider.ts
  5. +3
    -3
      src/git/gitProviderService.ts
  6. +2
    -1
      src/git/models/diff.ts
  7. +5
    -5
      src/git/models/patch.ts
  8. +12
    -13
      src/plus/drafts/draftsService.ts
  9. +1
    -1
      src/plus/webviews/graph/graphWebview.ts
  10. +18
    -22
      src/plus/webviews/patchDetails/patchDetailsWebview.ts
  11. +19
    -1
      src/plus/webviews/patchDetails/protocol.ts
  12. +1
    -20
      src/plus/webviews/patchDetails/registration.ts
  13. +2
    -2
      src/views/viewCommands.ts
  14. +1
    -4
      src/webviews/commitDetails/commitDetailsWebview.ts

+ 78
- 162
src/commands/patches.ts View File

@ -2,12 +2,11 @@ import type { TextEditor } from 'vscode';
import { window, workspace } from 'vscode';
import { Commands } from '../constants';
import type { Container } from '../container';
import type { PatchRevisionRange } from '../git/models/patch';
import { shortenRevision } from '../git/models/reference';
import { isSha, shortenRevision } from '../git/models/reference';
import type { Repository } from '../git/models/repository';
import type { Draft, LocalDraft } from '../gk/models/drafts';
import { showPatchesView } from '../plus/drafts/actions';
import type { Change } from '../plus/webviews/patchDetails/protocol';
import type { Change, CreateDraft } from '../plus/webviews/patchDetails/protocol';
import { getRepositoryOrShowPicker } from '../quickpicks/repositoryPicker';
import { command } from '../system/command';
import type { CommandContext } from './base';
@ -19,8 +18,8 @@ import {
} from './base';
export interface CreatePatchCommandArgs {
ref1?: string;
ref2?: string;
to?: string;
from?: string;
repoPath?: string;
}
@ -36,13 +35,13 @@ export class CreatePatchCommand extends Command {
if (isCommandContextViewNodeHasCommit(context)) {
args = {
repoPath: context.node.commit.repoPath,
ref1: context.node.commit.ref,
to: context.node.commit.ref,
};
} else if (isCommandContextViewNodeHasComparison(context)) {
args = {
repoPath: context.node.uri.fsPath,
ref1: context.node.compareWithRef.ref,
ref2: context.node.compareRef.ref,
to: context.node.compareRef.ref,
from: context.node.compareWithRef.ref,
};
}
}
@ -59,22 +58,11 @@ export class CreatePatchCommand extends Command {
repo = this.container.git.getRepository(args.repoPath);
}
if (repo == null) return undefined;
if (args?.ref1 == null) return;
if (args?.to == null) return;
const diff = await getDiffContents(this.container, repo, args);
const diff = await this.container.git.getDiff(repo.uri, args.to ?? 'HEAD', args.from);
if (diff == null) return;
// let repo;
// if (args?.repoPath == null) {
// repo = await getRepositoryOrShowPicker('Create Patch');
// } else {
// repo = this.container.git.getRepository(args.repoPath);
// }
// if (repo == null) return;
// const diff = await this.container.git.getDiff(repo.uri, args?.ref1 ?? 'HEAD', args?.ref2);
// if (diff == null) return;
const d = await workspace.openTextDocument({ content: diff.contents, language: 'diff' });
await window.showTextDocument(d);
@ -88,101 +76,6 @@ export class CreatePatchCommand extends Command {
}
}
async function getDiffContents(
container: Container,
repository: Repository,
args: CreatePatchCommandArgs,
): Promise<{ contents: string; revision: PatchRevisionRange } | undefined> {
const sha = args.ref1 ?? 'HEAD';
const diff = await container.git.getDiff(repository.uri, sha, args.ref2);
if (diff == null) return undefined;
return {
contents: diff.contents,
revision: {
baseSha: args.ref2 ?? `${sha}^`,
sha: sha,
},
};
}
interface CreateLocalChange {
title?: string;
description?: string;
changes: Change[];
}
async function createLocalChange(
container: Container,
repository: Repository,
args: CreatePatchCommandArgs,
): Promise<CreateLocalChange | undefined> {
if (args.ref1 == null) return undefined;
const sha = args.ref1 ?? 'HEAD';
// const [branchName] = await container.git.getCommitBranches(repository.uri, sha);
const change: Change = {
type: 'revision',
repository: {
name: repository.name,
path: repository.path,
uri: repository.uri.toString(),
},
files: undefined!,
revision: {
sha: sha,
baseSha: args.ref2 ?? `${sha}^`,
// branchName: branchName ?? 'HEAD',
},
};
const create: CreateLocalChange = { changes: [change] };
const commit = await container.git.getCommit(repository.uri, sha);
if (commit == null) return undefined;
const message = commit.message!.trim();
const index = message.indexOf('\n');
if (index < 0) {
create.title = message;
} else {
create.title = message.substring(0, index);
create.description = message.substring(index + 1);
}
if (args.ref2 == null) {
change.files = commit.files != null ? [...commit.files] : [];
} else {
const diff = await getDiffContents(container, repository, args);
if (diff == null) return undefined;
const result = await container.git.getDiffFiles(repository.uri, diff.contents);
if (result?.files == null) return;
create.title = `Comparing ${shortenRevision(args.ref2)} with ${shortenRevision(args.ref1)}`;
change.files = result.files;
}
// const change: Change = {
// type: 'commit',
// repository: {
// name: repository.name,
// path: repository.path,
// uri: repository.uri.toString(),
// },
// files: result.files,
// range: {
// ...range,
// branchName: branchName ?? 'HEAD',
// },
// };
return create;
}
@command()
export class CreateCloudPatchCommand extends Command {
constructor(private readonly container: Container) {
@ -195,13 +88,13 @@ export class CreateCloudPatchCommand extends Command {
if (isCommandContextViewNodeHasCommit(context)) {
args = {
repoPath: context.node.commit.repoPath,
ref1: context.node.commit.ref,
to: context.node.commit.ref,
};
} else if (isCommandContextViewNodeHasComparison(context)) {
args = {
repoPath: context.node.uri.fsPath,
ref1: context.node.compareWithRef.ref,
ref2: context.node.compareRef.ref,
to: context.node.compareRef.ref,
from: context.node.compareWithRef.ref,
};
}
}
@ -220,7 +113,7 @@ export class CreateCloudPatchCommand extends Command {
return showPatchesView({ mode: 'create' });
}
const create = await createLocalChange(this.container, repo, args);
const create = await createDraft(this.container, repo, args);
if (create == null) {
return showPatchesView({ mode: 'create', create: { repositories: [repo] } });
}
@ -366,60 +259,83 @@ export class OpenCloudPatchCommand extends Command {
async execute(args?: OpenCloudPatchCommandArgs) {
if (args?.id == null && args?.draft == null) {
void window.showErrorMessage('Cannot open cloud patch: no patch or patch id provided');
void window.showErrorMessage('Cannot open Cloud Patch; no patch or patch id provided');
return;
}
const draft = args?.draft ?? (await this.container.drafts.getDraft(args?.id));
if (draft == null) {
void window.showErrorMessage(`Cannot open cloud patch: patch ${args.id} not found`);
void window.showErrorMessage(`Cannot open Cloud Patch; patch '${args.id}' not found`);
return;
}
// let patch: DraftPatch | undefined;
// if (args?.patchId) {
// patch = await this.container.drafts.getPatch(args.patchId);
// } else {
// const patches = draft.changesets?.[0]?.patches;
// if (patches == null || patches.length === 0) {
// void window.showErrorMessage(`Cannot open cloud patch: no patch found under id ${args.patchId}`);
// return;
// }
// patch = patches[0];
// if (patch.repo == null && patch.repoData != null) {
// const repo = await this.container.git.findMatchingRepository({
// firstSha: patch.repoData.initialCommitSha,
// remoteUrl: patch.repoData.remote?.url,
// });
// if (repo != null) {
// patch.repo = repo;
// }
// }
void showPatchesView({ mode: 'view', draft: draft });
}
}
// if (patch.repo == null) {
// void window.showErrorMessage(`Cannot open cloud patch: no repository found for patch ${args.patchId}`);
// return;
// }
async function createDraft(
container: Container,
repository: Repository,
args: CreatePatchCommandArgs,
): Promise<CreateDraft | undefined> {
if (args.to == null) return undefined;
// // Opens the patch repository if it's not already open
// void this.container.git.getOrOpenRepository(patch.repo.uri);
const to = args.to ?? 'HEAD';
// const patchContents = await this.container.drafts.getPatchContents(patch.id);
// if (patchContents == null) {
// void window.showErrorMessage(`Cannot open cloud patch: patch not found of contents empty`);
// return;
// }
// patch.contents = patchContents;
// }
const change: Change = {
type: 'revision',
repository: {
name: repository.name,
path: repository.path,
uri: repository.uri.toString(),
},
files: undefined!,
revision: { to: to, from: args.from ?? `${to}^` },
};
// if (patch == null) {
// void window.showErrorMessage(`Cannot open cloud patch: patch not found`);
// return;
// }
const create: CreateDraft = { changes: [change] };
void showPatchesView({ mode: 'view', draft: draft });
const commit = await container.git.getCommit(repository.uri, to);
if (commit == null) return undefined;
const message = commit.message!.trim();
const index = message.indexOf('\n');
if (index < 0) {
create.title = message;
} else {
create.title = message.substring(0, index);
create.description = message.substring(index + 1);
}
if (args.from == null) {
if (commit.files == null) return;
change.files = [...commit.files];
} else {
const diff = await container.git.getDiff(repository.uri, to, args.from);
if (diff == null) return;
const result = await container.git.getDiffFiles(repository.uri, diff.contents);
if (result?.files == null) return;
change.files = result.files;
create.title = `Comparing ${shortenRevision(args.to)} with ${shortenRevision(args.from)}`;
if (!isSha(args.to)) {
const commit = await container.git.getCommit(repository.uri, args.to);
if (commit != null) {
change.revision.to = commit.sha;
}
}
if (!isSha(args.from)) {
const commit = await container.git.getCommit(repository.uri, args.from);
if (commit != null) {
change.revision.from = commit.sha;
}
}
}
return create;
}

+ 18
- 18
src/env/node/git/localGitProvider.ts View File

@ -2955,38 +2955,38 @@ export class LocalGitProvider implements GitProvider, Disposable {
@log()
async getDiff(
repoPath: string,
ref1: string,
ref2?: string,
to: string,
from?: string,
options?: { context?: number },
): Promise<GitDiff | undefined> {
const scope = getLogScope();
const params = [`-U${options?.context ?? 3}`];
if (ref1 === uncommitted) {
if (ref2 != null) {
params.push(ref2);
if (to === uncommitted) {
if (from != null) {
params.push(from);
} else {
// Get only unstaged changes
ref2 = 'HEAD';
from = 'HEAD';
}
} else if (ref1 === uncommittedStaged) {
} else if (to === uncommittedStaged) {
params.push('--staged');
if (ref2 != null) {
params.push(ref2);
if (from != null) {
params.push(from);
} else {
// Get only staged changes
ref2 = 'HEAD';
from = 'HEAD';
}
} else if (ref2 == null) {
if (ref1 === '' || ref1.toUpperCase() === 'HEAD') {
ref2 = 'HEAD';
params.push(ref2);
} else if (from == null) {
if (to === '' || to.toUpperCase() === 'HEAD') {
from = 'HEAD';
params.push(from);
} else {
ref2 = ref1;
params.push(`${ref1}^`, ref2);
from = `${to}^`;
params.push(from, to);
}
} else {
params.push(ref1, ref2);
params.push(from, to);
}
let data;
@ -2998,7 +2998,7 @@ export class LocalGitProvider implements GitProvider, Disposable {
return undefined;
}
const diff: GitDiff = { baseSha: ref2, contents: data };
const diff: GitDiff = { contents: data, from: from, to: to };
return diff;
}

+ 31
- 46
src/git/actions/commit.ts View File

@ -22,6 +22,9 @@ import type { GitFile } from '../models/file';
import type { GitRevisionReference } from '../models/reference';
import { getReferenceFromRevision, isUncommitted, isUncommittedStaged } from '../models/reference';
type Ref = { repoPath: string; ref: string };
type RefRange = { repoPath: string; rhs: string; lhs: string };
export async function applyChanges(file: string | GitFile, rev1: GitRevisionReference, rev2?: GitRevisionReference) {
let create = false;
let ref1 = rev1.ref;
@ -58,11 +61,11 @@ export async function applyChanges(file: string | GitFile, rev1: GitRevisionRefe
}
}
export async function copyIdToClipboard(ref: { repoPath: string; ref: string } | GitCommit) {
export async function copyIdToClipboard(ref: Ref | GitCommit) {
await env.clipboard.writeText(ref.ref);
}
export async function copyMessageToClipboard(ref: { repoPath: string; ref: string } | GitCommit): Promise<void> {
export async function copyMessageToClipboard(ref: Ref | GitCommit): Promise<void> {
let commit;
if (isCommit(ref)) {
commit = ref;
@ -81,16 +84,16 @@ export async function copyMessageToClipboard(ref: { repoPath: string; ref: strin
export async function openAllChanges(commit: GitCommit, options?: TextDocumentShowOptions): Promise<void>;
export async function openAllChanges(
files: GitFile[],
refs: { repoPath: string; ref1: string; ref2: string },
refs: RefRange,
options?: TextDocumentShowOptions,
): Promise<void>;
export async function openAllChanges(
commitOrFiles: GitCommit | GitFile[],
refsOrOptions: { repoPath: string; ref1: string; ref2: string } | TextDocumentShowOptions | undefined,
refsOrOptions: RefRange | TextDocumentShowOptions | undefined,
options?: TextDocumentShowOptions,
) {
let files;
let refs;
let refs: RefRange | undefined;
if (isCommit(commitOrFiles)) {
if (commitOrFiles.files == null) {
await commitOrFiles.ensureFullDetails();
@ -99,15 +102,15 @@ export async function openAllChanges(
files = commitOrFiles.files ?? [];
refs = {
repoPath: commitOrFiles.repoPath,
rhs: commitOrFiles.sha,
// Don't need to worry about verifying the previous sha, as the DiffWith command will
ref1: commitOrFiles.unresolvedPreviousSha,
ref2: commitOrFiles.sha,
lhs: commitOrFiles.unresolvedPreviousSha,
};
options = refsOrOptions as TextDocumentShowOptions | undefined;
} else {
files = commitOrFiles;
refs = refsOrOptions as { repoPath: string; ref1: string; ref2: string };
refs = refsOrOptions as RefRange;
}
if (files.length > 10) {
@ -127,14 +130,8 @@ export async function openAllChanges(
}
export async function openAllChangesWithDiffTool(commit: GitCommit): Promise<void>;
export async function openAllChangesWithDiffTool(
files: GitFile[],
ref: { repoPath: string; ref: string },
): Promise<void>;
export async function openAllChangesWithDiffTool(
commitOrFiles: GitCommit | GitFile[],
ref?: { repoPath: string; ref: string },
) {
export async function openAllChangesWithDiffTool(files: GitFile[], ref: Ref): Promise<void>;
export async function openAllChangesWithDiffTool(commitOrFiles: GitCommit | GitFile[], ref?: Ref) {
let files;
if (isCommit(commitOrFiles)) {
if (commitOrFiles.files == null) {
@ -167,12 +164,12 @@ export async function openAllChangesWithDiffTool(
export async function openAllChangesWithWorking(commit: GitCommit, options?: TextDocumentShowOptions): Promise<void>;
export async function openAllChangesWithWorking(
files: GitFile[],
ref: { repoPath: string; ref: string },
ref: Ref,
options?: TextDocumentShowOptions,
): Promise<void>;
export async function openAllChangesWithWorking(
commitOrFiles: GitCommit | GitFile[],
refOrOptions: { repoPath: string; ref: string } | TextDocumentShowOptions | undefined,
refOrOptions: Ref | TextDocumentShowOptions | undefined,
options?: TextDocumentShowOptions,
) {
let files;
@ -191,7 +188,7 @@ export async function openAllChangesWithWorking(
options = refOrOptions as TextDocumentShowOptions | undefined;
} else {
files = commitOrFiles;
ref = refOrOptions as { repoPath: string; ref: string };
ref = refOrOptions as Ref;
}
if (files.length > 10) {
@ -217,17 +214,17 @@ export async function openChanges(
): Promise<void>;
export async function openChanges(
file: GitFile,
refs: { repoPath: string; ref1: string; ref2: string },
refs: RefRange,
options?: TextDocumentShowOptions & { lhsTitle?: string; rhsTitle?: string },
): Promise<void>;
export async function openChanges(
file: GitFile,
commitOrRefs: GitCommit | { repoPath: string; ref1: string; ref2: string },
commitOrRefs: GitCommit | RefRange,
options?: TextDocumentShowOptions & { lhsTitle?: string; rhsTitle?: string },
): Promise<void>;
export async function openChanges(
file: string | GitFile,
commitOrRefs: GitCommit | { repoPath: string; ref1: string; ref2: string },
commitOrRefs: GitCommit | RefRange,
options?: TextDocumentShowOptions & { lhsTitle?: string; rhsTitle?: string },
) {
const isArgCommit = isCommit(commitOrRefs);
@ -253,38 +250,30 @@ export async function openChanges(
return;
}
const refs = isArgCommit
const refs: RefRange = isArgCommit
? {
repoPath: commitOrRefs.repoPath,
rhs: commitOrRefs.sha,
// Don't need to worry about verifying the previous sha, as the DiffWith command will
ref1: commitOrRefs.unresolvedPreviousSha,
ref2: commitOrRefs.sha,
lhs: commitOrRefs.unresolvedPreviousSha,
}
: commitOrRefs;
const rhsUri = GitUri.fromFile(file, refs.repoPath);
const lhsUri =
file.status === 'R' || file.status === 'C' ? GitUri.fromFile(file, refs.repoPath, refs.ref1, true) : rhsUri;
file.status === 'R' || file.status === 'C' ? GitUri.fromFile(file, refs.repoPath, refs.lhs, true) : rhsUri;
void (await executeCommand<DiffWithCommandArgs>(Commands.DiffWith, {
repoPath: refs.repoPath,
lhs: { uri: lhsUri, sha: refs.ref1, title: options?.lhsTitle },
rhs: { uri: rhsUri, sha: refs.ref2, title: options?.rhsTitle },
lhs: { uri: lhsUri, sha: refs.lhs, title: options?.lhsTitle },
rhs: { uri: rhsUri, sha: refs.rhs, title: options?.rhsTitle },
showOptions: options,
}));
}
export function openChangesWithDiffTool(file: string | GitFile, commit: GitCommit, tool?: string): Promise<void>;
export function openChangesWithDiffTool(
file: GitFile,
ref: { repoPath: string; ref: string },
tool?: string,
): Promise<void>;
export async function openChangesWithDiffTool(
file: string | GitFile,
commitOrRef: GitCommit | { repoPath: string; ref: string },
tool?: string,
) {
export function openChangesWithDiffTool(file: GitFile, ref: Ref, tool?: string): Promise<void>;
export async function openChangesWithDiffTool(file: string | GitFile, commitOrRef: GitCommit | Ref, tool?: string) {
if (typeof file === 'string') {
if (!isCommit(commitOrRef)) throw new Error('Invalid arguments');
@ -313,12 +302,12 @@ export async function openChangesWithWorking(
): Promise<void>;
export async function openChangesWithWorking(
file: GitFile,
ref: { repoPath: string; ref: string },
ref: Ref,
options?: TextDocumentShowOptions & { lhsTitle?: string },
): Promise<void>;
export async function openChangesWithWorking(
file: string | GitFile,
commitOrRef: GitCommit | { repoPath: string; ref: string },
commitOrRef: GitCommit | Ref,
options?: TextDocumentShowOptions & { lhsTitle?: string },
) {
if (typeof file === 'string') {
@ -360,15 +349,11 @@ export async function openDirectoryCompare(
return Container.instance.git.openDirectoryCompare(repoPath, ref, ref2, tool);
}
export async function openDirectoryCompareWithPrevious(
ref: { repoPath: string; ref: string } | GitCommit,
): Promise<void> {
export async function openDirectoryCompareWithPrevious(ref: Ref | GitCommit): Promise<void> {
return openDirectoryCompare(ref.repoPath, ref.ref, `${ref.ref}^`);
}
export async function openDirectoryCompareWithWorking(
ref: { repoPath: string; ref: string } | GitCommit,
): Promise<void> {
export async function openDirectoryCompareWithWorking(ref: Ref | GitCommit): Promise<void> {
return openDirectoryCompare(ref.repoPath, ref.ref, undefined);
}

+ 2
- 2
src/git/gitProvider.ts View File

@ -285,8 +285,8 @@ export interface GitProvider extends Disposable {
getDefaultBranchName(repoPath: string | undefined, remote?: string): Promise<string | undefined>;
getDiff?(
repoPath: string | Uri,
ref1: string,
ref2?: string,
to: string,
from?: string,
options?: { context?: number },
): Promise<GitDiff | undefined>;
getDiffFiles?(repoPath: string | Uri, contents: string): Promise<GitDiffFiles | undefined>;

+ 3
- 3
src/git/gitProviderService.ts View File

@ -1834,12 +1834,12 @@ export class GitProviderService implements Disposable {
@log()
async getDiff(
repoPath: string | Uri,
ref1: string,
ref2?: string,
to: string,
from?: string,
options?: { context?: number },
): Promise<GitDiff | undefined> {
const { provider, path } = this.getProvider(repoPath);
return provider.getDiff?.(path, ref1, ref2, options);
return provider.getDiff?.(path, to, from, options);
}
@log({ args: { 1: false } })

+ 2
- 1
src/git/models/diff.ts View File

@ -1,8 +1,9 @@
import type { GitFileChange } from './file';
export interface GitDiff {
readonly baseSha: string;
readonly contents: string;
readonly from: string;
readonly to: string;
}
export interface GitDiffHunkLine {

+ 5
- 5
src/git/models/patch.ts View File

@ -4,13 +4,13 @@ import type { GitDiffFiles } from './diff';
import type { Repository } from './repository';
/**
* For a single commit `sha` is the commit SHA and `baseSha` is its parent `<sha>^`
* For a commit range `sha` is the tip SHA and `baseSha` is the base SHA
* For a WIP `sha` is the "uncommitted" SHA and `baseSha` is the current HEAD SHA
* For a single commit `to` is the commit SHA and `from` is its parent `<sha>^`
* For a commit range `to` is the tip SHA and `from` is the base SHA
* For a WIP `to` is the "uncommitted" SHA and `from` is the current HEAD SHA
*/
export interface PatchRevisionRange {
baseSha: string;
sha: string;
from: string;
to: string;
}
export interface GitPatch {

+ 12
- 13
src/plus/drafts/draftsService.ts View File

@ -212,18 +212,20 @@ export class DraftService implements Disposable {
private async getCreateDraftPatchRequestFromChange(
change: CreateDraftChange,
): Promise<CreateDraftPatchRequestFromChange> {
const isWIP = isUncommitted(change.revision.sha);
const isWIP = isUncommitted(change.revision.to);
const [branchNamesResult, diffResult, firstShaResult, remoteResult, userResult] = await Promise.allSettled([
isWIP
? this.container.git.getBranch(change.repository.uri).then(b => (b != null ? [b.name] : undefined))
: this.container.git.getCommitBranches(change.repository.uri, change.revision.sha),
: this.container.git
.getCommitBranches(change.repository.uri, change.revision.to)
.then(branches =>
branches.length
? branches
: this.container.git.getCommitBranches(change.repository.uri, change.revision.from),
),
change.contents == null
? this.container.git.getDiff(
change.repository.path,
isWIP ? change.revision.sha : change.revision.baseSha,
isWIP ? change.revision.baseSha : change.revision.sha,
)
? this.container.git.getDiff(change.repository.path, change.revision.to, change.revision.from)
: undefined,
this.container.git.getFirstCommitSha(change.repository.uri),
this.container.git.getBestRemoteWithProvider(change.repository.uri),
@ -263,18 +265,15 @@ export class DraftService implements Disposable {
const diff = getSettledValue(diffResult);
const contents = change.contents ?? diff?.contents;
if (contents == null) throw new Error(`Unable to diff ${change.revision.baseSha} and ${change.revision.sha}`);
if (contents == null) throw new Error(`Unable to diff ${change.revision.from} and ${change.revision.to}`);
const user = getSettledValue(userResult);
// We need to get the branch name from the baseSha if the change is a stash.
let branchNames = getSettledValue(branchNamesResult);
if (!isWIP && !branchNames?.length) {
branchNames = await this.container.git.getCommitBranches(change.repository.uri, change.revision.baseSha);
}
const branchNames = getSettledValue(branchNamesResult);
const branchName = branchNames?.[0] ?? '';
let baseSha = change.revision.baseSha;
let baseSha = change.revision.from;
if (!isSha(baseSha)) {
const commit = await this.container.git.getCommit(change.repository.uri, baseSha);
if (commit != null) {

+ 1
- 1
src/plus/webviews/graph/graphWebview.ts View File

@ -2443,7 +2443,7 @@ export class GraphWebviewProvider implements WebviewProvider
if (ref == null) return Promise.resolve();
return executeCommand<CreatePatchCommandArgs>(Commands.CreateCloudPatch, {
ref1: ref.ref,
to: ref.ref,
repoPath: ref.repoPath,
});
}

+ 18
- 22
src/plus/webviews/patchDetails/patchDetailsWebview.ts View File

@ -34,6 +34,7 @@ import type { ShowInCommitGraphCommandArgs } from '../graph/protocol';
import type {
ApplyPatchParams,
Change,
CreateDraft,
CreatePatchParams,
DidExplainParams,
DraftPatchCheckedParams,
@ -67,7 +68,7 @@ import {
UpdateCreatePatchRepositoryCheckedStateCommandType,
UpdatePreferencesCommandType,
} from './protocol';
import type { CreateDraft, PatchDetailsWebviewShowingArgs } from './registration';
import type { PatchDetailsWebviewShowingArgs } from './registration';
import type { RepositoryChangeset } from './repositoryChangeset';
import { RepositoryRefChangeset, RepositoryWipChangeset } from './repositoryChangeset';
@ -289,7 +290,7 @@ export class PatchDetailsWebviewProvider
new RepositoryWipChangeset(
this.container,
repo,
{ baseSha: 'HEAD', sha: uncommitted },
{ to: uncommitted, from: 'HEAD' },
this.onRepositoryWipChanged.bind(this),
false,
true,
@ -427,7 +428,7 @@ export class PatchDetailsWebviewProvider
let { revision, repository } = repoChangeset;
if (change.type === 'wip' && change.checked === 'staged') {
revision = { ...revision, sha: uncommittedStaged };
revision = { ...revision, to: uncommittedStaged };
}
createChanges.push({
@ -676,10 +677,7 @@ export class PatchDetailsWebviewProvider
new RepositoryWipChangeset(
this.container,
r,
{
baseSha: 'HEAD',
sha: uncommitted,
},
{ to: uncommitted, from: 'HEAD' },
this.onRepositoryWipChanged.bind(this),
true,
true, // TODO revisit
@ -934,17 +932,19 @@ export class PatchDetailsWebviewProvider
if (change == null) return [undefined];
if (change.type === 'revision') {
const commit = await this.container.git.getCommit(file.repoPath, change.revision.sha ?? uncommitted);
const commit = await this.container.git.getCommit(file.repoPath, change.revision.to ?? uncommitted);
if (
change.revision.sha === change.revision.baseSha ||
change.revision.sha === change.revision.baseSha.substring(0, change.revision.baseSha.length - 1)
change.revision.to === change.revision.from ||
(change.revision.from.length === change.revision.to.length + 1 &&
change.revision.from.endsWith('^') &&
change.revision.from.startsWith(change.revision.to))
) {
return [commit];
}
return [commit, change.revision];
} else if (change.type === 'wip') {
return [await this.container.git.getCommit(file.repoPath, change.revision.sha ?? uncommitted)];
return [await this.container.git.getCommit(file.repoPath, change.revision.to ?? uncommitted)];
}
return [undefined];
@ -1010,7 +1010,7 @@ export class PatchDetailsWebviewProvider
void openChanges(
file,
revision != null
? { repoPath: commit.repoPath, ref1: revision.sha ?? uncommitted, ref2: revision.baseSha }
? { repoPath: commit.repoPath, rhs: revision.to ?? uncommitted, lhs: revision.from }
: commit,
{
preserveFocus: true,
@ -1028,15 +1028,11 @@ export class PatchDetailsWebviewProvider
const [commit, file, revision] = result;
void openChangesWithWorking(
file,
revision != null ? { repoPath: commit.repoPath, ref: revision.baseSha } : commit,
{
preserveFocus: true,
preview: true,
...params.showOptions,
lhsTitle: this.mode === 'view' ? `${basename(file.path)} (Patch)` : undefined,
},
);
void openChangesWithWorking(file, revision != null ? { repoPath: commit.repoPath, ref: revision.to } : commit, {
preserveFocus: true,
preview: true,
...params.showOptions,
lhsTitle: this.mode === 'view' ? `${basename(file.path)} (Patch)` : undefined,
});
}
}

+ 19
- 1
src/plus/webviews/patchDetails/protocol.ts View File

@ -3,7 +3,8 @@ import type { Config } from '../../../config';
import type { WebviewIds, WebviewViewIds } from '../../../constants';
import type { GitFileChangeShape } from '../../../git/models/file';
import type { PatchRevisionRange } from '../../../git/models/patch';
import type { DraftPatch, DraftPatchFileChange } from '../../../gk/models/drafts';
import type { Repository } from '../../../git/models/repository';
import type { Draft, DraftPatch, DraftPatchFileChange, LocalDraft } from '../../../gk/models/drafts';
import type { GkRepositoryId } from '../../../gk/models/repositoryIdentities';
import type { DateTimeFormat } from '../../../system/date';
import type { Serialized } from '../../../system/serialize';
@ -19,6 +20,23 @@ export type PatchDetails = Serialized<
}
>;
interface CreateDraftFromChanges {
title?: string;
description?: string;
changes: Change[];
repositories?: never;
}
interface CreateDraftFromRepositories {
title?: string;
description?: string;
changes?: never;
repositories: Repository[] | undefined;
}
export type CreateDraft = CreateDraftFromChanges | CreateDraftFromRepositories;
export type ViewDraft = LocalDraft | Draft;
interface LocalDraftDetails {
draftType: 'local';

+ 1
- 20
src/plus/webviews/patchDetails/registration.ts View File

@ -1,30 +1,11 @@
import { ViewColumn } from 'vscode';
import { Commands } from '../../../constants';
import type { DraftSelectedEvent } from '../../../eventBus';
import type { Repository } from '../../../git/models/repository';
import { executeCommand } from '../../../system/command';
import { configuration } from '../../../system/configuration';
import { setContext } from '../../../system/context';
import type { Serialized } from '../../../system/serialize';
import type { WebviewPanelShowCommandArgs, WebviewsController } from '../../../webviews/webviewsController';
import type { Change, State } from './protocol';
interface CreateDraftFromChanges {
title?: string;
description?: string;
changes: Change[];
repositories?: never;
}
interface CreateDraftFromRepositories {
title?: string;
description?: string;
changes?: never;
repositories: Repository[] | undefined;
}
export type CreateDraft = CreateDraftFromChanges | CreateDraftFromRepositories;
export type ViewDraft = DraftSelectedEvent['data']['draft'];
import type { CreateDraft, State, ViewDraft } from './protocol';
export type ShowCreateDraft = {
mode: 'create';

+ 2
- 2
src/views/viewCommands.ts View File

@ -1067,8 +1067,8 @@ export class ViewCommands {
diff,
{
repoPath: node.repoPath,
ref1: node.ref1,
ref2: node.ref2,
lhs: node.ref1,
rhs: node.ref2,
},
options,
);

+ 1
- 4
src/webviews/commitDetails/commitDetailsWebview.ts View File

@ -504,10 +504,7 @@ export class CommitDetailsWebviewProvider
uri: e.changes.repository.uri,
},
files: e.changes.files,
revision: {
baseSha: 'HEAD',
sha: uncommitted,
},
revision: { to: uncommitted, from: 'HEAD' },
checked: e.checked,
};

Loading…
Cancel
Save