<commit_before>// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

patch class _WindowsCodePageDecoder {
  /* patch */ static String _decodeBytes(List<int> bytes)
      native "SystemEncodingToString";
}


patch class _WindowsCodePageEncoder {
  /* patch */ static List<int> _encodeString(String string)
      native "StringToSystemEncoding";
}


patch class Process {
  /* patch */ static Future<Process> start(
      String executable,
      List<String> arguments,
      {String workingDirectory,
       Map<String, String> environment,
       bool runInShell}) {
    _ProcessImpl process = new _ProcessImpl(executable,
                                            arguments,
                                            workingDirectory,
                                            environment,
                                            runInShell);
    return process._start();
  }

  /* patch */ static Future<ProcessResult> run(
      String executable,
      List<String> arguments,
      {String workingDirectory,
       Map<String, String> environment,
       bool runInShell,
       Encoding stdoutEncoding: Encoding.SYSTEM,
       Encoding stderrEncoding: Encoding.SYSTEM}) {
    return _runNonInteractiveProcess(executable,
                                     arguments,
                                     workingDirectory,
                                     environment,
                                     runInShell,
                                     stdoutEncoding,
                                     stderrEncoding);
  }
}


patch class _ProcessUtils {
  /* patch */ static void _exit(int status) native "Process_Exit";
  /* patch */ static void _setExitCode(int status)
      native "Process_SetExitCode";
  /* patch */ static void _sleep(int millis) native "Process_Sleep";
  /* patch */ static int _pid(Process process) native "Process_Pid";
}


class _ProcessStartStatus {
  int _errorCode;  // Set to OS error code if process start failed.
  String _errorMessage;  // Set to OS error message if process start failed.
}


class _ProcessImpl extends NativeFieldWrapperClass1 implements Process {
  _ProcessImpl(String path,
               List<String> arguments,
               String this._workingDirectory,
               Map<String, String> environment,
               bool runInShell) {
    if (identical(runInShell, true)) {
      arguments = _getShellArguments(path, arguments);
      path = _getShellCommand();
    }

    if (path is !String) {
      throw new ArgumentError("Path is not a String: $path");
    }
    _path = path;

    if (arguments is !List) {
      throw new ArgumentError("Arguments is not a List: $arguments");
    }
    int len = arguments.length;
    _arguments = new List<String>(len);
    for (int i = 0; i < len; i++) {
      var arg = arguments[i];
      if (arg is !String) {
        throw new ArgumentError("Non-string argument: $arg");
      }
      _arguments[i] = arguments[i];
      if (Platform.operatingSystem == 'windows') {
        _arguments[i] = _windowsArgumentEscape(_arguments[i]);
      }
    }

    if (_workingDirectory != null && _workingDirectory is !String) {
      throw new ArgumentError(
          "WorkingDirectory is not a String: $_workingDirectory");
    }

    if (environment != null) {
      var env = environment;
      if (env is !Map) {
        throw new ArgumentError("Environment is not a map: $env");
      }
      _environment = [];
      env.forEach((key, value) {
        if (key is !String || value is !String) {
          throw new ArgumentError(
              "Environment key or value is not a string: ($key, $value)");
        }
        _environment.add('$key=$value');
      });
    }

    // stdin going to process.
    _stdin = new _StdSink(new _Socket._writePipe());
    // stdout coming from process.
    _stdout = new _StdStream(new _Socket._readPipe());
    // stderr coming from process.
    _stderr = new _StdStream(new _Socket._readPipe());
    _exitHandler = new _Socket._readPipe();
    _ended = false;
    _started = false;
  }

  static String _getShellCommand() {
    if (Platform.operatingSystem == 'windows') {
      return 'cmd.exe';
    }
    return '/bin/sh';
  }

