|  | #!/usr/bin/env python3 | 
|  | # Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file | 
|  | # for details. All rights reserved. Use of this source code is governed by a | 
|  | # BSD-style license that can be found in the LICENSE file. | 
|  | # | 
|  | # This python script creates a tar archive and a C++ source file which contains | 
|  | # the tar archive as an array of bytes. | 
|  |  | 
|  | import os | 
|  | import sys | 
|  | from os.path import join, splitext | 
|  | import time | 
|  | from optparse import OptionParser | 
|  | from datetime import date | 
|  | import tarfile | 
|  | import tempfile | 
|  | import gzip | 
|  |  | 
|  |  | 
|  | def CreateTarArchive(tar_path, client_root, compress, files): | 
|  | mode_string = 'w' | 
|  | tar = tarfile.open(tar_path, mode=mode_string) | 
|  | for input_file_name in files: | 
|  | # Chop off client_root. | 
|  | archive_file_name = input_file_name[len(client_root):] | 
|  | # Replace back slash with forward slash. So we do not have Windows paths. | 
|  | archive_file_name = archive_file_name.replace("\\", "/") | 
|  | # Open input file and add it to the archive. | 
|  | with open(input_file_name, 'rb') as input_file: | 
|  | tarInfo = tarfile.TarInfo(name=archive_file_name) | 
|  | input_file.seek(0, 2) | 
|  | tarInfo.size = input_file.tell() | 
|  | tarInfo.mtime = 0  # For deterministic builds. | 
|  | input_file.seek(0) | 
|  | tar.addfile(tarInfo, fileobj=input_file) | 
|  | tar.close() | 
|  | if compress: | 
|  | with open(tar_path, "rb") as fin: | 
|  | uncompressed = fin.read() | 
|  | with open(tar_path, "wb") as fout: | 
|  | # mtime=0 for deterministic builds. | 
|  | gz = gzip.GzipFile(fileobj=fout, mode="wb", filename="", mtime=0) | 
|  | gz.write(uncompressed) | 
|  | gz.close() | 
|  |  | 
|  |  | 
|  | def MakeArchive(options): | 
|  | if not options.client_root: | 
|  | sys.stderr.write('--client_root not specified') | 
|  | return -1 | 
|  |  | 
|  | files = [] | 
|  | for dirname, dirnames, filenames in os.walk(options.client_root): | 
|  | # strip out all dot files. | 
|  | filenames = [f for f in filenames if not f[0] == '.'] | 
|  | dirnames[:] = [d for d in dirnames if not d[0] == '.'] | 
|  | for f in filenames: | 
|  | src_path = os.path.join(dirname, f) | 
|  | if (os.path.isdir(src_path)): | 
|  | continue | 
|  | files.append(src_path) | 
|  |  | 
|  | # Ensure consistent file ordering for reproducible builds. | 
|  | files.sort() | 
|  |  | 
|  | # Write out archive. | 
|  | CreateTarArchive(options.tar_output, options.client_root, options.compress, | 
|  | files) | 
|  | return 0 | 
|  |  | 
|  |  | 
|  | def WriteCCFile( | 
|  | output_file, | 
|  | outer_namespace, | 
|  | inner_namespace, | 
|  | name, | 
|  | tar_archive, | 
|  | ): | 
|  | with open(output_file, 'w') as out: | 
|  | out.write(''' | 
|  | // Copyright (c) %d, the Dart project authors.  Please see the AUTHORS file | 
|  | // for details. All rights reserved. Use of this source code is governed by a | 
|  | // BSD-style license that can be found in the LICENSE file. | 
|  |  | 
|  | ''' % date.today().year) | 
|  | out.write(''' | 
|  |  | 
|  | #include <stdint.h> | 
|  |  | 
|  | ''') | 
|  | out.write('namespace %s {\n' % outer_namespace) | 
|  | if inner_namespace != None: | 
|  | out.write('namespace %s {\n' % inner_namespace) | 
|  | out.write('\n\n') | 
|  | # Write the byte contents of the archive as a comma separated list of | 
|  | # integers, one integer for each byte. | 
|  | out.write('static const uint8_t %s_[] = {\n' % name) | 
|  | line = '   ' | 
|  | lineCounter = 0 | 
|  | for byte in tar_archive: | 
|  | line += r" %d," % (byte if isinstance(byte, int) else ord(byte)) | 
|  | lineCounter += 1 | 
|  | if lineCounter == 10: | 
|  | out.write(line + '\n') | 
|  | line = '   ' | 
|  | lineCounter = 0 | 
|  | if lineCounter != 0: | 
|  | out.write(line + '\n') | 
|  | out.write('};\n') | 
|  | out.write('\nunsigned int %s_len = %d;\n' % (name, len(tar_archive))) | 
|  | out.write('\nconst uint8_t* %s = %s_;\n\n' % (name, name)) | 
|  | if inner_namespace != None: | 
|  | out.write('}  // namespace %s\n' % inner_namespace) | 
|  | out.write('} // namespace %s\n' % outer_namespace) | 
|  |  | 
|  |  | 
|  | def MakeCCFile(options): | 
|  | if not options.output: | 
|  | sys.stderr.write('--output not specified\n') | 
|  | return -1 | 
|  | if not options.name: | 
|  | sys.stderr.write('--name not specified\n') | 
|  | return -1 | 
|  | if not options.tar_input: | 
|  | sys.stderr.write('--tar_input not specified\n') | 
|  | return -1 | 
|  |  | 
|  | # Read it back in. | 
|  | with open(options.tar_input, 'rb') as tar_file: | 
|  | tar_archive = tar_file.read() | 
|  |  | 
|  | # Write CC file. | 
|  | WriteCCFile(options.output, options.outer_namespace, | 
|  | options.inner_namespace, options.name, tar_archive) | 
|  | return 0 | 
|  |  | 
|  |  | 
|  | def Main(args): | 
|  | try: | 
|  | # Parse input. | 
|  | parser = OptionParser() | 
|  | parser.add_option( | 
|  | "--output", action="store", type="string", help="output file name") | 
|  | parser.add_option("--tar_input",\ | 
|  | action="store", type="string", | 
|  | help="input tar archive") | 
|  | parser.add_option( | 
|  | "--tar_output", | 
|  | action="store", | 
|  | type="string", | 
|  | help="tar output file name") | 
|  | parser.add_option( | 
|  | "--outer_namespace", | 
|  | action="store", | 
|  | type="string", | 
|  | help="outer C++ namespace", | 
|  | default="dart") | 
|  | parser.add_option( | 
|  | "--inner_namespace", | 
|  | action="store", | 
|  | type="string", | 
|  | help="inner C++ namespace", | 
|  | default="bin") | 
|  | parser.add_option( | 
|  | "--name", | 
|  | action="store", | 
|  | type="string", | 
|  | help="name of tar archive symbol") | 
|  | parser.add_option("--compress", action="store_true", default=False) | 
|  | parser.add_option( | 
|  | "--client_root", | 
|  | action="store", | 
|  | type="string", | 
|  | help="root directory client resources") | 
|  |  | 
|  | (options, args) = parser.parse_args() | 
|  |  | 
|  | if options.tar_output: | 
|  | return MakeArchive(options) | 
|  | else: | 
|  | return MakeCCFile(options) | 
|  |  | 
|  | except Exception as inst: | 
|  | sys.stderr.write('create_archive.py exception\n') | 
|  | sys.stderr.write(str(inst)) | 
|  | sys.stderr.write('\n') | 
|  | return -1 | 
|  |  | 
|  |  | 
|  | if __name__ == '__main__': | 
|  | sys.exit(Main(sys.argv)) |