| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """ | 6 """ |
| 7 This tool creates a tarball with all the sources, but without .svn directories. | 7 This tool creates a tarball with all the sources, but without .git directories. |
| 8 | 8 |
| 9 It can also remove files which are not strictly required for build, so that | 9 It can also remove files which are not strictly required for build, so that |
| 10 the resulting tarball can be reasonably small (last time it was ~110 MB). | 10 the resulting tarball can be reasonably small (last time it was ~110 MB). |
| 11 | 11 |
| 12 Example usage: | 12 Example usage: |
| 13 | 13 |
| 14 export_tarball.py /foo/bar | 14 export_tarball.py /foo/bar |
| 15 | 15 |
| 16 The above will create file /foo/bar.tar.bz2. | 16 The above will create file /foo/bar.tar.bz2. |
| 17 """ | 17 """ |
| 18 | 18 |
| 19 import optparse | 19 import optparse |
| 20 import os | 20 import os |
| 21 import subprocess | 21 import subprocess |
| 22 import sys | 22 import sys |
| 23 import tarfile | 23 import tarfile |
| 24 | 24 |
| 25 | 25 |
| 26 NONESSENTIAL_DIRS = ( | 26 NONESSENTIAL_DIRS = ( |
| 27 'breakpad/src/processor/testdata', | |
| 28 'chrome/browser/resources/tracing/tests', | |
| 29 'chrome/common/extensions/docs', | 27 'chrome/common/extensions/docs', |
| 30 'courgette/testdata', | 28 'chrome/tools/test/reference_build', |
| 31 'data', | |
| 32 'native_client/src/trusted/service_runtime/testdata', | |
| 33 'src/chrome/test/data', | |
| 34 'o3d/documentation', | |
| 35 'o3d/samples', | |
| 36 'o3d/tests', | |
| 37 'ppapi/examples', | 29 'ppapi/examples', |
| 38 'ppapi/native_client/tests', | |
| 39 'third_party/angle/samples/gles2_book', | |
| 40 'third_party/findbugs', | 30 'third_party/findbugs', |
| 41 'third_party/hunspell_dictionaries', | 31 'third_party/hunspell_dictionaries', |
| 42 'third_party/hunspell/tests', | 32 'third_party/hunspell/tests', |
| 43 'third_party/lighttpd', | |
| 44 'third_party/sqlite/src/test', | 33 'third_party/sqlite/src/test', |
| 45 'third_party/sqlite/test', | |
| 46 'third_party/vc_80', | |
| 47 'third_party/xdg-utils/tests', | 34 'third_party/xdg-utils/tests', |
| 48 'third_party/yasm/source/patched-yasm/modules/arch/x86/tests', | 35 'third_party/yasm/source/patched-yasm/modules/arch/x86/tests', |
| 49 'third_party/yasm/source/patched-yasm/modules/dbgfmts/dwarf2/tests', | 36 'third_party/yasm/source/patched-yasm/modules/dbgfmts/dwarf2/tests', |
| 50 'third_party/yasm/source/patched-yasm/modules/objfmts/bin/tests', | 37 'third_party/yasm/source/patched-yasm/modules/objfmts/bin/tests', |
| 51 'third_party/yasm/source/patched-yasm/modules/objfmts/coff/tests', | 38 'third_party/yasm/source/patched-yasm/modules/objfmts/coff/tests', |
| 52 'third_party/yasm/source/patched-yasm/modules/objfmts/elf/tests', | 39 'third_party/yasm/source/patched-yasm/modules/objfmts/elf/tests', |
| 53 'third_party/yasm/source/patched-yasm/modules/objfmts/macho/tests', | 40 'third_party/yasm/source/patched-yasm/modules/objfmts/macho/tests', |
| 54 'third_party/yasm/source/patched-yasm/modules/objfmts/rdf/tests', | 41 'third_party/yasm/source/patched-yasm/modules/objfmts/rdf/tests', |
| 55 'third_party/yasm/source/patched-yasm/modules/objfmts/win32/tests', | 42 'third_party/yasm/source/patched-yasm/modules/objfmts/win32/tests', |
| 56 'third_party/yasm/source/patched-yasm/modules/objfmts/win64/tests', | 43 'third_party/yasm/source/patched-yasm/modules/objfmts/win64/tests', |
| 57 'third_party/yasm/source/patched-yasm/modules/objfmts/xdf/tests', | 44 'third_party/yasm/source/patched-yasm/modules/objfmts/xdf/tests', |
| 58 'third_party/WebKit/LayoutTests', | 45 'third_party/WebKit/LayoutTests', |
| 59 'third_party/WebKit/Source/JavaScriptCore/tests', | |
| 60 'third_party/WebKit/Source/WebCore/ChangeLog', | |
| 61 'third_party/WebKit/Source/WebKit2', | |
| 62 'third_party/WebKit/Tools/Scripts', | 46 'third_party/WebKit/Tools/Scripts', |
| 63 'tools/gyp/test', | 47 'tools/gyp/test', |
| 64 'v8/test', | 48 'v8/test', |
| 65 'webkit/data/layout_tests', | |
| 66 'webkit/tools/test/reference_build', | |
| 67 ) | 49 ) |
| 68 | 50 |
| 69 TESTDIRS = ( | 51 ESSENTIAL_FILES = ( |
| 52 'chrome/test/data/webui/i18n_process_css_test.html', |
| 53 ) |
| 54 |
| 55 TEST_DIRS = ( |
| 56 'breakpad/src/processor/testdata', |
| 57 'courgette/testdata', |
| 70 'chrome/test/data', | 58 'chrome/test/data', |
| 71 'content/test/data', | 59 'content/test/data', |
| 72 'media/test/data', | 60 'media/test/data', |
| 61 'native_client/src/trusted/service_runtime/testdata', |
| 73 'net/data', | 62 'net/data', |
| 63 'ppapi/native_client/tests', |
| 74 ) | 64 ) |
| 75 | 65 |
| 76 | 66 |
| 77 def GetSourceDirectory(): | 67 def GetSourceDirectory(): |
| 78 return os.path.realpath( | 68 return os.path.realpath( |
| 79 os.path.join(os.path.dirname(__file__), '..', '..', '..', 'src')) | 69 os.path.join(os.path.dirname(__file__), '..', '..', '..', 'src')) |
| 80 | 70 |
| 81 | 71 |
| 82 # Workaround lack of the exclude parameter in add method in python-2.4. | 72 # Workaround lack of the exclude parameter in add method in python-2.4. |
| 83 # TODO(phajdan.jr): remove the workaround when it's not needed on the bot. | 73 # TODO(phajdan.jr): remove the workaround when it's not needed on the bot. |
| 84 class MyTarFile(tarfile.TarFile): | 74 class MyTarFile(tarfile.TarFile): |
| 85 def set_remove_nonessential_files(self, remove): | 75 def set_remove_nonessential_files(self, remove): |
| 86 self.__remove_nonessential_files = remove | 76 self.__remove_nonessential_files = remove |
| 87 | 77 |
| 88 def set_verbose(self, verbose): | 78 def set_verbose(self, verbose): |
| 89 self.__verbose = verbose | 79 self.__verbose = verbose |
| 90 | 80 |
| 91 def __report_skipped(self, name): | 81 def __report_skipped(self, name): |
| 92 if self.__verbose: | 82 if self.__verbose: |
| 93 print 'D\t%s' % name | 83 print 'D\t%s' % name |
| 94 | 84 |
| 95 def __report_added(self, name): | 85 def __report_added(self, name): |
| 96 if self.__verbose: | 86 if self.__verbose: |
| 97 print 'A\t%s' % name | 87 print 'A\t%s' % name |
| 98 | 88 |
| 99 def add(self, name, arcname=None, recursive=True, exclude=None, filter=None): | 89 def add(self, name, arcname=None, recursive=True, exclude=None, filter=None): |
| 100 head, tail = os.path.split(name) | 90 _, file_name = os.path.split(name) |
| 101 if tail in ('.svn', '.git'): | 91 if file_name in ('.git', 'out'): |
| 102 self.__report_skipped(name) | 92 self.__report_skipped(name) |
| 103 return | 93 return |
| 104 | 94 |
| 105 if self.__remove_nonessential_files: | 95 if self.__remove_nonessential_files: |
| 106 # WebKit change logs take quite a lot of space. This saves ~10 MB | 96 # WebKit change logs take quite a lot of space. This saves ~10 MB |
| 107 # in a bzip2-compressed tarball. | 97 # in a bzip2-compressed tarball. |
| 108 if 'ChangeLog' in name: | 98 if 'ChangeLog' in name: |
| 109 self.__report_skipped(name) | 99 self.__report_skipped(name) |
| 110 return | 100 return |
| 111 | 101 |
| 112 # Remove contents of non-essential directories, but preserve gyp files, | 102 # Preserve GYP/GN files, so that build/gyp_chromium / gn gen can work. |
| 113 # so that build/gyp_chromium can work. | 103 # Also keep files that are essential. |
| 114 for nonessential_dir in (NONESSENTIAL_DIRS + TESTDIRS): | 104 rel_name = os.path.relpath(name, GetSourceDirectory()) |
| 115 dir_path = os.path.join(GetSourceDirectory(), nonessential_dir) | 105 keep_file = ('.gyp' in file_name or |
| 116 if (name.startswith(dir_path) and | 106 '.gn' in file_name or |
| 117 os.path.isfile(name) and | 107 rel_name in ESSENTIAL_FILES) |
| 118 'gyp' not in name): | 108 |
| 119 self.__report_skipped(name) | 109 # Remove contents of non-essential directories. |
| 120 return | 110 if not keep_file: |
| 111 for nonessential_dir in (NONESSENTIAL_DIRS + TEST_DIRS): |
| 112 if rel_name.startswith(nonessential_dir) and os.path.isfile(name): |
| 113 self.__report_skipped(name) |
| 114 return |
| 121 | 115 |
| 122 self.__report_added(name) | 116 self.__report_added(name) |
| 123 tarfile.TarFile.add(self, name, arcname=arcname, recursive=recursive) | 117 tarfile.TarFile.add(self, name, arcname=arcname, recursive=recursive) |
| 124 | 118 |
| 125 | 119 |
| 126 def main(argv): | 120 def main(argv): |
| 127 parser = optparse.OptionParser() | 121 parser = optparse.OptionParser() |
| 128 parser.add_option("--basename") | 122 parser.add_option("--basename") |
| 129 parser.add_option("--remove-nonessential-files", | 123 parser.add_option("--remove-nonessential-files", |
| 130 dest="remove_nonessential_files", | 124 dest="remove_nonessential_files", |
| (...skipping 28 matching lines...) Expand all Loading... |
| 159 return 1 | 153 return 1 |
| 160 | 154 |
| 161 output_fullname = args[0] + '.tar' | 155 output_fullname = args[0] + '.tar' |
| 162 output_basename = options.basename or os.path.basename(args[0]) | 156 output_basename = options.basename or os.path.basename(args[0]) |
| 163 | 157 |
| 164 archive = MyTarFile.open(output_fullname, 'w') | 158 archive = MyTarFile.open(output_fullname, 'w') |
| 165 archive.set_remove_nonessential_files(options.remove_nonessential_files) | 159 archive.set_remove_nonessential_files(options.remove_nonessential_files) |
| 166 archive.set_verbose(options.verbose) | 160 archive.set_verbose(options.verbose) |
| 167 try: | 161 try: |
| 168 if options.test_data: | 162 if options.test_data: |
| 169 for directory in TESTDIRS: | 163 for directory in TEST_DIRS: |
| 170 archive.add(os.path.join(GetSourceDirectory(), directory), | 164 archive.add(os.path.join(GetSourceDirectory(), directory), |
| 171 arcname=os.path.join(output_basename, directory)) | 165 arcname=os.path.join(output_basename, directory)) |
| 172 else: | 166 else: |
| 173 archive.add(GetSourceDirectory(), arcname=output_basename) | 167 archive.add(GetSourceDirectory(), arcname=output_basename) |
| 174 finally: | 168 finally: |
| 175 archive.close() | 169 archive.close() |
| 176 | 170 |
| 177 if options.progress: | 171 if options.progress: |
| 178 sys.stdout.flush() | 172 sys.stdout.flush() |
| 179 pv = subprocess.Popen( | 173 pv = subprocess.Popen( |
| 180 ['pv', '--force', output_fullname], | 174 ['pv', '--force', output_fullname], |
| 181 stdout=subprocess.PIPE, | 175 stdout=subprocess.PIPE, |
| 182 stderr=sys.stdout) | 176 stderr=sys.stdout) |
| 183 with open(output_fullname + '.xz', 'w') as f: | 177 with open(output_fullname + '.xz', 'w') as f: |
| 184 rc = subprocess.call(['xz', '-9', '-'], stdin=pv.stdout, stdout=f) | 178 rc = subprocess.call(['xz', '-9', '-'], stdin=pv.stdout, stdout=f) |
| 185 pv.wait() | 179 pv.wait() |
| 186 else: | 180 else: |
| 187 rc = subprocess.call(['xz', '-9', output_fullname]) | 181 rc = subprocess.call(['xz', '-9', output_fullname]) |
| 188 | 182 |
| 189 if rc != 0: | 183 if rc != 0: |
| 190 print 'xz -9 failed!' | 184 print 'xz -9 failed!' |
| 191 return 1 | 185 return 1 |
| 192 | 186 |
| 193 return 0 | 187 return 0 |
| 194 | 188 |
| 195 | 189 |
| 196 if __name__ == "__main__": | 190 if __name__ == "__main__": |
| 197 sys.exit(main(sys.argv[1:])) | 191 sys.exit(main(sys.argv[1:])) |
| OLD | NEW |