diff --git a/src/vs/workbench/parts/git/browser/gitOperations.ts b/src/vs/workbench/parts/git/browser/gitOperations.ts index 146631f12b3f..669c5a923206 100644 --- a/src/vs/workbench/parts/git/browser/gitOperations.ts +++ b/src/vs/workbench/parts/git/browser/gitOperations.ts @@ -4,38 +4,22 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import git = require('vs/workbench/parts/git/common/git'); -import winjs = require('vs/base/common/winjs.base'); +import { IGitOperation, IRawStatus } from 'vs/workbench/parts/git/common/git'; +import { TPromise } from 'vs/base/common/winjs.base'; -export class GitOperation implements git.IGitOperation { +export class GitOperation implements IGitOperation { - constructor(public id: string, private fn: () => winjs.Promise) { - // noop + id: string; + + constructor(id: string, private fn: () => TPromise) { + this.id = id; } - public run(): winjs.Promise { + run(): TPromise { return this.fn(); } - public dispose(): void { + dispose(): void { // noop } -} - -export class CommandOperation implements git.IGitOperation { - - public id: string = git.ServiceOperations.COMMAND; - - constructor(public input:string) { - // noop - } - - public run(): winjs.Promise { - return winjs.TPromise.as(null); - } - - public dispose(): void { - this.id = null; - this.input = null; - } -} +} \ No newline at end of file diff --git a/src/vs/workbench/parts/git/browser/gitServices.ts b/src/vs/workbench/parts/git/browser/gitServices.ts index c46514fc0ec8..0dd68257327a 100644 --- a/src/vs/workbench/parts/git/browser/gitServices.ts +++ b/src/vs/workbench/parts/git/browser/gitServices.ts @@ -4,40 +4,40 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import nls = require('vs/nls'); -import platform = require('vs/base/common/platform'); -import winjs = require('vs/base/common/winjs.base'); -import lifecycle = require('vs/base/common/lifecycle'); -import types = require('vs/base/common/types'); -import actions = require('vs/base/common/actions'); -import errors = require('vs/base/common/errors'); -import mime = require('vs/base/common/mime'); -import paths = require('vs/base/common/paths'); -import ee = require('vs/base/common/eventEmitter'); -import WorkbenchEditorCommon = require('vs/workbench/common/editor'); -import git = require('vs/workbench/parts/git/common/git'); -import model = require('vs/workbench/parts/git/common/gitModel'); -import giteditorinputs = require('vs/workbench/parts/git/browser/gitEditorInputs'); -import operations = require('vs/workbench/parts/git/browser/gitOperations'); -import filesCommon = require('vs/workbench/parts/files/common/files'); +import { localize } from 'vs/nls'; +import * as platform from 'vs/base/common/platform'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { Action } from 'vs/base/common/actions'; +import { isPromiseCanceledError, create as createError } from 'vs/base/common/errors'; +import * as mime from 'vs/base/common/mime'; +import * as paths from 'vs/base/common/paths'; +import { EventEmitter } from 'vs/base/common/eventEmitter'; +import { EditorInput } from 'vs/workbench/common/editor'; +import { IFileStatus, IGitServiceError, GitErrorCodes, Status, StatusType, AutoFetcherState, IGitConfiguration, IAutoFetcher, ServiceEvents, ServiceState, + IModel, IGitOperation, IRawGitService, IGitService, IGitCredentialScope, RawServiceState, ServiceOperations, IPushOptions, ICommit, IRawStatus } from 'vs/workbench/parts/git/common/git'; +import { Model } from 'vs/workbench/parts/git/common/gitModel'; +import { NativeGitIndexStringEditorInput, GitIndexDiffEditorInput, GitWorkingTreeDiffEditorInput, GitDiffEditorInput } from 'vs/workbench/parts/git/browser/gitEditorInputs'; +import { GitOperation } from 'vs/workbench/parts/git/browser/gitOperations'; +import { EventType as WorkbenchFileEventType, TextFileChangeEvent } from 'vs/workbench/parts/files/common/files'; import { IFileService, EventType as FileEventType, FileChangesEvent, FileChangeType } from 'vs/platform/files/common/files'; -import async = require('vs/base/common/async'); +import { ThrottledDelayer, PeriodThrottledDelayer } from 'vs/base/common/async'; import severity from 'vs/base/common/severity'; -import {IOutputService} from 'vs/workbench/parts/output/common/output'; -import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService'; -import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; -import {IEventService} from 'vs/platform/event/common/event'; -import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; -import {IMessageService, CloseAction} from 'vs/platform/message/common/message'; -import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; -import {ILifecycleService} from 'vs/platform/lifecycle/common/lifecycle'; +import { IOutputService } from 'vs/workbench/parts/output/common/output'; +import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IEventService } from 'vs/platform/event/common/event'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IMessageService, CloseAction } from 'vs/platform/message/common/message'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import URI from 'vs/base/common/uri'; import * as semver from 'semver'; import { shell } from 'electron'; -import {IStorageService, StorageScope} from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import Event from 'vs/base/common/event'; import { domEvent } from 'vs/base/browser/event'; -import {IEditorGroupService} from 'vs/workbench/services/group/common/groupService'; +import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; function toReadablePath(path: string): string { if (!platform.isWindows) { @@ -47,19 +47,18 @@ function toReadablePath(path: string): string { return path.replace(/\//g, '\\'); } -class EditorInputCache -{ - private gitService: git.IGitService; +class EditorInputCache { + private gitService: GitService; private fileService: IFileService; private eventService: IEventService; private instantiationService: IInstantiationService; private editorService: IWorkbenchEditorService; private editorGroupService: IEditorGroupService; private contextService: IWorkspaceContextService; - private cache: { [key: string]: winjs.TPromise }; - private toDispose: lifecycle.IDisposable[]; + private cache: { [key: string]: TPromise }; + private toDispose: IDisposable[]; - constructor(gitService: git.IGitService, // gitService passed as argument, not by injection + constructor(gitService: GitService, @IInstantiationService instantiationService: IInstantiationService, @IFileService fileService: IFileService, @IEventService eventService: IEventService, @@ -79,10 +78,10 @@ class EditorInputCache this.cache = {}; this.toDispose = []; - this.toDispose.push(this.gitService.getModel().addListener2('fileStatus:dispose', (fileStatus: git.IFileStatus) => this.onFileStatusDispose(fileStatus))); + this.toDispose.push(this.gitService.getModel().addListener2('fileStatus:dispose', (fileStatus: IFileStatus) => this.onFileStatusDispose(fileStatus))); } - public getInput(status: git.IFileStatus): winjs.TPromise { + getInput(status: IFileStatus): TPromise { var result = this.cache[status.getId()]; if (result) { @@ -94,15 +93,15 @@ class EditorInputCache return result; } - private createInput(status: git.IFileStatus): winjs.TPromise { - return winjs.TPromise.join([this.createLeftInput(status), this.createRightInput(status)]).then((result) => { + private createInput(status: IFileStatus): TPromise { + return TPromise.join([this.createLeftInput(status), this.createRightInput(status)]).then((result) => { var leftInput = result[0]; var rightInput = result[1]; var fileSegment: string; var folderSegment: string; - if (status.getStatus() === git.Status.INDEX_RENAMED) { + if (status.getStatus() === Status.INDEX_RENAMED) { let pathComponents = status.getRename().split('/'); fileSegment = pathComponents[pathComponents.length - 1]; folderSegment = toReadablePath(pathComponents.slice(0, pathComponents.length - 1).join('/')); @@ -114,48 +113,48 @@ class EditorInputCache if (!leftInput) { if (!rightInput) { - var error = new Error(nls.localize('cantOpen', "Can't open this git resource.")); - ( error).gitErrorCode = git.GitErrorCodes.CantOpenResource; - return winjs.Promise.wrapError(error); + var error = new Error(localize('cantOpen', "Can't open this git resource.")); + (error).gitErrorCode = GitErrorCodes.CantOpenResource; + return TPromise.wrapError(error); } - return winjs.TPromise.as(rightInput); + return TPromise.as(rightInput); } switch (status.getStatus()) { - case git.Status.INDEX_MODIFIED: - return winjs.TPromise.as(new giteditorinputs.GitIndexDiffEditorInput(nls.localize('gitIndexChanges', "{0} (index) ↔ {1}", fileSegment, fileSegment), nls.localize('gitIndexChangesDesc', "{0} - Changes on index", folderSegment), leftInput, rightInput, status)); - case git.Status.INDEX_RENAMED: - return winjs.TPromise.as(new giteditorinputs.GitIndexDiffEditorInput(nls.localize('gitIndexChangesRenamed', "{0} ← {1}", status.getRename(), status.getPath()), nls.localize('gitIndexChangesRenamedDesc', "{0} - Renamed - Changes on index", folderSegment), leftInput, rightInput, status)); - case git.Status.MODIFIED: - return winjs.TPromise.as(new giteditorinputs.GitWorkingTreeDiffEditorInput(nls.localize('workingTreeChanges', "{0} (HEAD) ↔ {1}", fileSegment, fileSegment), nls.localize('workingTreeChangesDesc', "{0} - Changes on working tree", folderSegment), leftInput, rightInput, status)); + case Status.INDEX_MODIFIED: + return TPromise.as(new GitIndexDiffEditorInput(localize('gitIndexChanges', "{0} (index) ↔ {1}", fileSegment, fileSegment), localize('gitIndexChangesDesc', "{0} - Changes on index", folderSegment), leftInput, rightInput, status)); + case Status.INDEX_RENAMED: + return TPromise.as(new GitIndexDiffEditorInput(localize('gitIndexChangesRenamed', "{0} ← {1}", status.getRename(), status.getPath()), localize('gitIndexChangesRenamedDesc', "{0} - Renamed - Changes on index", folderSegment), leftInput, rightInput, status)); + case Status.MODIFIED: + return TPromise.as(new GitWorkingTreeDiffEditorInput(localize('workingTreeChanges', "{0} (HEAD) ↔ {1}", fileSegment, fileSegment), localize('workingTreeChangesDesc', "{0} - Changes on working tree", folderSegment), leftInput, rightInput, status)); default: - return winjs.TPromise.as(new giteditorinputs.GitDiffEditorInput(nls.localize('gitMergeChanges', "{0} (merge) ↔ {1}", fileSegment, fileSegment), nls.localize('gitMergeChangesDesc', "{0} - Merge changes", folderSegment), leftInput, rightInput, status)); + return TPromise.as(new GitDiffEditorInput(localize('gitMergeChanges', "{0} (merge) ↔ {1}", fileSegment, fileSegment), localize('gitMergeChangesDesc', "{0} - Merge changes", folderSegment), leftInput, rightInput, status)); } - }).then((editorInput:WorkbenchEditorCommon.EditorInput) => { + }).then((editorInput: EditorInput) => { editorInput.addOneTimeDisposableListener('dispose', () => { delete this.cache[status.getId()]; }); return editorInput; }, (errs) => { - return winjs.Promise.wrapError(types.isArray(errs) ? errs[0] || errs[1] : errs); + return TPromise.wrapError(Array.isArray(errs) ? errs[0] || errs[1] : errs); }); } - private createLeftInput(status: git.IFileStatus): winjs.Promise { + private createLeftInput(status: IFileStatus): TPromise { var path = status.getPath(); var model = this.gitService.getModel(); switch (status.getStatus()) { - case git.Status.INDEX_MODIFIED: - case git.Status.INDEX_RENAMED: + case Status.INDEX_MODIFIED: + case Status.INDEX_RENAMED: return this.gitService.show(path, status, 'HEAD', status.getMimetype()); - case git.Status.MODIFIED: - var indexStatus = model.getStatus().find(path, git.StatusType.INDEX); + case Status.MODIFIED: + var indexStatus = model.getStatus().find(path, StatusType.INDEX); - if (indexStatus && indexStatus.getStatus() === git.Status.INDEX_RENAMED) { + if (indexStatus && indexStatus.getStatus() === Status.INDEX_RENAMED) { return this.gitService.show(indexStatus.getRename(), status, '~', status.getMimetype()); } @@ -166,48 +165,48 @@ class EditorInputCache return this.gitService.show(path, status, 'HEAD', status.getMimetype()); default: - return winjs.TPromise.as(null); + return TPromise.as(null); } } - private createRightInput(status: git.IFileStatus): winjs.Promise { + private createRightInput(status: IFileStatus): TPromise { const model = this.gitService.getModel(); const path = status.getPath(); let resource = URI.file(paths.join(model.getRepositoryRoot(), path)); switch (status.getStatus()) { - case git.Status.INDEX_MODIFIED: - case git.Status.INDEX_ADDED: - case git.Status.INDEX_COPIED: + case Status.INDEX_MODIFIED: + case Status.INDEX_ADDED: + case Status.INDEX_COPIED: return this.gitService.show(path, status, '~', status.getMimetype()); - case git.Status.INDEX_RENAMED: + case Status.INDEX_RENAMED: return this.gitService.show(status.getRename(), status, '~', status.getMimetype()); - case git.Status.INDEX_DELETED: - case git.Status.DELETED: + case Status.INDEX_DELETED: + case Status.DELETED: return this.gitService.show(path, status, 'HEAD', status.getMimetype()); - case git.Status.MODIFIED: - case git.Status.UNTRACKED: - case git.Status.IGNORED: - var indexStatus = model.getStatus().find(path, git.StatusType.INDEX); + case Status.MODIFIED: + case Status.UNTRACKED: + case Status.IGNORED: + var indexStatus = model.getStatus().find(path, StatusType.INDEX); - if (indexStatus && indexStatus.getStatus() === git.Status.INDEX_RENAMED) { + if (indexStatus && indexStatus.getStatus() === Status.INDEX_RENAMED) { resource = URI.file(paths.join(model.getRepositoryRoot(), indexStatus.getRename())); } return this.editorService.createInput({ resource }); - case git.Status.BOTH_MODIFIED: + case Status.BOTH_MODIFIED: return this.editorService.createInput({ resource }); default: - return winjs.TPromise.as(null); + return TPromise.as(null); } } - private onFileStatusDispose(fileStatus: git.IFileStatus): void { + private onFileStatusDispose(fileStatus: IFileStatus): void { var id = fileStatus.getId(); var editorInputPromise = this.cache[id]; @@ -221,7 +220,7 @@ class EditorInputCache * But we should not do it while the input is still open. This method will eventually call dispose * when the editor input goes out of the visible editors. */ - private eventuallyDispose(editorInput: WorkbenchEditorCommon.EditorInput): void { + private eventuallyDispose(editorInput: EditorInput): void { if (!this.maybeDispose(editorInput)) { var listener = this.editorGroupService.onEditorsChanged(() => { if (this.maybeDispose(editorInput)) { @@ -231,7 +230,7 @@ class EditorInputCache } } - private maybeDispose(editorInput: WorkbenchEditorCommon.EditorInput): boolean { + private maybeDispose(editorInput: EditorInput): boolean { if (!editorInput.isDirty() && !this.editorService.getVisibleEditors().some((editor) => editor.input && editor.input.matches(editorInput))) { editorInput.dispose(); return true; @@ -240,40 +239,39 @@ class EditorInputCache return false; } - public dispose(): void { + dispose(): void { Object.keys(this.cache).forEach(key => { this.cache[key].done((editorInput) => { editorInput.dispose(); }); delete this.cache[key]; }); - this.toDispose = lifecycle.dispose(this.toDispose); + this.toDispose = dispose(this.toDispose); } } -export class AutoFetcher implements git.IAutoFetcher, lifecycle.IDisposable -{ +export class AutoFetcher implements IAutoFetcher, IDisposable { private static MIN_TIMEOUT = 2 * 60 * 1000; // every two minutes private static MAX_TIMEOUT = 5 * 60 * 1000; // every five minutes - private _state: git.AutoFetcherState; - private gitService: git.IGitService; + private _state: AutoFetcherState; + private gitService: GitService; private eventService: IEventService; private messageService: IMessageService; private configurationService: IConfigurationService; private instantiationService: IInstantiationService; - private currentRequest: winjs.Promise; + private currentRequest: TPromise; private timeout: number; - private toDispose: lifecycle.IDisposable[]; - private gitServiceStateDisposable: lifecycle.IDisposable; + private toDispose: IDisposable[]; + private gitServiceStateDisposable: IDisposable; - constructor(gitService: git.IGitService, // gitService passed as argument, not by injection + constructor(gitService: GitService, // gitService passed as argument, not by injection @IEventService eventService: IEventService, @IMessageService messageService: IMessageService, @IWorkbenchEditorService editorService: IWorkbenchEditorService, @IConfigurationService configurationService: IConfigurationService, @IInstantiationService instantiationService: IInstantiationService ) { - this._state = git.AutoFetcherState.Disabled; + this._state = AutoFetcherState.Disabled; this.gitService = gitService; this.eventService = eventService; this.messageService = messageService; @@ -284,14 +282,14 @@ export class AutoFetcher implements git.IAutoFetcher, lifecycle.IDisposable this.toDispose = []; this.toDispose.push(this.configurationService.onDidUpdateConfiguration(e => this.onConfiguration(e.config.git))); - this.onConfiguration(configurationService.getConfiguration('git')); + this.onConfiguration(configurationService.getConfiguration('git')); } - public get state(): git.AutoFetcherState { + get state(): AutoFetcherState { return this._state; } - private onConfiguration(config: git.IGitConfiguration): void { + private onConfiguration(config: IGitConfiguration): void { if (config.autofetch === false) { this.disable(); } else { @@ -299,69 +297,69 @@ export class AutoFetcher implements git.IAutoFetcher, lifecycle.IDisposable } } - public enable(): void { - if (this._state !== git.AutoFetcherState.Disabled) { + enable(): void { + if (this._state !== AutoFetcherState.Disabled) { return; } - this.gitServiceStateDisposable = this.gitService.addListener2(git.ServiceEvents.STATE_CHANGED, (e) => this.onGitServiceStateChange(e)); - this._state = git.AutoFetcherState.Active; + this.gitServiceStateDisposable = this.gitService.addListener2(ServiceEvents.STATE_CHANGED, (e) => this.onGitServiceStateChange(e)); + this._state = AutoFetcherState.Active; this.onGitServiceStateChange(this.gitService.getState()); } - public disable(): void { + disable(): void { if (this.gitServiceStateDisposable) { this.gitServiceStateDisposable.dispose(); this.gitServiceStateDisposable = null; } this.deactivate(); - this._state = git.AutoFetcherState.Disabled; + this._state = AutoFetcherState.Disabled; } - private onGitServiceStateChange(state: git.ServiceState): void { - if (state === git.ServiceState.OK) { + private onGitServiceStateChange(state: ServiceState): void { + if (state === ServiceState.OK) { this.activate(); } else { this.deactivate(); } } - public activate(): void { + activate(): void { if (this.currentRequest) { this.currentRequest.cancel(); } - this._state = git.AutoFetcherState.Active; + this._state = AutoFetcherState.Active; this.loop(); } - public deactivate(): void { + deactivate(): void { if (!this.currentRequest) { return; } - this._state = git.AutoFetcherState.Inactive; + this._state = AutoFetcherState.Inactive; this.currentRequest.cancel(); this.currentRequest = null; } private loop(): void { - this._state = git.AutoFetcherState.Fetching; + this._state = AutoFetcherState.Fetching; const remotes = this.gitService.getModel().getRemotes(); if (remotes.length === 0) { this.timeout = AutoFetcher.MIN_TIMEOUT; - this.currentRequest = winjs.TPromise.as(null); + this.currentRequest = TPromise.as(null); } else { this.currentRequest = this.gitService.fetch().then(() => { this.timeout = AutoFetcher.MIN_TIMEOUT; }, (err) => { - if (errors.isPromiseCanceledError(err)) { - return winjs.Promise.wrapError(err); - } else if (err.gitErrorCode === git.GitErrorCodes.AuthenticationFailed) { - return winjs.Promise.wrapError(err); + if (isPromiseCanceledError(err)) { + return TPromise.wrapError(err); + } else if (err.gitErrorCode === GitErrorCodes.AuthenticationFailed) { + return TPromise.wrapError(err); } else { this.timeout = Math.min(Math.round(this.timeout * 1.2), AutoFetcher.MAX_TIMEOUT); // backoff } @@ -369,47 +367,47 @@ export class AutoFetcher implements git.IAutoFetcher, lifecycle.IDisposable } this.currentRequest.then(() => { - this._state = git.AutoFetcherState.Active; - this.currentRequest = winjs.TPromise.timeout(this.timeout); + this._state = AutoFetcherState.Active; + this.currentRequest = TPromise.timeout(this.timeout); return this.currentRequest; }).then(() => this.loop(), (err) => this.deactivate()); } - public dispose(): void { + dispose(): void { this.disable(); } } interface IGitCredentialRequest { guid: string; - scope: git.IGitCredentialScope; + scope: IGitCredentialScope; } const IgnoreOldGitStorageKey = 'settings.workspace.git.ignoreOld'; -export class GitService extends ee.EventEmitter +export class GitService extends EventEmitter implements - git.IGitService { + IGitService { - public _serviceBrand: any; + _serviceBrand: any; private eventService: IEventService; private contextService: IWorkspaceContextService; private messageService: IMessageService; - private instantiationService:IInstantiationService; + private instantiationService: IInstantiationService; private editorService: IWorkbenchEditorService; private lifecycleService: ILifecycleService; private outputService: IOutputService; - protected raw: git.IRawGitService; + protected raw: IRawGitService; - private state: git.ServiceState; - private operations: git.IGitOperation[]; - private model: git.IModel; + private state: ServiceState; + private operations: IGitOperation[]; + private model: IModel; private inputCache: EditorInputCache; - private toDispose: lifecycle.IDisposable[]; + private toDispose: IDisposable[]; private needsRefresh: boolean; - private statusDelayer: async.ThrottledDelayer; - private reactiveStatusDelayer: async.PeriodThrottledDelayer; + private statusDelayer: ThrottledDelayer; + private reactiveStatusDelayer: PeriodThrottledDelayer; private autoFetcher: AutoFetcher; private isStatusPending = false; private isFocused = true; @@ -419,15 +417,15 @@ export class GitService extends ee.EventEmitter set allowHugeRepositories(value: boolean) { this._allowHugeRepositories = value; - if (value && this.state === git.ServiceState.Huge) { - this.transition(git.ServiceState.OK); + if (value && this.state === ServiceState.Huge) { + this.transition(ServiceState.OK); } } get onOutput(): Event { return this.raw.onOutput; } constructor( - raw: git.IRawGitService, + raw: IRawGitService, @IInstantiationService instantiationService: IInstantiationService, @IEventService eventService: IEventService, @IMessageService messageService: IMessageService, @@ -449,14 +447,14 @@ export class GitService extends ee.EventEmitter this.lifecycleService = lifecycleService; this.raw = raw; - this.state = git.ServiceState.NotInitialized; + this.state = ServiceState.NotInitialized; this.operations = []; - this.model = new model.Model(); + this.model = new Model(); this.toDispose = []; this.needsRefresh = false; - this.statusDelayer = new async.ThrottledDelayer(500); - this.reactiveStatusDelayer = new async.PeriodThrottledDelayer(500, 10000); + this.statusDelayer = new ThrottledDelayer(500); + this.reactiveStatusDelayer = new PeriodThrottledDelayer(500, 10000); this.autoFetcher = this.instantiationService.createInstance(AutoFetcher, this); this._allowHugeRepositories = false; @@ -468,7 +466,7 @@ export class GitService extends ee.EventEmitter if (!storageService.getBoolean(IgnoreOldGitStorageKey, StorageScope.GLOBAL, false)) { this.raw.serviceState().done(state => { - if (state !== git.RawServiceState.OK) { + if (state !== RawServiceState.OK) { return; } @@ -479,14 +477,14 @@ export class GitService extends ee.EventEmitter if (version && semver.satisfies(version, '<2.0.0')) { messageService.show(severity.Warning, { - message: nls.localize('updateGit', "You seem to have git {0} installed. Code works best with git >=2.0.0.", version), + message: localize('updateGit', "You seem to have git {0} installed. Code works best with git >=2.0.0.", version), actions: [ CloseAction, - new actions.Action('neverShowAgain', nls.localize('neverShowAgain', "Don't show again"), null, true, () => { + new Action('neverShowAgain', localize('neverShowAgain', "Don't show again"), null, true, () => { storageService.store(IgnoreOldGitStorageKey, true, StorageScope.GLOBAL); return null; }), - new actions.Action('downloadLatest', nls.localize('download', "Download"), '', true, () => { + new Action('downloadLatest', localize('download', "Download"), '', true, () => { shell.openExternal('https://git-scm.com/'); return null; }) @@ -498,16 +496,16 @@ export class GitService extends ee.EventEmitter } } - private registerListeners():void { - this.toDispose.push(this.eventService.addListener2(FileEventType.FILE_CHANGES,(e) => this.onFileChanges(e))); - this.toDispose.push(this.eventService.addListener2(filesCommon.EventType.FILE_SAVED, (e) => this.onTextFileChange(e))); - this.toDispose.push(this.eventService.addListener2(filesCommon.EventType.FILE_REVERTED, (e) => this.onTextFileChange(e))); + private registerListeners(): void { + this.toDispose.push(this.eventService.addListener2(FileEventType.FILE_CHANGES, (e) => this.onFileChanges(e))); + this.toDispose.push(this.eventService.addListener2(WorkbenchFileEventType.FILE_SAVED, (e) => this.onTextFileChange(e))); + this.toDispose.push(this.eventService.addListener2(WorkbenchFileEventType.FILE_REVERTED, (e) => this.onTextFileChange(e))); this.toDispose.push(this.configurationService.onDidUpdateConfiguration(() => { if (this._allowHugeRepositories) { return; } - const config = this.configurationService.getConfiguration('git'); + const config = this.configurationService.getConfiguration('git'); this._allowHugeRepositories = config.allowLargeRepositories; if (this._allowHugeRepositories) { @@ -529,7 +527,7 @@ export class GitService extends ee.EventEmitter this.toDispose.push(blurEvent(() => this.isFocused = false)); } - private onTextFileChange(e:filesCommon.TextFileChangeEvent): void { + private onTextFileChange(e: TextFileChangeEvent): void { var shouldTriggerStatus = paths.basename(e.resource.fsPath) === '.gitignore'; if (!shouldTriggerStatus) { @@ -573,42 +571,42 @@ export class GitService extends ee.EventEmitter this.triggerAutoStatus(); } - private onGitServiceOperationEnd(e: { operation: git.IGitOperation; }): void { - if (e.operation.id === git.ServiceOperations.COMMAND) { + private onGitServiceOperationEnd(e: { operation: IGitOperation; }): void { + if (e.operation.id === ServiceOperations.COMMAND) { this.triggerAutoStatus(); } } - public getState(): git.ServiceState { + getState(): ServiceState { return this.state; } - public getModel(): git.IModel { + getModel(): IModel { return this.model; } - public status(): winjs.Promise { + status(): TPromise { return this.statusDelayer.trigger(() => this._status()); } - private _status(): winjs.Promise { - const config = this.configurationService.getConfiguration('git'); + private _status(): TPromise { + const config = this.configurationService.getConfiguration('git'); if (this._allowHugeRepositories || config.allowLargeRepositories) { - return this.run(git.ServiceOperations.STATUS, () => this.raw.status()); + return this.run(ServiceOperations.STATUS, () => this.raw.status()); } - if (this.state === git.ServiceState.Huge) { - return winjs.TPromise.as(this.model); + if (this.state === ServiceState.Huge) { + return TPromise.as(this.model); } return this.raw.statusCount().then(count => { if (count > 5000 && !this._allowHugeRepositories) { - this.transition(git.ServiceState.Huge); - return winjs.TPromise.as(this.model); + this.transition(ServiceState.Huge); + return TPromise.as(this.model); } - return this.run(git.ServiceOperations.STATUS, () => this.raw.status()); + return this.run(ServiceOperations.STATUS, () => this.raw.status()); }); } @@ -621,14 +619,14 @@ export class GitService extends ee.EventEmitter this.isStatusPending = false; - const config = this.configurationService.getConfiguration('git'); + const config = this.configurationService.getConfiguration('git'); if (!config.autorefresh) { return; } this.reactiveStatusDelayer.trigger(() => this.status()).done(null, e => { - if (errors.isPromiseCanceledError(e)) { + if (isPromiseCanceledError(e)) { return; } @@ -636,101 +634,101 @@ export class GitService extends ee.EventEmitter }); } - public init(): winjs.Promise { - return this.run(git.ServiceOperations.INIT, () => this.raw.init()); + init(): TPromise { + return this.run(ServiceOperations.INIT, () => this.raw.init()); } - public add(files?: git.IFileStatus[]): winjs.Promise { - return this.run(git.ServiceOperations.ADD, () => this.raw.add(GitService.toPaths(files))); + add(files?: IFileStatus[]): TPromise { + return this.run(ServiceOperations.ADD, () => this.raw.add(GitService.toPaths(files))); } - public stage(filePath: string, content: string): winjs.Promise { - return this.run(git.ServiceOperations.STAGE, () => this.raw.stage(filePath, content)); + stage(filePath: string, content: string): TPromise { + return this.run(ServiceOperations.STAGE, () => this.raw.stage(filePath, content)); } - public branch(name: string, checkout: boolean = false): winjs.Promise { - return this.run(git.ServiceOperations.BRANCH, () => this.raw.branch(name, checkout)); + branch(name: string, checkout: boolean = false): TPromise { + return this.run(ServiceOperations.BRANCH, () => this.raw.branch(name, checkout)); } - public checkout(treeish: string = '', files: git.IFileStatus[] = null): winjs.Promise { - return this.run(git.ServiceOperations.CHECKOUT, () => this.raw.checkout(treeish, GitService.toPaths(files))); + checkout(treeish: string = '', files: IFileStatus[] = null): TPromise { + return this.run(ServiceOperations.CHECKOUT, () => this.raw.checkout(treeish, GitService.toPaths(files))); } - public clean(files: git.IFileStatus[]): winjs.Promise { - return this.run(git.ServiceOperations.CLEAN, () => this.raw.clean(files.map((s) => s.getPath()))); + clean(files: IFileStatus[]): TPromise { + return this.run(ServiceOperations.CLEAN, () => this.raw.clean(files.map((s) => s.getPath()))); } - public undo(): winjs.Promise { - return this.run(git.ServiceOperations.UNDO, () => this.raw.undo()); + undo(): TPromise { + return this.run(ServiceOperations.UNDO, () => this.raw.undo()); } - public reset(treeish: string, hard?: boolean): winjs.Promise { - return this.run(git.ServiceOperations.RESET, () => this.raw.reset(treeish, hard)); + reset(treeish: string, hard?: boolean): TPromise { + return this.run(ServiceOperations.RESET, () => this.raw.reset(treeish, hard)); } - public revertFiles(treeish: string, files?: git.IFileStatus[]): winjs.Promise { - return this.run(git.ServiceOperations.REVERT, () => this.raw.revertFiles(treeish, (files || []).map((s) => s.getPath()))); + revertFiles(treeish: string, files?: IFileStatus[]): TPromise { + return this.run(ServiceOperations.REVERT, () => this.raw.revertFiles(treeish, (files || []).map((s) => s.getPath()))); } - public fetch(): winjs.Promise { - return this.run(git.ServiceOperations.BACKGROUND_FETCH, () => this.raw.fetch()); + fetch(): TPromise { + return this.run(ServiceOperations.BACKGROUND_FETCH, () => this.raw.fetch()); } - public pull(rebase?: boolean): winjs.Promise { - return this.run(git.ServiceOperations.PULL, () => this.raw.pull(rebase)); + pull(rebase?: boolean): TPromise { + return this.run(ServiceOperations.PULL, () => this.raw.pull(rebase)); } - public push(remote?: string, name?: string, options?:git.IPushOptions): winjs.Promise { - return this.run(git.ServiceOperations.PUSH, () => this.raw.push(remote, name, options)); + push(remote?: string, name?: string, options?: IPushOptions): TPromise { + return this.run(ServiceOperations.PUSH, () => this.raw.push(remote, name, options)); } - public sync(rebase?: boolean): winjs.Promise { + sync(rebase?: boolean): TPromise { const head = this.model.getHEAD(); const isAhead = head && head.upstream && !!head.ahead; if (!isAhead) { - return this.run(git.ServiceOperations.SYNC, () => this.raw.pull(rebase)); + return this.run(ServiceOperations.SYNC, () => this.raw.pull(rebase)); } else { - return this.run(git.ServiceOperations.SYNC, () => this.raw.sync()); + return this.run(ServiceOperations.SYNC, () => this.raw.sync()); } } - public commit(message:string, amend: boolean = false, stage: boolean = false, signoff: boolean = false): winjs.Promise { - return this.run(git.ServiceOperations.COMMIT, () => this.raw.commit(message, amend, stage, signoff)); + commit(message: string, amend: boolean = false, stage: boolean = false, signoff: boolean = false): TPromise { + return this.run(ServiceOperations.COMMIT, () => this.raw.commit(message, amend, stage, signoff)); } - public getCommitTemplate(): winjs.Promise { + getCommitTemplate(): TPromise { return this.raw.getCommitTemplate(); } - public getCommit(ref: string): winjs.TPromise { + getCommit(ref: string): TPromise { return this.raw.getCommit(ref); } - public detectMimetypes(path: string, treeish: string = '~'): winjs.Promise { + detectMimetypes(path: string, treeish: string = '~'): TPromise { return this.raw.detectMimetypes(path, treeish); } - private run(operationId: string, fn: () => winjs.Promise): winjs.Promise { + private run(operationId: string, fn: () => TPromise): TPromise { return this.raw.serviceState().then(state => { - if (state === git.RawServiceState.GitNotFound) { - this.transition(git.ServiceState.NoGit); - return winjs.TPromise.as(null); - } else if (state === git.RawServiceState.Disabled) { - this.transition(git.ServiceState.Disabled); - return winjs.TPromise.as(null); + if (state === RawServiceState.GitNotFound) { + this.transition(ServiceState.NoGit); + return TPromise.as(null); + } else if (state === RawServiceState.Disabled) { + this.transition(ServiceState.Disabled); + return TPromise.as(null); } else { return this._run(operationId, fn); } }); } - private _run(operationId: string, fn: () => winjs.Promise): winjs.Promise { - var operation = new operations.GitOperation(operationId, fn); + private _run(operationId: string, fn: () => TPromise): TPromise { + var operation = new GitOperation(operationId, fn); this.operations.push(operation); - this.emit(git.ServiceEvents.OPERATION_START, operation); - this.emit(git.ServiceEvents.OPERATION, operation); + this.emit(ServiceEvents.OPERATION_START, operation); + this.emit(ServiceEvents.OPERATION, operation); var onDone = (error: any = null) => { var index = this.operations.indexOf(operation); @@ -740,97 +738,97 @@ export class GitService extends ee.EventEmitter } var e = { operation: operation, error: error }; - this.emit(git.ServiceEvents.OPERATION_END, e); + this.emit(ServiceEvents.OPERATION_END, e); this.onGitServiceOperationEnd(e); - this.emit(git.ServiceEvents.OPERATION, operation); + this.emit(ServiceEvents.OPERATION, operation); }; - return operation.run().then((status: git.IRawStatus) => { + return operation.run().then((status: IRawStatus) => { this.model.update(status); onDone(); if (status) { - this.transition(types.isUndefinedOrNull(status.state) ? git.ServiceState.OK : status.state); + this.transition(status.state === null || status.state === undefined ? ServiceState.OK : status.state); } else { - this.transition(git.ServiceState.NotARepo); + this.transition(ServiceState.NotARepo); } return this.model; }, (e) => { onDone(e); - if (errors.isPromiseCanceledError(e)) { - return winjs.Promise.wrapError(e); + if (isPromiseCanceledError(e)) { + return TPromise.wrapError(e); } var gitErrorCode: string = e.gitErrorCode || null; - if (gitErrorCode === git.GitErrorCodes.NotAtRepositoryRoot) { - this.transition(git.ServiceState.NotAtRepoRoot); - return winjs.TPromise.as(this.model); + if (gitErrorCode === GitErrorCodes.NotAtRepositoryRoot) { + this.transition(ServiceState.NotAtRepoRoot); + return TPromise.as(this.model); } - this.emit(git.ServiceEvents.ERROR, e); - this.transition(git.ServiceState.OK); + this.emit(ServiceEvents.ERROR, e); + this.transition(ServiceState.OK); - if (gitErrorCode === git.GitErrorCodes.NoUserNameConfigured || gitErrorCode === git.GitErrorCodes.NoUserEmailConfigured) { - this.messageService.show(severity.Warning, nls.localize('configureUsernameEmail', "Please configure your git user name and e-mail.")); + if (gitErrorCode === GitErrorCodes.NoUserNameConfigured || gitErrorCode === GitErrorCodes.NoUserEmailConfigured) { + this.messageService.show(severity.Warning, localize('configureUsernameEmail', "Please configure your git user name and e-mail.")); - return winjs.TPromise.as(null); + return TPromise.as(null); - } else if (gitErrorCode === git.GitErrorCodes.BadConfigFile) { - this.messageService.show(severity.Error, nls.localize('badConfigFile', "Git {0}", e.message)); - return winjs.TPromise.as(null); + } else if (gitErrorCode === GitErrorCodes.BadConfigFile) { + this.messageService.show(severity.Error, localize('badConfigFile', "Git {0}", e.message)); + return TPromise.as(null); - } else if (gitErrorCode === git.GitErrorCodes.UnmergedChanges) { - this.messageService.show(severity.Warning, nls.localize('unmergedChanges', "You should first resolve the unmerged changes before committing your changes.")); - return winjs.TPromise.as(null); + } else if (gitErrorCode === GitErrorCodes.UnmergedChanges) { + this.messageService.show(severity.Warning, localize('unmergedChanges', "You should first resolve the unmerged changes before committing your changes.")); + return TPromise.as(null); } var error: Error; - var showOutputAction = new actions.Action('show.gitOutput', nls.localize('showOutput', "Show Output"), null, true, () => this.outputService.getChannel('Git').show()); - var cancelAction = new actions.Action('close.message', nls.localize('cancel', "Cancel"), null, true, ()=>winjs.TPromise.as(true)); + var showOutputAction = new Action('show.gitOutput', localize('showOutput', "Show Output"), null, true, () => this.outputService.getChannel('Git').show()); + var cancelAction = new Action('close.message', localize('cancel', "Cancel"), null, true, () => TPromise.as(true)); - error = errors.create( - nls.localize('checkNativeConsole', "There was an issue running a git operation. Please review the output or use a console to check the state of your repository."), + error = createError( + localize('checkNativeConsole', "There was an issue running a git operation. Please review the output or use a console to check the state of your repository."), { actions: [showOutputAction, cancelAction] } ); (error).gitErrorCode = gitErrorCode; - return winjs.Promise.wrapError(error); + return TPromise.wrapError(error); }); } - private transition(state: git.ServiceState): void { + private transition(state: ServiceState): void { var oldState = this.state; this.state = state; if (state !== oldState) { - this.emit(git.ServiceEvents.STATE_CHANGED, state); + this.emit(ServiceEvents.STATE_CHANGED, state); } } - public buffer(path: string, treeish: string = '~'): winjs.TPromise { + buffer(path: string, treeish: string = '~'): TPromise { return this.raw.show(path, treeish); } - public show(path: string, status: git.IFileStatus, treeish: string = '~', mimetype: string = 'text/plain'): winjs.Promise { - return this.detectMimetypes(path, treeish).then((mimetypes:string[]) => { + show(path: string, status: IFileStatus, treeish: string = '~', mimetype: string = 'text/plain'): TPromise { + return this.detectMimetypes(path, treeish).then((mimetypes: string[]) => { var pathComponents = status.getPathComponents(); var fileSegment = pathComponents[pathComponents.length - 1]; var folderSegment = toReadablePath(pathComponents.slice(0, pathComponents.length - 1).join('/')); - var label:string; - var description:string; + var label: string; + var description: string; if (treeish === '~') { - label = nls.localize('changesFromIndex', "{0} (index)", fileSegment); - description = nls.localize('changesFromIndexDesc', "{0} - Changes on index", folderSegment); + label = localize('changesFromIndex', "{0} (index)", fileSegment); + description = localize('changesFromIndexDesc', "{0} - Changes on index", folderSegment); } else { - label = nls.localize('changesFromTree', "{0} ({1})", fileSegment, treeish); - description = nls.localize('changesFromTreeDesc', "{0} - Changes on {1}", folderSegment, treeish); + label = localize('changesFromTree', "{0} ({1})", fileSegment, treeish); + description = localize('changesFromTreeDesc', "{0} - Changes on {1}", folderSegment, treeish); } if (mime.isUnspecific(mimetypes)) { @@ -843,42 +841,42 @@ export class GitService extends ee.EventEmitter // // Our solution now is to detect binary files and immediately return an input that is flagged as binary unknown mime type. if (mime.isBinaryMime(mime.guessMimeTypes(path)) || mimetypes.indexOf(mime.MIME_BINARY) >= 0) { - return winjs.Promise.wrapError(new Error('The resource seems to be binary and cannot be displayed')); + return TPromise.wrapError(new Error('The resource seems to be binary and cannot be displayed')); } // Text - return winjs.TPromise.as(this.instantiationService.createInstance(giteditorinputs.NativeGitIndexStringEditorInput, label, description, mimetypes.join(', '), status, path, treeish)); + return TPromise.as(this.instantiationService.createInstance(NativeGitIndexStringEditorInput, label, description, mimetypes.join(', '), status, path, treeish)); }); } - public getInput(status: git.IFileStatus): winjs.TPromise { + getInput(status: IFileStatus): TPromise { return this.inputCache.getInput(status).then(null, (err) => { - if (err.gitErrorCode = git.GitErrorCodes.CantOpenResource) { - this.messageService.show(severity.Warning, nls.localize('cantOpenResource', "Can't open this git resource.")); - return winjs.TPromise.as(null); + if (err.gitErrorCode = GitErrorCodes.CantOpenResource) { + this.messageService.show(severity.Warning, localize('cantOpenResource', "Can't open this git resource.")); + return TPromise.as(null); } - return winjs.Promise.wrapError(err); + return TPromise.wrapError(err); }); } - public isInitialized(): boolean { - return this.state === git.ServiceState.OK; + isInitialized(): boolean { + return this.state === ServiceState.OK; } - public isIdle(): boolean { - return this.isInitialized() && !this.operations.some(op => op.id !== git.ServiceOperations.BACKGROUND_FETCH); + isIdle(): boolean { + return this.isInitialized() && !this.operations.some(op => op.id !== ServiceOperations.BACKGROUND_FETCH); } - public getRunningOperations(): git.IGitOperation[] { + getRunningOperations(): IGitOperation[] { return this.operations; } - public getAutoFetcher(): git.IAutoFetcher { + getAutoFetcher(): IAutoFetcher { return this.autoFetcher; } - private static toPaths(files: git.IFileStatus[]): string[] { + private static toPaths(files: IFileStatus[]): string[] { if (!files) { return null; } @@ -889,8 +887,8 @@ export class GitService extends ee.EventEmitter */ switch (status.getStatus()) { - case git.Status.MODIFIED: - case git.Status.DELETED: + case Status.MODIFIED: + case Status.DELETED: if (status.getRename()) { return status.getRename(); } @@ -901,8 +899,8 @@ export class GitService extends ee.EventEmitter }); } - public dispose(): void { - this.emit(git.ServiceEvents.DISPOSE); + dispose(): void { + this.emit(ServiceEvents.DISPOSE); if (this.model) { this.model.dispose(); diff --git a/src/vs/workbench/parts/git/common/git.ts b/src/vs/workbench/parts/git/common/git.ts index 45f9fd24aca5..e377ab56cd0e 100644 --- a/src/vs/workbench/parts/git/common/git.ts +++ b/src/vs/workbench/parts/git/common/git.ts @@ -149,7 +149,7 @@ export interface IModel extends IEventEmitter { export interface IGitOperation extends IDisposable { id: string; - run(): TPromise; + run(): TPromise; } // Service enums @@ -325,7 +325,6 @@ export interface IGitService extends IEventEmitter { getState(): ServiceState; getModel(): IModel; - show(path: string, status: IFileStatus, treeish?: string, mimetype?: string): TPromise; getInput(status: IFileStatus): TPromise; isInitialized(): boolean; isIdle(): boolean;