| #!/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) | 
 |  |