#!/usr/bin/python


# execute the command line and keep track of its output,
# performing accounting for showing progress and other goodies


import sys
import select
import popen2
import re
import os

command=""
logfile_name=None
progress_name=None
pattern_re= None
job_name= None

def print_help():
  print sys.argv[0],"-l=<logfile> -p=<progressdatafile> -m=<pattern> -n=<name/label> <comand>"

def read_progress_info(progress_name):
  try:
    f=open(progress_name,"r")
  except:
    return None
  return int(f.readline().strip())


if len(sys.argv) < 2:
 print_help()
 sys.exit(1)

args= sys.argv[1:]
while args:
  arg= args[0]
  if arg[:3]=="-l=":
    logfile_name=arg[3:]
  elif arg[:3]=="-p=":
    progress_name=arg[3:]
  elif arg[:3]=="-m=":
    pattern_re=arg[3:]
  elif arg[:3]=="-n=":
    job_name=arg[3:]
  else:
    break
  del args[0]
command= " ".join(args)


if not progress_name and job_name:
  progress_name= "progressdata."+job_name


# execute the command listening to stdout and stderr,
# if we find the matching pattern, we increment the counter
# at the end of everything (if exit status is 0), 
# we save the value of the counter to be used for next time 
# if a previous counter could be read, then it will be used
# to report the progress of the current execution

def execute_command(command, pattern=None, total_commands= None, logfile= None, job_name=None):
  new_command_count= 0

  child= popen2.Popen3(command+" 2>&1", True)
  #child.fromchild, child.tochild, child.childerr
  st= child.poll()
  timeout= 0.0
  stdout= child.fromchild.fileno()
  while st == -1:
    # check if there's something to read
    has_data,_,_= select.select([stdout], [], [], timeout)
    if not has_data:
      timeout= 0.1
    else:
      if stdout in has_data:
        line= child.fromchild.readline()
        if logfile:
          logfile.write(line)
	else:
	  print job_name+": "+line
        if pattern and pattern.match(line):
          new_command_count+=1
          if total_commands:
            print job_name or command, " %.01f%%"%(new_command_count*100.0/total_commands)
          else:
            print job_name or command, new_command_count, line

      # to check if there's more data 
      timeout= 0.0
    st= child.poll()

  return new_command_count, st


if logfile_name:
	logfile=open(logfile_name,"w+")
else:
	logfile= None

try:
	progress_data= read_progress_info(progress_name)
except:
	progress_data= None

if pattern_re:
  pattern= re.compile(pattern_re)
else:
  pattern= None

print "Execute ''",command, "'' logging output to ", logfile
if not progress_data:
	print "No data about previous executions found, collecting new data for progress tracking"
count, status= execute_command(command, pattern, progress_data, logfile, job_name)
print command, "finished with status",status

if status == 0 and progress_name:
	f= open(progress_name, "w+")
	f.write("%i\n"%count)
	f.close()
	try:
	    os.chmod(progress_name, 0666)
	except:
	    pass

if logfile:
  logfile.close()

import posix

if posix.WIFEXITED(status):
  sys.exit(posix.WEXITSTATUS(status))
else:
  sys.exit(1)


