backupFileService.ts 4.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
/*---------------------------------------------------------------------------------------------
 *  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 * as path from 'path';
import * as crypto from 'crypto';
import pfs = require('vs/base/node/pfs');
import Uri from 'vs/base/common/uri';
12
import { IBackupWorkspacesFormat } from 'vs/platform/backup/common/backup';
13 14 15 16 17 18 19 20 21 22
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IFileService } from 'vs/platform/files/common/files';
import { TPromise } from 'vs/base/common/winjs.base';

export class BackupFileService implements IBackupFileService {

	public _serviceBrand: any;

	protected backupHome: string;
D
Daniel Imms 已提交
23
	protected workspacesJsonPath: string;
24 25 26

	constructor(
		private currentWorkspace: Uri,
27
		@IEnvironmentService private environmentService: IEnvironmentService,
28 29 30
		@IFileService private fileService: IFileService
	) {
		this.backupHome = environmentService.backupHome;
D
Daniel Imms 已提交
31 32 33
		this.workspacesJsonPath = environmentService.backupWorkspacesPath;
	}

34
	public getWorkspaceBackupPaths(): TPromise<string[]> {
35
		if (this.environmentService.isExtensionDevelopment) {
36 37 38
			return TPromise.as([]);
		}

39 40
		return this.loadWorkspaces().then(workspacesJsonContent => {
			return workspacesJsonContent.folderWorkspaces;
41 42 43
		});
	}

44
	public hasBackup(resource: Uri): TPromise<boolean> {
45 46 47 48
		const backupResource = this.getBackupResource(resource);
		if (!backupResource) {
			return TPromise.as(false);
		}
49
		return pfs.exists(backupResource.fsPath);
50 51 52 53
	}

	public getBackupResource(resource: Uri): Uri {
		// Hot exit is disabled for empty workspaces
54
		if (!this.currentWorkspace || this.environmentService.isExtensionDevelopment) {
55 56 57
			return null;
		}

58 59
		// Only hash the file path if the file is not untitled
		const backupName = resource.scheme === 'untitled' ? resource.fsPath : crypto.createHash('md5').update(resource.fsPath).digest('hex');
60 61 62 63 64 65 66 67 68
		const backupPath = path.join(this.getWorkspaceBackupDirectory(), resource.scheme, backupName);
		return Uri.file(backupPath);
	}

	private getWorkspaceBackupDirectory(): string {
		const workspaceHash = crypto.createHash('md5').update(this.currentWorkspace.fsPath).digest('hex');
		return path.join(this.backupHome, workspaceHash);
	}

69
	public backupResource(resource: Uri, content: string): TPromise<void> {
70
		if (this.environmentService.isExtensionDevelopment) {
71 72 73
			return TPromise.as(void 0);
		}

74
		const backupResource = this.getBackupResource(resource);
75

76 77 78 79
		// Hot exit is disabled for empty workspaces
		if (!backupResource) {
			return TPromise.as(void 0);
		}
80

81
		return this.fileService.updateContent(backupResource, content).then(() => void 0);
82 83
	}

84
	public discardResourceBackup(resource: Uri): TPromise<void> {
85
		if (this.environmentService.isExtensionDevelopment) {
86 87 88
			return TPromise.as(void 0);
		}

89
		const backupResource = this.getBackupResource(resource);
90

91 92 93 94
		// Hot exit is disabled for empty workspaces
		if (!backupResource) {
			return TPromise.as(void 0);
		}
95

96
		return this.fileService.del(backupResource);
97 98
	}

99
	public discardAllWorkspaceBackups(): TPromise<void> {
100
		if (this.environmentService.isExtensionDevelopment) {
101 102 103
			return TPromise.as(void 0);
		}

104 105 106
		return this.fileService.del(Uri.file(this.getWorkspaceBackupDirectory()));
	}

107
	private loadWorkspaces(): TPromise<IBackupWorkspacesFormat> {
108 109 110 111 112 113 114 115 116 117 118 119 120
		return pfs.readFile(this.workspacesJsonPath, 'utf8').then(content => {
			let result: IBackupWorkspacesFormat;
			try {
				result = JSON.parse(content.toString());
				// Ensure folderWorkspaces is a string[]
				if (result.folderWorkspaces) {
					const fws = result.folderWorkspaces;
					if (!Array.isArray(fws) || fws.some(f => typeof f !== 'string')) {
						result = Object.create(null);
					}
				}
			} catch (ex) {
				result = Object.create(null);
D
Daniel Imms 已提交
121 122
			}

123 124 125 126 127 128
			if (!result.folderWorkspaces) {
				result.folderWorkspaces = [];
			}
			return result;
		}, () => {
			return { folderWorkspaces: [] };
D
Daniel Imms 已提交
129 130
		});
	}
131
}