Browse Source

Continues refinement of the commit quickpicks

main
Eric Amodio 2 years ago
parent
commit
17c1e42614
2 changed files with 105 additions and 70 deletions
  1. +76
    -59
      src/commands/quickCommand.steps.ts
  2. +29
    -11
      src/quickpicks/commitQuickPickItems.ts

+ 76
- 59
src/commands/quickCommand.steps.ts View File

@ -12,6 +12,7 @@ import {
GitContributor,
GitLog,
GitReference,
GitRemote,
GitRevision,
GitRevisionReference,
GitStash,
@ -62,7 +63,9 @@ import {
RepositoryQuickPickItem,
TagQuickPickItem,
} from '../quickpicks';
import { Arrays, Iterables, Strings } from '../system';
import { filterMap, intersection, isStringArray } from '../system/array';
import { map } from '../system/iterable';
import { pad, pluralize, truncate } from '../system/string';
import { ViewsWithRepositoryFolders } from '../views/viewBase';
import { Commands } from './common';
import { GitActions } from './gitCommands.actions';
@ -83,25 +86,23 @@ export function appendReposToTitle<
Context extends { repos: Repository[] },
>(title: string, state: State, context: Context, additionalContext?: string) {
if (context.repos.length === 1) {
return `${title}${Strings.truncate(additionalContext ?? '', quickPickTitleMaxChars - title.length)}`;
return `${title}${truncate(additionalContext ?? '', quickPickTitleMaxChars - title.length)}`;
}
let repoContext;
if ((state as { repo: Repository }).repo != null) {
repoContext = `${additionalContext ?? ''}${Strings.pad(GlyphChars.Dot, 2, 2)}${
repoContext = `${additionalContext ?? ''}${pad(GlyphChars.Dot, 2, 2)}${
(state as { repo: Repository }).repo.formattedName
}`;
} else if ((state as { repos: Repository[] }).repos.length === 1) {
repoContext = `${additionalContext ?? ''}${Strings.pad(GlyphChars.Dot, 2, 2)}${
repoContext = `${additionalContext ?? ''}${pad(GlyphChars.Dot, 2, 2)}${
(state as { repos: Repository[] }).repos[0].formattedName
}`;
} else {
repoContext = `${Strings.pad(GlyphChars.Dot, 2, 2)}${
(state as { repos: Repository[] }).repos.length
} repositories`;
repoContext = `${pad(GlyphChars.Dot, 2, 2)}${(state as { repos: Repository[] }).repos.length} repositories`;
}
return `${title}${Strings.truncate(repoContext, quickPickTitleMaxChars - title.length)}`;
return `${title}${truncate(repoContext, quickPickTitleMaxChars - title.length)}`;
}
export async function getBranches(
@ -213,12 +214,12 @@ export async function getBranchesAndOrTags(
if (include.includes('branches') && branchesByRepo != null) {
branches = GitBranch.sort(
Arrays.intersection(...branchesByRepo, (b1: GitBranch, b2: GitBranch) => b1.name === b2.name),
intersection(...branchesByRepo, (b1: GitBranch, b2: GitBranch) => b1.name === b2.name),
);
}
if (include.includes('tags') && tagsByRepo != null) {
tags = GitTag.sort(Arrays.intersection(...tagsByRepo, (t1: GitTag, t2: GitTag) => t1.name === t2.name));
tags = GitTag.sort(intersection(...tagsByRepo, (t1: GitTag, t2: GitTag) => t1.name === t2.name));
}
}
@ -865,7 +866,7 @@ export async function* pickCommitStep<
return log == null
? [DirectiveQuickPickItem.create(Directive.Back, true), DirectiveQuickPickItem.create(Directive.Cancel)]
: [
...Iterables.map(log.commits.values(), commit =>
...map(log.commits.values(), commit =>
CommitQuickPickItem.create(
commit,
picked != null &&
@ -1014,7 +1015,7 @@ export function* pickCommitsStep<
return log == null
? [DirectiveQuickPickItem.create(Directive.Back, true), DirectiveQuickPickItem.create(Directive.Cancel)]
: [
...Iterables.map(log.commits.values(), commit =>
...map(log.commits.values(), commit =>
CommitQuickPickItem.create(
commit,
picked != null &&
@ -1210,8 +1211,8 @@ export async function* pickRepositoriesStep<
let actives: Repository[];
if (state.repos != null) {
if (Arrays.isStringArray(state.repos)) {
actives = Arrays.filterMap(state.repos, path => context.repos.find(r => r.path === path));
if (isStringArray(state.repos)) {
actives = filterMap(state.repos, path => context.repos.find(r => r.path === path));
if (options.skipIfPossible && actives.length !== 0 && state.repos.length === actives.length) {
return actives;
}
@ -1298,7 +1299,7 @@ export function* pickStashStep<
stash == null
? [DirectiveQuickPickItem.create(Directive.Back, true), DirectiveQuickPickItem.create(Directive.Cancel)]
: [
...Iterables.map(stash.commits.values(), commit =>
...map(stash.commits.values(), commit =>
CommitQuickPickItem.create(
commit,
picked != null &&
@ -1463,11 +1464,11 @@ export async function* showCommitOrStashStep<
async function getShowCommitOrStashStepItems<
State extends PartialStepState & { repo: Repository; reference: GitCommit | GitStashCommit },
>(state: State): Promise<CommandQuickPickItem[]> {
const items: (CommandQuickPickItem | QuickPickSeparator)[] = [new CommitFilesQuickPickItem(state.reference)];
const items: (CommandQuickPickItem | QuickPickSeparator)[] = [];
if (GitCommit.isStash(state.reference)) {
items.push(QuickPickSeparator.create(), new CommitCopyMessageQuickPickItem(state.reference));
let unpublished: boolean | undefined;
if (GitCommit.isStash(state.reference)) {
items.push(
QuickPickSeparator.create('Actions'),
new GitCommandQuickPickItem('Apply Stash...', {
@ -1478,7 +1479,6 @@ async function getShowCommitOrStashStepItems<
reference: state.reference,
},
}),
new GitCommandQuickPickItem('Delete Stash...', {
command: 'stash',
state: {
@ -1487,12 +1487,15 @@ async function getShowCommitOrStashStepItems<
reference: state.reference,
},
}),
QuickPickSeparator.create(),
new CommitCopyMessageQuickPickItem(state.reference),
);
} else {
const remotes = await Container.instance.git.getRemotesWithProviders(state.repo.path, { sort: true });
if (remotes?.length) {
items.push(
QuickPickSeparator.create(),
QuickPickSeparator.create(GitRemote.getHighlanderProviderName(remotes) ?? 'Remote'),
new OpenRemoteResourceCommandQuickPickItem(remotes, {
type: RemoteResourceType.Commit,
sha: state.reference.sha,
@ -1504,26 +1507,22 @@ async function getShowCommitOrStashStepItems<
);
}
items.push(
QuickPickSeparator.create(),
new CommitCopyIdQuickPickItem(state.reference),
new CommitCopyMessageQuickPickItem(state.reference),
);
items.push(QuickPickSeparator.create('Actions'));
const branch = await Container.instance.git.getBranch(state.repo.path);
const branches =
const [branches, published] = await Promise.all([
branch != null
? await Container.instance.git.getCommitBranches(state.repo.path, state.reference.ref, {
? Container.instance.git.getCommitBranches(state.repo.path, state.reference.ref, {
branch: branch.name,
commitDate: GitCommit.is(state.reference) ? state.reference.committer.date : undefined,
})
: undefined;
const commitOnCurrentBranch = Boolean(branches?.length);
: undefined,
!branch?.remote && branch?.upstream != null ? state.reference.isPushed() : undefined,
]);
const commitOnCurrentBranch = Boolean(branches?.length);
if (commitOnCurrentBranch) {
items.push(QuickPickSeparator.create('Actions'));
const unpublished = !branch?.remote && branch?.upstream && !(await state.reference.isPushed());
unpublished = !published;
if (unpublished) {
// TODO@eamodio Add Undo commit, if HEAD & unpushed
@ -1592,9 +1591,7 @@ async function getShowCommitOrStashStepItems<
reference: state.reference,
},
}),
);
items.push(
QuickPickSeparator.create(),
new GitCommandQuickPickItem('Create Branch at Commit...', {
command: 'branch',
@ -1612,11 +1609,15 @@ async function getShowCommitOrStashStepItems<
reference: state.reference,
},
}),
QuickPickSeparator.create('Copy'),
new CommitCopyIdQuickPickItem(state.reference),
new CommitCopyMessageQuickPickItem(state.reference),
);
}
items.push(
QuickPickSeparator.create('Open Changes'),
QuickPickSeparator.create('Open'),
new CommitOpenAllChangesCommandQuickPickItem(state.reference),
new CommitOpenAllChangesWithWorkingCommandQuickPickItem(state.reference),
new CommitOpenAllChangesWithDiffToolCommandQuickPickItem(state.reference),
@ -1651,6 +1652,14 @@ async function getShowCommitOrStashStepItems<
}),
);
items.splice(
0,
0,
new CommitFilesQuickPickItem(state.reference, {
unpublished: unpublished,
hint: 'Click to see all changed files',
}),
);
return items as CommandQuickPickItem[];
}
@ -1682,11 +1691,15 @@ export function* showCommitOrStashFilesStep<
placeholder: GitReference.toString(state.reference, { capitalize: true, icon: false }),
ignoreFocusOut: true,
items: [
new CommitFilesQuickPickItem(state.reference, state.fileName == null),
new CommitFilesQuickPickItem(state.reference, {
picked: state.fileName == null,
hint: `Click to see ${GitCommit.isStash(state.reference) ? 'stash' : 'commit'} actions`,
}),
QuickPickSeparator.create('Files'),
...(state.reference.files?.map(
fs => new CommitFileQuickPickItem(state.reference, fs, options?.picked === fs.path),
) ?? []),
],
] as (CommitFilesQuickPickItem | CommitFileQuickPickItem)[],
matchOnDescription: true,
// additionalButtons: [QuickCommandButtons.RevealInSideBar, QuickCommandButtons.SearchInSideBar],
onDidClickItemButton: (quickpick, button, _item) => {
@ -1750,7 +1763,7 @@ export async function* showCommitOrStashFileStep<
}),
state,
context,
`${Strings.pad(GlyphChars.Dot, 2, 2)}${GitUri.getFormattedFileName(state.fileName)}`,
`${pad(GlyphChars.Dot, 2, 2)}${GitUri.getFormattedFileName(state.fileName)}`,
),
placeholder: `${GitUri.getFormattedPath(state.fileName, {
relativeTo: state.repo.path,
@ -1816,36 +1829,38 @@ async function getShowCommitOrStashFileStepItems<
const file = await state.reference.findFile(state.fileName);
if (file == null) return [];
const items: (CommandQuickPickItem | QuickPickSeparator)[] = [
new CommitFilesQuickPickItem(state.reference, undefined, GitUri.getFormattedFileName(state.fileName)),
];
const items: (CommandQuickPickItem | QuickPickSeparator)[] = [];
if (GitCommit.isStash(state.reference)) {
items.push(
QuickPickSeparator.create(),
new CommitCopyMessageQuickPickItem(state.reference),
QuickPickSeparator.create('Actions'),
new CommitApplyFileChangesCommandQuickPickItem(state.reference, file),
new CommitRestoreFileChangesCommandQuickPickItem(state.reference, file),
QuickPickSeparator.create(),
new CommitCopyMessageQuickPickItem(state.reference),
);
} else {
const remotes = await Container.instance.git.getRemotesWithProviders(state.repo.path, { sort: true });
if (remotes?.length) {
items.push(
QuickPickSeparator.create(),
QuickPickSeparator.create(GitRemote.getHighlanderProviderName(remotes) ?? 'Remote'),
new OpenRemoteResourceCommandQuickPickItem(remotes, {
type: RemoteResourceType.Revision,
fileName: state.fileName,
commit: state.reference,
}),
new OpenRemoteResourceCommandQuickPickItem(remotes, {
type: RemoteResourceType.Commit,
sha: state.reference.ref,
}),
QuickPickSeparator.create(),
new CopyRemoteResourceCommandQuickPickItem(remotes, {
type: RemoteResourceType.Revision,
fileName: state.fileName,
commit: state.reference,
}),
QuickPickSeparator.create(),
new OpenRemoteResourceCommandQuickPickItem(remotes, {
type: RemoteResourceType.Commit,
sha: state.reference.ref,
}),
new CopyRemoteResourceCommandQuickPickItem(remotes, {
type: RemoteResourceType.Commit,
sha: state.reference.sha,
@ -1854,20 +1869,17 @@ async function getShowCommitOrStashFileStepItems<
}
items.push(
QuickPickSeparator.create(),
QuickPickSeparator.create('Actions'),
new CommitApplyFileChangesCommandQuickPickItem(state.reference, file),
new CommitRestoreFileChangesCommandQuickPickItem(state.reference, file),
QuickPickSeparator.create('Copy'),
new CommitCopyIdQuickPickItem(state.reference),
new CommitCopyMessageQuickPickItem(state.reference),
QuickPickSeparator.create('Actions'),
);
}
items.push(
new CommitApplyFileChangesCommandQuickPickItem(state.reference, file),
new CommitRestoreFileChangesCommandQuickPickItem(state.reference, file),
);
items.push(
QuickPickSeparator.create('Open Changes'),
QuickPickSeparator.create('Open'),
new CommitOpenChangesCommandQuickPickItem(state.reference, state.fileName),
new CommitOpenChangesWithWorkingCommandQuickPickItem(state.reference, state.fileName),
new CommitOpenChangesWithDiffToolCommandQuickPickItem(state.reference, state.fileName),
@ -1899,6 +1911,11 @@ async function getShowCommitOrStashFileStepItems<
}),
);
items.splice(
0,
0,
new CommitFilesQuickPickItem(state.reference, { file: file, hint: 'Click to see all changed files' }),
);
return items as CommandQuickPickItem[];
}
@ -1937,10 +1954,10 @@ function getShowRepositoryStatusStepItems<
workingTreeStatus = 'No working tree changes';
} else {
workingTreeStatus = `$(files) ${
computed.staged ? `${Strings.pluralize('staged file', computed.staged)} (${computed.stagedStatus})` : ''
computed.staged ? `${pluralize('staged file', computed.staged)} (${computed.stagedStatus})` : ''
}${
computed.unstaged
? `${computed.staged ? ', ' : ''}${Strings.pluralize('unstaged file', computed.unstaged)} (${
? `${computed.staged ? ', ' : ''}${pluralize('unstaged file', computed.unstaged)} (${
computed.unstagedStatus
})`
: ''
@ -1981,7 +1998,7 @@ function getShowRepositoryStatusStepItems<
if (context.status.state.behind !== 0) {
items.push(
new GitCommandQuickPickItem(
`$(cloud-download) ${Strings.pluralize('commit', context.status.state.behind)} behind`,
`$(cloud-download) ${pluralize('commit', context.status.state.behind)} behind`,
{
command: 'log',
state: {
@ -1999,7 +2016,7 @@ function getShowRepositoryStatusStepItems<
if (context.status.state.ahead !== 0) {
items.push(
new GitCommandQuickPickItem(
`$(cloud-upload) ${Strings.pluralize('commit', context.status.state.ahead)} ahead`,
`$(cloud-upload) ${pluralize('commit', context.status.state.ahead)} ahead`,
{
command: 'log',
state: {

+ 29
- 11
src/quickpicks/commitQuickPickItems.ts View File

@ -4,25 +4,43 @@ import { QuickCommandButtons } from '../commands/quickCommand.buttons';
import { GlyphChars } from '../constants';
import { Container } from '../container';
import { CommitFormatter } from '../git/formatters';
import { GitCommit, GitFile, GitStatusFile } from '../git/models';
import { GitCommit, GitFile, GitFileChange, GitStatusFile } from '../git/models';
import { Keys } from '../keyboard';
import { Strings } from '../system';
import { basename } from '../system/path';
import { pad } from '../system/string';
import { CommandQuickPickItem } from './quickPicksItems';
export class CommitFilesQuickPickItem extends CommandQuickPickItem {
constructor(readonly commit: GitCommit, picked: boolean = true, fileName?: string) {
constructor(
readonly commit: GitCommit,
options?: {
file?: GitFileChange;
unpublished?: boolean | undefined;
picked?: boolean;
hint?: string;
},
) {
super(
{
label: commit.summary,
description: CommitFormatter.fromTemplate(`\${author}, \${ago} $(git-commit) \${id}`, commit),
detail: `$(files) ${commit.formatStats({
expand: true,
separator: ', ',
empty: 'No files changed',
})}${fileName ? `${Strings.pad(GlyphChars.Dot, 2, 2)}${fileName}` : ''}`,
description: `${CommitFormatter.fromTemplate(`\${author}, \${ago} $(git-commit) \${id}`, commit)}${
options?.unpublished ? ' (unpublished)' : ''
}`,
detail: `${
options?.file != null
? `$(file) ${basename(options.file.path)}${options.file.formatStats({
expand: true,
separator: ', ',
prefix: ` ${GlyphChars.Dot} `,
})}`
: `$(files) ${commit.formatStats({
expand: true,
separator: ', ',
empty: 'No files changed',
})}`
}${options?.hint != null ? `${pad(GlyphChars.Dash, 4, 2, GlyphChars.Space)}${options.hint}` : ''}`,
alwaysShow: true,
picked: picked,
picked: options?.picked ?? true,
buttons: GitCommit.isStash(commit)
? [QuickCommandButtons.RevealInSideBar]
: [QuickCommandButtons.RevealInSideBar, QuickCommandButtons.SearchInSideBar],
@ -41,7 +59,7 @@ export class CommitFilesQuickPickItem extends CommandQuickPickItem {
export class CommitFileQuickPickItem extends CommandQuickPickItem {
constructor(readonly commit: GitCommit, readonly file: GitFile, picked?: boolean) {
super({
label: `${Strings.pad(GitFile.getStatusCodicon(file.status), 0, 2)}${basename(file.path)}`,
label: `${pad(GitFile.getStatusCodicon(file.status), 0, 2)}${basename(file.path)}`,
description: GitFile.getFormattedDirectory(file, true),
picked: picked,
});

Loading…
Cancel
Save