blob: 2a722c52465e8ca5215e900ddf730c625750a23e [file] [log] [blame]
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001#!/usr/bin/env python
2#
3# Copyright (C) 2019 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may not
6# use this file except in compliance with the License. You may obtain a copy of
7# the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations under
15# the License.
Daniel Normane5b134a2019-04-17 14:54:06 -070016"""This script merges two partial target files packages.
Bill Peckhame9eb5f92019-02-01 15:52:10 -080017
Daniel Normane5b134a2019-04-17 14:54:06 -070018One package contains system files, and the other contains non-system files.
19It produces a complete target files package that can be used to generate an
20OTA package.
Bill Peckhame9eb5f92019-02-01 15:52:10 -080021
22Usage: merge_target_files.py [args]
23
24 --system-target-files system-target-files-zip-archive
25 The input target files package containing system bits. This is a zip
26 archive.
27
Daniel Norman2c99c5b2019-03-07 13:01:48 -080028 --system-item-list system-item-list-file
29 The optional path to a newline-separated config file that replaces the
30 contents of default_system_item_list if provided.
31
32 --system-misc-info-keys system-misc-info-keys-file
33 The optional path to a newline-separated config file that replaces the
34 contents of default_system_misc_info_keys if provided.
35
Bill Peckhame9eb5f92019-02-01 15:52:10 -080036 --other-target-files other-target-files-zip-archive
37 The input target files package containing other bits. This is a zip
38 archive.
39
Daniel Norman2c99c5b2019-03-07 13:01:48 -080040 --other-item-list other-item-list-file
41 The optional path to a newline-separated config file that replaces the
42 contents of default_other_item_list if provided.
43
Bill Peckhame9eb5f92019-02-01 15:52:10 -080044 --output-target-files output-target-files-package
Daniel Normanfdb38812019-04-15 09:47:24 -070045 If provided, the output merged target files package. Also a zip archive.
46
47 --output-dir output-directory
48 If provided, the destination directory for saving merged files. Requires
49 the --output-item-list flag.
50 Can be provided alongside --output-target-files, or by itself.
51
52 --output-item-list output-item-list-file.
53 The optional path to a newline-separated config file that specifies the
54 file patterns to copy into the --output-dir. Required if providing
55 the --output-dir flag.
Daniel Normana4911da2019-03-15 14:36:21 -070056
Daniel Norman3b64ce12019-04-16 16:11:35 -070057 --output-ota output-ota-package
58 The output ota package. This is a zip archive. Use of this flag may
59 require passing the --path common flag; see common.py.
60
Daniel Norman1bd2a1d2019-04-18 12:32:18 -070061 --output-img output-img-package
62 The output img package, suitable for use with 'fastboot update'. Use of
63 this flag may require passing the --path common flag; see common.py.
64
Daniel Normanf0318252019-04-15 11:34:56 -070065 --output-super-empty output-super-empty-image
66 If provided, creates a super_empty.img file from the merged target
67 files package and saves it at this path.
68
Daniel Normana4911da2019-03-15 14:36:21 -070069 --rebuild_recovery
70 Rebuild the recovery patch used by non-A/B devices and write it to the
71 system image.
Bill Peckham364c1cc2019-03-29 18:27:23 -070072
73 --keep-tmp
74 Keep tempoary files for debugging purposes.
Bill Peckhame9eb5f92019-02-01 15:52:10 -080075"""
76
77from __future__ import print_function
78
Bill Peckhame9eb5f92019-02-01 15:52:10 -080079import fnmatch
80import logging
81import os
Daniel Normanfdb38812019-04-15 09:47:24 -070082import shutil
Bill Peckham540d91a2019-04-25 14:18:16 -070083import subprocess
Bill Peckhame9eb5f92019-02-01 15:52:10 -080084import sys
85import zipfile
86
Bill Peckhame9eb5f92019-02-01 15:52:10 -080087import add_img_to_target_files
Daniel Normanf0318252019-04-15 11:34:56 -070088import build_super_image
89import common
Daniel Norman1bd2a1d2019-04-18 12:32:18 -070090import img_from_target_files
Daniel Norman3b64ce12019-04-16 16:11:35 -070091import ota_from_target_files
Bill Peckhame9eb5f92019-02-01 15:52:10 -080092
93logger = logging.getLogger(__name__)
94OPTIONS = common.OPTIONS
95OPTIONS.verbose = True
Bill Peckhamf753e152019-02-19 18:02:46 -080096OPTIONS.system_target_files = None
Daniel Norman2c99c5b2019-03-07 13:01:48 -080097OPTIONS.system_item_list = None
98OPTIONS.system_misc_info_keys = None
Bill Peckhamf753e152019-02-19 18:02:46 -080099OPTIONS.other_target_files = None
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800100OPTIONS.other_item_list = None
Bill Peckhamf753e152019-02-19 18:02:46 -0800101OPTIONS.output_target_files = None
Daniel Normanfdb38812019-04-15 09:47:24 -0700102OPTIONS.output_dir = None
103OPTIONS.output_item_list = None
Daniel Norman3b64ce12019-04-16 16:11:35 -0700104OPTIONS.output_ota = None
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700105OPTIONS.output_img = None
Daniel Normanf0318252019-04-15 11:34:56 -0700106OPTIONS.output_super_empty = None
Daniel Normana4911da2019-03-15 14:36:21 -0700107OPTIONS.rebuild_recovery = False
Bill Peckhamf753e152019-02-19 18:02:46 -0800108OPTIONS.keep_tmp = False
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800109
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800110# default_system_item_list is a list of items to extract from the partial
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800111# system target files package as is, meaning these items will land in the
112# output target files package exactly as they appear in the input partial
113# system target files package.
114
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800115default_system_item_list = [
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800116 'META/apkcerts.txt',
117 'META/filesystem_config.txt',
118 'META/root_filesystem_config.txt',
119 'META/system_manifest.xml',
120 'META/system_matrix.xml',
121 'META/update_engine_config.txt',
122 'PRODUCT/*',
123 'ROOT/*',
124 'SYSTEM/*',
125]
126
127# system_extract_special_item_list is a list of items to extract from the
128# partial system target files package that need some special processing, such
129# as some sort of combination with items from the partial other target files
130# package.
131
132system_extract_special_item_list = [
133 'META/*',
134]
135
Daniel Normane5b134a2019-04-17 14:54:06 -0700136# default_system_misc_info_keys is a list of keys to obtain from the system
137# instance of META/misc_info.txt. The remaining keys from the other instance.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800138
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800139default_system_misc_info_keys = [
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800140 'avb_system_hashtree_enable',
141 'avb_system_add_hashtree_footer_args',
142 'avb_system_key_path',
143 'avb_system_algorithm',
144 'avb_system_rollback_index_location',
145 'avb_product_hashtree_enable',
146 'avb_product_add_hashtree_footer_args',
147 'avb_product_services_hashtree_enable',
148 'avb_product_services_add_hashtree_footer_args',
149 'system_root_image',
150 'root_dir',
151 'ab_update',
152 'default_system_dev_certificate',
153 'system_size',
154]
155
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800156# default_other_item_list is a list of items to extract from the partial
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800157# other target files package as is, meaning these items will land in the output
158# target files package exactly as they appear in the input partial other target
159# files package.
160
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800161default_other_item_list = [
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800162 'META/boot_filesystem_config.txt',
Bill Peckham736b2232019-05-06 12:50:55 -0700163 'META/file_contexts.bin',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800164 'META/otakeys.txt',
165 'META/releasetools.py',
166 'META/vendor_filesystem_config.txt',
167 'META/vendor_manifest.xml',
168 'META/vendor_matrix.xml',
169 'BOOT/*',
170 'DATA/*',
171 'ODM/*',
172 'OTA/android-info.txt',
173 'PREBUILT_IMAGES/*',
174 'RADIO/*',
175 'VENDOR/*',
176]
177
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800178# other_extract_special_item_list is a list of items to extract from the
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800179# partial other target files package that need some special processing, such as
180# some sort of combination with items from the partial system target files
181# package.
182
183other_extract_special_item_list = [
184 'META/*',
185]
186
187
Chris Grossfabf50a2019-05-02 12:42:09 -0700188def write_sorted_data(data, path):
189 """Write the sorted contents of either a list or dict to file.
190
191 This function sorts the contents of the list or dict and then
192 writes the resulting sorted contents to a file specified by path.
193
194 Args:
195 data: The list or dict to sort and write.
196 path: Path to the file to write the sorted values to. The file at path will
197 be overridden if it exists.
198 """
199 with open(path, 'w') as output:
200 sorted_data = sorted(data.keys()) if isinstance(data,
201 dict) else sorted(data)
202 for entry in sorted_data:
203 out_str = '{}={}\n'.format(entry, data[entry]) if isinstance(
204 data, dict) else '{}\n'.format(entry)
205 output.write(out_str)
206
207
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800208def extract_items(target_files, target_files_temp_dir, extract_item_list):
209 """Extract items from target files to temporary directory.
210
211 This function extracts from the specified target files zip archive into the
212 specified temporary directory, the items specified in the extract item list.
213
214 Args:
215 target_files: The target files zip archive from which to extract items.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800216 target_files_temp_dir: The temporary directory where the extracted items
Daniel Normane5b134a2019-04-17 14:54:06 -0700217 will land.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800218 extract_item_list: A list of items to extract.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800219 """
220
221 logger.info('extracting from %s', target_files)
222
223 # Filter the extract_item_list to remove any items that do not exist in the
224 # zip file. Otherwise, the extraction step will fail.
225
226 with zipfile.ZipFile(
Daniel Normane5b134a2019-04-17 14:54:06 -0700227 target_files, 'r', allowZip64=True) as target_files_zipfile:
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800228 target_files_namelist = target_files_zipfile.namelist()
229
230 filtered_extract_item_list = []
231 for pattern in extract_item_list:
232 matching_namelist = fnmatch.filter(target_files_namelist, pattern)
233 if not matching_namelist:
234 logger.warning('no match for %s', pattern)
235 else:
236 filtered_extract_item_list.append(pattern)
237
Bill Peckham8ff3fbd2019-02-22 10:57:43 -0800238 # Extract from target_files into target_files_temp_dir the
239 # filtered_extract_item_list.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800240
Daniel Normane5b134a2019-04-17 14:54:06 -0700241 common.UnzipToDir(target_files, target_files_temp_dir,
242 filtered_extract_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800243
244
Daniel Normanfdb38812019-04-15 09:47:24 -0700245def copy_items(from_dir, to_dir, patterns):
246 """Similar to extract_items() except uses an input dir instead of zip."""
247 file_paths = []
248 for dirpath, _, filenames in os.walk(from_dir):
Daniel Normane5b134a2019-04-17 14:54:06 -0700249 file_paths.extend(
250 os.path.relpath(path=os.path.join(dirpath, filename), start=from_dir)
251 for filename in filenames)
Daniel Normanfdb38812019-04-15 09:47:24 -0700252
253 filtered_file_paths = set()
254 for pattern in patterns:
255 filtered_file_paths.update(fnmatch.filter(file_paths, pattern))
256
257 for file_path in filtered_file_paths:
258 original_file_path = os.path.join(from_dir, file_path)
259 copied_file_path = os.path.join(to_dir, file_path)
260 copied_file_dir = os.path.dirname(copied_file_path)
261 if not os.path.exists(copied_file_dir):
262 os.makedirs(copied_file_dir)
263 if os.path.islink(original_file_path):
264 os.symlink(os.readlink(original_file_path), copied_file_path)
265 else:
266 shutil.copyfile(original_file_path, copied_file_path)
267
268
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800269def read_config_list(config_file_path):
270 """Reads a config file into a list of strings.
271
272 Expects the file to be newline-separated.
273
274 Args:
275 config_file_path: The path to the config file to open and read.
Daniel Normane5b134a2019-04-17 14:54:06 -0700276
277 Returns:
278 The list of strings in the config file.
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800279 """
280 with open(config_file_path) as config_file:
281 return config_file.read().splitlines()
282
283
Daniel Normane5b134a2019-04-17 14:54:06 -0700284def validate_config_lists(system_item_list, system_misc_info_keys,
285 other_item_list):
Daniel Normane5964522019-03-19 10:32:03 -0700286 """Performs validations on the merge config lists.
287
288 Args:
Daniel Normane5b134a2019-04-17 14:54:06 -0700289 system_item_list: The list of items to extract from the partial system
290 target files package as is.
291 system_misc_info_keys: A list of keys to obtain from the system instance of
292 META/misc_info.txt. The remaining keys from the other instance.
293 other_item_list: The list of items to extract from the partial other target
294 files package as is.
Daniel Normane5964522019-03-19 10:32:03 -0700295
296 Returns:
297 False if a validation fails, otherwise true.
298 """
299 default_combined_item_set = set(default_system_item_list)
300 default_combined_item_set.update(default_other_item_list)
301
302 combined_item_set = set(system_item_list)
303 combined_item_set.update(other_item_list)
304
305 # Check that the merge config lists are not missing any item specified
306 # by the default config lists.
307 difference = default_combined_item_set.difference(combined_item_set)
308 if difference:
Daniel Normane5b134a2019-04-17 14:54:06 -0700309 logger.error('Missing merge config items: %s', list(difference))
Daniel Normane5964522019-03-19 10:32:03 -0700310 logger.error('Please ensure missing items are in either the '
311 'system-item-list or other-item-list files provided to '
312 'this script.')
313 return False
314
Daniel Norman19b9fe92019-03-19 14:48:02 -0700315 if ('dynamic_partition_list' in system_misc_info_keys) or (
316 'super_partition_groups' in system_misc_info_keys):
317 logger.error('Dynamic partition misc info keys should come from '
318 'the other instance of META/misc_info.txt.')
319 return False
320
Daniel Normane5964522019-03-19 10:32:03 -0700321 return True
322
323
Daniel Normane5b134a2019-04-17 14:54:06 -0700324def process_ab_partitions_txt(system_target_files_temp_dir,
325 other_target_files_temp_dir,
326 output_target_files_temp_dir):
327 """Perform special processing for META/ab_partitions.txt.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800328
329 This function merges the contents of the META/ab_partitions.txt files from
330 the system directory and the other directory, placing the merged result in
331 the output directory. The precondition in that the files are already
332 extracted. The post condition is that the output META/ab_partitions.txt
333 contains the merged content. The format for each ab_partitions.txt a one
334 partition name per line. The output file contains the union of the parition
335 names.
336
337 Args:
Daniel Normane5b134a2019-04-17 14:54:06 -0700338 system_target_files_temp_dir: The name of a directory containing the special
339 items extracted from the system target files package.
340 other_target_files_temp_dir: The name of a directory containing the special
341 items extracted from the other target files package.
342 output_target_files_temp_dir: The name of a directory that will be used to
343 create the output target files package after all the special cases are
344 processed.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800345 """
346
Daniel Normane5b134a2019-04-17 14:54:06 -0700347 system_ab_partitions_txt = os.path.join(system_target_files_temp_dir, 'META',
348 'ab_partitions.txt')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800349
Daniel Normane5b134a2019-04-17 14:54:06 -0700350 other_ab_partitions_txt = os.path.join(other_target_files_temp_dir, 'META',
351 'ab_partitions.txt')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800352
353 with open(system_ab_partitions_txt) as f:
354 system_ab_partitions = f.read().splitlines()
355
356 with open(other_ab_partitions_txt) as f:
357 other_ab_partitions = f.read().splitlines()
358
359 output_ab_partitions = set(system_ab_partitions + other_ab_partitions)
360
Daniel Normane5b134a2019-04-17 14:54:06 -0700361 output_ab_partitions_txt = os.path.join(output_target_files_temp_dir, 'META',
362 'ab_partitions.txt')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800363
Chris Grossfabf50a2019-05-02 12:42:09 -0700364 write_sorted_data(data=output_ab_partitions, path=output_ab_partitions_txt)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800365
366
Bill Peckham364c1cc2019-03-29 18:27:23 -0700367def append_recovery_to_filesystem_config(output_target_files_temp_dir):
Daniel Normane5b134a2019-04-17 14:54:06 -0700368 """Perform special processing for META/filesystem_config.txt.
Bill Peckham364c1cc2019-03-29 18:27:23 -0700369
370 This function appends recovery information to META/filesystem_config.txt
371 so that recovery patch regeneration will succeed.
372
373 Args:
Daniel Normane5b134a2019-04-17 14:54:06 -0700374 output_target_files_temp_dir: The name of a directory that will be used to
375 create the output target files package after all the special cases are
376 processed. We find filesystem_config.txt here.
Bill Peckham364c1cc2019-03-29 18:27:23 -0700377 """
378
Daniel Normane5b134a2019-04-17 14:54:06 -0700379 filesystem_config_txt = os.path.join(output_target_files_temp_dir, 'META',
380 'filesystem_config.txt')
Bill Peckham364c1cc2019-03-29 18:27:23 -0700381
382 with open(filesystem_config_txt, 'a') as f:
383 # TODO(bpeckham) this data is hard coded. It should be generated
384 # programmatically.
Daniel Normane5b134a2019-04-17 14:54:06 -0700385 f.write('system/bin/install-recovery.sh 0 0 750 '
386 'selabel=u:object_r:install_recovery_exec:s0 capabilities=0x0\n')
387 f.write('system/recovery-from-boot.p 0 0 644 '
388 'selabel=u:object_r:system_file:s0 capabilities=0x0\n')
389 f.write('system/etc/recovery.img 0 0 440 '
390 'selabel=u:object_r:install_recovery_exec:s0 capabilities=0x0\n')
Bill Peckham364c1cc2019-03-29 18:27:23 -0700391
392
Daniel Normana61cde02019-05-03 14:19:13 -0700393def merge_dynamic_partition_info_dicts(system_dict,
394 other_dict,
395 include_dynamic_partition_list=True,
396 size_prefix='',
397 size_suffix='',
398 list_prefix='',
399 list_suffix=''):
400 """Merges dynamic partition info variables.
401
402 Args:
403 system_dict: The dictionary of dynamic partition info variables from the
404 partial system target files.
405 other_dict: The dictionary of dynamic partition info variables from the
406 partial other target files.
407 include_dynamic_partition_list: If true, merges the dynamic_partition_list
408 variable. Not all use cases need this variable merged.
409 size_prefix: The prefix in partition group size variables that precedes the
410 name of the partition group. For example, partition group 'group_a' with
411 corresponding size variable 'super_group_a_group_size' would have the
412 size_prefix 'super_'.
413 size_suffix: Similar to size_prefix but for the variable's suffix. For
414 example, 'super_group_a_group_size' would have size_suffix '_group_size'.
415 list_prefix: Similar to size_prefix but for the partition group's
416 partition_list variable.
417 list_suffix: Similar to size_suffix but for the partition group's
418 partition_list variable.
419
420 Returns:
421 The merged dynamic partition info dictionary.
422 """
423 merged_dict = {}
424 # Partition groups and group sizes are defined by the other (non-system)
425 # dict because these values may vary for each board that uses a shared system
426 # image.
427 merged_dict['super_partition_groups'] = other_dict['super_partition_groups']
428 if include_dynamic_partition_list:
429 system_dynamic_partition_list = system_dict.get('dynamic_partition_list',
430 '')
431 other_dynamic_partition_list = other_dict.get('dynamic_partition_list', '')
432 merged_dict['dynamic_partition_list'] = (
433 '%s %s' %
434 (system_dynamic_partition_list, other_dynamic_partition_list)).strip()
435 for partition_group in merged_dict['super_partition_groups'].split(' '):
436 # Set the partition group's size using the value from the other dict.
437 key = '%s%s%s' % (size_prefix, partition_group, size_suffix)
438 if key not in other_dict:
439 raise ValueError('Other dict does not contain required key %s.' % key)
440 merged_dict[key] = other_dict[key]
441
442 # Set the partition group's partition list using a concatenation of the
443 # system and other partition lists.
444 key = '%s%s%s' % (list_prefix, partition_group, list_suffix)
445 merged_dict[key] = (
446 '%s %s' % (system_dict.get(key, ''), other_dict.get(key, ''))).strip()
447 return merged_dict
448
449
Daniel Normane5b134a2019-04-17 14:54:06 -0700450def process_misc_info_txt(system_target_files_temp_dir,
451 other_target_files_temp_dir,
452 output_target_files_temp_dir, system_misc_info_keys):
453 """Perform special processing for META/misc_info.txt.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800454
455 This function merges the contents of the META/misc_info.txt files from the
456 system directory and the other directory, placing the merged result in the
457 output directory. The precondition in that the files are already extracted.
458 The post condition is that the output META/misc_info.txt contains the merged
459 content.
460
461 Args:
Daniel Normane5b134a2019-04-17 14:54:06 -0700462 system_target_files_temp_dir: The name of a directory containing the special
463 items extracted from the system target files package.
464 other_target_files_temp_dir: The name of a directory containing the special
465 items extracted from the other target files package.
466 output_target_files_temp_dir: The name of a directory that will be used to
467 create the output target files package after all the special cases are
468 processed.
469 system_misc_info_keys: A list of keys to obtain from the system instance of
470 META/misc_info.txt. The remaining keys from the other instance.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800471 """
472
473 def read_helper(d):
474 misc_info_txt = os.path.join(d, 'META', 'misc_info.txt')
475 with open(misc_info_txt) as f:
476 return list(f.read().splitlines())
477
478 system_info_dict = common.LoadDictionaryFromLines(
479 read_helper(system_target_files_temp_dir))
480
481 # We take most of the misc info from the other target files.
482
483 merged_info_dict = common.LoadDictionaryFromLines(
484 read_helper(other_target_files_temp_dir))
485
486 # Replace certain values in merged_info_dict with values from
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800487 # system_info_dict.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800488
489 for key in system_misc_info_keys:
490 merged_info_dict[key] = system_info_dict[key]
491
Daniel Norman19b9fe92019-03-19 14:48:02 -0700492 # Merge misc info keys used for Dynamic Partitions.
493 if (merged_info_dict.get('use_dynamic_partitions') == 'true') and (
494 system_info_dict.get('use_dynamic_partitions') == 'true'):
Daniel Normana61cde02019-05-03 14:19:13 -0700495 merged_dynamic_partitions_dict = merge_dynamic_partition_info_dicts(
496 system_dict=system_info_dict,
497 other_dict=merged_info_dict,
498 size_prefix='super_',
499 size_suffix='_group_size',
500 list_prefix='super_',
501 list_suffix='_partition_list')
502 merged_info_dict.update(merged_dynamic_partitions_dict)
Daniel Norman19b9fe92019-03-19 14:48:02 -0700503
Daniel Normane5b134a2019-04-17 14:54:06 -0700504 output_misc_info_txt = os.path.join(output_target_files_temp_dir, 'META',
505 'misc_info.txt')
Chris Grossfabf50a2019-05-02 12:42:09 -0700506 write_sorted_data(data=merged_info_dict, path=output_misc_info_txt)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800507
508
Daniel Normana61cde02019-05-03 14:19:13 -0700509def process_dynamic_partitions_info_txt(system_target_files_dir,
510 other_target_files_dir,
511 output_target_files_dir):
512 """Perform special processing for META/dynamic_partitions_info.txt.
513
514 This function merges the contents of the META/dynamic_partitions_info.txt
515 files from the system directory and the other directory, placing the merged
516 result in the output directory.
517
518 This function does nothing if META/dynamic_partitions_info.txt from the other
519 directory does not exist.
520
521 Args:
522 system_target_files_dir: The name of a directory containing the special
523 items extracted from the system target files package.
524 other_target_files_dir: The name of a directory containing the special items
525 extracted from the other target files package.
526 output_target_files_dir: The name of a directory that will be used to create
527 the output target files package after all the special cases are processed.
528 """
529
530 if not os.path.exists(
531 os.path.join(other_target_files_dir, 'META',
532 'dynamic_partitions_info.txt')):
533 return
534
535 def read_helper(d):
536 dynamic_partitions_info_txt = os.path.join(d, 'META',
537 'dynamic_partitions_info.txt')
538 with open(dynamic_partitions_info_txt) as f:
539 return list(f.read().splitlines())
540
541 system_dynamic_partitions_dict = common.LoadDictionaryFromLines(
542 read_helper(system_target_files_dir))
543 other_dynamic_partitions_dict = common.LoadDictionaryFromLines(
544 read_helper(other_target_files_dir))
545
546 merged_dynamic_partitions_dict = merge_dynamic_partition_info_dicts(
547 system_dict=system_dynamic_partitions_dict,
548 other_dict=other_dynamic_partitions_dict,
549 # META/dynamic_partitions_info.txt does not use dynamic_partition_list.
550 include_dynamic_partition_list=False,
551 size_suffix='_size',
552 list_suffix='_partition_list')
553
554 output_dynamic_partitions_info_txt = os.path.join(
555 output_target_files_dir, 'META', 'dynamic_partitions_info.txt')
Chris Grossfabf50a2019-05-02 12:42:09 -0700556 write_sorted_data(
557 data=merged_dynamic_partitions_dict,
558 path=output_dynamic_partitions_info_txt)
559
560
561def process_apex_keys_apk_certs_common(system_target_files_dir,
562 other_target_files_dir,
563 output_target_files_dir, file_name):
564 """Perform special processing for META/apexkeys.txt or META/apkcerts.txt.
565
566 This function merges the contents of the META/apexkeys.txt or
567 META/apkcerts.txt
568 files from the system directory and the other directory, placing the merged
569 result in the output directory. The precondition in that the files are already
570 extracted.
571 The post condition is that the output META/apexkeys.txt or META/apkcerts.txt
572 contains the merged content.
573
574 Args:
575 system_target_files_dir: The name of a directory containing the special
576 items extracted from the system target files package.
577 other_target_files_dir: The name of a directory containing the special items
578 extracted from the other target files package.
579 output_target_files_dir: The name of a directory that will be used to create
580 the output target files package after all the special cases are processed.
581 file_name: The name of the file to merge. One of apkcerts.txt or
582 apexkeys.txt.
583 """
584
585 def read_helper(d):
586 temp = {}
587 file_path = os.path.join(d, 'META', file_name)
588 with open(file_path) as f:
589 for line in f:
590 if line.strip():
591 temp[line.split()[0]] = line.strip()
592 return temp
593
594 system_dict = read_helper(system_target_files_dir)
595 other_dict = read_helper(other_target_files_dir)
596
597 for key in system_dict:
598 if key in other_dict and other_dict[key] != system_dict[key]:
599 raise ValueError('Conflicting entries found in %s:\n %s and\n %s' %
600 (file_name, system_dict[key], other_dict[key]))
601 other_dict[key] = system_dict[key]
602
603 output_file = os.path.join(output_target_files_dir, 'META', file_name)
604
605 write_sorted_data(data=other_dict.values(), path=output_file)
Daniel Normana61cde02019-05-03 14:19:13 -0700606
607
Bill Peckham736b2232019-05-06 12:50:55 -0700608def process_special_cases(system_target_files_temp_dir,
Daniel Normane5b134a2019-04-17 14:54:06 -0700609 other_target_files_temp_dir,
610 output_target_files_temp_dir, system_misc_info_keys,
611 rebuild_recovery):
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800612 """Perform special-case processing for certain target files items.
613
614 Certain files in the output target files package require special-case
615 processing. This function performs all that special-case processing.
616
617 Args:
Daniel Normane5b134a2019-04-17 14:54:06 -0700618 system_target_files_temp_dir: The name of a directory containing the special
619 items extracted from the system target files package.
620 other_target_files_temp_dir: The name of a directory containing the special
621 items extracted from the other target files package.
622 output_target_files_temp_dir: The name of a directory that will be used to
623 create the output target files package after all the special cases are
624 processed.
625 system_misc_info_keys: A list of keys to obtain from the system instance of
626 META/misc_info.txt. The remaining keys from the other instance.
Bill Peckham364c1cc2019-03-29 18:27:23 -0700627 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
Daniel Normane5b134a2019-04-17 14:54:06 -0700628 devices and write it to the system image.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800629 """
630
Bill Peckham364c1cc2019-03-29 18:27:23 -0700631 if 'ab_update' in system_misc_info_keys:
632 process_ab_partitions_txt(
633 system_target_files_temp_dir=system_target_files_temp_dir,
634 other_target_files_temp_dir=other_target_files_temp_dir,
635 output_target_files_temp_dir=output_target_files_temp_dir)
636
637 if rebuild_recovery:
638 append_recovery_to_filesystem_config(
639 output_target_files_temp_dir=output_target_files_temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800640
641 process_misc_info_txt(
642 system_target_files_temp_dir=system_target_files_temp_dir,
643 other_target_files_temp_dir=other_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800644 output_target_files_temp_dir=output_target_files_temp_dir,
645 system_misc_info_keys=system_misc_info_keys)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800646
Daniel Normana61cde02019-05-03 14:19:13 -0700647 process_dynamic_partitions_info_txt(
Daniel Norman714bd122019-05-08 16:20:02 -0700648 system_target_files_dir=system_target_files_temp_dir,
649 other_target_files_dir=other_target_files_temp_dir,
650 output_target_files_dir=output_target_files_temp_dir)
Daniel Normana61cde02019-05-03 14:19:13 -0700651
Chris Grossfabf50a2019-05-02 12:42:09 -0700652 process_apex_keys_apk_certs_common(
653 system_target_files_dir=system_target_files_temp_dir,
654 other_target_files_dir=other_target_files_temp_dir,
655 output_target_files_dir=output_target_files_temp_dir,
656 file_name='apkcerts.txt')
657
658 process_apex_keys_apk_certs_common(
659 system_target_files_dir=system_target_files_temp_dir,
660 other_target_files_dir=other_target_files_temp_dir,
661 output_target_files_dir=output_target_files_temp_dir,
662 file_name='apexkeys.txt')
663
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800664
Daniel Normane5b134a2019-04-17 14:54:06 -0700665def merge_target_files(temp_dir, system_target_files, system_item_list,
666 system_misc_info_keys, other_target_files,
667 other_item_list, output_target_files, output_dir,
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700668 output_item_list, output_ota, output_img,
669 output_super_empty, rebuild_recovery):
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800670 """Merge two target files packages together.
671
672 This function takes system and other target files packages as input, performs
673 various file extractions, special case processing, and finally creates a
674 merged zip archive as output.
675
676 Args:
677 temp_dir: The name of a directory we use when we extract items from the
Daniel Normane5b134a2019-04-17 14:54:06 -0700678 input target files packages, and also a scratch directory that we use for
679 temporary files.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800680 system_target_files: The name of the zip archive containing the system
Daniel Normane5b134a2019-04-17 14:54:06 -0700681 partial target files package.
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800682 system_item_list: The list of items to extract from the partial system
Daniel Normane5b134a2019-04-17 14:54:06 -0700683 target files package as is, meaning these items will land in the output
684 target files package exactly as they appear in the input partial system
685 target files package.
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800686 system_misc_info_keys: The list of keys to obtain from the system instance
Daniel Normane5b134a2019-04-17 14:54:06 -0700687 of META/misc_info.txt. The remaining keys from the other instance.
688 other_target_files: The name of the zip archive containing the other partial
689 target files package.
690 other_item_list: The list of items to extract from the partial other target
691 files package as is, meaning these items will land in the output target
692 files package exactly as they appear in the input partial other target
693 files package.
694 output_target_files: The name of the output zip archive target files package
695 created by merging system and other.
696 output_dir: The destination directory for saving merged files.
697 output_item_list: The list of items to copy into the output_dir.
Daniel Norman3b64ce12019-04-16 16:11:35 -0700698 output_ota: The name of the output zip archive ota package.
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700699 output_img: The name of the output zip archive img package.
Daniel Normanf0318252019-04-15 11:34:56 -0700700 output_super_empty: If provided, creates a super_empty.img file from the
Daniel Normane5b134a2019-04-17 14:54:06 -0700701 merged target files package and saves it at this path.
Daniel Normana4911da2019-03-15 14:36:21 -0700702 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
Daniel Normane5b134a2019-04-17 14:54:06 -0700703 devices and write it to the system image.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800704 """
705
Daniel Normane5b134a2019-04-17 14:54:06 -0700706 logger.info('starting: merge system %s and other %s into output %s',
707 system_target_files, other_target_files, output_target_files)
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800708
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800709 # Create directory names that we'll use when we extract files from system,
710 # and other, and for zipping the final output.
711
712 system_target_files_temp_dir = os.path.join(temp_dir, 'system')
713 other_target_files_temp_dir = os.path.join(temp_dir, 'other')
714 output_target_files_temp_dir = os.path.join(temp_dir, 'output')
715
716 # Extract "as is" items from the input system partial target files package.
717 # We extract them directly into the output temporary directory since the
718 # items do not need special case processing.
719
Bill Peckham889b0c62019-02-21 18:53:37 -0800720 extract_items(
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800721 target_files=system_target_files,
722 target_files_temp_dir=output_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800723 extract_item_list=system_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800724
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800725 # Extract "as is" items from the input other partial target files package. We
726 # extract them directly into the output temporary directory since the items
727 # do not need special case processing.
728
Bill Peckham889b0c62019-02-21 18:53:37 -0800729 extract_items(
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800730 target_files=other_target_files,
731 target_files_temp_dir=output_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800732 extract_item_list=other_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800733
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800734 # Extract "special" items from the input system partial target files package.
735 # We extract these items to different directory since they require special
736 # processing before they will end up in the output directory.
737
Bill Peckham889b0c62019-02-21 18:53:37 -0800738 extract_items(
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800739 target_files=system_target_files,
740 target_files_temp_dir=system_target_files_temp_dir,
741 extract_item_list=system_extract_special_item_list)
742
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800743 # Extract "special" items from the input other partial target files package.
744 # We extract these items to different directory since they require special
745 # processing before they will end up in the output directory.
746
Bill Peckham889b0c62019-02-21 18:53:37 -0800747 extract_items(
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800748 target_files=other_target_files,
749 target_files_temp_dir=other_target_files_temp_dir,
750 extract_item_list=other_extract_special_item_list)
751
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800752 # Now that the temporary directories contain all the extracted files, perform
753 # special case processing on any items that need it. After this function
754 # completes successfully, all the files we need to create the output target
755 # files package are in place.
756
Bill Peckham889b0c62019-02-21 18:53:37 -0800757 process_special_cases(
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800758 system_target_files_temp_dir=system_target_files_temp_dir,
759 other_target_files_temp_dir=other_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800760 output_target_files_temp_dir=output_target_files_temp_dir,
Bill Peckham364c1cc2019-03-29 18:27:23 -0700761 system_misc_info_keys=system_misc_info_keys,
762 rebuild_recovery=rebuild_recovery)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800763
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800764 # Regenerate IMAGES in the temporary directory.
765
Daniel Normana4911da2019-03-15 14:36:21 -0700766 add_img_args = ['--verbose']
767 if rebuild_recovery:
768 add_img_args.append('--rebuild_recovery')
769 add_img_args.append(output_target_files_temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800770
771 add_img_to_target_files.main(add_img_args)
772
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700773 # Create super_empty.img using the merged misc_info.txt.
774
775 misc_info_txt = os.path.join(output_target_files_temp_dir, 'META',
776 'misc_info.txt')
777
778 def read_helper():
779 with open(misc_info_txt) as f:
780 return list(f.read().splitlines())
781
782 use_dynamic_partitions = common.LoadDictionaryFromLines(
783 read_helper()).get('use_dynamic_partitions')
784
785 if use_dynamic_partitions != 'true' and output_super_empty:
786 raise ValueError(
787 'Building super_empty.img requires use_dynamic_partitions=true.')
788 elif use_dynamic_partitions == 'true':
789 super_empty_img = os.path.join(output_target_files_temp_dir, 'IMAGES',
790 'super_empty.img')
791 build_super_image_args = [
792 misc_info_txt,
793 super_empty_img,
794 ]
795 build_super_image.main(build_super_image_args)
796
797 # Copy super_empty.img to the user-provided output_super_empty location.
798 if output_super_empty:
799 shutil.copyfile(super_empty_img, output_super_empty)
800
Daniel Normanb8a2f9d2019-04-24 12:55:51 -0700801 # Create the IMG package from the merged target files (before zipping, in
802 # order to avoid an unnecessary unzip and copy).
803
804 if output_img:
805 img_from_target_files_args = [
806 output_target_files_temp_dir,
807 output_img,
808 ]
809 img_from_target_files.main(img_from_target_files_args)
810
Daniel Normanfdb38812019-04-15 09:47:24 -0700811 # Finally, create the output target files zip archive and/or copy the
812 # output items to the output target files directory.
813
814 if output_dir:
815 copy_items(output_target_files_temp_dir, output_dir, output_item_list)
816
817 if not output_target_files:
818 return
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800819
820 output_zip = os.path.abspath(output_target_files)
821 output_target_files_list = os.path.join(temp_dir, 'output.list')
Daniel Normane5b134a2019-04-17 14:54:06 -0700822 output_target_files_meta_dir = os.path.join(output_target_files_temp_dir,
823 'META')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800824
Bill Peckham9662cfb2019-04-24 17:59:01 -0700825 find_command = [
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800826 'find',
827 output_target_files_meta_dir,
828 ]
Bill Peckham9662cfb2019-04-24 17:59:01 -0700829 find_process = common.Run(find_command, stdout=subprocess.PIPE, verbose=False)
Daniel Normana61cde02019-05-03 14:19:13 -0700830 meta_content = common.RunAndCheckOutput(['sort'],
831 stdin=find_process.stdout,
Bill Peckham9662cfb2019-04-24 17:59:01 -0700832 verbose=False)
833
834 find_command = [
Daniel Normane5b134a2019-04-17 14:54:06 -0700835 'find', output_target_files_temp_dir, '-path',
836 output_target_files_meta_dir, '-prune', '-o', '-print'
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800837 ]
Bill Peckham9662cfb2019-04-24 17:59:01 -0700838 find_process = common.Run(find_command, stdout=subprocess.PIPE, verbose=False)
Daniel Normana61cde02019-05-03 14:19:13 -0700839 other_content = common.RunAndCheckOutput(['sort'],
840 stdin=find_process.stdout,
Bill Peckham9662cfb2019-04-24 17:59:01 -0700841 verbose=False)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800842
843 with open(output_target_files_list, 'wb') as f:
844 f.write(meta_content)
845 f.write(other_content)
846
847 command = [
Bill Peckhamf753e152019-02-19 18:02:46 -0800848 'soong_zip',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800849 '-d',
Daniel Normane5b134a2019-04-17 14:54:06 -0700850 '-o',
851 output_zip,
852 '-C',
853 output_target_files_temp_dir,
854 '-l',
855 output_target_files_list,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800856 ]
857 logger.info('creating %s', output_target_files)
Bill Peckham889b0c62019-02-21 18:53:37 -0800858 common.RunAndWait(command, verbose=True)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800859
Daniel Norman3b64ce12019-04-16 16:11:35 -0700860 # Create the OTA package from the merged target files package.
861
862 if output_ota:
863 ota_from_target_files_args = [
864 output_zip,
865 output_ota,
866 ]
867 ota_from_target_files.main(ota_from_target_files_args)
868
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700869
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800870def call_func_with_temp_dir(func, keep_tmp):
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800871 """Manage the creation and cleanup of the temporary directory.
872
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800873 This function calls the given function after first creating a temporary
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800874 directory. It also cleans up the temporary directory.
875
876 Args:
Daniel Normane5b134a2019-04-17 14:54:06 -0700877 func: The function to call. Should accept one parameter, the path to the
878 temporary directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800879 keep_tmp: Keep the temporary directory after processing is complete.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800880 """
881
882 # Create a temporary directory. This will serve as the parent of directories
883 # we use when we extract items from the input target files packages, and also
884 # a scratch directory that we use for temporary files.
885
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800886 temp_dir = common.MakeTempDir(prefix='merge_target_files_')
887
888 try:
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800889 func(temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800890 except:
891 raise
892 finally:
893 if keep_tmp:
894 logger.info('keeping %s', temp_dir)
895 else:
896 common.Cleanup()
897
898
899def main():
900 """The main function.
901
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800902 Process command line arguments, then call merge_target_files to
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800903 perform the heavy lifting.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800904 """
905
906 common.InitLogging()
907
Bill Peckhamf753e152019-02-19 18:02:46 -0800908 def option_handler(o, a):
909 if o == '--system-target-files':
910 OPTIONS.system_target_files = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800911 elif o == '--system-item-list':
912 OPTIONS.system_item_list = a
913 elif o == '--system-misc-info-keys':
914 OPTIONS.system_misc_info_keys = a
Bill Peckhamf753e152019-02-19 18:02:46 -0800915 elif o == '--other-target-files':
916 OPTIONS.other_target_files = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800917 elif o == '--other-item-list':
918 OPTIONS.other_item_list = a
Bill Peckhamf753e152019-02-19 18:02:46 -0800919 elif o == '--output-target-files':
920 OPTIONS.output_target_files = a
Daniel Normanfdb38812019-04-15 09:47:24 -0700921 elif o == '--output-dir':
922 OPTIONS.output_dir = a
923 elif o == '--output-item-list':
924 OPTIONS.output_item_list = a
Daniel Norman3b64ce12019-04-16 16:11:35 -0700925 elif o == '--output-ota':
926 OPTIONS.output_ota = a
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700927 elif o == '--output-img':
928 OPTIONS.output_img = a
Daniel Normanf0318252019-04-15 11:34:56 -0700929 elif o == '--output-super-empty':
930 OPTIONS.output_super_empty = a
Daniel Normana4911da2019-03-15 14:36:21 -0700931 elif o == '--rebuild_recovery':
932 OPTIONS.rebuild_recovery = True
Bill Peckham364c1cc2019-03-29 18:27:23 -0700933 elif o == '--keep-tmp':
Bill Peckhamf753e152019-02-19 18:02:46 -0800934 OPTIONS.keep_tmp = True
935 else:
936 return False
937 return True
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800938
Bill Peckhamf753e152019-02-19 18:02:46 -0800939 args = common.ParseOptions(
Daniel Normane5b134a2019-04-17 14:54:06 -0700940 sys.argv[1:],
941 __doc__,
Bill Peckhamf753e152019-02-19 18:02:46 -0800942 extra_long_opts=[
943 'system-target-files=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800944 'system-item-list=',
945 'system-misc-info-keys=',
Bill Peckhamf753e152019-02-19 18:02:46 -0800946 'other-target-files=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800947 'other-item-list=',
Bill Peckhamf753e152019-02-19 18:02:46 -0800948 'output-target-files=',
Daniel Normanfdb38812019-04-15 09:47:24 -0700949 'output-dir=',
950 'output-item-list=',
Daniel Norman3b64ce12019-04-16 16:11:35 -0700951 'output-ota=',
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700952 'output-img=',
Daniel Normanf0318252019-04-15 11:34:56 -0700953 'output-super-empty=',
Daniel Normana4911da2019-03-15 14:36:21 -0700954 'rebuild_recovery',
Bill Peckham364c1cc2019-03-29 18:27:23 -0700955 'keep-tmp',
Bill Peckhamf753e152019-02-19 18:02:46 -0800956 ],
957 extra_option_handler=option_handler)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800958
Daniel Normane5b134a2019-04-17 14:54:06 -0700959 if (args or OPTIONS.system_target_files is None or
960 OPTIONS.other_target_files is None or
961 (OPTIONS.output_target_files is None and OPTIONS.output_dir is None) or
962 (OPTIONS.output_dir is not None and OPTIONS.output_item_list is None)):
Bill Peckhamf753e152019-02-19 18:02:46 -0800963 common.Usage(__doc__)
Bill Peckham889b0c62019-02-21 18:53:37 -0800964 sys.exit(1)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800965
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800966 if OPTIONS.system_item_list:
967 system_item_list = read_config_list(OPTIONS.system_item_list)
968 else:
969 system_item_list = default_system_item_list
970
971 if OPTIONS.system_misc_info_keys:
972 system_misc_info_keys = read_config_list(OPTIONS.system_misc_info_keys)
973 else:
974 system_misc_info_keys = default_system_misc_info_keys
975
976 if OPTIONS.other_item_list:
977 other_item_list = read_config_list(OPTIONS.other_item_list)
978 else:
979 other_item_list = default_other_item_list
980
Daniel Normanfdb38812019-04-15 09:47:24 -0700981 if OPTIONS.output_item_list:
982 output_item_list = read_config_list(OPTIONS.output_item_list)
983 else:
984 output_item_list = None
985
Daniel Normane5964522019-03-19 10:32:03 -0700986 if not validate_config_lists(
987 system_item_list=system_item_list,
Daniel Norman19b9fe92019-03-19 14:48:02 -0700988 system_misc_info_keys=system_misc_info_keys,
Daniel Normane5964522019-03-19 10:32:03 -0700989 other_item_list=other_item_list):
990 sys.exit(1)
991
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800992 call_func_with_temp_dir(
993 lambda temp_dir: merge_target_files(
994 temp_dir=temp_dir,
995 system_target_files=OPTIONS.system_target_files,
996 system_item_list=system_item_list,
997 system_misc_info_keys=system_misc_info_keys,
998 other_target_files=OPTIONS.other_target_files,
999 other_item_list=other_item_list,
Daniel Normana4911da2019-03-15 14:36:21 -07001000 output_target_files=OPTIONS.output_target_files,
Daniel Normanfdb38812019-04-15 09:47:24 -07001001 output_dir=OPTIONS.output_dir,
1002 output_item_list=output_item_list,
Daniel Norman3b64ce12019-04-16 16:11:35 -07001003 output_ota=OPTIONS.output_ota,
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001004 output_img=OPTIONS.output_img,
Daniel Normanf0318252019-04-15 11:34:56 -07001005 output_super_empty=OPTIONS.output_super_empty,
Daniel Normane5b134a2019-04-17 14:54:06 -07001006 rebuild_recovery=OPTIONS.rebuild_recovery), OPTIONS.keep_tmp)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001007
1008
1009if __name__ == '__main__':
Bill Peckham889b0c62019-02-21 18:53:37 -08001010 main()