<commit_before>// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

import ctxm = require('./context');

//
// Utilities passed to each task
// which provides contextual logging to server etc...
//
export class Utilities {
	constructor(context: ctxm.Context) {
		this.ctx = context;
	}

	private ctx: ctxm.Context;

	//
	// '-a -b "quoted b value" -c -d "quoted d value"' becomes
	// [ '-a', '-b', '"quoted b value"', '-c', '-d', '"quoted d value"' ]
	//
	public argStringToArray(argString: string): string[] {
		return argString.match(/([^" ]*("[^"]*")[^" ]*)|[^" ]+/g);	
	}

    // spawn a process with stdout/err piped to context's logger
	// callback(err)
	public spawn(name: string, args: string[], options, callback: (err: any, returnCode: number) => void) {
		var failed = false;
		options = options || {};
		args = args || [];

		var ops = {
			cwd: process.cwd(),
			env: process.env,
			failOnStdErr: true,
			failOnNonZeroRC: true 
		};

		// write over specified options over default options (ops)
		for (var op in options) {
			ops[op] = options[op];
		}

        this.ctx.verbose('cwd: ' + ops.cwd);
        this.ctx.info('running: ' + name + ' ' + args.join(' '));

		var cp = require('child_process').spawn;

		var runCP = cp(name, args, ops);

		runCP.stdout.on('data', (data) => { 			
		  	this.ctx.info(data.toString('utf8'));
		});

		runCP.stderr.on('data', (data) => {
			failed = ops.failOnStdErr;
			if (ops.failOnStdErr) {
		        this.ctx.error(data.toString('utf8'));
			} else {
				this.ctx.info(data.toString('utf8'));
			}
		});

		runCP.on('exit', (code) => {
            if (failed) {
                callback(new Error('Failed with Error Output'), code);
                return;
            }
<commit_msg>Fix utility to handle input arguments with double quotes<commit_after>// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

import ctxm = require('./context');

//
// Utilities passed to each task
// which provides contextual logging to server etc...
//
export class Utilities {
	constructor(context: ctxm.Context) {
		this.ctx = context;
	}

	private ctx: ctxm.Context;

	//
	// '-a -b "quoted b value" -c -d "quoted d value"' becomes
	// [ '-a', '-b', '"quoted b value"', '-c', '-d', '"quoted d value"' ]
	//
	public argStringToArray(argString: string): string[] {
		var args = argString.match(/([^" ]*("[^"]*")[^" ]*)|[^" ]+/g);	
        //remove double quotes from each string in args as child_process.spawn() cannot handle literla quotes as part of arguments
        for(var i = 0; i < args; i ++)
        {
            args[i] = args[i].replace(/"/g", "");
        }
        return args;
	}

    // spawn a process with stdout/err piped to context's logger
	// callback(err)
	public spawn(name: string, args: string[], options, callback: (err: any, returnCode: number) => void) {
		var failed = false;
		options = options || {};
		args = args || [];

		var ops = {
			cwd: process.cwd(),
			env: process.env,
			failOnStdErr: true,
			failOnNonZeroRC: true 
		};

		// write over specified options over default options (ops)
		for (var op in options) {
			ops[op] = options[op];
		}

        this.ctx.verbose('cwd: ' + ops.cwd);
        this.ctx.verbose('args: ' + args.toString());
        this.ctx.info('running: ' + name + ' ' + args.join(' '));

		var cp = require('child_process').spawn;

		var runCP = cp(name, args, ops);

		runCP.stdout.on('data', (data) => { 			
		  	this.ctx.info(data.toString('utf8'));
		});

		runCP.stderr.on('data', (data) => {
			failed = ops.failOnStdErr;
			if (ops.failOnStdErr) {
		        this.ctx.error(data.toString('utf8'));
			} else {
				this.ctx.info(data.toString('utf8'));
			}
		});

		runCP.on('exit', (code) => {
            if (failed) {
                callback(new Error('Failed with Error Output'), code);
                return;
            }

{'fraction_non_alphanumeric': 0.17540821375556656, 'fraction_numerical': 0.0017318159327065809, 'mean_word_length': 2.6721162579473208, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1321531', 'n_tokens_mistral': 1445, 'n_tokens_neox': 1316, 'n_words': 372}