Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 #!/usr/bin/python | |
| 2 # -*- coding: utf-8 -*- | |
|
sosa
2010/11/08 23:57:56
Still don't need this
| |
| 3 | |
| 4 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | |
| 5 # Use of this source code is governed by a BSD-style license that can be | |
| 6 # found in the LICENSE file. | |
| 7 | |
| 8 """ | |
| 9 This script is to generate a zip file of delta-generator and it's dependencies | |
|
scottz-goog
2010/11/09 03:52:50
No spaces needed here and might as well end with a
| |
| 10 """ | |
| 11 | |
| 12 import logging.handlers | |
| 13 import optparse | |
| 14 import os | |
| 15 import re | |
| 16 import shutil | |
| 17 import subprocess | |
| 18 import sys | |
| 19 import tempfile | |
| 20 | |
| 21 # GLOBALS | |
| 22 | |
| 23 logging_format = '%(asctime)s - %(filename)s - %(levelname)-8s: %(message)s' | |
| 24 date_format = '%Y/%m/%d %H:%M:%S' | |
| 25 logging.basicConfig(level=logging.INFO, format=logging_format, | |
| 26 datefmt=date_format) | |
| 27 | |
| 28 def CreateTempDir(): | |
| 29 """Creates a tempdir and returns the name of the tempdir. | |
| 30 """ | |
|
sosa
2010/11/08 23:57:56
Preference is to save whitespace ... so if """docs
| |
| 31 temp_dir = tempfile.mkdtemp(suffix='au', prefix='tmp') | |
| 32 logging.info('Using tempdir = %s', temp_dir) | |
| 33 return temp_dir | |
| 34 | |
| 35 | |
| 36 def CopyRequiredFiles(dest_files_root): | |
| 37 """ | |
| 38 Generates a list of files that are required for au-generator zip file | |
| 39 Args: | |
| 40 dest_files_root: location of the directory where we should copy the files | |
| 41 """ | |
| 42 if not dest_files_root: | |
| 43 logging.error('Invalid option passed for dest_files_root') | |
| 44 sys.exit(1) | |
| 45 # Files that need to go through ldd | |
| 46 ldd_files = ['/usr/bin/delta_generator', '/usr/bin/bsdiff', | |
| 47 '/usr/bin/bspatch', '/usr/bin/cgpt'] | |
| 48 # statically linked files and scripts etc., | |
|
scottz-goog
2010/11/09 03:52:50
Is there any other general name we can give these?
Raja Aluri
2010/11/09 22:59:45
Lack of a better name, I can call it non_ldd_files
| |
| 49 static_files = ['~/trunk/src/scripts/common.sh', | |
| 50 '~/trunk/src/scripts/cros_generate_update_payload', | |
| 51 '~/trunk/src/scripts/chromeos-common.sh'] | |
| 52 # We need directories to be copied recursively to a destination within tempdir | |
| 53 recurse_dirs = {'~/trunk/src/scripts/lib/shflags': 'lib/shflags'} | |
|
scottz-goog
2010/11/09 03:52:50
Is this ever going to be more than this one path?
Raja Aluri
2010/11/09 22:59:45
For now it's only one directory, but in the future
| |
| 54 | |
| 55 black_list = [ | |
| 56 'linux-vdso.so', | |
| 57 'libgcc_s.so', | |
| 58 'librt.so', | |
| 59 'libstdc', | |
| 60 'libgcc_s.so', | |
| 61 'libc.so', | |
| 62 'ld-linux-x86-64', | |
| 63 'libm.so', | |
| 64 'libdl.so', | |
| 65 'libresolv.so', | |
| 66 ] | |
| 67 | |
| 68 all_files = ldd_files + static_files | |
| 69 all_files = map(os.path.expanduser, all_files) | |
| 70 | |
| 71 for file_name in all_files: | |
| 72 if not os.path.isfile(file_name): | |
| 73 logging.error('file = %s does not exist', file_name) | |
| 74 sys.exit(1) | |
| 75 | |
| 76 logging.debug('Given files that need to be copied = %s', all_files) | |
|
scottz-goog
2010/11/09 03:52:50
' '.join(all_files) ? This avoids putting a list o
| |
| 77 all_files += DepsToCopy(ldd_files=ldd_files,black_list=black_list) | |
| 78 for file_name in all_files: | |
| 79 logging.info('Copying file %s to %s', file_name, dest_files_root) | |
| 80 shutil.copy2(file_name, dest_files_root) | |
| 81 | |
| 82 for (source_dir, target_dir) in recurse_dirs.iteritems(): | |
|
scottz-goog
2010/11/09 03:52:50
no parans necessary here others can disagree but i
Raja Aluri
2010/11/09 22:59:45
Done.
| |
| 83 logging.info('Processing directory %s', source_dir) | |
| 84 full_path = os.path.expanduser(source_dir) | |
| 85 if not os.path.isdir(full_path): | |
| 86 logging.error("Directory given for %s expanded to %s doens't exist.", | |
| 87 source_dir, full_path) | |
| 88 sys.exit(1) | |
| 89 dest = os.path.join(dest_files_root, target_dir) | |
| 90 logging.info('Copying directory %s to %s.', full_path, target_dir) | |
| 91 shutil.copytree(full_path, dest, symlinks=None, ignore=None) | |
|
scottz-goog
2010/11/09 03:52:50
shutil.copytree(src, dst, symlinks=False, ignore=N
Raja Aluri
2010/11/09 22:59:45
Done.
| |
| 92 | |
| 93 | |
| 94 def DepsToCopy(ldd_files,black_list): | |
|
scottz-goog
2010/11/09 03:52:50
Move this above any function that calls it please.
scottz-goog
2010/11/09 03:52:50
(ldd_files, black_list)
Raja Aluri
2010/11/09 22:59:45
Done.
Raja Aluri
2010/11/09 22:59:45
Done.
| |
| 95 """ | |
| 96 Returns a list of deps for a given dynamic executables list. | |
| 97 Args: | |
| 98 ldd_files: List of dynamic files that needs to have the deps evaluated | |
| 99 black_list: List of files that we should ignore | |
| 100 Returns: | |
| 101 library_list: List of files that are dependencies | |
| 102 """ | |
| 103 for file_name in ldd_files: | |
| 104 logging.info('Running ldd on %s', file_name) | |
| 105 cmd = ['/usr/bin/ldd', file_name] | |
| 106 stdout_data = '' | |
| 107 stderr_data = '' | |
| 108 | |
| 109 try: | |
| 110 proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, | |
| 111 stderr=subprocess.PIPE) | |
| 112 (stdout_data, stderr_data) = proc.communicate(input=None) | |
| 113 except subprocess.CalledProcessError, e: | |
| 114 logging.error('Command %s failed', cmd) | |
| 115 logging.error('error code %s', e.returncode) | |
| 116 logging.error('ouput %s', e.output) | |
| 117 raise | |
| 118 | |
| 119 library_list = [] | |
| 120 | |
| 121 if stdout_data: | |
|
scottz-goog
2010/11/09 03:52:50
if not stdout_data:
Error/Do whatever is proper
| |
| 122 logging.debug('ldd for %s = stdout = %s stderr =%s', file_name, | |
| 123 stdout_data, stderr_data) | |
| 124 library_list = _SplitAndStrip(stdout_data) | |
| 125 | |
| 126 if library_list: | |
| 127 library_list = _ExcludeBlacklist(library_list, black_list) | |
| 128 | |
| 129 if library_list: | |
| 130 logging.info('Required libraries for %s=%s=', file_name, library_list) | |
| 131 | |
| 132 return library_list | |
| 133 | |
| 134 | |
| 135 def CleanUp(temp_dir): | |
| 136 """ | |
| 137 Cleans up the tempdir | |
| 138 Args: | |
| 139 temp_dir = name of the directory to cleanup | |
| 140 """ | |
| 141 if not temp_dir: | |
| 142 return | |
| 143 shutil.rmtree(temp_dir, ignore_errors=True) | |
| 144 logging.info('Removed tempdir = %s', temp_dir) | |
| 145 | |
| 146 | |
| 147 def GenerateZipFile(base_name, root_dir): | |
| 148 """Returns true if able to generate zip file | |
| 149 Args: | |
| 150 base_name: name of the zip file | |
| 151 root_dir: location of the directory that we should zip | |
| 152 Returns: | |
| 153 True | |
|
sosa
2010/11/08 23:57:56
True if?
| |
| 154 """ | |
| 155 logging.info('Generating zip file %s.zip with contents from %s', base_name, | |
| 156 root_dir) | |
| 157 current_dir = os.getcwd() | |
| 158 os.chdir(root_dir) | |
| 159 try: | |
| 160 output = subprocess.Popen(['zip', '-r', '-9', base_name, '.'], | |
| 161 stdout=subprocess.PIPE).communicate()[0] | |
| 162 except OSError, e: | |
| 163 logging.error('Execution failed:%s', e.strerror) | |
|
sosa
2010/11/08 23:57:56
If you don't use the output variable (output = abo
| |
| 164 return False | |
| 165 finally: | |
| 166 os.chdir(current_dir) | |
| 167 | |
| 168 return True | |
| 169 | |
| 170 | |
| 171 def _ExcludeBlacklist(library_list, black_list): | |
|
sosa
2010/11/08 23:57:56
blacklist=[] as default up here?
| |
| 172 """ | |
| 173 Deletes the set of files from black_list from the library_list | |
| 174 Args: | |
| 175 library_list: List of the library names to filter through black_list | |
| 176 black_list: List of the black listed names to filter | |
| 177 Returns: | |
| 178 Filtered library_list | |
| 179 """ | |
| 180 return_list = [] | |
| 181 pattern = re.compile(r'%s' % '|'.join(black_list)) | |
|
scottz-goog
2010/11/09 03:52:50
r'|'.join(black_list)?
Raja Aluri
2010/11/09 22:59:45
Done.
| |
| 182 | |
| 183 logging.debug('PATTERN: %s=', pattern) | |
| 184 | |
| 185 for library in library_list: | |
| 186 if pattern.search(library): | |
| 187 logging.debug('BLACK-LISTED = %s=', library) | |
| 188 continue | |
| 189 return_list.append(library) | |
| 190 | |
| 191 logging.debug('Returning return_list=%s=', return_list) | |
| 192 | |
| 193 return return_list | |
| 194 | |
| 195 | |
| 196 def _SplitAndStrip(data=None): | |
|
scottz-goog
2010/11/09 03:52:50
Should be above any functions that call it.
Raja Aluri
2010/11/09 22:59:45
Done.
| |
| 197 """ | |
| 198 Prunes the ldd output, so that we can get a meaningful list of library names | |
| 199 Example of data: | |
| 200 linux-vdso.so.1 => (0x00007ffffc96a000) | |
| 201 libbz2.so.1 => /lib/libbz2.so.1 (0x00007f3ff8782000) | |
| 202 libc.so.6 => /lib/libc.so.6 (0x00007f3ff83ff000) | |
| 203 /lib64/ld-linux-x86-64.so.2 (0x00007f3ff89b3000) | |
| 204 Args: | |
| 205 data: list of libraries from ldd output | |
| 206 Returns: | |
| 207 list of libararies that we should copy | |
| 208 | |
| 209 """ | |
| 210 if not data: | |
|
scottz-goog
2010/11/09 03:52:50
Why should this ever be called with a None value?
Raja Aluri
2010/11/09 22:59:45
Done.
| |
| 211 return None | |
| 212 return_list = [] | |
| 213 for line in data.split('\n'): | |
| 214 line = re.sub('.*not a dynamic executable.*', '', line) | |
| 215 line = re.sub('.* =>\s+', '', line) | |
| 216 line = re.sub('\(0x.*\)\s?', '', line) | |
| 217 line = line.strip() | |
| 218 if not len(line): | |
| 219 continue | |
| 220 logging.debug('MATCHED line = %s', line) | |
| 221 return_list.append(line) | |
| 222 | |
| 223 return return_list | |
| 224 | |
| 225 | |
| 226 def CopyZipToFinalDestination(output_dir, zip_file_name): | |
| 227 """ | |
| 228 Copies the generated zip file to a final destination | |
| 229 Args: | |
| 230 output_dir: Directory where the file should be copied to | |
| 231 zip_file_name: name of the zip file that should be copied | |
| 232 Returns: | |
| 233 True on Success | |
|
scottz-goog
2010/11/09 03:52:50
False if it fails...
Raja Aluri
2010/11/09 22:59:45
Done.
| |
| 234 """ | |
| 235 if not os.path.isfile(zip_file_name): | |
| 236 logging.error("Zip file %s doesn't exist. Returning False", zip_file_name) | |
| 237 return False | |
| 238 | |
| 239 if not os.path.isdir(output_dir): | |
| 240 logging.debug('Creating %s', output_dir) | |
| 241 os.makedirs(output_dir) | |
| 242 logging.info('Copying %s to %s', zip_file_name, output_dir) | |
| 243 shutil.copy2(zip_file_name, output_dir) | |
| 244 return True | |
| 245 | |
| 246 | |
| 247 def main(): | |
| 248 """ | |
|
scottz-goog
2010/11/09 03:52:50
Docstring all on one line.
Raja Aluri
2010/11/09 22:59:45
Done.
| |
| 249 Main function to start the script | |
| 250 """ | |
| 251 parser = optparse.OptionParser() | |
| 252 | |
| 253 parser.add_option( '-d', '--debug', dest='debug', action='store_true', | |
| 254 default=False, help='Verbose Default: False',) | |
|
scottz-goog
2010/11/09 03:52:50
('-d'
Also properly align default with the rest of
Raja Aluri
2010/11/09 22:59:45
Done.
| |
| 255 parser.add_option('-o', '--output-dir', dest='output_dir', | |
| 256 default='/tmp/au-generator.zip', | |
| 257 help='Specify the output location for copying the zipfile') | |
| 258 parser.add_option('-z', '--zip-name', dest='zip_name', | |
| 259 default='au-generator.zip', help='Name of the zip file') | |
| 260 parser.add_option('-k', '--keep-temp', dest='keep_temp', default=False, | |
| 261 action='store_true', help='Keep the temp files...',) | |
| 262 | |
| 263 (options, args) = parser.parse_args() | |
| 264 if options.debug: | |
| 265 logging.setLevel(logging.DEBUG) | |
|
scottz-goog
2010/11/09 03:52:50
Generally for clarity it is good to separate if st
Raja Aluri
2010/11/09 22:59:45
Done.
| |
| 266 logging.debug('Options are %s ', options) | |
| 267 | |
| 268 temp_dir = CreateTempDir() | |
| 269 dest_files_root = os.path.join(temp_dir, 'au-generator') | |
| 270 os.makedirs(dest_files_root) | |
| 271 CopyRequiredFiles(dest_files_root=dest_files_root) | |
|
scottz-goog
2010/11/09 03:52:50
this is no longer a keyword option as defined abov
Raja Aluri
2010/11/09 22:59:45
Done.
| |
| 272 zip_file_name = os.path.join(temp_dir, options.zip_name) | |
| 273 GenerateZipFile(base_name=zip_file_name, root_dir=dest_files_root) | |
|
scottz-goog
2010/11/09 03:52:50
also no longer keyword options.
Raja Aluri
2010/11/09 22:59:45
Done.
| |
| 274 CopyZipToFinalDestination(output_dir=options.output_dir, | |
| 275 zip_file_name=zip_file_name) | |
|
scottz-goog
2010/11/09 03:52:50
same..
| |
| 276 if not options.keep_temp: | |
| 277 CleanUp(temp_dir=temp_dir) | |
|
scottz-goog
2010/11/09 03:52:50
same..
Raja Aluri
2010/11/09 22:59:45
Done.
| |
| 278 | |
| 279 | |
| 280 if __name__ == '__main__': | |
| 281 main() | |
| 282 sys.exit(0) | |
|
scottz-goog
2010/11/09 03:52:50
sys.exit(0) is not necessary the exit code will be
Raja Aluri
2010/11/09 22:59:45
Done.
| |
| OLD | NEW |