| The Android Open Source Project | 88b6079 | 2009-03-03 19:28:42 -0800 | [diff] [blame] | 1 | #!/usr/bin/python -E | 
|  | 2 |  | 
|  | 3 | import sys, os, re | 
|  | 4 |  | 
|  | 5 | excludes = [r'.*?/\.obj.*?', | 
|  | 6 | r'.*?~', | 
|  | 7 | r'.*?\/.DS_Store', | 
|  | 8 | r'.*?\/.gdb_history', | 
|  | 9 | r'.*?\/buildspec.mk', | 
|  | 10 | r'.*?/\..*?\.swp', | 
|  | 11 | r'.*?/out/.*?', | 
|  | 12 | r'.*?/install/.*?'] | 
|  | 13 |  | 
|  | 14 | excludes_compiled = map(re.compile, excludes) | 
|  | 15 |  | 
|  | 16 | def filter_excludes(str): | 
|  | 17 | for e in excludes_compiled: | 
|  | 18 | if e.match(str): | 
|  | 19 | return False | 
|  | 20 | return True | 
|  | 21 |  | 
|  | 22 | def split_perforce_parts(s): | 
|  | 23 | spaces = ((s.count(" ") + 1) / 3) * 2 | 
|  | 24 | pos = 0 | 
|  | 25 | while spaces > 0: | 
|  | 26 | pos = s.find(" ", pos) + 1 | 
|  | 27 | spaces = spaces - 1 | 
|  | 28 | return s[pos:] | 
|  | 29 |  | 
|  | 30 | def quotate(s): | 
|  | 31 | return '"' + s + '"' | 
|  | 32 |  | 
|  | 33 | class PerforceError(Exception): | 
|  | 34 | def __init__(self,value): | 
|  | 35 | self.value = value | 
|  | 36 | def __str__(self): | 
|  | 37 | return repr(self.value) | 
|  | 38 |  | 
|  | 39 |  | 
|  | 40 | def run(command, regex, filt): | 
|  | 41 | def matchit(s): | 
|  | 42 | m = regex_compiled.match(s) | 
|  | 43 | if m: | 
|  | 44 | return m.group(1) | 
|  | 45 | else: | 
|  | 46 | return "" | 
|  | 47 | def filterit(s): | 
|  | 48 | if filt_compiled.match(s): | 
|  | 49 | return True | 
|  | 50 | else: | 
|  | 51 | return False | 
|  | 52 |  | 
|  | 53 | fd = os.popen(command); | 
|  | 54 | lines = fd.readlines() | 
|  | 55 | status = fd.close() | 
|  | 56 | if status: | 
|  | 57 | raise PerforceError("error calling " + command) | 
|  | 58 |  | 
|  | 59 | regex_compiled = re.compile(regex) | 
|  | 60 | filt_compiled = re.compile(filt) | 
|  | 61 |  | 
|  | 62 | if len(lines) >= 1: | 
|  | 63 | lines = filter(filterit, lines) | 
|  | 64 | if len(lines) >= 1: | 
|  | 65 | return map(matchit, lines) | 
|  | 66 | return None | 
|  | 67 |  | 
|  | 68 | try: | 
|  | 69 | if len(sys.argv) == 1: | 
|  | 70 | do_exclude = True | 
|  | 71 | elif len(sys.argv) == 2 and sys.argv[1] == "-a": | 
|  | 72 | do_exclude = False | 
|  | 73 | else: | 
|  | 74 | print "usage: checktree [-a]" | 
|  | 75 | print "  -a  don't filter common crud in the tree" | 
|  | 76 | sys.exit(1) | 
|  | 77 |  | 
|  | 78 | have = run("p4 have ...", r'[^#]+#[0-9]+ - (.*)', r'.*') | 
|  | 79 |  | 
|  | 80 | cwd = os.getcwd() | 
|  | 81 | files = run("find . -not -type d", r'.(.*)', r'.*') | 
|  | 82 | files = map(lambda s: cwd+s, files) | 
|  | 83 |  | 
|  | 84 | added_depot_path = run("p4 opened ...", r'([^#]+)#.*', r'.*?#[0-9]+ - add .*'); | 
|  | 85 | added = [] | 
|  | 86 | if added_depot_path: | 
|  | 87 | added_depot_path = map(quotate, added_depot_path) | 
|  | 88 |  | 
|  | 89 | where = "p4 where " + " ".join(added_depot_path) | 
|  | 90 | added = run(where, r'(.*)', r'.*') | 
|  | 91 | added = map(split_perforce_parts, added) | 
|  | 92 |  | 
|  | 93 | extras = [] | 
|  | 94 |  | 
|  | 95 | # Python 2.3 -- still default on Mac OS X -- does not have set() | 
|  | 96 | # Make dict's here to support the "in" operations below | 
|  | 97 | have = dict().fromkeys(have, 1) | 
|  | 98 | added = dict().fromkeys(added, 1) | 
|  | 99 |  | 
|  | 100 | for file in files: | 
|  | 101 | if not file in have: | 
|  | 102 | if not file in added: | 
|  | 103 | extras.append(file) | 
|  | 104 |  | 
|  | 105 | if do_exclude: | 
|  | 106 | extras = filter(filter_excludes, extras) | 
|  | 107 |  | 
|  | 108 | for s in extras: | 
|  | 109 | print s.replace(" ", "\\ ") | 
|  | 110 |  | 
|  | 111 | except PerforceError, e: | 
|  | 112 | sys.exit(2) | 
|  | 113 |  |