public exec()

in node/toolrunner.ts [883:988]


    public exec(options?: IExecOptions): Q.Promise<number> {
        if (this.pipeOutputToTool) {
            return this.execWithPiping(this.pipeOutputToTool, options);
        }

        var defer = Q.defer<number>();

        this._debug('exec tool: ' + this.toolPath);
        this._debug('arguments:');
        this.args.forEach((arg) => {
            this._debug('   ' + arg);
        });

        const optionsNonNull = this._cloneExecOptions(options);
        if (!optionsNonNull.silent) {
            optionsNonNull.outStream!.write(this._getCommandString(optionsNonNull) + os.EOL);
        }

        let state = new ExecState(optionsNonNull, this.toolPath);
        state.on('debug', (message: string) => {
            this._debug(message);
        });

        let cp = child.spawn(this._getSpawnFileName(options), this._getSpawnArgs(optionsNonNull), this._getSpawnOptions(options));
        this.childProcess = cp;
        // it is possible for the child process to end its last line without a new line.
        // because stdout is buffered, this causes the last line to not get sent to the parent
        // stream. Adding this event forces a flush before the child streams are closed.
        cp.stdout?.on('finish', () => {
            if (!optionsNonNull.silent) {
                optionsNonNull.outStream!.write(os.EOL);
            }
        });

        var stdbuffer: string = '';
        cp.stdout?.on('data', (data: Buffer) => {
            this.emit('stdout', data);

            if (!optionsNonNull.silent) {
                optionsNonNull.outStream!.write(data);
            }

            this._processLineBuffer(data, stdbuffer, (line: string) => {
                this.emit('stdline', line);
            });
        });


        var errbuffer: string = '';
        cp.stderr?.on('data', (data: Buffer) => {
            state.processStderr = true;
            this.emit('stderr', data);

            if (!optionsNonNull.silent) {
                var s = optionsNonNull.failOnStdErr ? optionsNonNull.errStream! : optionsNonNull.outStream!;
                s.write(data);
            }

            this._processLineBuffer(data, errbuffer, (line: string) => {
                this.emit('errline', line);
            });
        });

        cp.on('error', (err: Error) => {
            state.processError = err.message;
            state.processExited = true;
            state.processClosed = true;
            state.CheckComplete();
        });

        cp.on('exit', (code: number, signal: any) => {
            state.processExitCode = code;
            state.processExited = true;
            this._debug(`Exit code ${code} received from tool '${this.toolPath}'`);
            state.CheckComplete()
        });

        cp.on('close', (code: number, signal: any) => {
            state.processExitCode = code;
            state.processExited = true;
            state.processClosed = true;
            this._debug(`STDIO streams have closed for tool '${this.toolPath}'`)
            state.CheckComplete();
        });

        state.on('done', (error: Error, exitCode: number) => {
            if (stdbuffer.length > 0) {
                this.emit('stdline', stdbuffer);
            }

            if (errbuffer.length > 0) {
                this.emit('errline', errbuffer);
            }

            cp.removeAllListeners();

            if (error) {
                defer.reject(error);
            }
            else {
                defer.resolve(exitCode);
            }
        });

        return defer.promise;
    }