rawGitService.ts 5.5 KB
Newer Older
E
Erich Gamma 已提交
1 2 3 4 5 6
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
'use strict';

J
Joao Moreno 已提交
7
import { join } from 'path';
J
Joao Moreno 已提交
8
import { TPromise, Promise } from 'vs/base/common/winjs.base';
J
Joao Moreno 已提交
9 10
import { detectMimesFromFile, detectMimesFromStream } from 'vs/base/node/mime';
import { realpath, exists} from 'vs/base/node/pfs';
E
Erich Gamma 已提交
11
import { Repository, GitError } from 'vs/workbench/parts/git/node/git.lib';
J
Joao Moreno 已提交
12
import { IRawGitService, RawServiceState, IRawStatus, IRef, GitErrorCodes, IPushOptions } from 'vs/workbench/parts/git/common/git';
J
Joao Moreno 已提交
13
import Event, { Emitter } from 'vs/base/common/event';
E
Erich Gamma 已提交
14 15 16 17

export class RawGitService implements IRawGitService {

	private repo: Repository;
J
Joao Moreno 已提交
18
	private _repositoryRoot: TPromise<string>;
J
Joao Moreno 已提交
19 20
	private _onOutput: Emitter<string>;
	get onOutput(): Event<string> { return this._onOutput.event; }
E
Erich Gamma 已提交
21 22 23