  static List<String> _getShellArguments(String executable,
                                         List<String> arguments) {
    List<String> shellArguments = [];
    if (Platform.operatingSystem == 'windows') {
      shellArguments.add('/c');
      shellArguments.add(executable);
      for (var arg in arguments) {
        shellArguments.add(arg);
      }
    } else {
      var commandLine = new StringBuffer();
      executable = executable.replaceAll("'", "'\"'\"'");
      commandLine.write("'$executable'");
      shellArguments.add("-c");
      for (var arg in arguments) {
        arg = arg.replaceAll("'", "'\"'\"'");
        commandLine.write(" '$arg'");
      }
      shellArguments.add(commandLine.toString());
    }
    return shellArguments;
  }

  String _windowsArgumentEscape(String argument) {
    var result = argument;
    if (argument.contains('\t') ||
        argument.contains(' ') ||
        argument.contains('"')) {
      // Produce something that the C runtime on Windows will parse
      // back as this string.

      // Replace any number of '\' followed by '"' with
      // twice as many '\' followed by '\"'.
      var backslash = '\\'.codeUnitAt(0);
      var sb = new StringBuffer();
      var nextPos = 0;
      var quotePos = argument.indexOf('"', nextPos);
      while (quotePos != -1) {
        var numBackslash = 0;
        var pos = quotePos - 1;
        while (pos >= 0 && argument.codeUnitAt(pos) == backslash) {
          numBackslash++;
          pos--;
        }
        sb.write(argument.substring(nextPos, quotePos - numBackslash));
        for (var i = 0; i < numBackslash; i++) {
          sb.write(r'\\');
        }
        sb.write(r'\"');
        nextPos = quotePos + 1;
        quotePos = argument.indexOf('"', nextPos);
      }
      sb.write(argument.substring(nextPos, argument.length));
      result = sb.toString();

      // Add '"' at the beginning and end and replace all '\' at
      // the end with two '\'.<commit_msg>Temporary, only escape quotes if run in shell.<commit_after>// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

patch class _WindowsCodePageDecoder {
  /* patch */ static String _decodeBytes(List<int> bytes)
      native "SystemEncodingToString";
}


patch class _WindowsCodePageEncoder {
  /* patch */ static List<int> _encodeString(String string)
      native "StringToSystemEncoding";
}


patch class Process {
  /* patch */ static Future<Process> start(
      String executable,
      List<String> arguments,
      {String workingDirectory,
       Map<String, String> environment,
       bool runInShell}) {
    _ProcessImpl process = new _ProcessImpl(executable,
                                            arguments,
                                            workingDirectory,
                                            environment,
                                            runInShell);
    return process._start();
  }

  /* patch */ static Future<ProcessResult> run(
      String executable,
      List<String> arguments,
      {String workingDirectory,
       Map<String, String> environment,
       bool runInShell,
       Encoding stdoutEncoding: Encoding.SYSTEM,
       Encoding stderrEncoding: Encoding.SYSTEM}) {
    return _runNonInteractiveProcess(executable,
                                     arguments,
                                     workingDirectory,
                                     environment,
                                     runInShell,
                                     stdoutEncoding,
                                     stderrEncoding);
  }
}


patch class _ProcessUtils {
  /* patch */ static void _exit(int status) native "Process_Exit";
  /* patch */ static void _setExitCode(int status)
      native "Process_SetExitCode";
  /* patch */ static void _sleep(int millis) native "Process_Sleep";
  /* patch */ static int _pid(Process process) native "Process_Pid";
}


class _ProcessStartStatus {
  int _errorCode;  // Set to OS error code if process start failed.
  String _errorMessage;  // Set to OS error message if process start failed.
}


class _ProcessImpl extends NativeFieldWrapperClass1 implements Process {
  _ProcessImpl(String path,
               List<String> arguments,
               String this._workingDirectory,
               Map<String, String> environment,
               bool runInShell) {
    runInShell = identical(runInShell, true);
    if (runInShell) {
      arguments = _getShellArguments(path, arguments);
      path = _getShellCommand();
    }

    if (path is !String) {
      throw new ArgumentError("Path is not a String: $path");
    }
    _path = path;

    if (arguments is !List) {
      throw new ArgumentError("Arguments is not a List: $arguments");
    }
    int len = arguments.length;
    _arguments = new List<String>(len);
    for (int i = 0; i < len; i++) {
      var arg = arguments[i];
      if (arg is !String) {
        throw new ArgumentError("Non-string argument: $arg");
      }
      _arguments[i] = arguments[i];
      if (Platform.operatingSystem == 'windows') {
        _arguments[i] = _windowsArgumentEscape(_arguments[i],
                                               shellEscape: runInShell);
      }
    }

    if (_workingDirectory != null && _workingDirectory is !String) {
      throw new ArgumentError(
          "WorkingDirectory is not a String: $_workingDirectory");
    }

    if (environment != null) {
      var env = environment;
      if (env is !Map) {
        throw new ArgumentError("Environment is not a map: $env");
      }
      _environment = [];
      env.forEach((key, value) {
        if (key is !String || value is !String) {
          throw new ArgumentError(
              "Environment key or value is not a string: ($key, $value)");
        }
        _environment.add('$key=$value');
      });
    }

    // stdin going to process.
    _stdin = new _StdSink(new _Socket._writePipe());
    // stdout coming from process.
    _stdout = new _StdStream(new _Socket._readPipe());
    // stderr coming from process.
    _stderr = new _StdStream(new _Socket._readPipe());
    _exitHandler = new _Socket._readPipe();
    _ended = false;
    _started = false;
  }

  static String _getShellCommand() {
    if (Platform.operatingSystem == 'windows') {
      return 'cmd.exe';
    }
    return '/bin/sh';
  }

  static List<String> _getShellArguments(String executable,
                                         List<String> arguments) {
    List<String> shellArguments = [];
    if (Platform.operatingSystem == 'windows') {
      shellArguments.add('/c');
      shellArguments.add(executable);
      for (var arg in arguments) {
        shellArguments.add(arg);
      }
    } else {
      var commandLine = new StringBuffer();
      executable = executable.replaceAll("'", "'\"'\"'");
      commandLine.write("'$executable'");
      shellArguments.add("-c");
      for (var arg in arguments) {
        arg = arg.replaceAll("'", "'\"'\"'");
        commandLine.write(" '$arg'");
      }
      shellArguments.add(commandLine.toString());
    }
    return shellArguments;
  }

  String _windowsArgumentEscape(String argument, { bool shellEscape: false }) {
    var result = argument;
    if (argument.contains('\t') ||
        argument.contains(' ') ||
        // TODO(ajohnsen): Remove shellEscape.
        (shellEscape && argument.contains('"'))) {
      // Produce something that the C runtime on Windows will parse
      // back as this string.

      // Replace any number of '\' followed by '"' with
      // twice as many '\' followed by '\"'.
      var backslash = '\\'.codeUnitAt(0);
      var sb = new StringBuffer();
      var nextPos = 0;
      var quotePos = argument.indexOf('"', nextPos);
      while (quotePos != -1) {
        var numBackslash = 0;
        var pos = quotePos - 1;
        while (pos >= 0 && argument.codeUnitAt(pos) == backslash) {
          numBackslash++;
          pos--;
        }
        sb.write(argument.substring(nextPos, quotePos - numBackslash));
        for (var i = 0; i < numBackslash; i++) {
          sb.write(r'\\');
        }
        sb.write(r'\"');
        nextPos = quotePos + 1;
        quotePos = argument.indexOf('"', nextPos);
      }
      sb.write(argument.substring(nextPos, argument.length));
      result = sb.toString();

      // Add '"' at the beginning and end and replace all '\' at
      // the end with two '\'.
{'fraction_non_alphanumeric': 0.11299435028248588, 'fraction_numerical': 0.0021670149369243867, 'mean_word_length': 2.067173035841443, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 34, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '793430', 'n_tokens_mistral': 3474, 'n_tokens_neox': 3391, 'n_words': 1004}