gen-build-info.py revision 48dc01db0b865b73f41cef53bcb72f65fd027af4
148dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien#!/usr/bin/env python
248dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
348dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chienimport datetime
448dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chienimport hashlib
548dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chienimport os
648dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chienimport re
748dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chienimport sys
848dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chienimport subprocess
948dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
1048dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chiendef get_repo_revision(repo_dir):
1148dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    if not os.path.exists(os.path.join(repo_dir, '.git')):
1248dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        return 'Unknown (not git)'
1348dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
1448dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    proc = subprocess.Popen(['git', 'log', '-1', '--format=%H'],
1548dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien                            stdout=subprocess.PIPE,
1648dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien                            stderr=subprocess.PIPE,
1748dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien                            cwd=repo_dir)
1848dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    out, err = proc.communicate()
1948dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    proc.wait()
2048dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
2148dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    return out.strip() + ' (git)'
2248dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
2348dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chiendef compute_sha1(path, global_hasher = None):
2448dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    f = open(path, 'rb')
2548dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    hasher = hashlib.sha1()
2648dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    while True:
2748dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        buf = f.read(512)
2848dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        hasher.update(buf)
2948dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        if global_hasher:
3048dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien            global_hasher.update(buf)
3148dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        if len(buf) < 512:
3248dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien            break
3348dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    f.close()
3448dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    return hasher.hexdigest()
3548dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
3648dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chiendef compute_sha1_list(paths):
3748dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    hasher = hashlib.sha1()
3848dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    sha1sums = []
3948dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    for path in paths:
4048dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        sha1sums.append(compute_sha1(path, hasher))
4148dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    return (hasher.hexdigest(), sha1sums)
4248dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
4348dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chiendef quote_str(s):
4448dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    result = '"'
4548dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    for c in s:
4648dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        if c == '\\':
4748dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien            result += '\\\\'
4848dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        elif c == '\r':
4948dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien            result += '\\r'
5048dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        elif c == '\n':
5148dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien            result += '\\n'
5248dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        elif c == '\t':
5348dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien            result += '\\t'
5448dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        elif c == '\"':
5548dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien            result += '\\"'
5648dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        elif c == '\'':
5748dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien            result += '\\\''
5848dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        else:
5948dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien            result += c
6048dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    result += '"'
6148dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    return result
6248dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
6348dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chiendef main():
6448dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    # Check Argument
6548dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    if len(sys.argv) < 2:
6648dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        print >> sys.stderr, 'USAGE:', sys.argv[0], '[REPO] [LIBs]'
6748dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        sys.exit(1)
6848dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
6948dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    # Record Build Time
7048dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    build_time = datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S')
7148dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
7248dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    # Repository Directory (For build revision)
7348dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    repo_dir = sys.argv[1]
7448dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    build_rev = get_repo_revision(repo_dir)
7548dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
7648dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    # Compute SHA1
7748dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    lib_list = list(set(sys.argv[2:]))
7848dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    lib_list.sort()
7948dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    build_sha1, sha1sum_list = compute_sha1_list(lib_list)
8048dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
8148dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    # Build file list string
8248dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    lib_list_str = ''
8348dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    for i, path in enumerate(lib_list):
8448dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        lib_list_str += '   %s %s\n' % (sha1sum_list[i], path)
8548dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
8648dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    # Print the automatically generated code
8748dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    print """/* Automatically generated file (DON'T MODIFY) */
8848dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
8948dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien/* Repository directory: %s */
9048dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
9148dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien/* File list:
9248dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien%s*/
9348dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
9448dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien#ifdef __cplusplus
9548dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chienextern "C" {
9648dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien#endif
9748dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
9848dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chienchar const *bccGetBuildTime() {
9948dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien  return %s;
10048dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien}
10148dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
10248dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chienchar const *bccGetBuildRev() {
10348dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien  return %s;
10448dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien}
10548dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
10648dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chienchar const *bccGetBuildSHA1() {
10748dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien  return %s;
10848dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien}
10948dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
11048dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien#ifdef __cplusplus
11148dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien}
11248dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien#endif
11348dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
11448dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien""" % (os.path.abspath(repo_dir),
11548dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien       lib_list_str,
11648dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien       quote_str(build_time),
11748dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien       quote_str(build_rev),
11848dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien       quote_str(build_sha1))
11948dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
12048dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chienif __name__ == '__main__':
12148dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    main()
122