hook up backup restorer for files

This commit is contained in:
Benjamin Pasero
2016-11-18 16:31:21 +01:00
parent 4439f3e20b
commit 5d69eae71e
6 changed files with 125 additions and 87 deletions

View File

@@ -18,7 +18,6 @@ import { IModeService } from 'vs/editor/common/services/modeService';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import Event, { Emitter } from 'vs/base/common/event';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
/**
* An editor input to be used for untitled text buffers.
@@ -45,7 +44,6 @@ export class UntitledEditorInput extends AbstractUntitledEditorInput {
@IInstantiationService private instantiationService: IInstantiationService,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IModeService private modeService: IModeService,
@IBackupFileService private backupFileService: IBackupFileService,
@ITextFileService private textFileService: ITextFileService
) {
super();
@@ -156,27 +154,14 @@ export class UntitledEditorInput extends AbstractUntitledEditorInput {
return TPromise.as(this.cachedModel);
}
// Otherwise Create Model and load, restoring from backup if necessary
return this.backupFileService.hasBackup(this.resource).then(hasBackup => {
if (hasBackup) {
const restoreResource = this.backupFileService.getBackupResource(this.resource);
// Otherwise Create Model and load
this.cachedModel = this.createModel();
return this.textFileService.resolveTextContent(restoreResource).then(rawTextContent => rawTextContent.value.lines.join('\n'));
}
return '';
}).then(content => {
const model = this.createModel(content);
return model.load().then((resolvedModel: UntitledEditorModel) => {
this.cachedModel = resolvedModel;
return this.cachedModel;
});
});
return this.cachedModel.load();
}
private createModel(content: string): UntitledEditorModel {
const model = this.instantiationService.createInstance(UntitledEditorModel, content, this.modeId, this.resource, this.hasAssociatedFilePath);
private createModel(): UntitledEditorModel {
const model = this.instantiationService.createInstance(UntitledEditorModel, this.modeId, this.resource, this.hasAssociatedFilePath);
// re-emit some events from the model
this.toUnbind.push(model.onDidChangeContent(() => this._onDidModelChangeContent.fire()));

View File

@@ -18,6 +18,8 @@ import { IModelService } from 'vs/editor/common/services/modelService';
import { IMode } from 'vs/editor/common/modes';
import Event, { Emitter } from 'vs/base/common/event';
import { RunOnceScheduler } from 'vs/base/common/async';
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
export class UntitledEditorModel extends StringEditorModel implements IEncodingSupport {
@@ -39,18 +41,19 @@ export class UntitledEditorModel extends StringEditorModel implements IEncodingS
private hasAssociatedFilePath: boolean;
constructor(
value: string,
modeId: string,
resource: URI,
hasAssociatedFilePath: boolean,
@IModeService modeService: IModeService,
@IModelService modelService: IModelService,
@IBackupFileService private backupFileService: IBackupFileService,
@ITextFileService private textFileService: ITextFileService,
@IConfigurationService private configurationService: IConfigurationService
) {
super(value, modeId, resource, modeService, modelService);
super('', modeId, resource, modeService, modelService);
this.hasAssociatedFilePath = hasAssociatedFilePath;
this.dirty = hasAssociatedFilePath || !!value; // untitled associated to file path are dirty right away as well as untitled with content
this.dirty = false;
this._onDidChangeContent = new Emitter<void>();
this._onDidChangeDirty = new Emitter<void>();
@@ -59,13 +62,6 @@ export class UntitledEditorModel extends StringEditorModel implements IEncodingS
this.contentChangeEventScheduler = new RunOnceScheduler(() => this._onDidChangeContent.fire(), UntitledEditorModel.DEFAULT_CONTENT_CHANGE_BUFFER_DELAY);
this.registerListeners();
// Indicate dirty state to listeners
if (this.dirty) {
setTimeout(() => {
this._onDidChangeDirty.fire();
}, 0 /* prevent race condition between creating input and emitting dirty event */);
}
}
public get onDidChangeContent(): Event<void> {
@@ -132,31 +128,53 @@ export class UntitledEditorModel extends StringEditorModel implements IEncodingS
return this.dirty;
}
private setDirty(dirty: boolean): void {
if (this.dirty === dirty) {
return;
}
this.dirty = dirty;
this._onDidChangeDirty.fire();
}
public getResource(): URI {
return this.resource;
}
public revert(): void {
this.dirty = false;
// Events
this._onDidChangeDirty.fire();
this.setDirty(false);
// Handle content change event buffered
this.contentChangeEventScheduler.schedule();
}
public load(): TPromise<EditorModel> {
return super.load().then((model) => {
const configuration = this.configurationService.getConfiguration<IFilesConfiguration>();
// Encoding
this.configuredEncoding = configuration && configuration.files && configuration.files.encoding;
// Check for backups first
return this.backupFileService.hasBackup(this.resource).then(hasBackup => {
if (hasBackup) {
return this.textFileService.resolveTextContent(this.backupFileService.getBackupResource(this.resource)).then(rawTextContent => rawTextContent.value.lines.join('\n'));
}
// Listen to content changes
this.textModelChangeListener = this.textEditorModel.onDidChangeContent(e => this.onModelContentChanged());
return null;
}).then(backupContent => {
if (backupContent) {
this.setValue(backupContent);
}
return model;
this.setDirty(this.hasAssociatedFilePath || !!backupContent); // untitled associated to file path are dirty right away as well as untitled with content
return super.load().then(model => {
const configuration = this.configurationService.getConfiguration<IFilesConfiguration>();
// Encoding
this.configuredEncoding = configuration && configuration.files && configuration.files.encoding;
// Listen to content changes
this.textModelChangeListener = this.textEditorModel.onDidChangeContent(e => this.onModelContentChanged());
return model;
});
});
}
@@ -165,16 +183,12 @@ export class UntitledEditorModel extends StringEditorModel implements IEncodingS
// mark the untitled editor as non-dirty once its content becomes empty and we do
// not have an associated path set. we never want dirty indicator in that case.
if (!this.hasAssociatedFilePath && this.textEditorModel.getLineCount() === 1 && this.textEditorModel.getLineContent(1) === '') {
if (this.dirty) {
this.dirty = false;
this._onDidChangeDirty.fire();
}
this.setDirty(false);
}
// turn dirty if we were not
else if (!this.dirty) {
this.dirty = true;
this._onDidChangeDirty.fire();
// turn dirty otherwise
else {
this.setDirty(true);
}
// Handle content change event buffered