gen-build-info.py revision 3bfcd866e752a77e42b93dea1754417e5c466472
1#!/usr/bin/env python
2
3import datetime
4import hashlib
5import os
6import re
7import sys
8import subprocess
9
10def get_repo_revision(repo_dir):
11    if not os.path.exists(os.path.join(repo_dir, '.git')):
12        return 'Unknown (not git)'
13
14    # Get the HEAD revision
15    proc = subprocess.Popen(['git', 'log', '-1', '--format=%H'],
16                            stdout=subprocess.PIPE,
17                            stderr=subprocess.PIPE,
18                            cwd=repo_dir)
19    out, err = proc.communicate()
20    proc.wait()
21
22    rev_sha1 = out.strip()
23
24    # Working Directory Modified
25    proc = subprocess.Popen(['git', 'status'],
26                            stdout=subprocess.PIPE,
27                            stderr=subprocess.PIPE,
28                            cwd=repo_dir)
29    out, err = proc.communicate()
30    proc.wait()
31
32    mod = ' modified' if out.find('(work directory clean)') == -1 else ''
33
34    return rev_sha1 + mod + ' (git)'
35
36def compute_sha1(path, global_hasher = None):
37    f = open(path, 'rb')
38    hasher = hashlib.sha1()
39    while True:
40        buf = f.read(512)
41        hasher.update(buf)
42        if global_hasher:
43            global_hasher.update(buf)
44        if len(buf) < 512:
45            break
46    f.close()
47    return hasher.hexdigest()
48
49def compute_sha1_list(paths):
50    hasher = hashlib.sha1()
51    sha1sums = []
52    for path in paths:
53        sha1sums.append(compute_sha1(path, hasher))
54    return (hasher.hexdigest(), sha1sums)
55
56def quote_str(s):
57    result = '"'
58    for c in s:
59        if c == '\\':
60            result += '\\\\'
61        elif c == '\r':
62            result += '\\r'
63        elif c == '\n':
64            result += '\\n'
65        elif c == '\t':
66            result += '\\t'
67        elif c == '\"':
68            result += '\\"'
69        elif c == '\'':
70            result += '\\\''
71        else:
72            result += c
73    result += '"'
74    return result
75
76def main():
77    # Check Argument
78    if len(sys.argv) < 2:
79        print >> sys.stderr, 'USAGE:', sys.argv[0], '[REPO] [LIBs]'
80        sys.exit(1)
81
82    # Record Build Time
83    build_time = datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S')
84
85    # Repository Directory (For build revision)
86    repo_dir = sys.argv[1]
87    build_rev = get_repo_revision(repo_dir)
88
89    # Compute SHA1
90    lib_list = list(set(sys.argv[2:]))
91    lib_list.sort()
92    build_sha1, sha1sum_list = compute_sha1_list(lib_list)
93
94    # Build file list string
95    lib_list_str = ''
96    for i, path in enumerate(lib_list):
97        lib_list_str += '   %s %s\n' % (sha1sum_list[i], path)
98
99    # Print the automatically generated code
100    print """/* Automatically generated file (DON'T MODIFY) */
101
102/* Repository directory: %s */
103
104/* File list:
105%s*/
106
107#ifdef __cplusplus
108extern "C" {
109#endif
110
111char const *bccGetBuildTime() {
112  return %s;
113}
114
115char const *bccGetBuildRev() {
116  return %s;
117}
118
119char const *bccGetBuildSHA1() {
120  return %s;
121}
122
123#ifdef __cplusplus
124}
125#endif
126
127""" % (os.path.abspath(repo_dir),
128       lib_list_str,
129       quote_str(build_time),
130       quote_str(build_rev),
131       quote_str(build_sha1))
132
133if __name__ == '__main__':
134    main()
135