git model

This commit is contained in:
Joao Moreno 2016-11-29 17:09:55 +01:00
parent bb6c30a333
commit 178310abe4
12 changed files with 270 additions and 36 deletions

View file

@ -91,9 +91,9 @@
]
},
"dependencies": {
"core-decorators": "^0.14.0",
"denodeify": "^1.2.1",
"lodash": "^4.17.2",
"mime": "^1.3.4",
"vscode-nls": "^2.0.1"
}
}
}

View file

@ -14,7 +14,6 @@ import { IDisposable, toDisposable, dispose } from './util';
import * as _ from 'lodash';
import { EventEmitter, Event } from 'vscode';
import * as nls from 'vscode-nls';
import * as mime from 'mime';
const localize = nls.loadMessageBundle(__filename);
const readdir = denodeify(fs.readdir);
@ -33,7 +32,6 @@ export interface IFileStatus {
x: string;
y: string;
path: string;
mimetype: string;
rename?: string;
}
@ -743,8 +741,7 @@ export class Repository {
current = {
x: status.charAt(i++),
y: status.charAt(i++),
path: '',
mimetype: ''
path: ''
};
i++;
@ -754,7 +751,6 @@ export class Repository {
}
current.path = readName();
current.mimetype = mime.lookup(current.path);
// If path ends with slash, it must be a nested git repo
if (current.path[current.path.length - 1] === '/') {

View file

@ -8,6 +8,7 @@
import { scm, ExtensionContext, workspace, Uri, window, Disposable } from 'vscode';
import * as path from 'path';
import { findGit, Git } from './git';
import { Model } from './model';
import { registerCommands } from './commands';
import * as nls from 'vscode-nls';
@ -61,6 +62,12 @@ async function init(disposables: Disposable[]): Promise<void> {
const pathHint = workspace.getConfiguration('git').get<string>('path');
const info = await findGit(pathHint);
const git = new Git({ gitPath: info.path, version: info.version });
const repository = git.open(rootPath);
const model = new Model(repository);
model.onDidChange(() => {
console.log(model.status);
});
const outputChannel = window.createOutputChannel('git');
outputChannel.appendLine(`Using git ${info.version} from ${info.path}`);

View file

@ -0,0 +1,76 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { EventEmitter, Event } from 'vscode';
import { Repository, IRef, IFileStatus, IRemote } from './git';
import { throttle } from './util';
import { decorate, debounce } from 'core-decorators';
export class Model {
private _onDidChange = new EventEmitter<void>();
readonly onDidChange: Event<void> = this._onDidChange.event;
constructor(private repository: Repository) {
}
private _status: IFileStatus[];
get status(): IFileStatus[] {
return this._status;
}
private _HEAD: IRef | undefined;
get HEAD(): IRef | undefined {
return this._HEAD;
}
private _refs: IRef[];
get refs(): IRef[] {
return this._refs;
}
private _remotes: IRemote[];
get remotes(): IRemote[] {
return this._remotes;
}
@debounce(500)
triggerUpdate(): void {
this.update();
}
@decorate(throttle)
private async update(): Promise<void> {
console.log('START');
const status = await this.repository.getStatus();
let HEAD: IRef | undefined;
try {
HEAD = await this.repository.getHEAD();
if (HEAD.name) {
try {
HEAD = await this.repository.getBranch(HEAD.name);
} catch (err) {
// noop
}
}
} catch (err) {
// noop
}
const [refs, remotes] = await Promise.all([this.repository.getRefs(), this.repository.getRemotes()]);
this._status = status;
this._HEAD = HEAD;
this._refs = refs;
this._remotes = remotes;
console.log('END');
this._onDidChange.fire();
}
}

View file

@ -1,7 +1,7 @@
{
"globalDependencies": {
"core-decorators": "registry:dt/core-decorators#0.10.0+20160316155526",
"denodeify": "registry:dt/denodeify#1.2.1+20160316155526",
"lodash": "registry:dt/lodash#4.14.0+20161110215204",
"mime": "registry:dt/mime#0.0.0+20160316155526"
"lodash": "registry:dt/lodash#4.14.0+20161110215204"
}
}
}

View file

@ -0,0 +1,133 @@
// Generated by typings
// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/56295f5058cac7ae458540423c50ac2dcf9fc711/core-decorators/core-decorators.d.ts
declare module "core-decorators" {
export interface ClassDecorator {
<TFunction extends Function>(target: TFunction): TFunction|void;
}
export interface ParameterDecorator {
(target: Object, propertyKey: string|symbol, parameterIndex: number): void;
}
export interface PropertyDecorator {
(target: Object, propertyKey: string|symbol): void;
}
export interface MethodDecorator {
<T>(target: Object, propertyKey: string|symbol, descriptor: TypedPropertyDescriptor<T>): TypedPropertyDescriptor<T>|void;
}
export interface PropertyOrMethodDecorator extends MethodDecorator, PropertyDecorator {
(target: Object, propertyKey: string|symbol): void;
}
export interface Deprecate extends MethodDecorator {
(message?: string, option?: DeprecateOption): MethodDecorator;
}
export interface DeprecateOption {
url: string;
}
export interface ThrottleOptions {
/** allows to trigger function on the leading. */
leading?: boolean;
/** allows to trigger function on the trailing edge of the wait interval. */
trailing?: boolean;
}
export interface Console {
log(message?: any, ...optionalParams: any[]): void;
time(timerName?: string): void;
timeEnd(timerName?: string): void;
}
/**
* Forces invocations of this function to always have this refer to the class instance,
* even if the function is passed around or would otherwise lose its this context. e.g. var fn = context.method;
*/
var autobind: Function;
/**
* Marks a property or method as not being writable.
*/
var readonly: PropertyOrMethodDecorator;
/**
* Checks that the marked method indeed overrides a function with the same signature somewhere on the prototype chain.
*/
var override: MethodDecorator;
/**
* Calls console.warn() with a deprecation message. Provide a custom message to override the default one. You can also provide an options hash with a url, for further reading.
*/
var deprecate: Deprecate;
/**
* Calls console.warn() with a deprecation message. Provide a custom message to override the default one. You can also provide an options hash with a url, for further reading.
*/
var deprecated: Deprecate;
/**
* Creates a new debounced function which will be invoked after wait milliseconds since the time it was invoked. Default timeout is 300 ms.
*/
var debounce: (wait: number) => MethodDecorator;
/**
* Creates a new throttled function which will be invoked in every wait milliseconds. Default timeout is 300 ms.
*/
var throttle: (wait: number, options?: ThrottleOptions) => MethodDecorator;
/**
* Suppresses any JavaScript console.warn() call while the decorated function is called. (i.e. on the stack)
*/
var suppressWarnings: MethodDecorator;
/**
* Marks a property or method as not being enumerable.
*/
var nonenumerable: PropertyOrMethodDecorator;
/**
* Marks a property or method as not being writable.
*/
var nonconfigurable: PropertyOrMethodDecorator;
/**
* Initial implementation included, likely slow. WIP.
*/
var memoize: MethodDecorator;
/**
* Immediately applies the provided function and arguments to the method, allowing you to wrap methods with arbitrary helpers like those provided by lodash.
* The first argument is the function to apply, all further arguments will be passed to that decorating function.
*/
var decorate: (func: Function, ...args: any[]) => MethodDecorator;
/**
* Prevents a property initializer from running until the decorated property is actually looked up.
* Useful to prevent excess allocations that might otherwise not be used, but be careful not to over-optimize things.
*/
var lazyInitialize: PropertyDecorator;
/**
* Mixes in all property descriptors from the provided Plain Old JavaScript Objects (aka POJOs) as arguments.
* Mixins are applied in the order they are passed, but do not override descriptors already on the class, including those inherited traditionally.
*/
var mixin: (...mixins: any[]) => ClassDecorator;
/**
* Mixes in all property descriptors from the provided Plain Old JavaScript Objects (aka POJOs) as arguments.
* Mixins are applied in the order they are passed, but do not override descriptors already on the class, including those inherited traditionally.
*/
var mixins: (...mixins: any[]) => ClassDecorator;
/**
* Uses console.time and console.timeEnd to provide function timings with a unique label whose default prefix is ClassName.method. Supply a first argument to override the prefix:
*/
var time: (label: string, console?: Console) => MethodDecorator;
export {
autobind,
readonly,
override,
deprecate,
deprecated,
debounce,
throttle,
suppressWarnings,
nonenumerable,
nonconfigurable,
memoize,
decorate,
lazyInitialize,
mixin,
mixins,
time,
};
}

View file

@ -0,0 +1,8 @@
{
"resolution": "main",
"tree": {
"src": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/56295f5058cac7ae458540423c50ac2dcf9fc711/core-decorators/core-decorators.d.ts",
"raw": "registry:dt/core-decorators#0.10.0+20160316155526",
"typings": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/56295f5058cac7ae458540423c50ac2dcf9fc711/core-decorators/core-decorators.d.ts"
}
}

View file

@ -1,15 +0,0 @@
// Generated by typings
// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/56295f5058cac7ae458540423c50ac2dcf9fc711/mime/mime.d.ts
declare module "mime" {
export function lookup(path: string): string;
export function extension(mime: string): string;
export function load(filepath: string): void;
export function define(mimes: Object): void;
interface Charsets {
lookup(mime: string): string;
}
export var charsets: Charsets;
export var default_type: string;
}

View file

@ -1,8 +0,0 @@
{
"resolution": "main",
"tree": {
"src": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/56295f5058cac7ae458540423c50ac2dcf9fc711/mime/mime.d.ts",
"raw": "registry:dt/mime#0.0.0+20160316155526",
"typings": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/56295f5058cac7ae458540423c50ac2dcf9fc711/mime/mime.d.ts"
}
}

View file

@ -1,3 +1,3 @@
/// <reference path="globals/core-decorators/index.d.ts" />
/// <reference path="globals/denodeify/index.d.ts" />
/// <reference path="globals/lodash/index.d.ts" />
/// <reference path="globals/mime/index.d.ts" />

View file

@ -34,4 +34,38 @@ export function filterEvent<T>(event: Event<T>, filter: (e: T) => boolean): Even
export function anyEvent<T>(...events: Event<T>[]): Event<T> {
return (listener, thisArgs = null, disposables?) => combinedDisposable(events.map(event => event(i => listener.call(thisArgs, i), disposables)));
}
export function done<T>(promise: Promise<T>): Promise<void> {
return promise.then(() => null, () => null);
}
export function throttle<T>(fn: () => Promise<T>): () => Promise<T> {
let current: Promise<T> | undefined;
let next: Promise<T> | undefined;
const trigger = () => {
if (next) {
return next;
}
if (current) {
next = done(current).then(() => {
next = undefined;
return trigger();
});
return next;
}
current = fn.call(this) as Promise<T>;
done(current).then(() => {
current = undefined;
});
return current;
};
return trigger;
}

View file

@ -1,10 +1,13 @@
{
"compilerOptions": {
"target": "es6",
"lib": ["es2016"],
"lib": [
"es2016"
],
"module": "commonjs",
"outDir": "./out",
"strictNullChecks": true
"strictNullChecks": true,
"experimentalDecorators": true
},
"exclude": [
"node_modules"