1#!/usr/bin/env python 2# 3# Copyright (C) 2011-2012 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17 18import datetime 19import os 20import re 21import sys 22import subprocess 23 24try: 25 import hashlib 26 sha1 = hashlib.sha1 27except ImportError, e: 28 import sha 29 sha1 = sha.sha 30 31def get_repo_revision(repo_dir): 32 if not os.path.exists(os.path.join(repo_dir, '.git')): 33 return 'Unknown (not git)' 34 35 # Get the HEAD revision 36 proc = subprocess.Popen(['git', 'log', '-1', '--format=%H'], 37 stdout=subprocess.PIPE, 38 stderr=subprocess.PIPE, 39 cwd=repo_dir) 40 out, err = proc.communicate() 41 proc.wait() 42 43 rev_sha1 = out.strip() 44 45 # Working Directory Modified 46 proc = subprocess.Popen(['git', 'status'], 47 stdout=subprocess.PIPE, 48 stderr=subprocess.PIPE, 49 cwd=repo_dir) 50 out, err = proc.communicate() 51 proc.wait() 52 53 if out.find('(working directory clean)') == -1: 54 mod = ' modified' 55 else: 56 mod = '' 57 58 return rev_sha1 + mod + ' (git)' 59 60def compute_sha1(path, global_hasher = None): 61 f = open(path, 'rb') 62 hasher = sha1() 63 while True: 64 buf = f.read(512) 65 hasher.update(buf) 66 if global_hasher: 67 global_hasher.update(buf) 68 if len(buf) < 512: 69 break 70 f.close() 71 return hasher.hexdigest() 72 73def compute_sha1_list(paths): 74 hasher = sha1() 75 sha1sums = [] 76 for path in paths: 77 sha1sums.append(compute_sha1(path, hasher)) 78 return (hasher.hexdigest(), sha1sums) 79 80def quote_str(s): 81 result = '"' 82 for c in s: 83 if c == '\\': 84 result += '\\\\' 85 elif c == '\r': 86 result += '\\r' 87 elif c == '\n': 88 result += '\\n' 89 elif c == '\t': 90 result += '\\t' 91 elif c == '\"': 92 result += '\\"' 93 elif c == '\'': 94 result += '\\\'' 95 else: 96 result += c 97 result += '"' 98 return result 99 100def main(): 101 # Check Argument 102 if len(sys.argv) < 2: 103 print >> sys.stderr, 'USAGE:', sys.argv[0], '[REPO] [LIBs]' 104 sys.exit(1) 105 106 # Record Build Time 107 build_time = datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S') 108 109 # Repository Directory (For build revision) 110 repo_dir = sys.argv[1] 111 build_rev = get_repo_revision(repo_dir) 112 113 # Compute SHA1 114 lib_list = list(set(sys.argv[2:])) 115 lib_list.sort() 116 build_sha1, sha1sum_list = compute_sha1_list(lib_list) 117 118 # Build file list string 119 lib_list_str = '' 120 for i, path in enumerate(lib_list): 121 lib_list_str += ' %s %s\n' % (sha1sum_list[i], path) 122 123 # Print the automatically generated code 124 print """/* Automatically generated file (DON'T MODIFY) */ 125 126/* Repository directory: %s */ 127 128/* File list: 129%s*/ 130 131#include "bcc/Config/BuildInfo.h" 132 133using namespace bcc; 134 135const char* BuildInfo::GetBuildTime() { 136 return %s; 137} 138 139const char *BuildInfo::GetBuildRev() { 140 return %s; 141} 142 143const char *BuildInfo::GetBuildSourceBlob() { 144 return %s; 145} 146 147""" % (os.path.abspath(repo_dir), 148 lib_list_str, 149 quote_str(build_time), 150 quote_str(build_rev), 151 quote_str(build_sha1)) 152 153if __name__ == '__main__': 154 main() 155