#!/usr/bin/env python2.4

import os
import sys
import time
import exceptions

from mercurial import commands

# colors {{{
NORMAL='[0;39m'
# RED: Failure or error message
RED='[1;31m'
# GREEN: Success message
GREEN='[1;32m'
# YELLOW: Descriptions
YELLOW='[1;33m'
# BLUE: System messages
BLUE='[1;34m'
# MAGENTA: Found devices or drivers
MAGENTA='[1;35m'
# CYAN: Questions
CYAN='[1;36m'
# BOLD WHITE: Hint
WHITE='[1;37m'
# }}}

def ishgrep(dir):
    return os.path.isdir(os.path.join(dir, '.hg'))

dirlist = [x for x in os.listdir('.') if os.path.isdir(x) and ishgrep(x)]


# dict of running processes
pl = {}
# dict of exited processes
pl_exit = {}
# list of processes in dir order
pl_list = []

class InfoObj:
    """Class to pass data"""

    def __init__(self, pid, fromchild, dir):
        self.pid = pid
        self.fromchild = fromchild
        self.dir = dir
        self.data = []

    def output(self):
        print GREEN + self.dir + NORMAL
        for line in self.data:
            print line ,



# deprecated {{{
def withdirectcall():
    tablebk = commands.table.copy()
    for i in dirlist:
        os.chdir(i)
        print i
        commands.dispatch(sys.argv[1:])
        commands.table = tablebk.copy()
        os.chdir(os.path.pardir)
# }}}

def withfork(num, bufsize=-1):
    if num == 0:
        return
    tmp = 0
    for i in dirlist[:num]:
        tmp += 1
        pr, pw = os.pipe()
        pid = os.fork()
        if not pid:
            # child
            os.dup2(pw, 1)
            os.dup2(pw, 2)
            os.close(pr)

            os.chdir(i)
            commands.run()
        os.close(pw)
        fromchild = os.fdopen(pr, 'r', bufsize)
        pl[pid] = InfoObj(pid, fromchild, i)
        pl_list.append(pl[pid])
        if tmp >= num:
            break
    del dirlist[:num]


def output():
    try:
        while True:
            if pl_exit.has_key(pl_list[0].pid):
                pl_list.pop(0).output()
            else:
                break
    except exceptions.IndexError:
        pass


j=7
if len(sys.argv) >= 3:
    if sys.argv[1] == '--j':
        j=abs(int(sys.argv.pop(2)))
        del sys.argv[1]
if len(sys.argv) < 2:
    commands.run()

while True:
    if len(pl) < j:
        withfork(j-len(pl))
    if not len(pl) and not len(dirlist):
        break
    for i in pl.keys():
        x = pl[i]
        try:
            pid, sts = os.waitpid(x.pid, os.WNOHANG)
            if x.pid == pid:
                # process exited
                x.data.extend(x.fromchild.readlines())
                x.fromchild = None
                pl_exit[i] = pl.pop(i)
                output()
                continue
        except os.error:
            print 'os.error'
    time.sleep(0.1)

if len(pl_list):
    sys.stderr.write(RED + 'WARNING:' + NORMAL + ' elements left in pl_list')
    output()

# vim:foldmethod=marker
