git: raw buffer

This commit is contained in:
Joao Moreno
2017-11-08 15:26:41 +01:00
parent d572f43247
commit 4b8c0ce265
3 changed files with 45 additions and 41 deletions

View File

@@ -138,9 +138,9 @@ export function findGit(hint: string | undefined): Promise<IGit> {
.then(null, () => Promise.reject(new Error('Git installation not found.')));
}
export interface IExecutionResult {
export interface IExecutionResult<T extends string | Buffer> {
exitCode: number;
stdout: string;
stdout: T;
stderr: string;
}
@@ -164,7 +164,7 @@ export interface SpawnOptions extends cp.SpawnOptions {
log?: boolean;
}
async function exec(child: cp.ChildProcess, options: SpawnOptions = {}): Promise<IExecutionResult> {
async function exec(child: cp.ChildProcess): Promise<IExecutionResult<Buffer>> {
if (!child.stdout || !child.stderr) {
throw new GitError({
message: 'Failed to get stdout or stderr from git process.'
@@ -183,18 +183,15 @@ async function exec(child: cp.ChildProcess, options: SpawnOptions = {}): Promise
disposables.push(toDisposable(() => ee.removeListener(name, fn)));
};
let encoding = options.encoding || 'utf8';
encoding = iconv.encodingExists(encoding) ? encoding : 'utf8';
const [exitCode, stdout, stderr] = await Promise.all<any>([
new Promise<number>((c, e) => {
once(child, 'error', cpErrorHandler(e));
once(child, 'exit', c);
}),
new Promise<string>(c => {
new Promise<Buffer>(c => {
const buffers: Buffer[] = [];
on(child.stdout, 'data', (b: Buffer) => buffers.push(b));
once(child.stdout, 'close', () => c(iconv.decode(Buffer.concat(buffers), encoding)));
once(child.stdout, 'close', () => c(Buffer.concat(buffers)));
}),
new Promise<string>(c => {
const buffers: Buffer[] = [];
@@ -355,7 +352,7 @@ export class Git {
return path.normalize(result.stdout.trim());
}
async exec(cwd: string, args: string[], options: SpawnOptions = {}): Promise<IExecutionResult> {
async exec(cwd: string, args: string[], options: SpawnOptions = {}): Promise<IExecutionResult<string>> {
options = assign({ cwd }, options || {});
return await this._exec(args, options);
}
@@ -365,21 +362,30 @@ export class Git {
return this.spawn(args, options);
}
private async _exec(args: string[], options: SpawnOptions = {}): Promise<IExecutionResult> {
private async _exec(args: string[], options: SpawnOptions = {}): Promise<IExecutionResult<string>> {
const child = this.spawn(args, options);
if (options.input) {
child.stdin.end(options.input, 'utf8');
}
const result = await exec(child, options);
const bufferResult = await exec(child);
if (options.log !== false && result.stderr.length > 0) {
this.log(`${result.stderr}\n`);
if (options.log !== false && bufferResult.stderr.length > 0) {
this.log(`${bufferResult.stderr}\n`);
}
if (result.exitCode) {
return Promise.reject<IExecutionResult>(new GitError({
let encoding = options.encoding || 'utf8';
encoding = iconv.encodingExists(encoding) ? encoding : 'utf8';
const result: IExecutionResult<string> = {
exitCode: bufferResult.exitCode,
stdout: iconv.decode(bufferResult.stdout, encoding),
stderr: bufferResult.stderr
};
if (bufferResult.exitCode) {
return Promise.reject<IExecutionResult<string>>(new GitError({
message: 'Failed to execute git',
stdout: result.stdout,
stderr: result.stderr,
@@ -510,7 +516,7 @@ export class Repository {
}
// TODO@Joao: rename to exec
async run(args: string[], options: SpawnOptions = {}): Promise<IExecutionResult> {
async run(args: string[], options: SpawnOptions = {}): Promise<IExecutionResult<string>> {
return await this.git.exec(this.repositoryRoot, args, options);
}
@@ -539,39 +545,28 @@ export class Repository {
return result.stdout;
}
async buffer(object: string, encoding: string = 'utf8'): Promise<string> {
async bufferString(object: string, encoding: string = 'utf8'): Promise<string> {
const stdout = await this.buffer(object);
return iconv.decode(stdout, iconv.encodingExists(encoding) ? encoding : 'utf8');
}
async buffer(object: string): Promise<Buffer> {
const child = this.stream(['show', object]);
if (!child.stdout) {
return Promise.reject<string>('Can\'t open file from git');
return Promise.reject<Buffer>('Can\'t open file from git');
}
const { exitCode, stdout } = await exec(child, { encoding });
const { exitCode, stdout } = await exec(child);
if (exitCode) {
return Promise.reject<string>(new GitError({
return Promise.reject<Buffer>(new GitError({
message: 'Could not show object.',
exitCode
}));
}
return stdout;
// TODO@joao
// return new Promise((c, e) => {
// detectMimesFromStream(child.stdout, null, (err, result) => {
// if (err) {
// e(err);
// } else if (isBinaryMime(result.mimes)) {
// e(<IFileOperationResult>{
// message: localize('fileBinaryError', "File seems to be binary and cannot be opened as text"),
// fileOperationResult: FileOperationResult.FILE_IS_BINARY
// });
// } else {
// c(this.doBuffer(object));
// }
// });
// });
}
async add(paths: string[]): Promise<void> {
@@ -591,6 +586,7 @@ export class Repository {
child.stdin.end(data, 'utf8');
const { exitCode, stdout } = await exec(child);
const hash = stdout.toString('utf8');
if (exitCode) {
throw new GitError({
@@ -599,7 +595,7 @@ export class Repository {
});
}
await this.run(['update-index', '--cacheinfo', '100644', stdout, path]);
await this.run(['update-index', '--cacheinfo', '100644', hash, path]);
}
async checkout(treeish: string, paths: string[]): Promise<void> {