Browse Source

Adds revert git command

main
Eric Amodio 5 years ago
parent
commit
8566ed72e8
2 changed files with 189 additions and 1 deletions
  1. +185
    -0
      src/commands/git/revert.ts
  2. +4
    -1
      src/commands/gitCommands.ts

+ 185
- 0
src/commands/git/revert.ts View File

@ -0,0 +1,185 @@
'use strict';
/* eslint-disable no-loop-func */
import { Container } from '../../container';
import { GitReference, Repository } from '../../git/gitService';
import { GlyphChars } from '../../constants';
import { Iterables, Strings } from '../../system';
import { QuickCommandBase, StepAsyncGenerator, StepSelection, StepState } from '../quickCommand';
import {
CommitQuickPickItem,
Directive,
DirectiveQuickPickItem,
GitFlagsQuickPickItem,
RepositoryQuickPickItem
} from '../../quickpicks';
import { runGitCommandInTerminal } from '../../terminal';
import { Logger } from '../../logger';
interface State {
repo: Repository;
references?: GitReference[];
flags: string[];
}
export interface RevertGitCommandArgs {
readonly command: 'revert';
state?: Partial<State>;
}
export class RevertGitCommand extends QuickCommandBase<State> {
constructor(args?: RevertGitCommandArgs) {
super('revert', 'revert', 'Revert', false, { description: 'via Terminal' });
if (args === undefined || args.state === undefined) return;
let counter = 0;
if (args.state.repo !== undefined) {
counter++;
}
if (args.state.references !== undefined) {
counter++;
}
this._initialState = {
counter: counter,
confirm: true,
...args.state
};
}
execute(state: State) {
runGitCommandInTerminal(
'revert',
[...state.flags, ...state.references!.map(c => c.ref).reverse()].join(' '),
state.repo.path,
true
);
}
protected async *steps(): StepAsyncGenerator {
const state: StepState<State> = this._initialState === undefined ? { counter: 0 } : this._initialState;
let oneRepo = false;
while (true) {
try {
if (state.repo === undefined || state.counter < 1) {
const repos = [...(await Container.git.getOrderedRepositories())];
if (repos.length === 1) {
oneRepo = true;
state.counter++;
state.repo = repos[0];
} else {
const active = state.repo ? state.repo : await Container.git.getActiveRepository();
const step = this.createPickStep<RepositoryQuickPickItem>({
title: this.title,
placeholder: 'Choose a repository',
items: await Promise.all(
repos.map(r =>
RepositoryQuickPickItem.create(r, r.id === (active && active.id), {
branch: true,
fetched: true,
status: true
})
)
)
});
const selection: StepSelection<typeof step> = yield step;
if (!this.canPickStepMoveNext(step, state, selection)) {
break;
}
state.repo = selection[0].item;
}
}
const destination = await state.repo.getBranch();
if (destination === undefined) break;
if (state.references === undefined || state.counter < 2) {
const log = await Container.git.getLog(state.repo.path, {
ref: destination.ref,
merges: false
});
const step = this.createPickStep<CommitQuickPickItem>({
title: `${this.title} on ${destination.name}${Strings.pad(GlyphChars.Dot, 2, 2)}${
state.repo.formattedName
}`,
multiselect: log !== undefined,
placeholder:
log === undefined ? `${destination.name} has no commits` : 'Choose commits to revert',
matchOnDescription: true,
matchOnDetail: true,
items:
log === undefined
? [
DirectiveQuickPickItem.create(Directive.Back, true),
DirectiveQuickPickItem.create(Directive.Cancel)
]
: [
...Iterables.map(log.commits.values(), commit =>
CommitQuickPickItem.create(
commit,
state.references
? state.references.some(r => r.ref === commit.ref)
: undefined,
{ compact: true, icon: true }
)
)
]
});
const selection: StepSelection<typeof step> = yield step;
if (!this.canPickStepMoveNext(step, state, selection)) {
if (oneRepo) {
break;
}
continue;
}
state.references = selection.map(i => i.item);
}
const step = this.createConfirmStep<GitFlagsQuickPickItem>(
`Confirm ${this.title}${Strings.pad(GlyphChars.Dot, 2, 2)}${state.repo.formattedName}`,
[
{
label: this.title,
description: `${
state.references.length === 1
? state.references[0].name
: `${state.references.length} commits`
} on ${destination.name}`,
detail: `Will revert ${
state.references.length === 1
? `commit ${state.references[0].name}`
: `${state.references.length} commits`
} on ${destination.name}`,
item: []
}
]
);
const selection: StepSelection<typeof step> = yield step;
if (!this.canPickStepMoveNext(step, state, selection)) {
continue;
}
state.flags = selection[0].item;
this.execute(state as State);
break;
} catch (ex) {
Logger.error(ex, this.title);
throw ex;
}
}
return undefined;
}
}

+ 4
- 1
src/commands/gitCommands.ts View File

@ -18,6 +18,7 @@ import { PullGitCommand, PullGitCommandArgs } from './git/pull';
import { PushGitCommand, PushGitCommandArgs } from './git/push';
import { RebaseGitCommand, RebaseGitCommandArgs } from './git/rebase';
import { ResetGitCommand, ResetGitCommandArgs } from './git/reset';
import { RevertGitCommand, RevertGitCommandArgs } from './git/revert';
import { StashGitCommand, StashGitCommandArgs } from './git/stash';
import { SwitchGitCommand, SwitchGitCommandArgs } from './git/switch';
import { Container } from '../container';
@ -33,6 +34,7 @@ export type GitCommandsCommandArgs =
| PushGitCommandArgs
| RebaseGitCommandArgs
| ResetGitCommandArgs
| RevertGitCommandArgs
| StashGitCommandArgs
| SwitchGitCommandArgs;
@ -51,6 +53,7 @@ class PickCommandStep implements QuickPickStep {
new PushGitCommand(args && args.command === 'push' ? args : undefined),
new RebaseGitCommand(args && args.command === 'rebase' ? args : undefined),
new ResetGitCommand(args && args.command === 'reset' ? args : undefined),
new RevertGitCommand(args && args.command === 'revert' ? args : undefined),
new StashGitCommand(args && args.command === 'stash' ? args : undefined),
new SwitchGitCommand(args && args.command === 'switch' ? args : undefined)
];
@ -74,7 +77,7 @@ class PickCommandStep implements QuickPickStep {
find(commandName: string, fuzzy: boolean = false) {
if (fuzzy) {
const cmd = commandName.toLowerCase();
const cmd = commandName.toLowerCase();
return this.items.find(c => c.isMatch(cmd));
}

Loading…
Cancel
Save