Browse Source

Adds default confirm selection for flags

Makes git flags type safe
main
Eric Amodio 5 years ago
parent
commit
4893385052
11 changed files with 192 additions and 178 deletions
  1. +16
    -11
      src/commands/git/cherry-pick.ts
  2. +22
    -22
      src/commands/git/fetch.ts
  3. +22
    -19
      src/commands/git/merge.ts
  4. +24
    -27
      src/commands/git/pull.ts
  5. +22
    -22
      src/commands/git/push.ts
  6. +16
    -11
      src/commands/git/rebase.ts
  7. +16
    -12
      src/commands/git/reset.ts
  8. +4
    -14
      src/commands/git/revert.ts
  9. +36
    -38
      src/commands/git/stash.ts
  10. +1
    -1
      src/commands/quickCommand.ts
  11. +13
    -1
      src/quickpicks/gitQuickPicks.ts

+ 16
- 11
src/commands/git/cherry-pick.ts View File

@ -8,6 +8,7 @@ import {
getBranchesAndOrTags, getBranchesAndOrTags,
getValidateGitReferenceFn, getValidateGitReferenceFn,
QuickCommandBase, QuickCommandBase,
QuickPickStep,
StepAsyncGenerator, StepAsyncGenerator,
StepSelection, StepSelection,
StepState StepState
@ -16,17 +17,19 @@ import {
CommitQuickPickItem, CommitQuickPickItem,
Directive, Directive,
DirectiveQuickPickItem, DirectiveQuickPickItem,
GitFlagsQuickPickItem,
FlagsQuickPickItem,
ReferencesQuickPickItem, ReferencesQuickPickItem,
RepositoryQuickPickItem RepositoryQuickPickItem
} from '../../quickpicks'; } from '../../quickpicks';
import { runGitCommandInTerminal } from '../../terminal'; import { runGitCommandInTerminal } from '../../terminal';
import { Logger } from '../../logger'; import { Logger } from '../../logger';
type Flags = '--edit';
interface State { interface State {
repo: Repository; repo: Repository;
references?: GitReference[]; references?: GitReference[];
flags: string[];
flags: Flags[];
} }
export interface CherryPickGitCommandArgs { export interface CherryPickGitCommandArgs {
@ -80,6 +83,10 @@ export class CherryPickGitCommand extends QuickCommandBase {
let repos; let repos;
let selectedBranchOrTag: GitReference | undefined; let selectedBranchOrTag: GitReference | undefined;
if (state.flags == null) {
state.flags = [];
}
while (true) { while (true) {
try { try {
if (repos === undefined) { if (repos === undefined) {
@ -198,10 +205,10 @@ export class CherryPickGitCommand extends QuickCommandBase {
state.references = selection.map(i => i.item); state.references = selection.map(i => i.item);
} }
const step = this.createConfirmStep<GitFlagsQuickPickItem>(
const step: QuickPickStep<FlagsQuickPickItem<Flags>> = this.createConfirmStep(
`Confirm ${this.title}${Strings.pad(GlyphChars.Dot, 2, 2)}${state.repo.formattedName}`, `Confirm ${this.title}${Strings.pad(GlyphChars.Dot, 2, 2)}${state.repo.formattedName}`,
[ [
{
FlagsQuickPickItem.create<Flags>(state.flags, [], {
label: this.title, label: this.title,
description: `${ description: `${
state.references!.length === 1 state.references!.length === 1
@ -212,10 +219,9 @@ export class CherryPickGitCommand extends QuickCommandBase {
state.references!.length === 1 state.references!.length === 1
? `commit ${state.references![0].name}` ? `commit ${state.references![0].name}`
: `${state.references!.length} commits` : `${state.references!.length} commits`
} onto ${destination.name}`,
item: []
},
{
} onto ${destination.name}`
}),
FlagsQuickPickItem.create<Flags>(state.flags, ['--edit'], {
label: `${this.title} & Edit`, label: `${this.title} & Edit`,
description: `--edit ${ description: `--edit ${
state.references!.length === 1 state.references!.length === 1
@ -226,9 +232,8 @@ export class CherryPickGitCommand extends QuickCommandBase {
state.references!.length === 1 state.references!.length === 1
? `commit ${state.references![0].name}` ? `commit ${state.references![0].name}`
: `${state.references!.length} commits` : `${state.references!.length} commits`
} onto ${destination.name}`,
item: ['--edit']
}
} onto ${destination.name}`
})
] ]
); );
const selection: StepSelection<typeof step> = yield step; const selection: StepSelection<typeof step> = yield step;

+ 22
- 22
src/commands/git/fetch.ts View File

@ -1,15 +1,17 @@
'use strict'; 'use strict';
import { Container } from '../../container'; import { Container } from '../../container';
import { Repository } from '../../git/gitService'; import { Repository } from '../../git/gitService';
import { QuickCommandBase, StepAsyncGenerator, StepSelection, StepState } from '../quickCommand';
import { GitFlagsQuickPickItem, RepositoryQuickPickItem } from '../../quickpicks';
import { QuickCommandBase, QuickPickStep, StepAsyncGenerator, StepSelection, StepState } from '../quickCommand';
import { FlagsQuickPickItem, RepositoryQuickPickItem } from '../../quickpicks';
import { Dates, Strings } from '../../system'; import { Dates, Strings } from '../../system';
import { GlyphChars } from '../../constants'; import { GlyphChars } from '../../constants';
import { Logger } from '../../logger'; import { Logger } from '../../logger';
type Flags = '--all' | '--prune';
interface State { interface State {
repos: Repository[]; repos: Repository[];
flags: string[];
flags: Flags[];
} }
export interface FetchGitCommandArgs { export interface FetchGitCommandArgs {
@ -48,6 +50,10 @@ export class FetchGitCommand extends QuickCommandBase {
const state: StepState<State> = this._initialState === undefined ? { counter: 0 } : this._initialState; const state: StepState<State> = this._initialState === undefined ? { counter: 0 } : this._initialState;
let repos; let repos;
if (state.flags == null) {
state.flags = [];
}
while (true) { while (true) {
try { try {
if (repos === undefined) { if (repos === undefined) {
@ -102,53 +108,49 @@ export class FetchGitCommand extends QuickCommandBase {
} }
} }
const step = this.createConfirmStep<GitFlagsQuickPickItem>(
const step: QuickPickStep<FlagsQuickPickItem<Flags>> = this.createConfirmStep(
`Confirm ${this.title}${Strings.pad(GlyphChars.Dot, 2, 2)}${ `Confirm ${this.title}${Strings.pad(GlyphChars.Dot, 2, 2)}${
state.repos.length === 1 state.repos.length === 1
? `${state.repos[0].formattedName}${fetchedOn}` ? `${state.repos[0].formattedName}${fetchedOn}`
: `${state.repos.length} repositories` : `${state.repos.length} repositories`
}`, }`,
[ [
{
FlagsQuickPickItem.create<Flags>(state.flags, [], {
label: this.title, label: this.title,
description: '', description: '',
detail: `Will fetch ${ detail: `Will fetch ${
state.repos.length === 1 state.repos.length === 1
? state.repos[0].formattedName ? state.repos[0].formattedName
: `${state.repos.length} repositories` : `${state.repos.length} repositories`
}`,
item: []
},
{
}`
}),
FlagsQuickPickItem.create<Flags>(state.flags, ['--prune'], {
label: `${this.title} & Prune`, label: `${this.title} & Prune`,
description: '--prune', description: '--prune',
detail: `Will fetch and prune ${ detail: `Will fetch and prune ${
state.repos.length === 1 state.repos.length === 1
? state.repos[0].formattedName ? state.repos[0].formattedName
: `${state.repos.length} repositories` : `${state.repos.length} repositories`
}`,
item: ['--prune']
},
{
}`
}),
FlagsQuickPickItem.create<Flags>(state.flags, ['--all'], {
label: `${this.title} All`, label: `${this.title} All`,
description: '--all', description: '--all',
detail: `Will fetch all remotes of ${ detail: `Will fetch all remotes of ${
state.repos.length === 1 state.repos.length === 1
? state.repos[0].formattedName ? state.repos[0].formattedName
: `${state.repos.length} repositories` : `${state.repos.length} repositories`
}`,
item: ['--all']
},
{
}`
}),
FlagsQuickPickItem.create<Flags>(state.flags, ['--all', '--prune'], {
label: `${this.title} All & Prune`, label: `${this.title} All & Prune`,
description: '--all --prune', description: '--all --prune',
detail: `Will fetch and prune all remotes of ${ detail: `Will fetch and prune all remotes of ${
state.repos.length === 1 state.repos.length === 1
? state.repos[0].formattedName ? state.repos[0].formattedName
: `${state.repos.length} repositories` : `${state.repos.length} repositories`
}`,
item: ['--all', '--prune']
}
}`
})
] ]
); );
const selection: StepSelection<typeof step> = yield step; const selection: StepSelection<typeof step> = yield step;
@ -162,8 +164,6 @@ export class FetchGitCommand extends QuickCommandBase {
} }
state.flags = selection[0].item; state.flags = selection[0].item;
} else {
state.flags = state.flags || [];
} }
this.execute(state as State); this.execute(state as State);

+ 22
- 19
src/commands/git/merge.ts View File

@ -6,6 +6,7 @@ import {
getBranchesAndOrTags, getBranchesAndOrTags,
getValidateGitReferenceFn, getValidateGitReferenceFn,
QuickCommandBase, QuickCommandBase,
QuickPickStep,
StepAsyncGenerator, StepAsyncGenerator,
StepSelection, StepSelection,
StepState StepState
@ -13,7 +14,7 @@ import {
import { import {
Directive, Directive,
DirectiveQuickPickItem, DirectiveQuickPickItem,
GitFlagsQuickPickItem,
FlagsQuickPickItem,
ReferencesQuickPickItem, ReferencesQuickPickItem,
RepositoryQuickPickItem RepositoryQuickPickItem
} from '../../quickpicks'; } from '../../quickpicks';
@ -21,10 +22,12 @@ import { Strings } from '../../system';
import { runGitCommandInTerminal } from '../../terminal'; import { runGitCommandInTerminal } from '../../terminal';
import { Logger } from '../../logger'; import { Logger } from '../../logger';
type Flags = '--ff-only' | '--no-ff' | '--squash';
interface State { interface State {
repo: Repository; repo: Repository;
reference: GitReference; reference: GitReference;
flags: string[];
flags: Flags[];
} }
export interface MergeGitCommandArgs { export interface MergeGitCommandArgs {
@ -68,6 +71,10 @@ export class MergeGitCommand extends QuickCommandBase {
const state: StepState<State> = this._initialState === undefined ? { counter: 0 } : this._initialState; const state: StepState<State> = this._initialState === undefined ? { counter: 0 } : this._initialState;
let repos; let repos;
if (state.flags == null) {
state.flags = [];
}
while (true) { while (true) {
try { try {
if (repos === undefined) { if (repos === undefined) {
@ -156,42 +163,38 @@ export class MergeGitCommand extends QuickCommandBase {
break; break;
} }
const step = this.createConfirmStep<GitFlagsQuickPickItem>(
const step: QuickPickStep<FlagsQuickPickItem<Flags>> = this.createConfirmStep(
`Confirm ${this.title}${Strings.pad(GlyphChars.Dot, 2, 2)}${state.repo.formattedName}`, `Confirm ${this.title}${Strings.pad(GlyphChars.Dot, 2, 2)}${state.repo.formattedName}`,
[ [
{
FlagsQuickPickItem.create<Flags>(state.flags, [], {
label: this.title, label: this.title,
description: `${state.reference.name} into ${destination.name}`, description: `${state.reference.name} into ${destination.name}`,
detail: `Will merge ${Strings.pluralize('commit', count)} from ${ detail: `Will merge ${Strings.pluralize('commit', count)} from ${
state.reference.name state.reference.name
} into ${destination.name}`,
item: []
},
{
} into ${destination.name}`
}),
FlagsQuickPickItem.create<Flags>(state.flags, ['--ff-only'], {
label: `Fast-forward ${this.title}`, label: `Fast-forward ${this.title}`,
description: `--ff-only ${state.reference.name} into ${destination.name}`, description: `--ff-only ${state.reference.name} into ${destination.name}`,
detail: `Will fast-forward merge ${Strings.pluralize('commit', count)} from ${ detail: `Will fast-forward merge ${Strings.pluralize('commit', count)} from ${
state.reference.name state.reference.name
} into ${destination.name}`,
item: ['--ff-only']
},
{
} into ${destination.name}`
}),
FlagsQuickPickItem.create<Flags>(state.flags, ['--no-ff'], {
label: `No Fast-forward ${this.title}`, label: `No Fast-forward ${this.title}`,
description: `--no-ff ${state.reference.name} into ${destination.name}`, description: `--no-ff ${state.reference.name} into ${destination.name}`,
detail: `Will create a merge commit when merging ${Strings.pluralize( detail: `Will create a merge commit when merging ${Strings.pluralize(
'commit', 'commit',
count count
)} from ${state.reference.name} into ${destination.name}`,
item: ['--no-ff']
},
{
)} from ${state.reference.name} into ${destination.name}`
}),
FlagsQuickPickItem.create<Flags>(state.flags, ['--squash'], {
label: `Squash ${this.title}`, label: `Squash ${this.title}`,
description: `--squash ${state.reference.name} into ${destination.name}`, description: `--squash ${state.reference.name} into ${destination.name}`,
detail: `Will squash ${Strings.pluralize('commit', count)} from ${ detail: `Will squash ${Strings.pluralize('commit', count)} from ${
state.reference.name state.reference.name
} into one when merging into ${destination.name}`,
item: ['--squash']
}
} into one when merging into ${destination.name}`
})
] ]
); );
const selection: StepSelection<typeof step> = yield step; const selection: StepSelection<typeof step> = yield step;

+ 24
- 27
src/commands/git/pull.ts View File

@ -2,15 +2,17 @@
import { QuickInputButton } from 'vscode'; import { QuickInputButton } from 'vscode';
import { Container } from '../../container'; import { Container } from '../../container';
import { Repository } from '../../git/gitService'; import { Repository } from '../../git/gitService';
import { QuickCommandBase, StepAsyncGenerator, StepSelection, StepState } from '../quickCommand';
import { GitFlagsQuickPickItem, RepositoryQuickPickItem } from '../../quickpicks';
import { QuickCommandBase, QuickPickStep, StepAsyncGenerator, StepSelection, StepState } from '../quickCommand';
import { FlagsQuickPickItem, RepositoryQuickPickItem } from '../../quickpicks';
import { Dates, Strings } from '../../system'; import { Dates, Strings } from '../../system';
import { GlyphChars } from '../../constants'; import { GlyphChars } from '../../constants';
import { Logger } from '../../logger'; import { Logger } from '../../logger';
type Flags = '--rebase';
interface State { interface State {
repos: Repository[]; repos: Repository[];
flags: string[];
flags: Flags[];
} }
export interface PullGitCommandArgs { export interface PullGitCommandArgs {
@ -58,6 +60,10 @@ export class PullGitCommand extends QuickCommandBase {
const state: StepState<State> = this._initialState === undefined ? { counter: 0 } : this._initialState; const state: StepState<State> = this._initialState === undefined ? { counter: 0 } : this._initialState;
let repos; let repos;
if (state.flags == null) {
state.flags = [];
}
while (true) { while (true) {
try { try {
if (repos === undefined) { if (repos === undefined) {
@ -102,25 +108,23 @@ export class PullGitCommand extends QuickCommandBase {
} }
if (this.confirm(state.confirm)) { if (this.confirm(state.confirm)) {
let step;
let step: QuickPickStep<FlagsQuickPickItem<Flags>>;
if (state.repos.length > 1) { if (state.repos.length > 1) {
step = this.createConfirmStep<GitFlagsQuickPickItem>(
step = this.createConfirmStep(
`Confirm ${this.title}${Strings.pad(GlyphChars.Dot, 2, 2)}${ `Confirm ${this.title}${Strings.pad(GlyphChars.Dot, 2, 2)}${
state.repos.length state.repos.length
} repositories`, } repositories`,
[ [
{
FlagsQuickPickItem.create<Flags>(state.flags, [], {
label: this.title, label: this.title,
description: '', description: '',
detail: `Will pull ${state.repos.length} repositories`,
item: []
},
{
detail: `Will pull ${state.repos.length} repositories`
}),
FlagsQuickPickItem.create<Flags>(state.flags, ['--rebase'], {
label: `${this.title} with Rebase`, label: `${this.title} with Rebase`,
description: '--rebase', description: '--rebase',
detail: `Will pull with rebase ${state.repos.length} repositories`,
item: ['--rebase']
}
detail: `Will pull with rebase ${state.repos.length} repositories`
})
] ]
); );
} else { } else {
@ -138,8 +142,6 @@ export class PullGitCommand extends QuickCommandBase {
} }
state.flags = selection[0].item; state.flags = selection[0].item;
} else {
state.flags = state.flags || [];
} }
this.execute(state as State); this.execute(state as State);
@ -170,35 +172,30 @@ export class PullGitCommand extends QuickCommandBase {
).fromNow()}`; ).fromNow()}`;
} }
const step = this.createConfirmStep<GitFlagsQuickPickItem>(
const step = this.createConfirmStep<FlagsQuickPickItem<pan>Flags>>(
`${title}${fetchedOn}`, `${title}${fetchedOn}`,
[ [
{
FlagsQuickPickItem.create<Flags>(state.flags!, [], {
label: this.title, label: this.title,
description: '', description: '',
detail: `Will pull ${detail}`,
item: []
},
{
detail: `Will pull ${detail}`
}),
FlagsQuickPickItem.create<Flags>(state.flags!, ['--rebase'], {
label: `${this.title} with Rebase`, label: `${this.title} with Rebase`,
description: '--rebase', description: '--rebase',
detail: `Will pull ${detail} with rebase`,
item: ['--rebase']
}
detail: `Will pull ${detail} with rebase`
})
], ],
undefined, undefined,
{ {
additionalButtons: [this.Buttons.Fetch], additionalButtons: [this.Buttons.Fetch],
onDidClickButton: async (quickpick, button) => { onDidClickButton: async (quickpick, button) => {
if (button !== this.Buttons.Fetch) return; if (button !== this.Buttons.Fetch) return;
quickpick.title = `${title}${Strings.pad(GlyphChars.Dot, 2, 2)}Fetching${GlyphChars.Ellipsis}`; quickpick.title = `${title}${Strings.pad(GlyphChars.Dot, 2, 2)}Fetching${GlyphChars.Ellipsis}`;
quickpick.busy = true; quickpick.busy = true;
quickpick.enabled = false; quickpick.enabled = false;
try { try {
await repo.fetch({ progress: true }); await repo.fetch({ progress: true });
const step = await this.getSingleRepoConfirmStep(state); const step = await this.getSingleRepoConfirmStep(state);
quickpick.title = step.title; quickpick.title = step.title;
quickpick.items = step.items as any; quickpick.items = step.items as any;

+ 22
- 22
src/commands/git/push.ts View File

@ -1,15 +1,17 @@
'use strict'; 'use strict';
import { Container } from '../../container'; import { Container } from '../../container';
import { Repository } from '../../git/gitService'; import { Repository } from '../../git/gitService';
import { QuickCommandBase, StepAsyncGenerator, StepSelection, StepState } from '../quickCommand';
import { Directive, DirectiveQuickPickItem, RepositoryQuickPickItem } from '../../quickpicks';
import { QuickCommandBase, QuickPickStep, StepAsyncGenerator, StepSelection, StepState } from '../quickCommand';
import { Directive, DirectiveQuickPickItem, FlagsQuickPickItem, RepositoryQuickPickItem } from '../../quickpicks';
import { Strings } from '../../system'; import { Strings } from '../../system';
import { GlyphChars } from '../../constants'; import { GlyphChars } from '../../constants';
import { Logger } from '../../logger'; import { Logger } from '../../logger';
type Flags = '--force';
interface State { interface State {
repos: Repository[]; repos: Repository[];
flags: string[];
flags: Flags[];
} }
export interface PushGitCommandArgs { export interface PushGitCommandArgs {
@ -47,6 +49,10 @@ export class PushGitCommand extends QuickCommandBase {
const state: StepState<State> = this._initialState === undefined ? { counter: 0 } : this._initialState; const state: StepState<State> = this._initialState === undefined ? { counter: 0 } : this._initialState;
let repos; let repos;
if (state.flags == null) {
state.flags = [];
}
while (true) { while (true) {
try { try {
if (repos === undefined) { if (repos === undefined) {
@ -91,25 +97,23 @@ export class PushGitCommand extends QuickCommandBase {
} }
if (this.confirm(state.confirm)) { if (this.confirm(state.confirm)) {
let step;
let step: QuickPickStep<FlagsQuickPickItem<Flags>>;
if (state.repos.length > 1) { if (state.repos.length > 1) {
step = this.createConfirmStep( step = this.createConfirmStep(
`Confirm ${this.title}${Strings.pad(GlyphChars.Dot, 2, 2)}${ `Confirm ${this.title}${Strings.pad(GlyphChars.Dot, 2, 2)}${
state.repos.length state.repos.length
} repositories`, } repositories`,
[ [
{
FlagsQuickPickItem.create<Flags>(state.flags, [], {
label: this.title, label: this.title,
description: '', description: '',
detail: `Will push ${state.repos.length} repositories`,
item: []
},
{
detail: `Will push ${state.repos.length} repositories`
}),
FlagsQuickPickItem.create<Flags>(state.flags, ['--force'], {
label: `Force ${this.title}`, label: `Force ${this.title}`,
description: '--force', description: '--force',
detail: `Will force push ${state.repos.length} repositories`,
item: ['--force']
}
detail: `Will force push ${state.repos.length} repositories`
})
] ]
); );
} else { } else {
@ -127,8 +131,6 @@ export class PushGitCommand extends QuickCommandBase {
} }
state.flags = selection[0].item; state.flags = selection[0].item;
} else {
state.flags = state.flags || [];
} }
this.execute(state as State); this.execute(state as State);
@ -166,18 +168,16 @@ export class PushGitCommand extends QuickCommandBase {
return this.createConfirmStep( return this.createConfirmStep(
`Confirm ${this.title}${Strings.pad(GlyphChars.Dot, 2, 2)}${repo.formattedName}`, `Confirm ${this.title}${Strings.pad(GlyphChars.Dot, 2, 2)}${repo.formattedName}`,
[ [
{
FlagsQuickPickItem.create<Flags>(state.flags!, [], {
label: this.title, label: this.title,
description: '', description: '',
detail: `Will push ${detail}`,
item: []
},
{
detail: `Will push ${detail}`
}),
FlagsQuickPickItem.create<Flags>(state.flags!, ['--force'], {
label: `Force ${this.title}`, label: `Force ${this.title}`,
description: '--force', description: '--force',
detail: `Will force push ${detail}`,
item: ['--force']
}
detail: `Will force push ${detail}`
})
] ]
); );
} }

+ 16
- 11
src/commands/git/rebase.ts View File

@ -7,6 +7,7 @@ import {
getBranchesAndOrTags, getBranchesAndOrTags,
getValidateGitReferenceFn, getValidateGitReferenceFn,
QuickCommandBase, QuickCommandBase,
QuickPickStep,
StepAsyncGenerator, StepAsyncGenerator,
StepSelection, StepSelection,
StepState StepState
@ -15,7 +16,7 @@ import {
CommitQuickPickItem, CommitQuickPickItem,
Directive, Directive,
DirectiveQuickPickItem, DirectiveQuickPickItem,
GitFlagsQuickPickItem,
FlagsQuickPickItem,
ReferencesQuickPickItem, ReferencesQuickPickItem,
RefQuickPickItem, RefQuickPickItem,
RepositoryQuickPickItem RepositoryQuickPickItem
@ -24,10 +25,12 @@ import { Iterables, Mutable, Strings } from '../../system';
import { runGitCommandInTerminal } from '../../terminal'; import { runGitCommandInTerminal } from '../../terminal';
import { Logger } from '../../logger'; import { Logger } from '../../logger';
type Flags = '--interactive';
interface State { interface State {
repo: Repository; repo: Repository;
reference: GitReference; reference: GitReference;
flags: string[];
flags: Flags[];
} }
export interface RebaseGitCommandArgs { export interface RebaseGitCommandArgs {
@ -92,6 +95,10 @@ export class RebaseGitCommand extends QuickCommandBase {
let selectedBranchOrTag: GitReference | undefined; let selectedBranchOrTag: GitReference | undefined;
let pickCommit = false; let pickCommit = false;
if (state.flags == null) {
state.flags = [];
}
while (true) { while (true) {
try { try {
if (repos === undefined) { if (repos === undefined) {
@ -238,27 +245,25 @@ export class RebaseGitCommand extends QuickCommandBase {
break; break;
} }
const step = this.createConfirmStep<GitFlagsQuickPickItem>(
const step: QuickPickStep<FlagsQuickPickItem<Flags>> = this.createConfirmStep(
`Confirm ${this.title}${Strings.pad(GlyphChars.Dot, 2, 2)}${state.repo.formattedName}`, `Confirm ${this.title}${Strings.pad(GlyphChars.Dot, 2, 2)}${state.repo.formattedName}`,
[ [
{
FlagsQuickPickItem.create<Flags>(state.flags, [], {
label: this.title, label: this.title,
description: `${destination.name} with ${state.reference.name}`, description: `${destination.name} with ${state.reference.name}`,
detail: `Will update ${destination.name} by applying ${Strings.pluralize( detail: `Will update ${destination.name} by applying ${Strings.pluralize(
'commit', 'commit',
count count
)} on top of ${state.reference.name}`,
item: []
},
{
)} on top of ${state.reference.name}`
}),
FlagsQuickPickItem.create<Flags>(state.flags, ['--interactive'], {
label: `Interactive ${this.title}`, label: `Interactive ${this.title}`,
description: `--interactive ${destination.name} with ${state.reference.name}`, description: `--interactive ${destination.name} with ${state.reference.name}`,
detail: `Will interactively update ${destination.name} by applying ${Strings.pluralize( detail: `Will interactively update ${destination.name} by applying ${Strings.pluralize(
'commit', 'commit',
count count
)} on top of ${state.reference.name}`,
item: ['--interactive']
}
)} on top of ${state.reference.name}`
})
] ]
); );
const selection: StepSelection<typeof step> = yield step; const selection: StepSelection<typeof step> = yield step;

+ 16
- 12
src/commands/git/reset.ts View File

@ -4,21 +4,23 @@ import { Container } from '../../container';
import { GitReference, Repository } from '../../git/gitService'; import { GitReference, Repository } from '../../git/gitService';
import { GlyphChars } from '../../constants'; import { GlyphChars } from '../../constants';
import { Iterables, Strings } from '../../system'; import { Iterables, Strings } from '../../system';
import { QuickCommandBase, StepAsyncGenerator, StepSelection, StepState } from '../quickCommand';
import { QuickCommandBase, QuickPickStep, StepAsyncGenerator, StepSelection, StepState } from '../quickCommand';
import { import {
CommitQuickPickItem, CommitQuickPickItem,
Directive, Directive,
DirectiveQuickPickItem, DirectiveQuickPickItem,
GitFlagsQuickPickItem,
FlagsQuickPickItem,
RepositoryQuickPickItem RepositoryQuickPickItem
} from '../../quickpicks'; } from '../../quickpicks';
import { runGitCommandInTerminal } from '../../terminal'; import { runGitCommandInTerminal } from '../../terminal';
import { Logger } from '../../logger'; import { Logger } from '../../logger';
type Flags = '--hard';
interface State { interface State {
repo: Repository; repo: Repository;
reference?: GitReference; reference?: GitReference;
flags: string[];
flags: Flags[];
} }
export interface ResetGitCommandArgs { export interface ResetGitCommandArgs {
@ -60,6 +62,10 @@ export class ResetGitCommand extends QuickCommandBase {
const state: StepState<State> = this._initialState === undefined ? { counter: 0 } : this._initialState; const state: StepState<State> = this._initialState === undefined ? { counter: 0 } : this._initialState;
let repos; let repos;
if (state.flags == null) {
state.flags = [];
}
while (true) { while (true) {
try { try {
if (repos === undefined) { if (repos === undefined) {
@ -141,21 +147,19 @@ export class ResetGitCommand extends QuickCommandBase {
state.reference = selection[0].item; state.reference = selection[0].item;
} }
const step = this.createConfirmStep<GitFlagsQuickPickItem>(
const step: QuickPickStep<FlagsQuickPickItem<Flags>> = this.createConfirmStep(
`Confirm ${this.title}${Strings.pad(GlyphChars.Dot, 2, 2)}${state.repo.formattedName}`, `Confirm ${this.title}${Strings.pad(GlyphChars.Dot, 2, 2)}${state.repo.formattedName}`,
[ [
{
FlagsQuickPickItem.create<Flags>(state.flags, [], {
label: `Soft ${this.title}`, label: `Soft ${this.title}`,
description: `--soft ${destination.name} to ${state.reference.name}`, description: `--soft ${destination.name} to ${state.reference.name}`,
detail: `Will soft reset (leaves changes in the working tree) ${destination.name} to ${state.reference.name}`,
item: ['--soft']
},
{
detail: `Will soft reset (leaves changes in the working tree) ${destination.name} to ${state.reference.name}`
}),
FlagsQuickPickItem.create<Flags>(state.flags, ['--hard'], {
label: `Hard ${this.title}`, label: `Hard ${this.title}`,
description: `--hard ${destination.name} to ${state.reference.name}`, description: `--hard ${destination.name} to ${state.reference.name}`,
detail: `Will hard reset (discards all changes) ${destination.name} to ${state.reference.name}`,
item: ['--hard']
}
detail: `Will hard reset (discards all changes) ${destination.name} to ${state.reference.name}`
})
] ]
); );
const selection: StepSelection<typeof step> = yield step; const selection: StepSelection<typeof step> = yield step;

+ 4
- 14
src/commands/git/revert.ts View File

@ -5,20 +5,13 @@ import { GitReference, Repository } from '../../git/gitService';
import { GlyphChars } from '../../constants'; import { GlyphChars } from '../../constants';
import { Iterables, Strings } from '../../system'; import { Iterables, Strings } from '../../system';
import { QuickCommandBase, StepAsyncGenerator, StepSelection, StepState } from '../quickCommand'; import { QuickCommandBase, StepAsyncGenerator, StepSelection, StepState } from '../quickCommand';
import {
CommitQuickPickItem,
Directive,
DirectiveQuickPickItem,
GitFlagsQuickPickItem,
RepositoryQuickPickItem
} from '../../quickpicks';
import { CommitQuickPickItem, Directive, DirectiveQuickPickItem, RepositoryQuickPickItem } from '../../quickpicks';
import { runGitCommandInTerminal } from '../../terminal'; import { runGitCommandInTerminal } from '../../terminal';
import { Logger } from '../../logger'; import { Logger } from '../../logger';
interface State { interface State {
repo: Repository; repo: Repository;
references?: GitReference[]; references?: GitReference[];
flags: string[];
} }
export interface RevertGitCommandArgs { export interface RevertGitCommandArgs {
@ -57,7 +50,7 @@ export class RevertGitCommand extends QuickCommandBase {
execute(state: State) { execute(state: State) {
runGitCommandInTerminal( runGitCommandInTerminal(
'revert', 'revert',
[...state.flags, ...state.references!.map(c => c.ref).reverse()].join(' '),
[...state.references!.map(c => c.ref).reverse()].join(' '),
state.repo.path, state.repo.path,
true true
); );
@ -151,7 +144,7 @@ export class RevertGitCommand extends QuickCommandBase {
state.references = selection.map(i => i.item); state.references = selection.map(i => i.item);
} }
const step = this.createConfirmStep<GitFlagsQuickPickItem>(
const step = this.createConfirmStep(
`Confirm ${this.title}${Strings.pad(GlyphChars.Dot, 2, 2)}${state.repo.formattedName}`, `Confirm ${this.title}${Strings.pad(GlyphChars.Dot, 2, 2)}${state.repo.formattedName}`,
[ [
{ {
@ -165,8 +158,7 @@ export class RevertGitCommand extends QuickCommandBase {
state.references.length === 1 state.references.length === 1
? `commit ${state.references[0].name}` ? `commit ${state.references[0].name}`
: `${state.references.length} commits` : `${state.references.length} commits`
} on ${destination.name}`,
item: []
} on ${destination.name}`
} }
] ]
); );
@ -176,8 +168,6 @@ export class RevertGitCommand extends QuickCommandBase {
continue; continue;
} }
state.flags = selection[0].item;
this.execute(state as State); this.execute(state as State);
break; break;
} catch (ex) { } catch (ex) {

+ 36
- 38
src/commands/git/stash.ts View File

@ -3,14 +3,21 @@
import { QuickInputButton, QuickInputButtons, QuickPickItem, Uri, window } from 'vscode'; import { QuickInputButton, QuickInputButtons, QuickPickItem, Uri, window } from 'vscode';
import { Container } from '../../container'; import { Container } from '../../container';
import { GitStashCommit, GitUri, Repository, SearchPattern } from '../../git/gitService'; import { GitStashCommit, GitUri, Repository, SearchPattern } from '../../git/gitService';
import { BreakQuickCommand, QuickCommandBase, StepAsyncGenerator, StepSelection, StepState } from '../quickCommand';
import {
BreakQuickCommand,
QuickCommandBase,
QuickPickStep,
StepAsyncGenerator,
StepSelection,
StepState
} from '../quickCommand';
import { import {
CommandQuickPickItem, CommandQuickPickItem,
CommitQuickPick, CommitQuickPick,
CommitQuickPickItem, CommitQuickPickItem,
Directive, Directive,
DirectiveQuickPickItem, DirectiveQuickPickItem,
GitFlagsQuickPickItem,
FlagsQuickPickItem,
QuickPickItemOfT, QuickPickItemOfT,
RepositoryQuickPickItem RepositoryQuickPickItem
} from '../../quickpicks'; } from '../../quickpicks';
@ -23,14 +30,12 @@ interface ApplyState {
subcommand: 'apply'; subcommand: 'apply';
repo: Repository; repo: Repository;
stash: { stashName: string; message: string; ref: string; repoPath: string }; stash: { stashName: string; message: string; ref: string; repoPath: string };
flags: string[];
} }
interface DropState { interface DropState {
subcommand: 'drop'; subcommand: 'drop';
repo: Repository; repo: Repository;
stash: { stashName: string; message: string; ref: string; repoPath: string }; stash: { stashName: string; message: string; ref: string; repoPath: string };
flags: string[];
} }
interface ListState { interface ListState {
@ -42,15 +47,16 @@ interface PopState {
subcommand: 'pop'; subcommand: 'pop';
repo: Repository; repo: Repository;
stash: { stashName: string; message: string; ref: string; repoPath: string }; stash: { stashName: string; message: string; ref: string; repoPath: string };
flags: string[];
} }
type PushFlags = '--include-untracked' | '--keep-index';
interface PushState { interface PushState {
subcommand: 'push'; subcommand: 'push';
repo: Repository; repo: Repository;
message?: string; message?: string;
uris?: Uri[]; uris?: Uri[];
flags: string[];
flags: PushFlags[];
} }
type State = ApplyState | DropState | ListState | PopState | PushState; type State = ApplyState | DropState | ListState | PopState | PushState;
@ -373,7 +379,7 @@ export class StashGitCommand extends QuickCommandBase {
? `${state.stash.message.substring(0, 80)}${GlyphChars.Ellipsis}` ? `${state.stash.message.substring(0, 80)}${GlyphChars.Ellipsis}`
: state.stash.message; : state.stash.message;
const step = this.createConfirmStep<GitFlagsQuickPickItem & { command: 'apply' | 'pop' }>(
const step = this.createConfirmStep<QuickPickItem & { command: 'apply' | 'pop' }>(
`Confirm ${this.title} ${getSubtitle(state.subcommand)}${Strings.pad(GlyphChars.Dot, 2, 2)}${ `Confirm ${this.title} ${getSubtitle(state.subcommand)}${Strings.pad(GlyphChars.Dot, 2, 2)}${
state.repo.formattedName state.repo.formattedName
}`, }`,
@ -389,8 +395,7 @@ export class StashGitCommand extends QuickCommandBase {
: `Will apply the changes from ${state.stash!.stashName} to the working tree of ${ : `Will apply the changes from ${state.stash!.stashName} to the working tree of ${
state.repo.formattedName state.repo.formattedName
}`, }`,
command: state.subcommand!,
item: []
command: state.subcommand!
}, },
// Alternate confirmation (if pop then apply, and vice versa) // Alternate confirmation (if pop then apply, and vice versa)
{ {
@ -404,8 +409,7 @@ export class StashGitCommand extends QuickCommandBase {
: `Will delete ${ : `Will delete ${
state.stash!.stashName state.stash!.stashName
} and apply the changes to the working tree of ${state.repo.formattedName}`, } and apply the changes to the working tree of ${state.repo.formattedName}`,
command: state.subcommand === 'pop' ? 'apply' : 'pop',
item: []
command: state.subcommand === 'pop' ? 'apply' : 'pop'
} }
], ],
undefined, undefined,
@ -429,9 +433,6 @@ export class StashGitCommand extends QuickCommandBase {
} }
state.subcommand = selection[0].command; state.subcommand = selection[0].command;
state.flags = selection[0].item;
} else {
state.flags = state.flags || [];
} }
void Container.git.stashApply(state.repo.path, state.stash!.stashName, state.subcommand === 'pop'); void Container.git.stashApply(state.repo.path, state.stash!.stashName, state.subcommand === 'pop');
@ -504,7 +505,7 @@ export class StashGitCommand extends QuickCommandBase {
? `${state.stash.message.substring(0, 80)}${GlyphChars.Ellipsis}` ? `${state.stash.message.substring(0, 80)}${GlyphChars.Ellipsis}`
: state.stash.message; : state.stash.message;
const step = this.createConfirmStep<QuickPickItem>(
const step = this.createConfirmStep(
`Confirm ${this.title} ${getSubtitle(state.subcommand)}${Strings.pad(GlyphChars.Dot, 2, 2)}${ `Confirm ${this.title} ${getSubtitle(state.subcommand)}${Strings.pad(GlyphChars.Dot, 2, 2)}${
state.repo.formattedName state.repo.formattedName
}`, }`,
@ -648,6 +649,10 @@ export class StashGitCommand extends QuickCommandBase {
// eslint-disable-next-line @typescript-eslint/require-await // eslint-disable-next-line @typescript-eslint/require-await
private async *push(state: StashStepState<PushState>): StepAsyncGenerator { private async *push(state: StashStepState<PushState>): StepAsyncGenerator {
if (state.flags == null) {
state.flags = [];
}
while (true) { while (true) {
if (state.message === undefined || state.counter < 3) { if (state.message === undefined || state.counter < 3) {
const step = this.createInputStep({ const step = this.createInputStep({
@ -668,52 +673,47 @@ export class StashGitCommand extends QuickCommandBase {
} }
if (this.confirm(state.confirm)) { if (this.confirm(state.confirm)) {
const step = this.createConfirmStep<GitFlagsQuickPickItem>(
const step: QuickPickStep<FlagsQuickPickItem<PushFlags>> = this.createConfirmStep(
`Confirm ${this.title} ${getSubtitle(state.subcommand)}${Strings.pad(GlyphChars.Dot, 2, 2)}${ `Confirm ${this.title} ${getSubtitle(state.subcommand)}${Strings.pad(GlyphChars.Dot, 2, 2)}${
state.repo.formattedName state.repo.formattedName
}`, }`,
state.uris === undefined || state.uris.length === 0 state.uris === undefined || state.uris.length === 0
? [ ? [
{
FlagsQuickPickItem.create<PushFlags>(state.flags, [], {
label: `${this.title} ${getSubtitle(state.subcommand)}`, label: `${this.title} ${getSubtitle(state.subcommand)}`,
description: state.message, description: state.message,
detail: 'Will stash uncommitted changes',
item: []
},
{
detail: 'Will stash uncommitted changes'
}),
FlagsQuickPickItem.create<PushFlags>(state.flags, ['--include-untracked'], {
label: `${this.title} ${getSubtitle(state.subcommand)} & Include Untracked`, label: `${this.title} ${getSubtitle(state.subcommand)} & Include Untracked`,
description: `--include-untracked ${state.message}`, description: `--include-untracked ${state.message}`,
detail: 'Will stash uncommitted changes, including untracked files',
item: ['--include-untracked']
},
{
detail: 'Will stash uncommitted changes, including untracked files'
}),
FlagsQuickPickItem.create<PushFlags>(state.flags, ['--keep-index'], {
label: `${this.title} ${getSubtitle(state.subcommand)} & Keep Staged`, label: `${this.title} ${getSubtitle(state.subcommand)} & Keep Staged`,
description: `--keep-index ${state.message}`, description: `--keep-index ${state.message}`,
detail: 'Will stash uncommitted changes, but will keep staged files intact',
item: ['--keep-index']
}
detail: 'Will stash uncommitted changes, but will keep staged files intact'
})
] ]
: [ : [
{
FlagsQuickPickItem.create<PushFlags>(state.flags, [], {
label: `${this.title} ${getSubtitle(state.subcommand)}`, label: `${this.title} ${getSubtitle(state.subcommand)}`,
description: state.message, description: state.message,
detail: `Will stash changes in ${ detail: `Will stash changes in ${
state.uris.length === 1 state.uris.length === 1
? GitUri.getFormattedPath(state.uris[0], { relativeTo: state.repo.path }) ? GitUri.getFormattedPath(state.uris[0], { relativeTo: state.repo.path })
: `${state.uris.length} files` : `${state.uris.length} files`
}`,
item: []
},
{
}`
}),
FlagsQuickPickItem.create<PushFlags>(state.flags, ['--keep-index'], {
label: `${this.title} ${getSubtitle(state.subcommand)} & Keep Staged`, label: `${this.title} ${getSubtitle(state.subcommand)} & Keep Staged`,
description: `--keep-index ${state.message}`, description: `--keep-index ${state.message}`,
detail: `Will stash changes in ${ detail: `Will stash changes in ${
state.uris.length === 1 state.uris.length === 1
? GitUri.getFormattedPath(state.uris[0], { relativeTo: state.repo.path }) ? GitUri.getFormattedPath(state.uris[0], { relativeTo: state.repo.path })
: `${state.uris.length} files` : `${state.uris.length} files`
}, but will keep staged files intact`,
item: ['--keep-index']
}
}, but will keep staged files intact`
})
], ],
undefined, undefined,
{ placeholder: `Confirm ${this.title} ${getSubtitle(state.subcommand)}` } { placeholder: `Confirm ${this.title} ${getSubtitle(state.subcommand)}` }
@ -725,8 +725,6 @@ export class StashGitCommand extends QuickCommandBase {
} }
state.flags = selection[0].item; state.flags = selection[0].item;
} else {
state.flags = state.flags || [];
} }
void Container.git.stashSave(state.repo.path, state.message, state.uris, { void Container.git.stashSave(state.repo.path, state.message, state.uris, {

+ 1
- 1
src/commands/quickCommand.ts View File

@ -169,7 +169,7 @@ export abstract class QuickCommandBase implements QuickPickItem {
placeholder: `Confirm ${this.title}`, placeholder: `Confirm ${this.title}`,
title: title, title: title,
items: [...confirmations, cancel || DirectiveQuickPickItem.create(Directive.Cancel)], items: [...confirmations, cancel || DirectiveQuickPickItem.create(Directive.Cancel)],
selectedItems: [confirmations[0]],
selectedItems: [confirmations.find(c => c.picked) || confirmations[0]],
...options ...options
}); });
} }

+ 13
- 1
src/quickpicks/gitQuickPicks.ts View File

@ -18,7 +18,19 @@ export interface QuickPickItemOfT extends QuickPickItem {
readonly item: T; readonly item: T;
} }
export interface GitFlagsQuickPickItem extends QuickPickItemOfT<string[]> {}
export interface FlagsQuickPickItem<T> extends QuickPickItemOfT<T[]> {}
export namespace FlagsQuickPickItem {
export function create<T>(flags: T[], item: T[], options: QuickPickItem) {
return { ...options, item: item, picked: hasFlags(flags, item) };
}
}
function hasFlags<T>(flags: T[], has?: T | T[]): boolean {
if (has === undefined) return flags.length === 0;
if (!Array.isArray(has)) return flags.includes(has);
return has.length === 0 ? flags.length === 0 : has.every(f => flags.includes(f));
}
export enum Directive { export enum Directive {
Back = 'Back', Back = 'Back',

Loading…
Cancel
Save