| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/env python | |
| 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 | |
| 4 # found in the LICENSE file. | |
| 5 | |
| 6 """ | |
| 7 This tool creates a tarball with all the sources, but without .svn directories. | |
| 8 | |
| 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). | |
| 11 | |
| 12 Example usage: | |
| 13 | |
| 14 export_tarball.py /foo/bar | |
| 15 | |
| 16 The above will create file /foo/bar.tar.bz2. | |
| 17 """ | |
| 18 | |
| 19 import optparse | |
| 20 import os | |
| 21 import subprocess | |
| 22 import sys | |
| 23 import tarfile | |
| 24 | |
| 25 | |
| 26 NONESSENTIAL_DIRS = ( | |
| 27 'breakpad/src/processor/testdata', | |
| 28 'chrome/browser/resources/tracing/tests', | |
| 29 'chrome/common/extensions/docs', | |
| 30 'courgette/testdata', | |
| 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', | |
| 38 'ppapi/native_client/tests', | |
| 39 'third_party/angle/samples/gles2_book', | |
| 40 'third_party/findbugs', | |
| 41 'third_party/hunspell_dictionaries', | |
| 42 'third_party/hunspell/tests', | |
| 43 'third_party/lighttpd', | |
| 44 'third_party/sqlite/src/test', | |
| 45 'third_party/sqlite/test', | |
| 46 'third_party/vc_80', | |
| 47 'third_party/xdg-utils/tests', | |
| 48 'third_party/yasm/source/patched-yasm/modules/arch/x86/tests', | |
| 49 'third_party/yasm/source/patched-yasm/modules/dbgfmts/dwarf2/tests', | |
| 50 'third_party/yasm/source/patched-yasm/modules/objfmts/bin/tests', | |
| 51 'third_party/yasm/source/patched-yasm/modules/objfmts/coff/tests', | |
| 52 'third_party/yasm/source/patched-yasm/modules/objfmts/elf/tests', | |
| 53 'third_party/yasm/source/patched-yasm/modules/objfmts/macho/tests', | |
| 54 'third_party/yasm/source/patched-yasm/modules/objfmts/rdf/tests', | |
| 55 'third_party/yasm/source/patched-yasm/modules/objfmts/win32/tests', | |
| 56 'third_party/yasm/source/patched-yasm/modules/objfmts/win64/tests', | |
| 57 'third_party/yasm/source/patched-yasm/modules/objfmts/xdf/tests', | |
| 58 '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', | |
| 63 'tools/gyp/test', | |
| 64 'v8/test', | |
| 65 'webkit/data/layout_tests', | |
| 66 'webkit/tools/test/reference_build', | |
| 67 ) | |
| 68 | |
| 69 TESTDIRS = ( | |
| 70 'chrome/test/data', | |
| 71 'content/test/data', | |
| 72 'media/test/data', | |
| 73 'net/data', | |
| 74 ) | |
| 75 | |
| 76 | |
| 77 def GetSourceDirectory(): | |
| 78 return os.path.realpath( | |
| 79 os.path.join(os.path.dirname(__file__), '..', '..', '..', 'src')) | |
| 80 | |
| 81 | |
| 82 # 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. | |
| 84 class MyTarFile(tarfile.TarFile): | |
| 85 def set_remove_nonessential_files(self, remove): | |
| 86 self.__remove_nonessential_files = remove | |
| 87 | |
| 88 def set_verbose(self, verbose): | |
| 89 self.__verbose = verbose | |
| 90 | |
| 91 def __report_skipped(self, name): | |
| 92 if self.__verbose: | |
| 93 print 'D\t%s' % name | |
| 94 | |
| 95 def __report_added(self, name): | |
| 96 if self.__verbose: | |
| 97 print 'A\t%s' % name | |
| 98 | |
| 99 def add(self, name, arcname=None, recursive=True, exclude=None, filter=None): | |
| 100 head, tail = os.path.split(name) | |
| 101 if tail in ('.svn', '.git'): | |
| 102 self.__report_skipped(name) | |
| 103 return | |
| 104 | |
| 105 if self.__remove_nonessential_files: | |
| 106 # WebKit change logs take quite a lot of space. This saves ~10 MB | |
| 107 # in a bzip2-compressed tarball. | |
| 108 if 'ChangeLog' in name: | |
| 109 self.__report_skipped(name) | |
| 110 return | |
| 111 | |
| 112 # Remove contents of non-essential directories, but preserve gyp files, | |
| 113 # so that build/gyp_chromium can work. | |
| 114 for nonessential_dir in (NONESSENTIAL_DIRS + TESTDIRS): | |
| 115 dir_path = os.path.join(GetSourceDirectory(), nonessential_dir) | |
| 116 if (name.startswith(dir_path) and | |
| 117 os.path.isfile(name) and | |
| 118 'gyp' not in name): | |
| 119 self.__report_skipped(name) | |
| 120 return | |
| 121 | |
| 122 self.__report_added(name) | |
| 123 tarfile.TarFile.add(self, name, arcname=arcname, recursive=recursive) | |
| 124 | |
| 125 | |
| 126 def main(argv): | |
| 127 parser = optparse.OptionParser() | |
| 128 parser.add_option("--basename") | |
| 129 parser.add_option("--remove-nonessential-files", | |
| 130 dest="remove_nonessential_files", | |
| 131 action="store_true", default=False) | |
| 132 parser.add_option("--test-data", action="store_true") | |
| 133 # TODO(phajdan.jr): Remove --xz option when it's not needed for compatibility. | |
| 134 parser.add_option("--xz", action="store_true") | |
| 135 parser.add_option("--verbose", action="store_true", default=False) | |
| 136 parser.add_option("--progress", action="store_true", default=False) | |
| 137 | |
| 138 options, args = parser.parse_args(argv) | |
| 139 | |
| 140 if len(args) != 1: | |
| 141 print 'You must provide only one argument: output file name' | |
| 142 print '(without .tar.xz extension).' | |
| 143 return 1 | |
| 144 | |
| 145 if not os.path.exists(GetSourceDirectory()): | |
| 146 print 'Cannot find the src directory ' + GetSourceDirectory() | |
| 147 return 1 | |
| 148 | |
| 149 # These two commands are from src/DEPS; please keep them in sync. | |
| 150 if subprocess.call(['python', 'build/util/lastchange.py', '-o', | |
| 151 'build/util/LASTCHANGE'], cwd=GetSourceDirectory()) != 0: | |
| 152 print 'Could not run build/util/lastchange.py to update LASTCHANGE.' | |
| 153 return 1 | |
| 154 if subprocess.call(['python', 'build/util/lastchange.py', '-s', | |
| 155 'third_party/WebKit', '-o', | |
| 156 'build/util/LASTCHANGE.blink'], | |
| 157 cwd=GetSourceDirectory()) != 0: | |
| 158 print 'Could not run build/util/lastchange.py to update LASTCHANGE.blink.' | |
| 159 return 1 | |
| 160 | |
| 161 output_fullname = args[0] + '.tar' | |
| 162 output_basename = options.basename or os.path.basename(args[0]) | |
| 163 | |
| 164 archive = MyTarFile.open(output_fullname, 'w') | |
| 165 archive.set_remove_nonessential_files(options.remove_nonessential_files) | |
| 166 archive.set_verbose(options.verbose) | |
| 167 try: | |
| 168 if options.test_data: | |
| 169 for directory in TESTDIRS: | |
| 170 archive.add(os.path.join(GetSourceDirectory(), directory), | |
| 171 arcname=os.path.join(output_basename, directory)) | |
| 172 else: | |
| 173 archive.add(GetSourceDirectory(), arcname=output_basename) | |
| 174 finally: | |
| 175 archive.close() | |
| 176 | |
| 177 if options.progress: | |
| 178 sys.stdout.flush() | |
| 179 pv = subprocess.Popen( | |
| 180 ['pv', '--force', output_fullname], | |
| 181 stdout=subprocess.PIPE, | |
| 182 stderr=sys.stdout) | |
| 183 with open(output_fullname + '.xz', 'w') as f: | |
| 184 rc = subprocess.call(['xz', '-9', '-'], stdin=pv.stdout, stdout=f) | |
| 185 pv.wait() | |
| 186 else: | |
| 187 rc = subprocess.call(['xz', '-9', output_fullname]) | |
| 188 | |
| 189 if rc != 0: | |
| 190 print 'xz -9 failed!' | |
| 191 return 1 | |
| 192 | |
| 193 return 0 | |
| 194 | |
| 195 | |
| 196 if __name__ == "__main__": | |
| 197 sys.exit(main(sys.argv[1:])) | |
| OLD | NEW |