188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project#!/usr/bin/python -E
288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Projectimport sys, os, re
488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Projectexcludes = [r'.*?/\.obj.*?',
688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            r'.*?~',
788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            r'.*?\/.DS_Store',
888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            r'.*?\/.gdb_history',
988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            r'.*?\/buildspec.mk',
1088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            r'.*?/\..*?\.swp',
1188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            r'.*?/out/.*?',
1288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            r'.*?/install/.*?']
1388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
1488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Projectexcludes_compiled = map(re.compile, excludes)
1588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
1688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Projectdef filter_excludes(str):
1788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    for e in excludes_compiled:
1888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        if e.match(str):
1988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            return False
2088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    return True
2188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
2288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Projectdef split_perforce_parts(s):
2388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    spaces = ((s.count(" ") + 1) / 3) * 2
2488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    pos = 0
2588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    while spaces > 0:
2688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        pos = s.find(" ", pos) + 1
2788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        spaces = spaces - 1
2888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    return s[pos:]
2988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
3088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Projectdef quotate(s):
3188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    return '"' + s + '"'
3288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
3388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Projectclass PerforceError(Exception):
3488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    def __init__(self,value):
3588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        self.value = value
3688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    def __str__(self):
3788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        return repr(self.value)
3888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    
3988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
4088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Projectdef run(command, regex, filt):
4188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    def matchit(s):
4288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        m = regex_compiled.match(s)
4388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        if m:
4488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            return m.group(1)
4588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        else:
4688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            return ""
4788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    def filterit(s):
4888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        if filt_compiled.match(s):
4988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            return True
5088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        else:
5188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            return False
5288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
5388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    fd = os.popen(command);
5488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    lines = fd.readlines()
5588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    status = fd.close()
5688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    if status:
5788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        raise PerforceError("error calling " + command)
5888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        
5988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    regex_compiled = re.compile(regex)
6088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    filt_compiled = re.compile(filt)
6188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
6288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    if len(lines) >= 1:
6388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        lines = filter(filterit, lines)
6488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        if len(lines) >= 1:
6588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            return map(matchit, lines)
6688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    return None
6788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
6888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Projecttry:
6988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    if len(sys.argv) == 1:
7088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        do_exclude = True
7188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    elif len(sys.argv) == 2 and sys.argv[1] == "-a":
7288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        do_exclude = False
7388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    else:
7488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        print "usage: checktree [-a]"
7588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        print "  -a  don't filter common crud in the tree"
7688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        sys.exit(1)
7788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
7888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    have = run("p4 have ...", r'[^#]+#[0-9]+ - (.*)', r'.*')
7988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
8088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    cwd = os.getcwd()
8188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    files = run("find . -not -type d", r'.(.*)', r'.*')
8288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    files = map(lambda s: cwd+s, files)
8388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
8488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    added_depot_path = run("p4 opened ...", r'([^#]+)#.*', r'.*?#[0-9]+ - add .*');
8588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    added = []
8688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    if added_depot_path:
8788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        added_depot_path = map(quotate, added_depot_path)
8888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
8988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        where = "p4 where " + " ".join(added_depot_path)
9088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        added = run(where, r'(.*)', r'.*')
9188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        added = map(split_perforce_parts, added)
9288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
9388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    extras = []
9488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
9588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    # Python 2.3 -- still default on Mac OS X -- does not have set()
9688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    # Make dict's here to support the "in" operations below
9788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    have = dict().fromkeys(have, 1)
9888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    added = dict().fromkeys(added, 1)
9988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
10088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    for file in files:
10188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        if not file in have:
10288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            if not file in added:
10388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project                extras.append(file)
10488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
10588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    if do_exclude:
10688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        extras = filter(filter_excludes, extras)
10788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
10888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    for s in extras:
10988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        print s.replace(" ", "\\ ")
11088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
11188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Projectexcept PerforceError, e:
11288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    sys.exit(2)
11388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
114