148dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien#!/usr/bin/env python
2ddf5661793de8fb4e16906b7f7822972fcb13c6dZonr Chang#
3ddf5661793de8fb4e16906b7f7822972fcb13c6dZonr Chang# Copyright (C) 2011-2012 The Android Open Source Project
4ddf5661793de8fb4e16906b7f7822972fcb13c6dZonr Chang#
5ddf5661793de8fb4e16906b7f7822972fcb13c6dZonr Chang# Licensed under the Apache License, Version 2.0 (the "License");
6ddf5661793de8fb4e16906b7f7822972fcb13c6dZonr Chang# you may not use this file except in compliance with the License.
7ddf5661793de8fb4e16906b7f7822972fcb13c6dZonr Chang# You may obtain a copy of the License at
8ddf5661793de8fb4e16906b7f7822972fcb13c6dZonr Chang#
9ddf5661793de8fb4e16906b7f7822972fcb13c6dZonr Chang#      http://www.apache.org/licenses/LICENSE-2.0
10ddf5661793de8fb4e16906b7f7822972fcb13c6dZonr Chang#
11ddf5661793de8fb4e16906b7f7822972fcb13c6dZonr Chang# Unless required by applicable law or agreed to in writing, software
12ddf5661793de8fb4e16906b7f7822972fcb13c6dZonr Chang# distributed under the License is distributed on an "AS IS" BASIS,
13ddf5661793de8fb4e16906b7f7822972fcb13c6dZonr Chang# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14ddf5661793de8fb4e16906b7f7822972fcb13c6dZonr Chang# See the License for the specific language governing permissions and
15ddf5661793de8fb4e16906b7f7822972fcb13c6dZonr Chang# limitations under the License.
16ddf5661793de8fb4e16906b7f7822972fcb13c6dZonr Chang#
1748dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
1848dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chienimport datetime
1948dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chienimport os
2048dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chienimport re
2148dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chienimport sys
2248dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chienimport subprocess
2348dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
241c13147fd7d2294a0f34a569fe36660b6b056a91Daniel Sandlertry:
251c13147fd7d2294a0f34a569fe36660b6b056a91Daniel Sandler    import hashlib
261c13147fd7d2294a0f34a569fe36660b6b056a91Daniel Sandler    sha1 = hashlib.sha1
271c13147fd7d2294a0f34a569fe36660b6b056a91Daniel Sandlerexcept ImportError, e:
281c13147fd7d2294a0f34a569fe36660b6b056a91Daniel Sandler    import sha
291c13147fd7d2294a0f34a569fe36660b6b056a91Daniel Sandler    sha1 = sha.sha
301c13147fd7d2294a0f34a569fe36660b6b056a91Daniel Sandler
3148dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chiendef get_repo_revision(repo_dir):
3248dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    if not os.path.exists(os.path.join(repo_dir, '.git')):
3348dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        return 'Unknown (not git)'
3448dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
353bfcd866e752a77e42b93dea1754417e5c466472Logan Chien    # Get the HEAD revision
3648dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    proc = subprocess.Popen(['git', 'log', '-1', '--format=%H'],
3748dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien                            stdout=subprocess.PIPE,
3848dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien                            stderr=subprocess.PIPE,
3948dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien                            cwd=repo_dir)
4048dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    out, err = proc.communicate()
4148dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    proc.wait()
4248dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
433bfcd866e752a77e42b93dea1754417e5c466472Logan Chien    rev_sha1 = out.strip()
443bfcd866e752a77e42b93dea1754417e5c466472Logan Chien
453bfcd866e752a77e42b93dea1754417e5c466472Logan Chien    # Working Directory Modified
463bfcd866e752a77e42b93dea1754417e5c466472Logan Chien    proc = subprocess.Popen(['git', 'status'],
473bfcd866e752a77e42b93dea1754417e5c466472Logan Chien                            stdout=subprocess.PIPE,
483bfcd866e752a77e42b93dea1754417e5c466472Logan Chien                            stderr=subprocess.PIPE,
493bfcd866e752a77e42b93dea1754417e5c466472Logan Chien                            cwd=repo_dir)
503bfcd866e752a77e42b93dea1754417e5c466472Logan Chien    out, err = proc.communicate()
513bfcd866e752a77e42b93dea1754417e5c466472Logan Chien    proc.wait()
523bfcd866e752a77e42b93dea1754417e5c466472Logan Chien
5376bb588a309ba11c1b6a3c2af3b97f784f29a833Logan Chien    if out.find('(working directory clean)') == -1:
541c13147fd7d2294a0f34a569fe36660b6b056a91Daniel Sandler      mod = ' modified'
551c13147fd7d2294a0f34a569fe36660b6b056a91Daniel Sandler    else:
561c13147fd7d2294a0f34a569fe36660b6b056a91Daniel Sandler      mod = ''
573bfcd866e752a77e42b93dea1754417e5c466472Logan Chien
583bfcd866e752a77e42b93dea1754417e5c466472Logan Chien    return rev_sha1 + mod + ' (git)'
5948dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
6048dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chiendef compute_sha1(path, global_hasher = None):
6148dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    f = open(path, 'rb')
621c13147fd7d2294a0f34a569fe36660b6b056a91Daniel Sandler    hasher = sha1()
6348dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    while True:
6448dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        buf = f.read(512)
6548dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        hasher.update(buf)
6648dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        if global_hasher:
6748dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien            global_hasher.update(buf)
6848dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        if len(buf) < 512:
6948dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien            break
7048dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    f.close()
7148dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    return hasher.hexdigest()
7248dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
7348dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chiendef compute_sha1_list(paths):
741c13147fd7d2294a0f34a569fe36660b6b056a91Daniel Sandler    hasher = sha1()
7548dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    sha1sums = []
7648dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    for path in paths:
7748dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        sha1sums.append(compute_sha1(path, hasher))
7848dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    return (hasher.hexdigest(), sha1sums)
7948dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
8048dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chiendef quote_str(s):
8148dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    result = '"'
8248dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    for c in s:
8348dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        if c == '\\':
8448dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien            result += '\\\\'
8548dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        elif c == '\r':
8648dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien            result += '\\r'
8748dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        elif c == '\n':
8848dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien            result += '\\n'
8948dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        elif c == '\t':
9048dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien            result += '\\t'
9148dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        elif c == '\"':
9248dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien            result += '\\"'
9348dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        elif c == '\'':
9448dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien            result += '\\\''
9548dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        else:
9648dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien            result += c
9748dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    result += '"'
9848dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    return result
9948dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
10048dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chiendef main():
10148dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    # Check Argument
10248dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    if len(sys.argv) < 2:
10348dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        print >> sys.stderr, 'USAGE:', sys.argv[0], '[REPO] [LIBs]'
10448dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        sys.exit(1)
10548dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
10648dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    # Record Build Time
10748dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    build_time = datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S')
10848dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
10948dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    # Repository Directory (For build revision)
11048dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    repo_dir = sys.argv[1]
11148dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    build_rev = get_repo_revision(repo_dir)
11248dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
11348dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    # Compute SHA1
11448dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    lib_list = list(set(sys.argv[2:]))
11548dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    lib_list.sort()
11648dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    build_sha1, sha1sum_list = compute_sha1_list(lib_list)
11748dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
11848dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    # Build file list string
11948dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    lib_list_str = ''
12048dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    for i, path in enumerate(lib_list):
12148dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien        lib_list_str += '   %s %s\n' % (sha1sum_list[i], path)
12248dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
12348dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    # Print the automatically generated code
12448dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    print """/* Automatically generated file (DON'T MODIFY) */
12548dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
12648dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien/* Repository directory: %s */
12748dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
12848dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien/* File list:
12948dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien%s*/
13048dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
1317a5d423014e1cc95e34764b3ddf8e80ace3509b8Zonr Chang#include "bcc/Config/BuildInfo.h"
13248dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
1337a5d423014e1cc95e34764b3ddf8e80ace3509b8Zonr Changusing namespace bcc;
13448dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
1357a5d423014e1cc95e34764b3ddf8e80ace3509b8Zonr Changconst char* BuildInfo::GetBuildTime() {
13648dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien  return %s;
13748dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien}
13848dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
1397a5d423014e1cc95e34764b3ddf8e80ace3509b8Zonr Changconst char *BuildInfo::GetBuildRev() {
14044d991658dbd5b80648a3944f1760ad19bbcac09Zonr Chang  return %s;
14148dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien}
14248dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
1437a5d423014e1cc95e34764b3ddf8e80ace3509b8Zonr Changconst char *BuildInfo::GetBuildSourceBlob() {
1447a5d423014e1cc95e34764b3ddf8e80ace3509b8Zonr Chang  return %s;
145aa72a210b0f73671b01984020a74360c10427e31Stephen Hines}
146aa72a210b0f73671b01984020a74360c10427e31Stephen Hines
14748dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien""" % (os.path.abspath(repo_dir),
14848dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien       lib_list_str,
14948dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien       quote_str(build_time),
15048dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien       quote_str(build_rev),
15148dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien       quote_str(build_sha1))
15248dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien
15348dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chienif __name__ == '__main__':
15448dc01db0b865b73f41cef53bcb72f65fd027af4Logan Chien    main()
155