# Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Shared process-related utility functions."""

import errno
import os
import subprocess
import sys

class CommandNotFound(Exception): pass


TASKKILL = os.path.join(os.environ['WINDIR'], 'system32', 'taskkill.exe')
TASKKILL_PROCESS_NOT_FOUND_ERR = 128
# On windows 2000 there is no taskkill.exe, we need to have pskill somewhere
# in the path.
PSKILL = 'pskill.exe'
PSKILL_PROCESS_NOT_FOUND_ERR = -1

def KillAll(executables):
  """Tries to kill all copies of each process in the processes list.  Returns
  an error if any running processes couldn't be killed.
  """
  result = 0
  if os.path.exists(TASKKILL):
    command = [TASKKILL, '/f', '/im']
    process_not_found_err = TASKKILL_PROCESS_NOT_FOUND_ERR
  else:
    command = [PSKILL, '/t']
    process_not_found_err = PSKILL_PROCESS_NOT_FOUND_ERR

  for name in executables:
    new_error = RunCommand(command + [name])
    # Ignore "process not found" error.
    if new_error != 0 and new_error != process_not_found_err:
      result = new_error
  return result

def RunCommandFull(command, verbose=True, collect_output=False,
                   print_output=True):
  """Runs the command list.

  Prints the given command (which should be a list of one or more strings).
  If specified, prints its stderr (and optionally stdout) to stdout,
  line-buffered, converting line endings to CRLF (see note below).  If
  specified, collects the output as a list of lines and returns it.  Waits
  for the command to terminate and returns its status.

  Args:
    command: the full command to run, as a list of one or more strings
    verbose: if True, combines all output (stdout and stderr) into stdout.
             Otherwise, prints only the command's stderr to stdout.
    collect_output: if True, collects the output of the command as a list of
                    lines and returns it
    print_output: if True, prints the output of the command

  Returns:
    A tuple consisting of the process's exit status and output.  If
    collect_output is False, the output will be [].

  Raises:
    CommandNotFound if the command executable could not be found.
  """
  print '\n' + subprocess.list2cmdline(command).replace('\\', '/') + '\n', ###

  if verbose:
    out = subprocess.PIPE
    err = subprocess.STDOUT
  else:
    out = file(os.devnull, 'w')
    err = subprocess.PIPE
  try:
    proc = subprocess.Popen(command, stdout=out, stderr=err, bufsize=1)
  except OSError, e:
    if e.errno == errno.ENOENT:
      raise CommandNotFound('Unable to find "%s"' % command[0])
    raise

  output = []

  if verbose:
    read_from = proc.stdout
  else:
    read_from = proc.stderr
  line = read_from.readline()
  while line:
    line = line.rstrip()

    if collect_output:
      output.append(line)

    if print_output:
      # Windows Python converts \n to \r\n automatically whenever it
      # encounters it written to a text file (including stdout).  The only
      # way around it is to write to a binary file, which isn't feasible for
      # stdout. So we end up with \r\n here even though we explicitly write
      # \n.  (We could write \r instead, which doesn't get converted to \r\n,
      # but that's probably more troublesome for people trying to read the
      # files.)
      print line + '\n',

      # Python on windows writes the buffer only when it reaches 4k. This is
      # not fast enough for all purposes.
      sys.stdout.flush()
    line = read_from.readline()

  # Make sure the process terminates.
  proc.wait()

  if not verbose:
    out.close()
  return (proc.returncode, output)

def RunCommand(command, verbose=True):
  """Runs the command list, printing its output and returning its exit status.

  Prints the given command (which should be a list of one or more strings),
  then runs it and prints its stderr (and optionally stdout) to stdout,
  line-buffered, converting line endings to CRLF.  Waits for the command to
  terminate and returns its status.

  Args:
    command: the full command to run, as a list of one or more strings
    verbose: if True, combines all output (stdout and stderr) into stdout.
             Otherwise, prints only the command's stderr to stdout.

  Returns:
    The process's exit status.

  Raises:
    CommandNotFound if the command executable could not be found.
  """
  return RunCommandFull(command, verbose)[0]

def RunCommandsInParallel(commands, verbose=True, collect_output=False,
                          print_output=True):
  """Runs a list of commands in parallel, waits for all commands to terminate
  and returns their status. If specified, the ouput of commands can be
  returned and/or printed.

  Args:
    commands: the list of commands to run, each as a list of one or more
              strings.
    verbose: if True, combines stdout and stderr into stdout.
             Otherwise, prints only the command's stderr to stdout.
    collect_output: if True, collects the output of the each command as a list
                    of lines and returns it.
    print_output: if True, prints the output of each command.

  Returns:
    A list of tuples consisting of each command's exit status and output.  If
    collect_output is False, the output will be [].

  Raises:
    CommandNotFound if any of the command executables could not be found.
  """

  command_num = len(commands)
  outputs = [[] for i in xrange(command_num)]
  procs = [None for i in xrange(command_num)]
  eofs = [False for i in xrange(command_num)]

  for command in commands:
    print '\n' + subprocess.list2cmdline(command).replace('\\', '/') + '\n',

  if verbose:
    out = subprocess.PIPE
    err = subprocess.STDOUT
  else:
    out = file(os.devnull, 'w')
    err = subprocess.PIPE

  for i in xrange(command_num):
    try:
      command = commands[i]
      procs[i] = subprocess.Popen(command, stdout=out, stderr=err, bufsize=1)
    except OSError, e:
      if e.errno == errno.ENOENT:
        raise CommandNotFound('Unable to find "%s"' % command[0])
      raise
      # We could consider terminating the processes already started.
      # But Popen.kill() is only available in version 2.6.
      # For now the clean up is done by KillAll.

  while True:
    eof_all = True
    for i in xrange(command_num):
      if eofs[i]:
        continue
      if verbose:
        read_from = procs[i].stdout
      else:
        read_from = procs[i].stderr
      line = read_from.readline()
      if line:
        eof_all = False
        line = line.rstrip()
        outputs[i].append(line)
        if print_output:
          # Windows Python converts \n to \r\n automatically whenever it
          # encounters it written to a text file (including stdout).  The only
          # way around it is to write to a binary file, which isn't feasible
          # for stdout. So we end up with \r\n here even though we explicitly
          # write \n.  (We could write \r instead, which doesn't get converted
          # to \r\n, but that's probably more troublesome for people trying to
          # read the files.)
          print line + '\n',
      else:
        eofs[i] = True
    if eof_all:
      break

  # Make sure the process terminates.
  for i in xrange(command_num):
    procs[i].wait()

  if not verbose:
    out.close()

  return [(procs[i].returncode, outputs[i]) for i in xrange(command_num)]
