| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2011 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 """Script to create Chrome Installer archive. | 6 """Script to create Chrome Installer archive. |
| 7 | 7 |
| 8 This script is used to create an archive of all the files required for a | 8 This script is used to create an archive of all the files required for a |
| 9 Chrome install in appropriate directory structure. It reads chrome.release | 9 Chrome install in appropriate directory structure. It reads chrome.release |
| 10 file as input, creates chrome.7z archive, compresses setup.exe and | 10 file as input, creates chrome.7z archive, compresses setup.exe and |
| 11 generates packed_files.txt for mini_installer project. | 11 generates packed_files.txt for mini_installer project. |
| 12 | 12 |
| 13 """ | 13 """ |
| 14 | 14 |
| 15 import ConfigParser | 15 import ConfigParser |
| 16 import glob | 16 import glob |
| 17 import md5 |
| 17 import optparse | 18 import optparse |
| 18 import os | 19 import os |
| 19 import shutil | 20 import shutil |
| 20 import subprocess | |
| 21 import sys | 21 import sys |
| 22 | 22 |
| 23 | 23 |
| 24 ARCHIVE_DIR = "installer_archive" | 24 ARCHIVE_DIR = "installer_archive" |
| 25 | 25 |
| 26 # suffix to uncompresed full archive file, appended to options.output_name | 26 # suffix to uncompresed full archive file, appended to options.output_name |
| 27 ARCHIVE_SUFFIX = ".7z" | 27 ARCHIVE_SUFFIX = ".7z" |
| 28 BSDIFF_EXEC = "bsdiff.exe" | 28 BSDIFF_EXEC = "bsdiff.exe" |
| 29 CHROME_DIR = "Chrome-bin" | 29 CHROME_DIR = "Chrome-bin" |
| 30 CHROME_PATCH_FILE_SUFFIX = "_patch" # prefixed by options.output_name | 30 CHROME_PATCH_FILE_SUFFIX = "_patch" # prefixed by options.output_name |
| 31 | 31 |
| 32 # compressed full archive suffix, will be prefixed by options.output_name | 32 # compressed full archive suffix, will be prefixed by options.output_name |
| 33 COMPRESSED_ARCHIVE_SUFFIX = ".packed.7z" | 33 COMPRESSED_ARCHIVE_SUFFIX = ".packed.7z" |
| 34 | 34 |
| 35 COMPRESSED_FILE_EXT = ".packed.7z" # extension of patch archive file | 35 COMPRESSED_FILE_EXT = ".packed.7z" # extension of patch archive file |
| 36 COURGETTE_EXEC = "courgette.exe" | 36 COURGETTE_EXEC = "courgette.exe" |
| 37 MINI_INSTALLER_INPUT_FILE = "packed_files.txt" | 37 MINI_INSTALLER_INPUT_FILE = "packed_files.txt" |
| 38 PACKED_FILE_COMMENTS = """ |
| 39 // This file is automatically generated by create_installer_archive.py. |
| 40 // It contains the resource entries that are going to be linked inside |
| 41 // mini_installer.exe. For each file to be linked there should be two |
| 42 // lines: |
| 43 // - The first line contains the output filename (without path) and the |
| 44 // type of the resource ('BN' - not compressed , 'BL' - LZ compressed, |
| 45 // 'B7' - LZMA compressed) |
| 46 // - The second line contains the path to the input file. Uses '/' to |
| 47 // separate path components. |
| 48 """ |
| 38 PATCH_FILE_EXT = '.diff' | 49 PATCH_FILE_EXT = '.diff' |
| 39 SETUP_EXEC = "setup.exe" | 50 SETUP_EXEC = "setup.exe" |
| 40 SETUP_PATCH_FILE_PREFIX = "setup_patch" | 51 SETUP_PATCH_FILE_PREFIX = "setup_patch" |
| 41 TEMP_ARCHIVE_DIR = "temp_installer_archive" | 52 TEMP_ARCHIVE_DIR = "temp_installer_archive" |
| 42 VERSION_FILE = "VERSION" | 53 VERSION_FILE = "VERSION" |
| 43 | 54 |
| 44 | 55 def BuildVersion(output_dir): |
| 45 def BuildVersion(build_dir): | |
| 46 """Returns the full build version string constructed from information in | 56 """Returns the full build version string constructed from information in |
| 47 VERSION_FILE. Any segment not found in that file will default to '0'. | 57 VERSION_FILE. Any segment not found in that file will default to '0'. |
| 48 """ | 58 """ |
| 49 major = 0 | 59 major = 0 |
| 50 minor = 0 | 60 minor = 0 |
| 51 build = 0 | 61 build = 0 |
| 52 patch = 0 | 62 patch = 0 |
| 53 for line in open(os.path.join(build_dir, '../../chrome', VERSION_FILE), 'r'): | 63 for line in open(os.path.join(output_dir, "..", "..", "chrome", VERSION_FILE),
'r'): |
| 54 line = line.rstrip() | 64 line = line.rstrip() |
| 55 if line.startswith('MAJOR='): | 65 if line.startswith('MAJOR='): |
| 56 major = line[6:] | 66 major = line[6:] |
| 57 elif line.startswith('MINOR='): | 67 elif line.startswith('MINOR='): |
| 58 minor = line[6:] | 68 minor = line[6:] |
| 59 elif line.startswith('BUILD='): | 69 elif line.startswith('BUILD='): |
| 60 build = line[6:] | 70 build = line[6:] |
| 61 elif line.startswith('PATCH='): | 71 elif line.startswith('PATCH='): |
| 62 patch = line[6:] | 72 patch = line[6:] |
| 63 return '%s.%s.%s.%s' % (major, minor, build, patch) | 73 return '%s.%s.%s.%s' % (major, minor, build, patch) |
| 64 | 74 |
| 65 | 75 def CompressUsingLZMA(output_dir, compressed_file, input_file): |
| 66 def CompressUsingLZMA(build_dir, compressed_file, input_file): | 76 lzma_exec = GetLZMAExec(output_dir) |
| 67 lzma_exec = GetLZMAExec(build_dir) | 77 cmd = ('%s a -t7z ' |
| 68 cmd = [lzma_exec, | |
| 69 'a', '-t7z', | |
| 70 # Flags equivalent to -mx9 (ultra) but with the bcj2 turned on (exe | 78 # Flags equivalent to -mx9 (ultra) but with the bcj2 turned on (exe |
| 71 # pre-filter). This results in a ~2.3MB decrease in installer size on | 79 # pre-filter). This results in a ~2.3MB decrease in installer size on |
| 72 # a 24MB installer. | 80 # a 24MB installer. |
| 73 # Additionally, these settings reflect a 7zip 4.42 and up change in | 81 # Additionally, these settings reflect a 7zip 4.42 and up change in |
| 74 # the definition of -mx9, increasting the dicionary size moving to | 82 # the definition of -mx9, increasting the dicionary size moving to |
| 75 # 26bit = 64MB. This results in an additional ~3.5MB decrease. | 83 # 26bit = 64MB. This results in an additional ~3.5MB decrease. |
| 76 # Older 7zip versions can support these settings, as these changes | 84 # Older 7zip versions can support these settings, as these changes |
| 77 # rely on existing functionality in the lzma format. | 85 # rely on existing functionality in the lzma format. |
| 78 '-m0=BCJ2', | 86 '-m0=BCJ2 ' |
| 79 '-m1=LZMA:d26:fb64', | 87 '-m1=LZMA:d26:fb64 ' |
| 80 '-m2=LZMA:d20:fb64:mf=bt2', | 88 '-m2=LZMA:d20:fb64:mf=bt2 ' |
| 81 '-m3=LZMA:d20:fb64:mf=bt2', | 89 '-m3=LZMA:d20:fb64:mf=bt2 ' |
| 82 '-mb0:1', | 90 '-mb0:1 -mb0s1:2 ' |
| 83 '-mb0s1:2', | 91 '-mb0s2:3 ' |
| 84 '-mb0s2:3', | 92 '"%s" "%s"') % (lzma_exec, compressed_file, input_file) |
| 85 compressed_file, | |
| 86 input_file,] | |
| 87 if os.path.exists(compressed_file): | 93 if os.path.exists(compressed_file): |
| 88 os.remove(compressed_file) | 94 os.remove(compressed_file) |
| 89 RunSystemCommand(cmd) | 95 RunSystemCommand(cmd) |
| 90 | 96 |
| 91 | 97 def CopyAllFilesToStagingDir(config, distribution, staging_dir, output_dir): |
| 92 def CopyAllFilesToStagingDir(config, distribution, staging_dir, build_dir): | |
| 93 """Copies the files required for installer archive. | 98 """Copies the files required for installer archive. |
| 94 Copies all common files required for various distributions of Chromium and | 99 Copies all common files required for various distributions of Chromium and |
| 95 also files for the specific Chromium build specified by distribution. | 100 also files for the specific Chromium build specified by distribution. |
| 96 """ | 101 """ |
| 97 CopySectionFilesToStagingDir(config, 'GENERAL', staging_dir, build_dir) | 102 CopySectionFilesToStagingDir(config, 'GENERAL', staging_dir, output_dir) |
| 98 if distribution: | 103 if distribution: |
| 99 if len(distribution) > 1 and distribution[0] == '_': | 104 if len(distribution) > 1 and distribution[0] == '_': |
| 100 distribution = distribution[1:] | 105 distribution = distribution[1:] |
| 101 CopySectionFilesToStagingDir(config, distribution.upper(), | 106 CopySectionFilesToStagingDir(config, distribution.upper(), |
| 102 staging_dir, build_dir) | 107 staging_dir, output_dir) |
| 103 | 108 |
| 109 def IsChromeFrameFile(file): |
| 110 for cf_file in ['npchrome_frame', 'chrome_launcher']: |
| 111 if file.lower().find(cf_file) != -1: |
| 112 return True |
| 113 return False |
| 104 | 114 |
| 105 def CopySectionFilesToStagingDir(config, section, staging_dir, build_dir): | 115 def CopySectionFilesToStagingDir(config, section, staging_dir, output_dir): |
| 106 """Copies installer archive files specified in section to staging dir. | 116 """Copies installer archive files specified in section to staging dir. |
| 107 This method copies reads section from config file and copies all the files | 117 This method copies reads section from config file and copies all the files |
| 108 specified to staging dir. | 118 specified to staging dir. |
| 109 """ | 119 """ |
| 110 for option in config.options(section): | 120 for option in config.options(section): |
| 111 if option.endswith('dir'): | 121 if option.endswith('dir'): |
| 112 continue | 122 continue |
| 113 | 123 |
| 114 dst = os.path.join(staging_dir, config.get(section, option)) | 124 dst = os.path.join(staging_dir, config.get(section, option)) |
| 115 if not os.path.exists(dst): | 125 if not os.path.exists(dst): |
| 116 os.makedirs(dst) | 126 os.makedirs(dst) |
| 117 for file in glob.glob(os.path.join(build_dir, option)): | 127 for file in glob.glob(os.path.join(output_dir, option)): |
| 118 shutil.copy(file, dst) | 128 if IsChromeFrameFile(file): |
| 129 try: |
| 130 shutil.copy(file, dst) |
| 131 except IOError: |
| 132 # TODO(robertshield): Temporary hack to work around problems building |
| 133 # Chrome Frame binaries on non-Chrome Frame builders. Remove this |
| 134 # asap. |
| 135 print 'Error attempting to copy ' + file + ' to ' + dst |
| 136 else: |
| 137 shutil.copy(file, dst) |
| 119 | 138 |
| 120 def GenerateDiffPatch(options, orig_file, new_file, patch_file): | 139 def GenerateDiffPatch(options, orig_file, new_file, patch_file): |
| 121 if (options.diff_algorithm == "COURGETTE"): | 140 if (options.diff_algorithm == "COURGETTE"): |
| 122 exe_file = os.path.join(options.last_chrome_installer, COURGETTE_EXEC) | 141 exe_file = os.path.join(options.last_chrome_installer, COURGETTE_EXEC) |
| 123 cmd = '%s -gen "%s" "%s" "%s"' % (exe_file, orig_file, new_file, patch_file) | 142 cmd = '%s -gen "%s" "%s" "%s"' % (exe_file, orig_file, new_file, patch_file) |
| 124 else: | 143 else: |
| 125 exe_file = os.path.join(options.build_dir, BSDIFF_EXEC) | 144 exe_file = os.path.join(options.output_dir, BSDIFF_EXEC) |
| 126 cmd = [exe_file, orig_file, new_file, patch_file,] | 145 cmd = '%s "%s" "%s" "%s"' % (exe_file, orig_file, new_file, patch_file) |
| 127 RunSystemCommand(cmd) | 146 RunSystemCommand(cmd) |
| 128 | 147 |
| 129 def GetLZMAExec(build_dir): | 148 def GetLZMAExec(output_dir): |
| 130 lzma_exec = os.path.join(build_dir, "..", "..", "third_party", | 149 lzma_exec = os.path.join(output_dir, "..", "..", "third_party", |
| 131 "lzma_sdk", "Executable", "7za.exe") | 150 "lzma_sdk", "Executable", "7za.exe") |
| 132 return lzma_exec | 151 return lzma_exec |
| 133 | 152 |
| 134 def GetPrevVersion(build_dir, temp_dir, last_chrome_installer): | 153 def GetPrevVersion(output_dir, temp_dir, last_chrome_installer): |
| 135 if not last_chrome_installer: | 154 if not last_chrome_installer: |
| 136 return '' | 155 return '' |
| 137 | 156 |
| 138 lzma_exec = GetLZMAExec(options.build_dir) | 157 lzma_exec = GetLZMAExec(options.output_dir) |
| 139 prev_archive_file = os.path.join(options.last_chrome_installer, | 158 prev_archive_file = os.path.join(options.last_chrome_installer, |
| 140 options.output_name + ARCHIVE_SUFFIX) | 159 options.output_name + ARCHIVE_SUFFIX) |
| 141 cmd = [lzma_exec, | 160 cmd = '%s x -o"%s" "%s" Chrome-bin/*/chrome.dll' % (lzma_exec, temp_dir, |
| 142 'x', | 161 prev_archive_file) |
| 143 '-o"%s"' % temp_dir, | |
| 144 prev_archive_file, | |
| 145 'Chrome-bin/*/chrome.dll',] | |
| 146 RunSystemCommand(cmd) | 162 RunSystemCommand(cmd) |
| 147 dll_path = glob.glob(os.path.join(temp_dir, 'Chrome-bin', '*', 'chrome.dll')) | 163 dll_path = glob.glob(os.path.join(temp_dir, 'Chrome-bin', '*', 'chrome.dll')) |
| 148 return os.path.split(os.path.split(dll_path[0])[0])[1] | 164 return os.path.split(os.path.split(dll_path[0])[0])[1] |
| 149 | 165 |
| 150 def MakeStagingDirectories(staging_dir): | 166 def MakeStagingDirectories(output_dir): |
| 151 """Creates a staging path for installer archive. If directory exists already, | 167 """Creates a staging path for installer archive. If directory exists already, |
| 152 deletes the existing directory. | 168 deletes the existing directory. |
| 153 """ | 169 """ |
| 154 file_path = os.path.join(staging_dir, TEMP_ARCHIVE_DIR) | 170 prefixed_archive_dir = (options.archive_prefix or "") + ARCHIVE_DIR |
| 171 file_path = os.path.join(output_dir, prefixed_archive_dir) |
| 155 if os.path.exists(file_path): | 172 if os.path.exists(file_path): |
| 156 shutil.rmtree(file_path) | 173 shutil.rmtree(file_path) |
| 157 os.makedirs(file_path) | 174 os.makedirs(file_path) |
| 158 | 175 |
| 159 temp_file_path = os.path.join(staging_dir, TEMP_ARCHIVE_DIR) | 176 prefixed_temp_archive_dir = (options.archive_prefix or "") + TEMP_ARCHIVE_DIR |
| 177 temp_file_path = os.path.join(output_dir, prefixed_temp_archive_dir) |
| 160 if os.path.exists(temp_file_path): | 178 if os.path.exists(temp_file_path): |
| 161 shutil.rmtree(temp_file_path) | 179 shutil.rmtree(temp_file_path) |
| 162 os.makedirs(temp_file_path) | 180 os.makedirs(temp_file_path) |
| 163 return (file_path, temp_file_path) | 181 return (file_path, temp_file_path) |
| 164 | 182 |
| 165 def Readconfig(build_dir, input_file, current_version): | 183 def Readconfig(output_dir, input_file, current_version): |
| 166 """Reads config information from input file after setting default value of | 184 """Reads config information from input file after setting default value of |
| 167 global variabes. | 185 global variabes. |
| 168 """ | 186 """ |
| 169 variables = {} | 187 variables = {} |
| 170 variables['ChromeDir'] = CHROME_DIR | 188 variables['ChromeDir'] = CHROME_DIR |
| 171 variables['VersionDir'] = os.path.join(variables['ChromeDir'], | 189 variables['VersionDir'] = os.path.join(variables['ChromeDir'], |
| 172 current_version) | 190 current_version) |
| 173 config = ConfigParser.SafeConfigParser(variables) | 191 config = ConfigParser.SafeConfigParser(variables) |
| 174 config.read(input_file) | 192 config.read(input_file) |
| 175 return config | 193 return config |
| 176 | 194 |
| 177 def RunSystemCommand(cmd): | 195 def RunSystemCommand(cmd): |
| 178 print 'Running', cmd | 196 print 'Running [' + cmd + ']' |
| 179 exit_code = subprocess.call(cmd) | 197 exit_code = os.system(cmd) |
| 180 if (exit_code != 0): | 198 if (exit_code != 0): |
| 181 raise Exception("Error while running cmd: %s, exit_code: %s" % | 199 raise Exception("Error while running cmd: %s, exit_code: %s" % |
| 182 (cmd, exit_code)) | 200 (cmd, exit_code)) |
| 183 | 201 |
| 184 def CreateArchiveFile(options, staging_dir, current_version, prev_version): | 202 def CreateArchiveFile(options, staging_dir, current_version, prev_version): |
| 185 """Creates a new installer archive file after deleting any existing old file. | 203 """Creates a new installer archive file after deleting any existing old file. |
| 186 """ | 204 """ |
| 187 # First create an uncompressed archive file for the current build (chrome.7z) | 205 # First create an uncompressed archive file for the current build (chrome.7z) |
| 188 lzma_exec = GetLZMAExec(options.build_dir) | 206 lzma_exec = GetLZMAExec(options.output_dir) |
| 189 archive_file = os.path.join(options.build_dir, | 207 archive_file = os.path.join(options.output_dir, |
| 190 options.output_name + ARCHIVE_SUFFIX) | 208 options.output_name + ARCHIVE_SUFFIX) |
| 191 cmd = [lzma_exec, | 209 cmd = '%s a -t7z "%s" "%s" -mx0' % (lzma_exec, archive_file, |
| 192 'a', | 210 os.path.join(staging_dir, CHROME_DIR)) |
| 193 '-t7z', | |
| 194 archive_file, | |
| 195 os.path.join(staging_dir, CHROME_DIR), | |
| 196 '-mx0',] | |
| 197 # There doesnt seem to be any way in 7za.exe to override existing file so | 211 # There doesnt seem to be any way in 7za.exe to override existing file so |
| 198 # we always delete before creating a new one. | 212 # we always delete before creating a new one. |
| 199 if not os.path.exists(archive_file): | 213 if not os.path.exists(archive_file): |
| 200 RunSystemCommand(cmd) | 214 RunSystemCommand(cmd) |
| 201 elif options.skip_rebuild_archive != "true": | 215 elif options.skip_rebuild_archive != "true": |
| 202 os.remove(archive_file) | 216 os.remove(archive_file) |
| 203 RunSystemCommand(cmd) | 217 RunSystemCommand(cmd) |
| 204 | 218 |
| 205 # If we are generating a patch, run bsdiff against previous build and | 219 # If we are generating a patch, run bsdiff against previous build and |
| 206 # compress the resulting patch file. If this is not a patch just compress the | 220 # compress the resulting patch file. If this is not a patch just compress the |
| 207 # uncompressed archive file. | 221 # uncompressed archive file. |
| 208 patch_name_prefix = options.output_name + CHROME_PATCH_FILE_SUFFIX | 222 patch_name_prefix = options.output_name + CHROME_PATCH_FILE_SUFFIX |
| 209 if options.last_chrome_installer: | 223 if options.last_chrome_installer: |
| 210 prev_archive_file = os.path.join(options.last_chrome_installer, | 224 prev_archive_file = os.path.join(options.last_chrome_installer, |
| 211 options.output_name + ARCHIVE_SUFFIX) | 225 options.output_name + ARCHIVE_SUFFIX) |
| 212 patch_file = os.path.join(options.build_dir, patch_name_prefix + | 226 patch_file = os.path.join(options.output_dir, patch_name_prefix + |
| 213 PATCH_FILE_EXT) | 227 PATCH_FILE_EXT) |
| 214 GenerateDiffPatch(options, prev_archive_file, archive_file, patch_file) | 228 GenerateDiffPatch(options, prev_archive_file, archive_file, patch_file) |
| 215 compressed_archive_file = patch_name_prefix + '_' + \ | 229 compressed_archive_file = patch_name_prefix + '_' + \ |
| 216 current_version + '_from_' + prev_version + \ | 230 current_version + '_from_' + prev_version + \ |
| 217 COMPRESSED_FILE_EXT | 231 COMPRESSED_FILE_EXT |
| 218 orig_file = patch_file | 232 orig_file = patch_file |
| 219 else: | 233 else: |
| 220 compressed_archive_file = options.output_name + COMPRESSED_ARCHIVE_SUFFIX | 234 compressed_archive_file = options.output_name + COMPRESSED_ARCHIVE_SUFFIX |
| 221 orig_file = archive_file | 235 orig_file = archive_file |
| 222 | 236 |
| 223 compressed_archive_file_path = os.path.join(options.build_dir, | 237 compressed_archive_file_path = os.path.join(options.output_dir, |
| 224 compressed_archive_file) | 238 compressed_archive_file) |
| 225 CompressUsingLZMA(options.build_dir, compressed_archive_file_path, orig_file) | 239 CompressUsingLZMA(options.output_dir, compressed_archive_file_path, orig_file) |
| 226 | 240 |
| 227 return compressed_archive_file | 241 return compressed_archive_file |
| 228 | 242 |
| 229 | 243 |
| 230 def PrepareSetupExec(options, staging_dir, current_version, prev_version): | 244 def PrepareSetupExec(options, staging_dir, current_version, prev_version): |
| 231 """Prepares setup.exe for bundling in mini_installer based on options.""" | 245 """Prepares setup.exe for bundling in mini_installer based on options.""" |
| 232 if options.setup_exe_format == "FULL": | 246 if options.setup_exe_format == "FULL": |
| 233 setup_file = SETUP_EXEC | 247 setup_file = SETUP_EXEC |
| 234 elif options.setup_exe_format == "DIFF": | 248 elif options.setup_exe_format == "DIFF": |
| 235 if not options.last_chrome_installer: | 249 if not options.last_chrome_installer: |
| 236 raise Exception( | 250 raise Exception( |
| 237 "To use DIFF for setup.exe, --last_chrome_installer is needed.") | 251 "To use DIFF for setup.exe, --last_chrome_installer is needed.") |
| 238 prev_setup_file = os.path.join(options.last_chrome_installer, SETUP_EXEC) | 252 prev_setup_file = os.path.join(options.last_chrome_installer, SETUP_EXEC) |
| 239 new_setup_file = os.path.join(options.build_dir, SETUP_EXEC) | 253 new_setup_file = os.path.join(options.output_dir, SETUP_EXEC) |
| 240 patch_file = os.path.join(options.build_dir, SETUP_PATCH_FILE_PREFIX + | 254 patch_file = os.path.join(options.output_dir, SETUP_PATCH_FILE_PREFIX + |
| 241 PATCH_FILE_EXT) | 255 PATCH_FILE_EXT) |
| 242 GenerateDiffPatch(options, prev_setup_file, new_setup_file, patch_file) | 256 GenerateDiffPatch(options, prev_setup_file, new_setup_file, patch_file) |
| 243 setup_file = SETUP_PATCH_FILE_PREFIX + '_' + current_version + \ | 257 setup_file = SETUP_PATCH_FILE_PREFIX + '_' + current_version + \ |
| 244 '_from_' + prev_version + COMPRESSED_FILE_EXT | 258 '_from_' + prev_version + COMPRESSED_FILE_EXT |
| 245 setup_file_path = os.path.join(options.build_dir, setup_file) | 259 setup_file_path = os.path.join(options.output_dir, setup_file) |
| 246 CompressUsingLZMA(options.build_dir, setup_file_path, patch_file) | 260 CompressUsingLZMA(options.output_dir, setup_file_path, patch_file) |
| 247 else: | 261 else: |
| 248 cmd = ['makecab.exe', | 262 cmd = 'makecab.exe /D CompressionType=LZX /V1 /L "%s" "%s"' % ( |
| 249 '/D', 'CompressionType=LZX', | 263 options.output_dir, os.path.join(options.output_dir, SETUP_EXEC)) |
| 250 '/V1', | |
| 251 '/L', options.build_dir, | |
| 252 os.path.join(options.build_dir, SETUP_EXEC),] | |
| 253 RunSystemCommand(cmd) | 264 RunSystemCommand(cmd) |
| 254 setup_file = SETUP_EXEC[:-1] + "_" | 265 setup_file = SETUP_EXEC[:len(SETUP_EXEC) - 1] + "_" |
| 255 return setup_file | 266 return setup_file |
| 256 | 267 |
| 257 | 268 |
| 258 _RESOURCE_FILE_TEMPLATE = """ | 269 def CreateResourceInputFile(output_dir, setup_format, archive_file, setup_file): |
| 259 // This file is automatically generated by create_installer_archive.py. | |
| 260 // It contains the resource entries that are going to be linked inside | |
| 261 // mini_installer.exe. For each file to be linked there should be two | |
| 262 // lines: | |
| 263 // - The first line contains the output filename (without path) and the | |
| 264 // type of the resource ('BN' - not compressed , 'BL' - LZ compressed, | |
| 265 // 'B7' - LZMA compressed) | |
| 266 // - The second line contains the path to the input file. Uses '/' to | |
| 267 // separate path components. | |
| 268 | |
| 269 %(setup_file)s %(setup_file_resource_type)s | |
| 270 %(setup_file_path)s | |
| 271 | |
| 272 %(archive_file)s B7 | |
| 273 %(archive_file_path)s | |
| 274 """ | |
| 275 | |
| 276 | |
| 277 def CreateResourceInputFile( | |
| 278 build_dir, setup_format, archive_file, setup_file, resource_file_path): | |
| 279 """Creates resource input file (packed_files.txt) for mini_installer project. | 270 """Creates resource input file (packed_files.txt) for mini_installer project. |
| 280 | 271 |
| 281 This method checks the format of setup.exe being used and according sets | 272 This method checks the format of setup.exe being used and according sets |
| 282 its resource type. | 273 its resource type. |
| 283 """ | 274 """ |
| 284 setup_resource_type = "BL" | 275 setup_resource_type = "BL" |
| 285 if (setup_format == "FULL"): | 276 if (options.setup_exe_format == "FULL"): |
| 286 setup_resource_type = "BN" | 277 setup_resource_type = "BN" |
| 287 elif (setup_format == "DIFF"): | 278 elif (options.setup_exe_format == "DIFF"): |
| 288 setup_resource_type = "B7" | 279 setup_resource_type = "B7" |
| 280 setup_file_entry = "%s\t\t%s\n\"%s\"" % (setup_file, setup_resource_type, |
| 281 os.path.join(output_dir, setup_file).replace("\\","/")) |
| 289 | 282 |
| 290 # Expand the resource file template. | 283 archive_file_entry = "\n%s\t\tB7\n\"%s\"\n" % (archive_file, |
| 291 args = { | 284 os.path.join(output_dir, archive_file).replace("\\","/")) |
| 292 'setup_file': setup_file, | 285 output_file = os.path.join(output_dir, MINI_INSTALLER_INPUT_FILE) |
| 293 'setup_file_resource_type': setup_resource_type, | 286 f = open(output_file, 'w') |
| 294 'setup_file_path': | 287 try: |
| 295 os.path.join(build_dir, setup_file).replace("\\","/"), | 288 f.write(PACKED_FILE_COMMENTS) |
| 296 'archive_file': archive_file, | 289 f.write(setup_file_entry) |
| 297 'archive_file_path': | 290 f.write(archive_file_entry) |
| 298 os.path.join(build_dir, archive_file).replace("\\","/"), | 291 finally: |
| 299 } | 292 f.close() |
| 300 resource_file = _RESOURCE_FILE_TEMPLATE % args | |
| 301 | |
| 302 with open(resource_file_path, 'w') as f: | |
| 303 f.write(resource_file) | |
| 304 | 293 |
| 305 | 294 |
| 306 def main(options): | 295 def main(options): |
| 307 """Main method that reads input file, creates archive file and write | 296 """Main method that reads input file, creates archive file and write |
| 308 resource input file. | 297 resource input file. |
| 309 """ | 298 """ |
| 310 current_version = BuildVersion(options.build_dir) | 299 current_version = BuildVersion(options.output_dir) |
| 311 | 300 |
| 312 config = Readconfig(options.build_dir, options.input_file, current_version) | 301 config = Readconfig(options.output_dir, options.input_file, current_version) |
| 313 | 302 |
| 314 (staging_dir, temp_dir) = MakeStagingDirectories(options.staging_dir) | 303 (staging_dir, temp_dir) = MakeStagingDirectories(options.output_dir) |
| 315 | 304 |
| 316 prev_version = GetPrevVersion(options.build_dir, temp_dir, | 305 prev_version = GetPrevVersion(options.output_dir, temp_dir, |
| 317 options.last_chrome_installer) | 306 options.last_chrome_installer) |
| 318 | 307 |
| 319 CopyAllFilesToStagingDir(config, options.distribution, | 308 CopyAllFilesToStagingDir(config, options.distribution, |
| 320 staging_dir, options.build_dir) | 309 staging_dir, options.output_dir) |
| 321 | 310 |
| 322 version_numbers = current_version.split('.') | 311 version_numbers = current_version.split('.') |
| 323 current_build_number = version_numbers[2] + '.' + version_numbers[3] | 312 current_build_number = version_numbers[2] + '.' + version_numbers[3] |
| 324 prev_build_number = '' | 313 prev_build_number = '' |
| 325 if prev_version: | 314 if prev_version: |
| 326 version_numbers = prev_version.split('.') | 315 version_numbers = prev_version.split('.') |
| 327 prev_build_number = version_numbers[2] + '.' + version_numbers[3] | 316 prev_build_number = version_numbers[2] + '.' + version_numbers[3] |
| 328 | 317 |
| 329 # Name of the archive file built (for example - chrome.7z or | 318 # Name of the archive file built (for example - chrome.7z or |
| 330 # patch-<old_version>-<new_version>.7z or patch-<new_version>.7z | 319 # patch-<old_version>-<new_version>.7z or patch-<new_version>.7z |
| 331 archive_file = CreateArchiveFile(options, staging_dir, | 320 archive_file = CreateArchiveFile(options, staging_dir, |
| 332 current_build_number, prev_build_number) | 321 current_build_number, prev_build_number) |
| 333 | 322 |
| 334 setup_file = PrepareSetupExec(options, staging_dir, | 323 setup_file = PrepareSetupExec(options, staging_dir, |
| 335 current_build_number, prev_build_number) | 324 current_build_number, prev_build_number) |
| 336 | 325 |
| 337 CreateResourceInputFile(options.build_dir, options.setup_exe_format, | 326 CreateResourceInputFile(options.output_dir, options.setup_exe_format, |
| 338 archive_file, setup_file, options.resource_file_path) | 327 archive_file, setup_file) |
| 339 | |
| 340 def _ParseOptions(): | |
| 341 parser = optparse.OptionParser() | |
| 342 parser.add_option('-i', '--input_file', | |
| 343 help='Input file describing which files to archive.') | |
| 344 parser.add_option('-o', '--build_dir', | |
| 345 help='Build directory. The paths in input_file are relative to this.') | |
| 346 parser.add_option('--staging_dir', | |
| 347 help='Staging directory where intermediate files and directories ' | |
| 348 'will be created'), | |
| 349 parser.add_option('--resource_file_path', | |
| 350 help='The path where the resource file will be output. ' | |
| 351 'Defaults to %s in the build directory.' % | |
| 352 MINI_INSTALLER_INPUT_FILE), | |
| 353 parser.add_option('-d', '--distribution', | |
| 354 help='Name of Chromium Distribution. Optional.') | |
| 355 parser.add_option('-s', '--skip_rebuild_archive', | |
| 356 default="False", help='Skip re-building Chrome.7z archive if it exists.') | |
| 357 parser.add_option('-l', '--last_chrome_installer', | |
| 358 help='Generate differential installer. The value of this parameter ' | |
| 359 'specifies the directory that contains base versions of ' | |
| 360 'setup.exe, courgette.exe (if --diff_algorithm is COURGETTE) ' | |
| 361 '& chrome.7z.') | |
| 362 parser.add_option('-f', '--setup_exe_format', default='COMPRESSED', | |
| 363 help='How setup.exe should be included {COMPRESSED|DIFF|FULL}.') | |
| 364 parser.add_option('-a', '--diff_algorithm', default='BSDIFF', | |
| 365 help='Diff algorithm to use when generating differential patches ' | |
| 366 '{BSDIFF|COURGETTE}.') | |
| 367 parser.add_option('-n', '--output_name', default='chrome', | |
| 368 help='Name used to prefix names of generated archives.') | |
| 369 | |
| 370 options, args = parser.parse_args() | |
| 371 | |
| 372 if not options.build_dir: | |
| 373 parser.error('You must provide a build dir.') | |
| 374 | |
| 375 if not options.staging_dir: | |
| 376 parser.error('You must provide a staging dir.') | |
| 377 | |
| 378 if not options.resource_file_path: | |
| 379 options.options.resource_file_path = os.path.join(options.build_dir, | |
| 380 MINI_INSTALLER_INPUT_FILE) | |
| 381 | |
| 382 print sys.argv | |
| 383 return options | |
| 384 | 328 |
| 385 | 329 |
| 386 if '__main__' == __name__: | 330 if '__main__' == __name__: |
| 387 sys.exit(main(_ParseOptions())) | 331 option_parser = optparse.OptionParser() |
| 332 option_parser.add_option('-o', '--output_dir', help='Output directory') |
| 333 option_parser.add_option('-i', '--input_file', help='Input file') |
| 334 option_parser.add_option('-d', '--distribution', |
| 335 help='Name of Chromium Distribution. Optional.') |
| 336 option_parser.add_option('-s', '--skip_rebuild_archive', |
| 337 default="False", help='Skip re-building Chrome.7z archive if it exists.') |
| 338 option_parser.add_option('-l', '--last_chrome_installer', |
| 339 help='Generate differential installer. The value of this parameter ' + |
| 340 'specifies the directory that contains base versions of ' + |
| 341 'setup.exe, courgette.exe (if --diff_algorithm is COURGETTE) ' + |
| 342 '& chrome.7z.') |
| 343 option_parser.add_option('-p', '--archive_prefix', |
| 344 help='Specifies a prefix to the archive path. Useful if building ' + |
| 345 'multiple installer archives.') |
| 346 option_parser.add_option('-f', '--setup_exe_format', default='COMPRESSED', |
| 347 help='How setup.exe should be included {COMPRESSED|DIFF|FULL}.') |
| 348 option_parser.add_option('-a', '--diff_algorithm', default='BSDIFF', |
| 349 help='Diff algorithm to use when generating differential patches ' + |
| 350 '{BSDIFF|COURGETTE}.') |
| 351 option_parser.add_option('-n', '--output_name', default='chrome', |
| 352 help='Name used to prefix names of generated archives.') |
| 353 |
| 354 options, args = option_parser.parse_args() |
| 355 print sys.argv |
| 356 sys.exit(main(options)) |
| OLD | NEW |