	constructor(repo: Repository) {
		this.repo = repo;
J
Joao Moreno 已提交
24 25 26 27 28 29 30 31 32 33 34 35

		let listener: () => void;

		this._onOutput = new Emitter<string>({
			onFirstListenerAdd: () => {
				listener = this.repo.onOutput(output => this._onOutput.fire(output));
			},
			onLastListenerRemove: () => {
				listener();
				listener = null;
			}
		});
J
Joao Moreno 已提交
36 37
	}

J
Joao Moreno 已提交
38 39 40 41
	getVersion(): TPromise<string> {
		return TPromise.as(this.repo.version);
	}

J
Joao Moreno 已提交
42
	private getRepositoryRoot(): TPromise<string> {
J
Joao Moreno 已提交
43
		return this._repositoryRoot || (this._repositoryRoot = realpath(this.repo.path));
E
Erich Gamma 已提交
44 45
	}

J
Joao Moreno 已提交
46
	serviceState(): TPromise<RawServiceState> {
J
Joao Moreno 已提交
47
		return TPromise.as<RawServiceState>(this.repo
E
Erich Gamma 已提交
48 49 50 51 52
			? RawServiceState.OK
			: RawServiceState.GitNotFound
		);
	}

J
Joao Moreno 已提交
53
	status(): TPromise<IRawStatus> {
J
Joao Moreno 已提交
54
		return this.repo.getStatus()
E
Erich Gamma 已提交
55 56 57 58 59 60 61
			.then(status => this.repo.getHEAD()
				.then(HEAD => {
					if (HEAD.name) {
						return this.repo.getBranch(HEAD.name).then(null, () => HEAD);
					} else {
						return HEAD;
					}
J
Joao Moreno 已提交
62 63
				}, (): IRef => null)
				.then(HEAD => Promise.join([this.getRepositoryRoot(), this.repo.getRefs(), this.repo.getRemotes()]).then(r => {
E
Erich Gamma 已提交
64
					return {
J
Joao Moreno 已提交
65
						repositoryRoot: r[0],
E
Erich Gamma 已提交
66 67
						status: status,
						HEAD: HEAD,
J
Joao Moreno 已提交
68 69
						refs: r[1],
						remotes: r[2]
E
Erich Gamma 已提交
70 71 72 73
					};
				})))
			.then(null, (err) => {
				if (err.gitErrorCode === GitErrorCodes.BadConfigFile) {
J
Joao Moreno 已提交
74
					return Promise.wrapError(err);
E
Erich Gamma 已提交
75
				} else if (err.gitErrorCode === GitErrorCodes.NotAtRepositoryRoot) {
J
Joao Moreno 已提交
76
					return Promise.wrapError(err);
E
Erich Gamma 已提交
77 78 79 80 81 82
				}

				return null;
			});
	}

J
Joao Moreno 已提交
83
	init(): TPromise<IRawStatus> {
E
Erich Gamma 已提交
84 85 86
		return this.repo.init().then(() => this.status());
	}

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

J
Joao Moreno 已提交
91
	stage(filePath: string, content: string): TPromise<IRawStatus> {
E
Erich Gamma 已提交
92 93 94
		return this.repo.stage(filePath, content).then(() => this.status());
	}

J
Joao Moreno 已提交
95
	branch(name: string, checkout?: boolean): TPromise<IRawStatus> {
E
Erich Gamma 已提交
96 97 98
		return this.repo.branch(name, checkout).then(() => this.status());
	}

J
Joao Moreno 已提交
99
	checkout(treeish?: string, filePaths?: string[]): TPromise<IRawStatus> {
E
Erich Gamma 已提交
100 101 102
		return this.repo.checkout(treeish, filePaths).then(() => this.status());
	}

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

J
Joao Moreno 已提交
107
	undo(): TPromise<IRawStatus> {
E
Erich Gamma 已提交
108 109 110
		return this.repo.undo().then(() => this.status());
	}

J
Joao Moreno 已提交
111
	reset(treeish: string, hard?: boolean): TPromise<IRawStatus> {
E
Erich Gamma 已提交
112 113 114
		return this.repo.reset(treeish, hard).then(() => this.status());
	}

J
Joao Moreno 已提交
115
	revertFiles(treeish: string, filePaths?: string[]): TPromise<IRawStatus> {
E
Erich Gamma 已提交
116 117 118
		return this.repo.revertFiles(treeish, filePaths).then(() => this.status());
	}

J
Joao Moreno 已提交
119
	fetch(): TPromise<IRawStatus> {
E
Erich Gamma 已提交
120 121
		return this.repo.fetch().then(null, (err) => {
			if (err.gitErrorCode === GitErrorCodes.NoRemoteRepositorySpecified) {
A
Alex Dima 已提交
122
				return TPromise.as(null);
E
Erich Gamma 已提交
123 124
			}

J
Joao Moreno 已提交
125
			return Promise.wrapError(err);
E
Erich Gamma 已提交
126 127 128
		}).then(() => this.status());
	}

J
Joao Moreno 已提交
129
	pull(rebase?: boolean): TPromise<IRawStatus> {
J
Joao Moreno 已提交
130
		return this.repo.pull(rebase).then(() => this.status());
E
Erich Gamma 已提交
131 132
	}

J
Joao Moreno 已提交
133
	push(remote?: string, name?: string, options?:IPushOptions): TPromise<IRawStatus> {
J
Joao Moreno 已提交
134
		return this.repo.push(remote, name, options).then(() => this.status());
E
Erich Gamma 已提交
135 136
	}

J
Joao Moreno 已提交
137
	sync(): TPromise<IRawStatus> {
E
Erich Gamma 已提交
138 139 140
		return this.repo.sync().then(() => this.status());
	}

J
Joao Moreno 已提交
141 142
	commit(message:string, amend?: boolean, stage?: boolean): TPromise<IRawStatus> {
		let promise: Promise = TPromise.as(null);
E
Erich Gamma 已提交
143 144 145 146 147 148 149 150 151 152

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

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

J
Joao Moreno 已提交
153
	detectMimetypes(filePath: string, treeish?: string): TPromise<string[]> {
J
Joao Moreno 已提交
154
		return exists(join(this.repo.path, filePath)).then((exists) => {
E
Erich Gamma 已提交
155
			if (exists) {
J
Joao Moreno 已提交
156
				return new TPromise<string[]>((c, e) => {
J
Joao Moreno 已提交
157
					detectMimesFromFile(join(this.repo.path, filePath), (err, result) => {
E
Erich Gamma 已提交
158 159 160 161 162 163
						if (err) { e(err); }
						else { c(result.mimes); }
					});
				});
			}

J
Joao Moreno 已提交
164
			const child = this.repo.show(treeish + ':' + filePath);
E
Erich Gamma 已提交
165

J
Joao Moreno 已提交
166
			return new TPromise<string[]>((c, e) => {
J
Joao Moreno 已提交
167
				detectMimesFromStream(child.stdout, filePath, (err, result) => {
E
Erich Gamma 已提交
168 169 170 171 172 173 174 175
					if (err) { e(err); }
					else { c(result.mimes); }
				});
			});
		});
	}

	// careful, this buffers the whole object into memory
J
Joao Moreno 已提交
176
	show(filePath: string, treeish?: string): TPromise<string> {
J
Joao Moreno 已提交
177
		treeish = (!treeish || treeish === '~') ? '' : treeish;
E
Erich Gamma 已提交
178 179 180 181 182
		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 已提交
183
			return TPromise.wrapError<string>(e);
E
Erich Gamma 已提交
184 185 186
		});
	}
}