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