rawGitService.ts 7.9 KB
Newer Older
E
Erich Gamma 已提交
1 2 3 4 5 6 7
/*---------------------------------------------------------------------------------------------
 *  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 path = require('path');
J
Joao Moreno 已提交
8
import { TPromise, Promise } from 'vs/base/common/winjs.base';
E
Erich Gamma 已提交
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
import mime = require('vs/base/node/mime');
import pfs = require('vs/base/node/pfs');
import { Repository, GitError } from 'vs/workbench/parts/git/node/git.lib';
import { IRawGitService, RawServiceState, IRawStatus, IHead, GitErrorCodes } from 'vs/workbench/parts/git/common/git';

function pathsAreEqual(p1: string, p2: string): boolean {
	if (/^(win32|darwin)$/.test(process.platform)) {
		p1 = p1.toLowerCase();
		p2 = p2.toLowerCase();
	}

	return p1 === p2;
}

export class RawGitService implements IRawGitService {

	private repo: Repository;
J
Joao Moreno 已提交
26
	private repoRealRootPath: TPromise<string>;
E
Erich Gamma 已提交
27 28 29 30 31 32

	constructor(repo: Repository) {
		this.repo = repo;
		this.repoRealRootPath = null;
	}

J
Joao Moreno 已提交
33 34
	public serviceState(): TPromise<RawServiceState> {
		return TPromise.as<RawServiceState>(this.repo
E
Erich Gamma 已提交
35 36 37 38 39
			? RawServiceState.OK
			: RawServiceState.GitNotFound
		);
	}

J
Joao Moreno 已提交
40
	public status(): TPromise<IRawStatus> {
E
Erich Gamma 已提交
41 42 43 44 45 46 47 48 49 50
		return this.checkRoot()
			.then(() => this.repo.getStatus())
			.then(status => this.repo.getHEAD()
				.then(HEAD => {
					if (HEAD.name) {
						return this.repo.getBranch(HEAD.name).then(null, () => HEAD);
					} else {
						return HEAD;
					}
				}, (): IHead => null)
J
Joao Moreno 已提交
51
				.then(HEAD => Promise.join([this.repo.getHeads(), this.repo.getTags()]).then(r => {
E
Erich Gamma 已提交
52 53 54 55 56 57 58 59 60
					return {
						status: status,
						HEAD: HEAD,
						heads: r[0],
						tags: r[1]
					};
				})))
			.then(null, (err) => {
				if (err.gitErrorCode === GitErrorCodes.BadConfigFile) {
J
Joao Moreno 已提交
61
					return Promise.wrapError(err);
E
Erich Gamma 已提交
62
				} else if (err.gitErrorCode === GitErrorCodes.NotAtRepositoryRoot) {
J
Joao Moreno 已提交
63
					return Promise.wrapError(err);
E
Erich Gamma 已提交
64 65 66 67 68 69
				}

				return null;
			});
	}

J
Joao Moreno 已提交
70
	public init(): TPromise<IRawStatus> {
E
Erich Gamma 已提交
71 72 73
		return this.repo.init().then(() => this.status());
	}

J
Joao Moreno 已提交
74
	public add(filePaths?: string[]): TPromise<IRawStatus> {
E
Erich Gamma 已提交
75 76 77
		return this.repo.add(filePaths).then(() => this.status());
	}

J
Joao Moreno 已提交
78
	public stage(filePath: string, content: string): TPromise<IRawStatus> {
E
Erich Gamma 已提交
79 80 81
		return this.repo.stage(filePath, content).then(() => this.status());
	}

J
Joao Moreno 已提交
82
	public branch(name: string, checkout?: boolean): TPromise<IRawStatus> {
E
Erich Gamma 已提交
83 84 85
		return this.repo.branch(name, checkout).then(() => this.status());
	}

J
Joao Moreno 已提交
86
	public checkout(treeish?: string, filePaths?: string[]): TPromise<IRawStatus> {
E
Erich Gamma 已提交
87 88 89
		return this.repo.checkout(treeish, filePaths).then(() => this.status());
	}

J
Joao Moreno 已提交
90
	public clean(filePaths: string[]): TPromise<IRawStatus> {
E
Erich Gamma 已提交
91 92 93
		return this.repo.clean(filePaths).then(() => this.status());
	}

J
Joao Moreno 已提交
94
	public undo(): TPromise<IRawStatus> {
E
Erich Gamma 已提交
95 96 97
		return this.repo.undo().then(() => this.status());
	}

J
Joao Moreno 已提交
98
	public reset(treeish: string, hard?: boolean): TPromise<IRawStatus> {
E
Erich Gamma 已提交
99 100 101
		return this.repo.reset(treeish, hard).then(() => this.status());
	}

J
Joao Moreno 已提交
102
	public revertFiles(treeish: string, filePaths?: string[]): TPromise<IRawStatus> {
E
Erich Gamma 已提交
103 104 105
		return this.repo.revertFiles(treeish, filePaths).then(() => this.status());
	}

J
Joao Moreno 已提交
106
	public fetch(): TPromise<IRawStatus> {
E
Erich Gamma 已提交
107 108
		return this.repo.fetch().then(null, (err) => {
			if (err.gitErrorCode === GitErrorCodes.NoRemoteRepositorySpecified) {
J
Joao Moreno 已提交
109
				return Promise.as(null);
E
Erich Gamma 已提交
110 111
			}

J
Joao Moreno 已提交
112
			return Promise.wrapError(err);
E
Erich Gamma 已提交
113 114 115
		}).then(() => this.status());
	}

J
Joao Moreno 已提交
116
	public pull(): TPromise<IRawStatus> {
E
Erich Gamma 已提交
117 118 119
		return this.repo.pull().then(() => this.status());
	}

J
Joao Moreno 已提交
120
	public push(): TPromise<IRawStatus> {
E
Erich Gamma 已提交
121 122 123
		return this.repo.push().then(() => this.status());
	}

J
Joao Moreno 已提交
124
	public sync(): TPromise<IRawStatus> {
E
Erich Gamma 已提交
125 126 127
		return this.repo.sync().then(() => this.status());
	}

J
Joao Moreno 已提交
128 129
	public commit(message:string, amend?: boolean, stage?: boolean): TPromise<IRawStatus> {
		var promise: Promise = Promise.as(null);
E
Erich Gamma 已提交
130 131 132 133 134 135 136 137 138 139

		if (stage) {
			promise = this.repo.add(null);
		}

		return promise
			.then(() => this.repo.commit(message, stage, amend))
			.then(() => this.status());
	}

J
Joao Moreno 已提交
140
	public detectMimetypes(filePath: string, treeish?: string): TPromise<string[]> {
E
Erich Gamma 已提交
141 142
		return pfs.exists(path.join(this.repo.path, filePath)).then((exists) => {
			if (exists) {
J
Joao Moreno 已提交
143
				return new TPromise<string[]>((c, e) => {
E
Erich Gamma 已提交
144 145 146 147 148 149 150 151 152
					mime.detectMimesFromFile(path.join(this.repo.path, filePath), (err, result) => {
						if (err) { e(err); }
						else { c(result.mimes); }
					});
				});
			}

			var child = this.repo.show(treeish + ':' + filePath);

J
Joao Moreno 已提交
153
			return new TPromise<string[]>((c, e) => {
E
Erich Gamma 已提交
154 155 156 157 158 159 160 161 162
				mime.detectMimesFromStream(child.stdout, filePath, (err, result) => {
					if (err) { e(err); }
					else { c(result.mimes); }
				});
			});
		});
	}

	// careful, this buffers the whole object into memory
J
Joao Moreno 已提交
163
	public show(filePath: string, treeish?: string): TPromise<string> {
E
Erich Gamma 已提交
164 165 166 167 168 169
		treeish = treeish === '~' ? '' : treeish;
		return this.repo.buffer(treeish + ':' + filePath).then(null, e => {
			if (e instanceof GitError) {
				return ''; // mostly untracked files end up in a git error
			}

J
Joao Moreno 已提交
170
			return TPromise.wrapError<string>(e);
E
Erich Gamma 已提交
171 172 173
		});
	}

J
Joao Moreno 已提交
174
	public onOutput(): Promise {
E
Erich Gamma 已提交
175 176
		var cancel: () => void;

J
Joao Moreno 已提交
177
		return new Promise((c, e, p) => {
E
Erich Gamma 已提交
178 179 180 181
			cancel = this.repo.onOutput(p);
		}, () => cancel());
	}

J
Joao Moreno 已提交
182
	private checkRoot(): Promise {
E
Erich Gamma 已提交
183 184 185 186 187
		if (!this.repoRealRootPath) {
			this.repoRealRootPath = pfs.realpath(this.repo.path);
		}

		return this.repo.getRoot().then(root => {
J
Joao Moreno 已提交
188
			return Promise.join([
E
Erich Gamma 已提交
189 190 191 192
				this.repoRealRootPath,
				pfs.realpath(root)
			]).then(paths => {
				if (!pathsAreEqual(paths[0], paths[1])) {
J
Joao Moreno 已提交
193
					return Promise.wrapError(new GitError({
E
Erich Gamma 已提交
194 195 196 197 198 199 200 201
						message: 'Not at the repository root',
						gitErrorCode: GitErrorCodes.NotAtRepositoryRoot
					}));
				}
			});
		});
	}
}
J
Joao Moreno 已提交
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282

export class RawGitServiceWrapper implements IRawGitService {

	constructor(private raw: TPromise<IRawGitService>) { }

	public serviceState(): TPromise<RawServiceState> {
		return this.raw.then(raw => raw.serviceState());
	}

	public status(): TPromise<IRawStatus> {
		return this.raw.then(raw => raw.status());
	}

	public init(): TPromise<IRawStatus> {
		return this.raw.then(raw => raw.init());
	}

	public add(filesPaths?: string[]): TPromise<IRawStatus> {
		return this.raw.then(raw => raw.add(filesPaths));
	}

	public stage(filePath: string, content: string): TPromise<IRawStatus> {
		return this.raw.then(raw => raw.stage(filePath, content));
	}

	public branch(name: string, checkout?: boolean): TPromise<IRawStatus> {
		return this.raw.then(raw => raw.branch(name, checkout));
	}

	public checkout(treeish?: string, filePaths?: string[]): TPromise<IRawStatus> {
		return this.raw.then(raw => raw.checkout(treeish, filePaths));
	}

	public clean(filePaths: string[]): TPromise<IRawStatus> {
		return this.raw.then(raw => raw.clean(filePaths));
	}

	public undo(): TPromise<IRawStatus> {
		return this.raw.then(raw => raw.undo());
	}

	public reset(treeish: string, hard?: boolean): TPromise<IRawStatus> {
		return this.raw.then(raw => raw.reset(treeish, hard));
	}

	public revertFiles(treeish: string, filePaths?: string[]): TPromise<IRawStatus> {
		return this.raw.then(raw => raw.revertFiles(treeish, filePaths));
	}

	public fetch(): TPromise<IRawStatus> {
		return this.raw.then(raw => raw.fetch());
	}

	public pull(): TPromise<IRawStatus> {
		return this.raw.then(raw => raw.pull());
	}

	public push(): TPromise<IRawStatus> {
		return this.raw.then(raw => raw.push());
	}

	public sync(): TPromise<IRawStatus> {
		return this.raw.then(raw => raw.sync());
	}

	public commit(message: string, amend?: boolean, stage?: boolean): TPromise<IRawStatus> {
		return this.raw.then(raw => raw.commit(message, amend, stage));
	}

	public detectMimetypes(path: string, treeish?: string): TPromise<string[]> {
		return this.raw.then(raw => raw.detectMimetypes(path, treeish));
	}

	public show(path: string, treeish?: string): TPromise<string> {
		return this.raw.then(raw => raw.show(path, treeish));
	}

	public onOutput(): Promise {
		return this.raw.then(raw => raw.onOutput());
	}
}