Browse Source

Reorganizes commit quick pick menus

Adds separators to better group commands
Adds isPushed to commits
main
Eric Amodio 2 years ago
parent
commit
454893f950
12 changed files with 330 additions and 202 deletions
  1. +229
    -172
      src/commands/quickCommand.steps.ts
  2. +17
    -7
      src/env/node/git/git.ts
  3. +7
    -0
      src/env/node/git/localGitProvider.ts
  4. +26
    -6
      src/env/node/git/shell.ts
  5. +1
    -0
      src/git/gitProvider.ts
  6. +8
    -0
      src/git/gitProviderService.ts
  7. +4
    -0
      src/git/models/commit.ts
  8. +6
    -0
      src/premium/github/githubGitProvider.ts
  9. +7
    -2
      src/quickpicks/commitQuickPickItems.ts
  10. +13
    -13
      src/quickpicks/gitQuickPickItems.ts
  11. +11
    -1
      src/quickpicks/quickPicksItems.ts
  12. +1
    -1
      src/quickpicks/remoteProviderPicker.ts

+ 229
- 172
src/commands/quickCommand.steps.ts View File

@ -12,7 +12,6 @@ import {
GitContributor,
GitLog,
GitReference,
GitRemote,
GitRevision,
GitRevisionReference,
GitStash,
@ -23,7 +22,7 @@ import {
Repository,
TagSortOptions,
} from '../git/models';
import { RemoteProvider, RemoteResourceType } from '../git/remotes/provider';
import { RemoteResourceType } from '../git/remotes/provider';
import { SearchPattern } from '../git/search';
import {
BranchQuickPickItem,
@ -57,6 +56,7 @@ import {
GitCommandQuickPickItem,
OpenChangedFilesCommandQuickPickItem,
OpenRemoteResourceCommandQuickPickItem,
QuickPickSeparator,
ReferencesQuickPickItem,
RefQuickPickItem,
RepositoryQuickPickItem,
@ -227,54 +227,79 @@ export async function getBranchesAndOrTags(
if ((branches == null || branches.length === 0) && (tags == null || tags.length === 0)) return [];
if (branches != null && branches.length !== 0 && (tags == null || tags.length === 0)) {
return Promise.all(
branches.map(b =>
BranchQuickPickItem.create(
b,
picked != null && (typeof picked === 'string' ? b.ref === picked : picked.includes(b.ref)),
{
buttons: buttons,
current: singleRepo ? 'checkmark' : false,
ref: singleRepo,
status: singleRepo,
type: 'remote',
},
),
),
);
return [
QuickPickSeparator.create('Branches'),
...(await Promise.all(
branches
.filter(b => !b.remote)
.map(b =>
BranchQuickPickItem.create(
b,
picked != null && (typeof picked === 'string' ? b.ref === picked : picked.includes(b.ref)),
{
buttons: buttons,
current: singleRepo ? 'checkmark' : false,
ref: singleRepo,
status: singleRepo,
type: 'remote',
},
),
),
)),
QuickPickSeparator.create('Remote Branches'),
...(await Promise.all(
branches
.filter(b => b.remote)
.map(b =>
BranchQuickPickItem.create(
b,
picked != null && (typeof picked === 'string' ? b.ref === picked : picked.includes(b.ref)),
{
buttons: buttons,
current: singleRepo ? 'checkmark' : false,
ref: singleRepo,
status: singleRepo,
type: 'remote',
},
),
),
)),
] as BranchQuickPickItem[];
}
if (tags != null && tags.length !== 0 && (branches == null || branches.length === 0)) {
return Promise.all(
tags.map(t =>
TagQuickPickItem.create(
t,
picked != null && (typeof picked === 'string' ? t.ref === picked : picked.includes(t.ref)),
{
buttons: buttons,
message: false, //singleRepo,
ref: singleRepo,
},
),
return tags.map(t =>
TagQuickPickItem.create(
t,
picked != null && (typeof picked === 'string' ? t.ref === picked : picked.includes(t.ref)),
{
buttons: buttons,
message: false, //singleRepo,
ref: singleRepo,
},
),
);
}
return Promise.all<BranchQuickPickItem | TagQuickPickItem>([
...branches!
.filter(b => !b.remote)
.map(b =>
BranchQuickPickItem.create(
b,
picked != null && (typeof picked === 'string' ? b.ref === picked : picked.includes(b.ref)),
{
buttons: buttons,
current: singleRepo ? 'checkmark' : false,
ref: singleRepo,
status: singleRepo,
},
return [
QuickPickSeparator.create('Branches'),
...(await Promise.all(
branches!
.filter(b => !b.remote)
.map(b =>
BranchQuickPickItem.create(
b,
picked != null && (typeof picked === 'string' ? b.ref === picked : picked.includes(b.ref)),
{
buttons: buttons,
current: singleRepo ? 'checkmark' : false,
ref: singleRepo,
status: singleRepo,
},
),
),
),
)),
QuickPickSeparator.create('Tags'),
...tags!.map(t =>
TagQuickPickItem.create(
t,
@ -287,22 +312,25 @@ export async function getBranchesAndOrTags(
},
),
),
...branches!
.filter(b => b.remote)
.map(b =>
BranchQuickPickItem.create(
b,
picked != null && (typeof picked === 'string' ? b.ref === picked : picked.includes(b.ref)),
{
buttons: buttons,
current: singleRepo ? 'checkmark' : false,
ref: singleRepo,
status: singleRepo,
type: 'remote',
},
QuickPickSeparator.create('Remote Branches'),
...(await Promise.all(
branches!
.filter(b => b.remote)
.map(b =>
BranchQuickPickItem.create(
b,
picked != null && (typeof picked === 'string' ? b.ref === picked : picked.includes(b.ref)),
{
buttons: buttons,
current: singleRepo ? 'checkmark' : false,
ref: singleRepo,
status: singleRepo,
type: 'remote',
},
),
),
),
]);
)),
] as (BranchQuickPickItem | TagQuickPickItem)[];
}
export function getValidateGitReferenceFn(
@ -1386,10 +1414,10 @@ export async function* showCommitOrStashStep<
placeholder: GitReference.toString(state.reference, { capitalize: true, icon: false }),
ignoreFocusOut: true,
items: await getShowCommitOrStashStepItems(state),
additionalButtons: GitReference.isStash(state.reference)
? [QuickCommandButtons.RevealInSideBar]
: [QuickCommandButtons.RevealInSideBar, QuickCommandButtons.SearchInSideBar],
onDidClickButton: (quickpick, button) => {
// additionalButtons: GitReference.isStash(state.reference)
// ? [QuickCommandButtons.RevealInSideBar]
// : [QuickCommandButtons.RevealInSideBar, QuickCommandButtons.SearchInSideBar],
onDidClickItemButton: (quickpick, button, _item) => {
if (button === QuickCommandButtons.SearchInSideBar) {
void Container.instance.searchAndCompareView.search(
state.repo.path,
@ -1436,19 +1464,19 @@ export async function* showCommitOrStashStep<
async function getShowCommitOrStashStepItems<
State extends PartialStepState & { repo: Repository; reference: GitCommit | GitStashCommit },
>(state: State) {
const items: CommandQuickPickItem[] = [new CommitFilesQuickPickItem(state.reference)];
>(state: State): Promise<CommandQuickPickItem[]> {
const items: (CommandQuickPickItem | QuickPickSeparator)[] = [new CommitFilesQuickPickItem(state.reference)];
const branch = await Container.instance.git.getBranch(state.repo.path);
let remotes: GitRemote<RemoteProvider>[] | undefined;
let isStash = false;
if (GitCommit.isStash(state.reference)) {
isStash = true;
items.push(new RevealInSideBarQuickPickItem(state.reference));
items.push(
QuickPickSeparator.create(),
new RevealInSideBarQuickPickItem(state.reference),
QuickPickSeparator.create(),
new CommitCopyMessageQuickPickItem(state.reference),
);
items.push(
QuickPickSeparator.create('Actions'),
new GitCommandQuickPickItem('Apply Stash...', {
command: 'stash',
state: {
@ -1468,13 +1496,34 @@ async function getShowCommitOrStashStepItems<
}),
);
} else {
remotes = await Container.instance.git.getRemotesWithProviders(state.repo.path, { sort: true });
items.push(
QuickPickSeparator.create(),
new RevealInSideBarQuickPickItem(state.reference),
new SearchForCommitQuickPickItem(state.reference),
);
const remotes = await Container.instance.git.getRemotesWithProviders(state.repo.path, { sort: true });
if (remotes?.length) {
items.push(
QuickPickSeparator.create(),
new OpenRemoteResourceCommandQuickPickItem(remotes, {
type: RemoteResourceType.Commit,
sha: state.reference.sha,
}),
new CopyRemoteResourceCommandQuickPickItem(remotes, {
type: RemoteResourceType.Commit,
sha: state.reference.sha,
}),
);
}
items.push(
QuickPickSeparator.create(),
new CommitCopyIdQuickPickItem(state.reference),
new CommitCopyMessageQuickPickItem(state.reference),
);
const branch = await Container.instance.git.getBranch(state.repo.path);
const branches =
branch != null
? await Container.instance.git.getCommitBranches(state.repo.path, state.reference.ref, {
@ -1482,8 +1531,26 @@ async function getShowCommitOrStashStepItems<
commitDate: GitCommit.is(state.reference) ? state.reference.committer.date : undefined,
})
: undefined;
const commitOnCurrentBranch = Boolean(branches?.length);
if (commitOnCurrentBranch) {
items.push(QuickPickSeparator.create('Actions'));
const unpublished = !branch?.remote && branch?.upstream && !(await state.reference.isPushed());
if (unpublished) {
// TODO@eamodio Add Undo commit, if HEAD & unpushed
items.push(
new GitCommandQuickPickItem('Push to Commit...', {
command: 'push',
state: {
repos: state.repo,
reference: state.reference,
},
}),
);
}
if (branches?.length) {
items.push(
new GitCommandQuickPickItem('Revert Commit...', {
command: 'revert',
@ -1492,17 +1559,6 @@ async function getShowCommitOrStashStepItems<
references: [state.reference],
},
}),
new GitCommandQuickPickItem('Reset Commit...', {
command: 'reset',
state: {
repo: state.repo,
reference: GitReference.create(`${state.reference.ref}^`, state.reference.repoPath, {
refType: 'revision',
name: `${state.reference.name}^`,
message: state.reference.message,
}),
},
}),
new GitCommandQuickPickItem(`Reset ${branch?.name ?? 'Current Branch'} to Commit...`, {
command: 'reset',
state: {
@ -1510,11 +1566,15 @@ async function getShowCommitOrStashStepItems<
reference: state.reference,
},
}),
new GitCommandQuickPickItem('Push to Commit...', {
command: 'push',
new GitCommandQuickPickItem(`Reset ${branch?.name ?? 'Current Branch'} to Previous Commit...`, {
command: 'reset',
state: {
repos: state.repo,
reference: state.reference,
repo: state.repo,
reference: GitReference.create(`${state.reference.ref}^`, state.reference.repoPath, {
refType: 'revision',
name: `${state.reference.name}^`,
message: state.reference.message,
}),
},
}),
);
@ -1545,6 +1605,10 @@ async function getShowCommitOrStashStepItems<
reference: state.reference,
},
}),
);
items.push(
QuickPickSeparator.create(),
new GitCommandQuickPickItem('Create Branch at Commit...', {
command: 'branch',
state: {
@ -1565,27 +1629,29 @@ async function getShowCommitOrStashStepItems<
}
items.push(
QuickPickSeparator.create('Open Changes'),
new CommitOpenAllChangesCommandQuickPickItem(state.reference),
new CommitOpenAllChangesWithDiffToolCommandQuickPickItem(state.reference),
new CommitOpenAllChangesWithWorkingCommandQuickPickItem(state.reference),
new CommitOpenDirectoryCompareCommandQuickPickItem(state.reference),
new CommitOpenDirectoryCompareWithWorkingCommandQuickPickItem(state.reference),
new CommitOpenAllChangesWithDiffToolCommandQuickPickItem(state.reference),
QuickPickSeparator.create(),
new CommitOpenFilesCommandQuickPickItem(state.reference),
new CommitOpenRevisionsCommandQuickPickItem(state.reference),
);
if (remotes?.length) {
items.push(
new OpenRemoteResourceCommandQuickPickItem(remotes, {
type: RemoteResourceType.Commit,
sha: state.reference.sha,
}),
);
}
items.push(
QuickPickSeparator.create('Compare'),
new CommitCompareWithHEADCommandQuickPickItem(state.reference),
new CommitCompareWithWorkingCommandQuickPickItem(state.reference),
);
items.push(
QuickPickSeparator.create(),
new CommitOpenDirectoryCompareCommandQuickPickItem(state.reference),
new CommitOpenDirectoryCompareWithWorkingCommandQuickPickItem(state.reference),
);
items.push(
QuickPickSeparator.create('Browse'),
new CommitBrowseRepositoryFromHereCommandQuickPickItem(state.reference, { openInNewWindow: false }),
new CommitBrowseRepositoryFromHereCommandQuickPickItem(state.reference, {
before: true,
@ -1596,26 +1662,9 @@ async function getShowCommitOrStashStepItems<
before: true,
openInNewWindow: true,
}),
new CommitCompareWithHEADCommandQuickPickItem(state.reference),
new CommitCompareWithWorkingCommandQuickPickItem(state.reference),
);
if (!isStash) {
items.push(new CommitCopyIdQuickPickItem(state.reference));
}
items.push(new CommitCopyMessageQuickPickItem(state.reference));
if (remotes?.length) {
items.push(
new CopyRemoteResourceCommandQuickPickItem(remotes, {
type: RemoteResourceType.Commit,
sha: state.reference.sha,
}),
);
}
return items;
return items as CommandQuickPickItem[];
}
export function* showCommitOrStashFilesStep<
@ -1652,8 +1701,8 @@ export function* showCommitOrStashFilesStep<
) ?? []),
],
matchOnDescription: true,
additionalButtons: [QuickCommandButtons.RevealInSideBar, QuickCommandButtons.SearchInSideBar],
onDidClickButton: (quickpick, button) => {
// additionalButtons: [QuickCommandButtons.RevealInSideBar, QuickCommandButtons.SearchInSideBar],
onDidClickItemButton: (quickpick, button, _item) => {
if (button === QuickCommandButtons.SearchInSideBar) {
void Container.instance.searchAndCompareView.search(
state.repo.path,
@ -1724,8 +1773,8 @@ export async function* showCommitOrStashFileStep<
ignoreFocusOut: true,
items: await getShowCommitOrStashFileStepItems(state),
matchOnDescription: true,
additionalButtons: [QuickCommandButtons.RevealInSideBar, QuickCommandButtons.SearchInSideBar],
onDidClickButton: (quickpick, button) => {
// additionalButtons: [QuickCommandButtons.RevealInSideBar, QuickCommandButtons.SearchInSideBar],
onDidClickItemButton: (quickpick, button, _item) => {
if (button === QuickCommandButtons.SearchInSideBar) {
void Container.instance.searchAndCompareView.search(
state.repo.path,
@ -1780,33 +1829,70 @@ async function getShowCommitOrStashFileStepItems<
const file = await state.reference.findFile(state.fileName);
if (file == null) return [];
const items: CommandQuickPickItem[] = [
const items: (CommandQuickPickItem | QuickPickSeparator)[] = [
new CommitFilesQuickPickItem(state.reference, undefined, GitUri.getFormattedFileName(state.fileName)),
];
let remotes: GitRemote<RemoteProvider>[] | undefined;
let isStash = false;
if (GitCommit.is(state.reference)) {
isStash = true;
items.push(new RevealInSideBarQuickPickItem(state.reference));
if (GitCommit.isStash(state.reference)) {
items.push(
QuickPickSeparator.create(),
new RevealInSideBarQuickPickItem(state.reference),
QuickPickSeparator.create(),
new CommitCopyMessageQuickPickItem(state.reference),
QuickPickSeparator.create('Actions'),
);
} else {
remotes = await Container.instance.git.getRemotesWithProviders(state.repo.path, { sort: true });
items.push(
QuickPickSeparator.create(),
new RevealInSideBarQuickPickItem(state.reference),
new SearchForCommitQuickPickItem(state.reference),
);
const remotes = await Container.instance.git.getRemotesWithProviders(state.repo.path, { sort: true });
if (remotes?.length) {
items.push(
QuickPickSeparator.create(),
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,
}),
new CopyRemoteResourceCommandQuickPickItem(remotes, {
type: RemoteResourceType.Commit,
sha: state.reference.sha,
}),
);
}
new CommitApplyFileChangesCommandQuickPickItem(state.reference, file),
new CommitRestoreFileChangesCommandQuickPickItem(state.reference, file),
items.push(
QuickPickSeparator.create(),
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'),
new CommitOpenChangesCommandQuickPickItem(state.reference, state.fileName),
new CommitOpenChangesWithDiffToolCommandQuickPickItem(state.reference, state.fileName),
new CommitOpenChangesWithWorkingCommandQuickPickItem(state.reference, state.fileName),
new CommitOpenChangesWithDiffToolCommandQuickPickItem(state.reference, state.fileName),
QuickPickSeparator.create(),
);
if (file.status !== 'D') {
@ -1814,21 +1900,14 @@ async function getShowCommitOrStashFileStepItems<
}
items.push(new CommitOpenRevisionCommandQuickPickItem(state.reference, file));
if (remotes?.length) {
items.push(
new OpenRemoteResourceCommandQuickPickItem(remotes, {
type: RemoteResourceType.Revision,
fileName: state.fileName,
commit: state.reference,
}),
new OpenRemoteResourceCommandQuickPickItem(remotes, {
type: RemoteResourceType.Commit,
sha: state.reference.ref,
}),
);
}
items.push(
QuickPickSeparator.create('Compare'),
new CommitCompareWithHEADCommandQuickPickItem(state.reference),
new CommitCompareWithWorkingCommandQuickPickItem(state.reference),
);
items.push(
QuickPickSeparator.create('Browse'),
new CommitBrowseRepositoryFromHereCommandQuickPickItem(state.reference, { openInNewWindow: false }),
new CommitBrowseRepositoryFromHereCommandQuickPickItem(state.reference, {
before: true,
@ -1839,31 +1918,9 @@ async function getShowCommitOrStashFileStepItems<
before: true,
openInNewWindow: true,
}),
new CommitCompareWithHEADCommandQuickPickItem(state.reference),
new CommitCompareWithWorkingCommandQuickPickItem(state.reference),
);
if (!isStash) {
items.push(new CommitCopyIdQuickPickItem(state.reference));
}
items.push(new CommitCopyMessageQuickPickItem(state.reference));
if (remotes?.length) {
items.push(
new CopyRemoteResourceCommandQuickPickItem(remotes, {
type: RemoteResourceType.Commit,
sha: state.reference.sha,
}),
new CopyRemoteResourceCommandQuickPickItem(remotes, {
type: RemoteResourceType.Revision,
fileName: state.fileName,
commit: state.reference,
}),
);
}
return items;
return items as CommandQuickPickItem[];
}
export function* showRepositoryStatusStep<

+ 17
- 7
src/env/node/git/git.ts View File

@ -75,11 +75,15 @@ function defaultExceptionHandler(ex: Error, cwd: string | undefined, start?: [nu
throw ex;
}
type ExitCodeOnlyGitCommandOptions = GitCommandOptions & { exitCodeOnly: true };
export class Git {
// A map of running git commands -- avoids running duplicate overlaping commands
private readonly pendingCommands = new Map<string, Promise<string | Buffer>>();
async git<TOut extends string | Buffer>(options: GitCommandOptions, ...args: any[]): Promise<TOut> {
async git(options: ExitCodeOnlyGitCommandOptions, ...args: any[]): Promise<number>;
async git<T extends string | Buffer>(options: GitCommandOptions, ...args: any[]): Promise<T>;
async git<T extends string | Buffer>(options: GitCommandOptions, ...args: any[]): Promise<T> {
const start = hrtime();
const { configs, correlationKey, errors: errorHandling, encoding, ...opts } = options;
@ -123,7 +127,7 @@ export class Git {
args.splice(0, 0, '-c', 'core.longpaths=true');
}
promise = run<TOut>(await this.path(), args, encoding ?? 'utf8', runOpts);
promise = run<T>(await this.path(), args, encoding ?? 'utf8', runOpts);
this.pendingCommands.set(command, promise);
} else {
@ -133,14 +137,14 @@ export class Git {
let exception: Error | undefined;
try {
return (await promise) as TOut;
return (await promise) as T;
} catch (ex) {
exception = ex;
switch (errorHandling) {
case GitErrorHandling.Ignore:
exception = undefined;
return '' as TOut;
return '' as T;
case GitErrorHandling.Throw:
throw ex;
@ -148,7 +152,7 @@ export class Git {
default: {
const result = defaultExceptionHandler(ex, options.cwd, start);
exception = undefined;
return result as TOut;
return result as T;
}
}
} finally {
@ -1035,15 +1039,21 @@ export class Git {
return data.length === 0 ? undefined : data.trim();
}
merge_base(repoPath: string, ref1: string, ref2: string, { forkPoint }: { forkPoint?: boolean } = {}) {
merge_base(repoPath: string, ref1: string, ref2: string, options?: { forkPoint?: boolean }) {
const params = ['merge-base'];
if (forkPoint) {
if (options?.forkPoint) {
params.push('--fork-point');
}
return this.git<string>({ cwd: repoPath }, ...params, ref1, ref2);
}
async merge_base__is_ancestor(repoPath: string, ref1: string, ref2: string): Promise<boolean> {
const params = ['merge-base', '--is-ancestor'];
const exitCode = await this.git({ cwd: repoPath, exitCodeOnly: true }, ...params, ref1, ref2);
return exitCode === 0;
}
reflog(
repoPath: string,
{

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

@ -3261,6 +3261,13 @@ export class LocalGitProvider implements GitProvider, Disposable {
return branches.length !== 0 || tags.length !== 0;
}
@log()
async hasCommitBeenPushed(repoPath: string, ref: string): Promise<boolean> {
if (repoPath == null) return false;
return this.git.merge_base__is_ancestor(repoPath, ref, '@{u}');
}
isTrackable(uri: Uri): boolean {
return this.supportedSchemes.has(uri.scheme);
}

+ 26
- 6
src/env/node/git/shell.ts View File

@ -170,16 +170,36 @@ export class RunError extends Error {
}
}
export function run<TOut extends string | Buffer>(
type ExitCodeOnlyRunOptions = RunOptions & { exitCodeOnly: true };
export function run(
command: string,
args: any[],
encoding: BufferEncoding | 'buffer' | string,
options: ExitCodeOnlyRunOptions,
): Promise<number>;
export function run<T extends string | Buffer>(
command: string,
args: any[],
encoding: BufferEncoding | 'buffer' | string,
options: RunOptions = {},
): Promise<TOut> {
options?: RunOptions,
): Promise<T>;
export function run<T extends number | string | Buffer>(
command: string,
args: any[],
encoding: BufferEncoding | 'buffer' | string,
options?: RunOptions & { exitCodeOnly?: boolean },
): Promise<T> {
const { stdin, stdinEncoding, ...opts }: RunOptions = { maxBuffer: 100 * 1024 * 1024, ...options };
return new Promise<TOut>((resolve, reject) => {
return new Promise<T>((resolve, reject) => {
const proc = execFile(command, args, opts, (error: ExecException | null, stdout, stderr) => {
if (options?.exitCodeOnly) {
resolve((error?.code ?? proc.exitCode) as T);
return;
}
if (error != null) {
if (bufferExceededRegex.test(error.message)) {
error.message = `Command output exceeded the allocated stdout buffer. Set 'options.maxBuffer' to a larger value than ${opts.maxBuffer} bytes`;
@ -206,8 +226,8 @@ export function run(
resolve(
encoding === 'utf8' || encoding === 'binary' || encoding === 'buffer'
? (stdout as TOut)
: (decode(Buffer.from(stdout, 'binary'), encoding) as TOut),
? (stdout as T)
: (decode(Buffer.from(stdout, 'binary'), encoding) as T),
);
});

+ 1
- 0
src/git/gitProvider.ts View File

@ -360,6 +360,7 @@ export interface GitProvider extends Disposable {
},
): Promise<boolean>;
hasCommitBeenPushed(repoPath: string, ref: string): Promise<boolean>;
isTrackable(uri: Uri): boolean;
getDiffTool(repoPath?: string): Promise<string | undefined>;

+ 8
- 0
src/git/gitProviderService.ts View File

@ -1777,6 +1777,14 @@ export class GitProviderService implements Disposable {
return provider.hasBranchOrTag(path, options);
}
@log({ args: { 1: false } })
async hasCommitBeenPushed(repoPath: string | Uri, ref: string): Promise<boolean> {
if (repoPath == null) return false;
const { provider, path } = this.getProvider(repoPath);
return provider.hasCommitBeenPushed(path, ref);
}
@log()
async hasRemotes(repoPath: string | Uri | undefined): Promise<boolean> {
if (repoPath == null) return false;

+ 4
- 0
src/git/models/commit.ts View File

@ -411,6 +411,10 @@ export class GitCommit implements GitRevisionReference {
: Promise.resolve(undefined);
}
async isPushed(): Promise<boolean> {
return this.container.git.hasCommitBeenPushed(this.repoPath, this.ref);
}
with(changes: {
sha?: string;
parents?: string[];

+ 6
- 0
src/premium/github/githubGitProvider.ts View File

@ -1928,6 +1928,12 @@ export class GitHubGitProvider implements GitProvider, Disposable {
return branches.length !== 0 || tags.length !== 0;
}
@log()
async hasCommitBeenPushed(_repoPath: string, _ref: string): Promise<boolean> {
// In this env we can't have unpushed commits
return true;
}
isTrackable(uri: Uri): boolean {
return this.supportedSchemes.has(uri.scheme);
}

+ 7
- 2
src/quickpicks/commitQuickPickItems.ts View File

@ -1,5 +1,6 @@
import { QuickPickItem, window } from 'vscode';
import { Commands, GitActions, OpenChangedFilesCommandArgs } from '../commands';
import { QuickCommandButtons } from '../commands/quickCommand.buttons';
import { GlyphChars } from '../constants';
import { Container } from '../container';
import { CommitFormatter } from '../git/formatters';
@ -20,7 +21,11 @@ export class CommitFilesQuickPickItem extends CommandQuickPickItem {
separator: ', ',
empty: 'No files changed',
})}${fileName ? `${Strings.pad(GlyphChars.Dot, 2, 2)}${fileName}` : ''}`,
alwaysShow: true,
picked: picked,
buttons: GitCommit.isStash(commit)
? [QuickCommandButtons.RevealInSideBar]
: [QuickCommandButtons.RevealInSideBar, QuickCommandButtons.SearchInSideBar],
},
undefined,
undefined,
@ -117,7 +122,7 @@ export class CommitCompareWithWorkingCommandQuickPickItem extends CommandQuickPi
export class CommitCopyIdQuickPickItem extends CommandQuickPickItem {
constructor(private readonly commit: GitCommit, item?: QuickPickItem) {
super(item ?? '$(clippy) Copy SHA');
super(item ?? '$(copy) Copy SHA');
}
override execute(): Promise<void> {
@ -132,7 +137,7 @@ export class CommitCopyIdQuickPickItem extends CommandQuickPickItem {
export class CommitCopyMessageQuickPickItem extends CommandQuickPickItem {
constructor(private readonly commit: GitCommit, item?: QuickPickItem) {
super(item ?? '$(clippy) Copy Message');
super(item ?? '$(copy) Copy Message');
}
override execute(): Promise<void> {

+ 13
- 13
src/quickpicks/gitQuickPickItems.ts View File

@ -39,7 +39,7 @@ export namespace BranchQuickPickItem {
export async function create(
branch: GitBranch,
picked?: boolean,
options: {
options?: {
alwaysShow?: boolean;
buttons?: QuickInputButton[];
checked?: boolean;
@ -47,28 +47,28 @@ export namespace BranchQuickPickItem {
ref?: boolean;
status?: boolean;
type?: boolean | 'remote';
} = {},
) {
},
): Promise<BranchQuickPickItem> {
let description = '';
if (options.type === true) {
if (options.current === true && branch.current) {
if (options?.type === true) {
if (options?.current === true && branch.current) {
description = 'current branch';
} else {
description = 'branch';
}
} else if (options.type === 'remote') {
} else if (options?.type === 'remote') {
if (branch.remote) {
description = 'remote branch';
}
} else if (options.current === true && branch.current) {
} else if (options?.current === true && branch.current) {
description = 'current branch';
}
if (options.status && !branch.remote && branch.upstream != null) {
if (options?.status && !branch.remote && branch.upstream != null) {
let arrows = GlyphChars.Dash;
const remote = await branch.getRemote();
if (!branch.upstream.missing) {
const remote = await branch.getRemote();
if (remote != null) {
let left;
let right;
@ -102,7 +102,7 @@ export namespace BranchQuickPickItem {
description = `${description ? `${description}${GlyphChars.Space.repeat(2)}${status}` : status}`;
}
if (options.ref) {
if (options?.ref) {
if (branch.sha) {
description = description
? `${description}${pad('$(git-commit)', 2, 2)}${GitRevision.shorten(branch.sha)}`
@ -117,14 +117,14 @@ export namespace BranchQuickPickItem {
}
const checked =
options.checked || (options.checked == null && options.current === 'checkmark' && branch.current);
options?.checked || (options?.checked == null && options?.current === 'checkmark' && branch.current);
const item: BranchQuickPickItem = {
label: `${pad('$(git-branch)', 0, 2)}${branch.starred ? '$(star-full) ' : ''}${branch.name}${
checked ? `${GlyphChars.Space.repeat(2)}$(check)${GlyphChars.Space}` : ''
}`,
description: description,
alwaysShow: options.alwaysShow,
buttons: options.buttons,
alwaysShow: options?.alwaysShow,
buttons: options?.buttons,
picked: picked ?? branch.current,
item: branch,
current: branch.current,

+ 11
- 1
src/quickpicks/quickPicksItems.ts View File

@ -1,4 +1,4 @@
import { commands, QuickPickItem } from 'vscode';
import { commands, QuickPickItem, QuickPickItemKind } from 'vscode';
import { Commands, GitActions } from '../commands';
import { Container } from '../container';
import { GitCommit, GitReference, GitRevisionReference } from '../git/models';
@ -12,6 +12,16 @@ declare module 'vscode' {
}
}
export interface QuickPickSeparator extends QuickPickItem {
kind: QuickPickItemKind.Separator;
}
export namespace QuickPickSeparator {
export function create(label?: string): QuickPickSeparator {
return { kind: QuickPickItemKind.Separator, label: label ?? '' };
}
}
export interface QuickPickItemOfT<T = any> extends QuickPickItem {
readonly item: T;
}

+ 1
- 1
src/quickpicks/remoteProviderPicker.ts View File

@ -98,7 +98,7 @@ export class CopyRemoteResourceCommandQuickPickItem extends CommandQuickPickItem
clipboard: true,
};
super(
`$(clippy) Copy ${providers?.length ? providers[0].name : 'Remote'} ${getNameFromRemoteResource(
`$(copy) Copy ${providers?.length ? providers[0].name : 'Remote'} ${getNameFromRemoteResource(
resource,
)} Url${providers?.length === 1 ? '' : GlyphChars.Ellipsis}`,
Commands.OpenOnRemote,

Loading…
Cancel
Save