#!/usr/bin/python -E

import sys, os, re

excludes = [r'.*?/\.obj.*?',
            r'.*?~',
            r'.*?\/.DS_Store',
            r'.*?\/.gdb_history',
            r'.*?\/buildspec.mk',
            r'.*?/\..*?\.swp',
            r'.*?/out/.*?',
            r'.*?/install/.*?']

excludes_compiled = map(re.compile, excludes)

def filter_excludes(str):
    for e in excludes_compiled:
        if e.match(str):
            return False
    return True

def split_perforce_parts(s):
    spaces = ((s.count(" ") + 1) / 3) * 2
    pos = 0
    while spaces > 0:
        pos = s.find(" ", pos) + 1
        spaces = spaces - 1
    return s[pos:]

def quotate(s):
    return '"' + s + '"'

class PerforceError(Exception):
    def __init__(self,value):
        self.value = value
    def __str__(self):
        return repr(self.value)
    

def run(command, regex, filt):
    def matchit(s):
        m = regex_compiled.match(s)
        if m:
            return m.group(1)
        else:
            return ""
    def filterit(s):
        if filt_compiled.match(s):
            return True
        else:
            return False

    fd = os.popen(command);
    lines = fd.readlines()
    status = fd.close()
    if status:
        raise PerforceError("error calling " + command)
        
    regex_compiled = re.compile(regex)
    filt_compiled = re.compile(filt)

    if len(lines) >= 1:
        lines = filter(filterit, lines)
        if len(lines) >= 1:
            return map(matchit, lines)
    return None

try:
    if len(sys.argv) == 1:
        do_exclude = True
    elif len(sys.argv) == 2 and sys.argv[1] == "-a":
        do_exclude = False
    else:
        print "usage: checktree [-a]"
        print "  -a  don't filter common crud in the tree"
        sys.exit(1)

    have = run("p4 have ...", r'[^#]+#[0-9]+ - (.*)', r'.*')

    cwd = os.getcwd()
    files = run("find . -not -type d", r'.(.*)', r'.*')
    files = map(lambda s: cwd+s, files)

    added_depot_path = run("p4 opened ...", r'([^#]+)#.*', r'.*?#[0-9]+ - add .*');
    added = []
    if added_depot_path:
        added_depot_path = map(quotate, added_depot_path)

        where = "p4 where " + " ".join(added_depot_path)
        added = run(where, r'(.*)', r'.*')
        added = map(split_perforce_parts, added)

    extras = []

    # Python 2.3 -- still default on Mac OS X -- does not have set()
    # Make dict's here to support the "in" operations below
    have = dict().fromkeys(have, 1)
    added = dict().fromkeys(added, 1)

    for file in files:
        if not file in have:
            if not file in added:
                extras.append(file)

    if do_exclude:
        extras = filter(filter_excludes, extras)

    for s in extras:
        print s.replace(" ", "\\ ")

except PerforceError, e:
    sys.exit(2)

