Refactors git models & parsers

Adds full git status parsing
Adds git status info into status quick pick
Switches to async/await in file blame/log
This commit is contained in:
Eric Amodio
2017-03-19 00:36:51 -04:00
parent 14eebbba15
commit ef74ae0950
19 changed files with 556 additions and 407 deletions

View File

@@ -1,6 +1,6 @@
'use strict';
import { QuickPickItem, Uri } from 'vscode';
import { getGitStatusIcon, GitCommit, GitFileStatus, GitService, GitUri } from '../gitService';
import { getGitStatusIcon, GitCommit, GitStatusFileStatus, GitService, GitUri } from '../gitService';
import { OpenFileCommandQuickPickItem } from './quickPicks';
import * as moment from 'moment';
import * as path from 'path';
@@ -24,9 +24,9 @@ export class CommitWithFileStatusQuickPickItem extends OpenFileCommandQuickPickI
gitUri: GitUri;
sha: string;
shortSha: string;
status: GitFileStatus;
status: GitStatusFileStatus;
constructor(commit: GitCommit, fileName: string, status: GitFileStatus) {
constructor(commit: GitCommit, fileName: string, status: GitStatusFileStatus) {
const icon = getGitStatusIcon(status);
let directory = path.dirname(fileName);

View File

@@ -2,15 +2,15 @@
import { Iterables } from '../system';
import { QuickPickItem, QuickPickOptions, Uri, window } from 'vscode';
import { Commands, Keyboard } from '../commands';
import { getGitStatusIcon, GitFileStatusItem } from '../gitService';
import { GitStatusFile, IGitStatus } from '../gitService';
import { CommandQuickPickItem, getQuickPickIgnoreFocusOut, OpenFileCommandQuickPickItem } from './quickPicks';
import * as path from 'path';
export class OpenStatusFileCommandQuickPickItem extends OpenFileCommandQuickPickItem {
constructor(status: GitFileStatusItem, item?: QuickPickItem) {
constructor(status: GitStatusFile, item?: QuickPickItem) {
const uri = Uri.file(path.resolve(status.repoPath, status.fileName));
const icon = getGitStatusIcon(status.status);
const icon = status.getIcon();
let directory = path.dirname(status.fileName);
if (!directory || directory === '.') {
@@ -26,7 +26,7 @@ export class OpenStatusFileCommandQuickPickItem extends OpenFileCommandQuickPick
export class OpenStatusFilesCommandQuickPickItem extends CommandQuickPickItem {
constructor(statuses: GitFileStatusItem[], item?: QuickPickItem) {
constructor(statuses: GitStatusFile[], item?: QuickPickItem) {
const repoPath = statuses.length && statuses[0].repoPath;
const uris = statuses.map(_ => Uri.file(path.resolve(repoPath, _.fileName)));
@@ -40,50 +40,71 @@ export class OpenStatusFilesCommandQuickPickItem extends CommandQuickPickItem {
export class RepoStatusQuickPick {
static async show(statuses: GitFileStatusItem[], goBackCommand?: CommandQuickPickItem): Promise<OpenStatusFileCommandQuickPickItem | OpenStatusFilesCommandQuickPickItem | CommandQuickPickItem | undefined> {
static async show(status: IGitStatus, goBackCommand?: CommandQuickPickItem): Promise<OpenStatusFileCommandQuickPickItem | OpenStatusFilesCommandQuickPickItem | CommandQuickPickItem | undefined> {
// Sort the status by staged and then filename
statuses.sort((a, b) => (a.staged ? -1 : 1) - (b.staged ? -1 : 1) || a.fileName.localeCompare(b.fileName));
const files = status.files;
files.sort((a, b) => (a.staged ? -1 : 1) - (b.staged ? -1 : 1) || a.fileName.localeCompare(b.fileName));
const items = Array.from(Iterables.map(statuses, s => new OpenStatusFileCommandQuickPickItem(s))) as (OpenStatusFileCommandQuickPickItem | OpenStatusFilesCommandQuickPickItem | CommandQuickPickItem)[];
const added = files.filter(_ => _.status === 'A' || _.status === '?');
const deleted = files.filter(_ => _.status === 'D');
const changed = files.filter(_ => _.status !== 'A' && _.status !== '?' && _.status !== 'D');
if (statuses.some(_ => _.staged)) {
const hasStaged = files.some(_ => _.staged);
let stagedStatus = '';
let unstagedStatus = '';
if (hasStaged) {
const stagedAdded = added.filter(_ => _.staged).length;
const stagedChanged = changed.filter(_ => _.staged).length;
const stagedDeleted = deleted.filter(_ => _.staged).length;
stagedStatus = `+${stagedAdded} ~${stagedChanged} -${stagedDeleted}`;
unstagedStatus = `+${added.length - stagedAdded} ~${changed.length - stagedChanged} -${deleted.length - stagedDeleted}`;
}
else {
unstagedStatus = `+${added.length} ~${changed.length} -${deleted.length}`;
}
const items = Array.from(Iterables.map(files, s => new OpenStatusFileCommandQuickPickItem(s))) as (OpenStatusFileCommandQuickPickItem | OpenStatusFilesCommandQuickPickItem | CommandQuickPickItem)[];
if (hasStaged) {
let index = 0;
const unstagedIndex = statuses.findIndex(_ => !_.staged);
const unstagedIndex = files.findIndex(_ => !_.staged);
if (unstagedIndex > -1) {
items.splice(unstagedIndex, 0, new CommandQuickPickItem({
label: `Unstaged Files`,
description: undefined
description: unstagedStatus
}, Commands.ShowQuickRepoStatus, [goBackCommand]));
items.splice(index++, 0, new OpenStatusFilesCommandQuickPickItem(statuses.filter(_ => _.status !== 'D' && _.staged), {
label: `$(file-symlink-file) Open Staged Files`,
items.splice(unstagedIndex, 0, new OpenStatusFilesCommandQuickPickItem(files.filter(_ => _.status !== 'D' && _.staged), {
label: `\u00a0\u00a0\u00a0\u00a0 $(file-symlink-file) Open Staged Files`,
description: undefined
}));
items.splice(index++, 0, new OpenStatusFilesCommandQuickPickItem(statuses.filter(_ => _.status !== 'D' && !_.staged), {
label: `$(file-symlink-file) Open Unstaged Files`,
items.push(new OpenStatusFilesCommandQuickPickItem(files.filter(_ => _.status !== 'D' && !_.staged), {
label: `\u00a0\u00a0\u00a0\u00a0 $(file-symlink-file) Open Unstaged Files`,
description: undefined
}));
}
items.splice(index++, 0, new CommandQuickPickItem({
label: `Staged Files`,
description: undefined
description: stagedStatus
}, Commands.ShowQuickRepoStatus, [goBackCommand]));
}
else if (statuses.some(_ => !_.staged)) {
else if (files.some(_ => !_.staged)) {
items.splice(0, 0, new CommandQuickPickItem({
label: `Unstaged Files`,
description: undefined
description: unstagedStatus
}, Commands.ShowQuickRepoStatus, [goBackCommand]));
}
if (statuses.length) {
if (files.length) {
items.splice(0, 0, new CommandQuickPickItem({
label: '$(x) Close Unchanged Files',
description: null
}, Commands.CloseUnchangedFiles));
items.splice(0, 0, new OpenStatusFilesCommandQuickPickItem(statuses.filter(_ => _.status !== 'D')));
items.splice(0, 0, new OpenStatusFilesCommandQuickPickItem(files.filter(_ => _.status !== 'D')));
}
if (goBackCommand) {
@@ -92,9 +113,18 @@ export class RepoStatusQuickPick {
const scope = await Keyboard.instance.beginScope({ left: goBackCommand });
let syncStatus = '';
if (status.upstream) {
syncStatus = status.state.ahead || status.state.behind
? `..${status.upstream} ${status.state.behind}\u2193 ${status.state.ahead}\u2191`
: `..${status.upstream} \u27F3`;
}
else {
}
const pick = await window.showQuickPick(items, {
matchOnDescription: true,
placeHolder: statuses.length ? 'Repository has changes' : 'Repository has no changes',
placeHolder: `${status.branch}${syncStatus}`,
ignoreFocusOut: getQuickPickIgnoreFocusOut(),
onDidSelectItem: (item: QuickPickItem) => {
scope.setKeyCommand('right', item);