blob: e8c3cf7efc0c631f02be0206b1df79ab642319ba [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',
163 'META/otakeys.txt',
164 'META/releasetools.py',
165 'META/vendor_filesystem_config.txt',
166 'META/vendor_manifest.xml',
167 'META/vendor_matrix.xml',
168 'BOOT/*',
169 'DATA/*',
170 'ODM/*',
171 'OTA/android-info.txt',
172 'PREBUILT_IMAGES/*',
173 'RADIO/*',
174 'VENDOR/*',
175]
176
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800177# other_extract_special_item_list is a list of items to extract from the
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800178# partial other target files package that need some special processing, such as
179# some sort of combination with items from the partial system target files
180# package.
181
182other_extract_special_item_list = [
183 'META/*',
184]
185
186
Chris Grossfabf50a2019-05-02 12:42:09 -0700187def write_sorted_data(data, path):
188 """Write the sorted contents of either a list or dict to file.
189
190 This function sorts the contents of the list or dict and then
191 writes the resulting sorted contents to a file specified by path.
192
193 Args:
194 data: The list or dict to sort and write.
195 path: Path to the file to write the sorted values to. The file at path will
196 be overridden if it exists.
197 """
198 with open(path, 'w') as output:
199 sorted_data = sorted(data.keys()) if isinstance(data,
200 dict) else sorted(data)
201 for entry in sorted_data:
202 out_str = '{}={}\n'.format(entry, data[entry]) if isinstance(
203 data, dict) else '{}\n'.format(entry)
204 output.write(out_str)
205
206
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800207def extract_items(target_files, target_files_temp_dir, extract_item_list):
208 """Extract items from target files to temporary directory.
209
210 This function extracts from the specified target files zip archive into the
211 specified temporary directory, the items specified in the extract item list.
212
213 Args:
214 target_files: The target files zip archive from which to extract items.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800215 target_files_temp_dir: The temporary directory where the extracted items
Daniel Normane5b134a2019-04-17 14:54:06 -0700216 will land.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800217 extract_item_list: A list of items to extract.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800218 """
219
220 logger.info('extracting from %s', target_files)
221
222 # Filter the extract_item_list to remove any items that do not exist in the
223 # zip file. Otherwise, the extraction step will fail.
224
225 with zipfile.ZipFile(
Daniel Normane5b134a2019-04-17 14:54:06 -0700226 target_files, 'r', allowZip64=True) as target_files_zipfile:
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800227 target_files_namelist = target_files_zipfile.namelist()
228
229 filtered_extract_item_list = []
230 for pattern in extract_item_list:
231 matching_namelist = fnmatch.filter(target_files_namelist, pattern)
232 if not matching_namelist:
233 logger.warning('no match for %s', pattern)
234 else:
235 filtered_extract_item_list.append(pattern)
236
Bill Peckham8ff3fbd2019-02-22 10:57:43 -0800237 # Extract from target_files into target_files_temp_dir the
238 # filtered_extract_item_list.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800239
Daniel Normane5b134a2019-04-17 14:54:06 -0700240 common.UnzipToDir(target_files, target_files_temp_dir,
241 filtered_extract_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800242
243
Daniel Normanfdb38812019-04-15 09:47:24 -0700244def copy_items(from_dir, to_dir, patterns):
245 """Similar to extract_items() except uses an input dir instead of zip."""
246 file_paths = []
247 for dirpath, _, filenames in os.walk(from_dir):
Daniel Normane5b134a2019-04-17 14:54:06 -0700248 file_paths.extend(
249 os.path.relpath(path=os.path.join(dirpath, filename), start=from_dir)
250 for filename in filenames)
Daniel Normanfdb38812019-04-15 09:47:24 -0700251
252 filtered_file_paths = set()
253 for pattern in patterns:
254 filtered_file_paths.update(fnmatch.filter(file_paths, pattern))
255
256 for file_path in filtered_file_paths:
257 original_file_path = os.path.join(from_dir, file_path)
258 copied_file_path = os.path.join(to_dir, file_path)
259 copied_file_dir = os.path.dirname(copied_file_path)
260 if not os.path.exists(copied_file_dir):
261 os.makedirs(copied_file_dir)
262 if os.path.islink(original_file_path):
263 os.symlink(os.readlink(original_file_path), copied_file_path)
264 else:
265 shutil.copyfile(original_file_path, copied_file_path)
266
267
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800268def read_config_list(config_file_path):
269 """Reads a config file into a list of strings.
270
271 Expects the file to be newline-separated.
272
273 Args:
274 config_file_path: The path to the config file to open and read.
Daniel Normane5b134a2019-04-17 14:54:06 -0700275
276 Returns:
277 The list of strings in the config file.
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800278 """
279 with open(config_file_path) as config_file:
280 return config_file.read().splitlines()
281
282
Daniel Normane5b134a2019-04-17 14:54:06 -0700283def validate_config_lists(system_item_list, system_misc_info_keys,
284 other_item_list):
Daniel Normane5964522019-03-19 10:32:03 -0700285 """Performs validations on the merge config lists.
286
287 Args:
Daniel Normane5b134a2019-04-17 14:54:06 -0700288 system_item_list: The list of items to extract from the partial system
289 target files package as is.
290 system_misc_info_keys: A list of keys to obtain from the system instance of
291 META/misc_info.txt. The remaining keys from the other instance.
292 other_item_list: The list of items to extract from the partial other target
293 files package as is.
Daniel Normane5964522019-03-19 10:32:03 -0700294
295 Returns:
296 False if a validation fails, otherwise true.
297 """
298 default_combined_item_set = set(default_system_item_list)
299 default_combined_item_set.update(default_other_item_list)
300
301 combined_item_set = set(system_item_list)
302 combined_item_set.update(other_item_list)
303
304 # Check that the merge config lists are not missing any item specified
305 # by the default config lists.
306 difference = default_combined_item_set.difference(combined_item_set)
307 if difference:
Daniel Normane5b134a2019-04-17 14:54:06 -0700308 logger.error('Missing merge config items: %s', list(difference))
Daniel Normane5964522019-03-19 10:32:03 -0700309 logger.error('Please ensure missing items are in either the '
310 'system-item-list or other-item-list files provided to '
311 'this script.')
312 return False
313
Daniel Norman19b9fe92019-03-19 14:48:02 -0700314 if ('dynamic_partition_list' in system_misc_info_keys) or (
315 'super_partition_groups' in system_misc_info_keys):
316 logger.error('Dynamic partition misc info keys should come from '
317 'the other instance of META/misc_info.txt.')
318 return False
319
Daniel Normane5964522019-03-19 10:32:03 -0700320 return True
321
322
Daniel Normane5b134a2019-04-17 14:54:06 -0700323def process_ab_partitions_txt(system_target_files_temp_dir,
324 other_target_files_temp_dir,
325 output_target_files_temp_dir):
326 """Perform special processing for META/ab_partitions.txt.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800327
328 This function merges the contents of the META/ab_partitions.txt files from
329 the system directory and the other directory, placing the merged result in
330 the output directory. The precondition in that the files are already
331 extracted. The post condition is that the output META/ab_partitions.txt
332 contains the merged content. The format for each ab_partitions.txt a one
333 partition name per line. The output file contains the union of the parition
334 names.
335
336 Args:
Daniel Normane5b134a2019-04-17 14:54:06 -0700337 system_target_files_temp_dir: The name of a directory containing the special
338 items extracted from the system target files package.
339 other_target_files_temp_dir: The name of a directory containing the special
340 items extracted from the other target files package.
341 output_target_files_temp_dir: The name of a directory that will be used to
342 create the output target files package after all the special cases are
343 processed.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800344 """
345
Daniel Normane5b134a2019-04-17 14:54:06 -0700346 system_ab_partitions_txt = os.path.join(system_target_files_temp_dir, 'META',
347 'ab_partitions.txt')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800348
Daniel Normane5b134a2019-04-17 14:54:06 -0700349 other_ab_partitions_txt = os.path.join(other_target_files_temp_dir, 'META',
350 'ab_partitions.txt')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800351
352 with open(system_ab_partitions_txt) as f:
353 system_ab_partitions = f.read().splitlines()
354
355 with open(other_ab_partitions_txt) as f:
356 other_ab_partitions = f.read().splitlines()
357
358 output_ab_partitions = set(system_ab_partitions + other_ab_partitions)
359
Daniel Normane5b134a2019-04-17 14:54:06 -0700360 output_ab_partitions_txt = os.path.join(output_target_files_temp_dir, 'META',
361 'ab_partitions.txt')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800362
Chris Grossfabf50a2019-05-02 12:42:09 -0700363 write_sorted_data(data=output_ab_partitions, path=output_ab_partitions_txt)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800364
365
Bill Peckham364c1cc2019-03-29 18:27:23 -0700366def append_recovery_to_filesystem_config(output_target_files_temp_dir):
Daniel Normane5b134a2019-04-17 14:54:06 -0700367 """Perform special processing for META/filesystem_config.txt.
Bill Peckham364c1cc2019-03-29 18:27:23 -0700368
369 This function appends recovery information to META/filesystem_config.txt
370 so that recovery patch regeneration will succeed.
371
372 Args:
Daniel Normane5b134a2019-04-17 14:54:06 -0700373 output_target_files_temp_dir: The name of a directory that will be used to
374 create the output target files package after all the special cases are
375 processed. We find filesystem_config.txt here.
Bill Peckham364c1cc2019-03-29 18:27:23 -0700376 """
377
Daniel Normane5b134a2019-04-17 14:54:06 -0700378 filesystem_config_txt = os.path.join(output_target_files_temp_dir, 'META',
379 'filesystem_config.txt')
Bill Peckham364c1cc2019-03-29 18:27:23 -0700380
381 with open(filesystem_config_txt, 'a') as f:
382 # TODO(bpeckham) this data is hard coded. It should be generated
383 # programmatically.
Daniel Normane5b134a2019-04-17 14:54:06 -0700384 f.write('system/bin/install-recovery.sh 0 0 750 '
385 'selabel=u:object_r:install_recovery_exec:s0 capabilities=0x0\n')
386 f.write('system/recovery-from-boot.p 0 0 644 '
387 'selabel=u:object_r:system_file:s0 capabilities=0x0\n')
388 f.write('system/etc/recovery.img 0 0 440 '
389 'selabel=u:object_r:install_recovery_exec:s0 capabilities=0x0\n')
Bill Peckham364c1cc2019-03-29 18:27:23 -0700390
391
Daniel Normana61cde02019-05-03 14:19:13 -0700392def merge_dynamic_partition_info_dicts(system_dict,
393 other_dict,
394 include_dynamic_partition_list=True,
395 size_prefix='',
396 size_suffix='',
397 list_prefix='',
398 list_suffix=''):
399 """Merges dynamic partition info variables.
400
401 Args:
402 system_dict: The dictionary of dynamic partition info variables from the
403 partial system target files.
404 other_dict: The dictionary of dynamic partition info variables from the
405 partial other target files.
406 include_dynamic_partition_list: If true, merges the dynamic_partition_list
407 variable. Not all use cases need this variable merged.
408 size_prefix: The prefix in partition group size variables that precedes the
409 name of the partition group. For example, partition group 'group_a' with
410 corresponding size variable 'super_group_a_group_size' would have the
411 size_prefix 'super_'.
412 size_suffix: Similar to size_prefix but for the variable's suffix. For
413 example, 'super_group_a_group_size' would have size_suffix '_group_size'.
414 list_prefix: Similar to size_prefix but for the partition group's
415 partition_list variable.
416 list_suffix: Similar to size_suffix but for the partition group's
417 partition_list variable.
418
419 Returns:
420 The merged dynamic partition info dictionary.
421 """
422 merged_dict = {}
423 # Partition groups and group sizes are defined by the other (non-system)
424 # dict because these values may vary for each board that uses a shared system
425 # image.
426 merged_dict['super_partition_groups'] = other_dict['super_partition_groups']
427 if include_dynamic_partition_list:
428 system_dynamic_partition_list = system_dict.get('dynamic_partition_list',
429 '')
430 other_dynamic_partition_list = other_dict.get('dynamic_partition_list', '')
431 merged_dict['dynamic_partition_list'] = (
432 '%s %s' %
433 (system_dynamic_partition_list, other_dynamic_partition_list)).strip()
434 for partition_group in merged_dict['super_partition_groups'].split(' '):
435 # Set the partition group's size using the value from the other dict.
436 key = '%s%s%s' % (size_prefix, partition_group, size_suffix)
437 if key not in other_dict:
438 raise ValueError('Other dict does not contain required key %s.' % key)
439 merged_dict[key] = other_dict[key]
440
441 # Set the partition group's partition list using a concatenation of the
442 # system and other partition lists.
443 key = '%s%s%s' % (list_prefix, partition_group, list_suffix)
444 merged_dict[key] = (
445 '%s %s' % (system_dict.get(key, ''), other_dict.get(key, ''))).strip()
446 return merged_dict
447
448
Daniel Normane5b134a2019-04-17 14:54:06 -0700449def process_misc_info_txt(system_target_files_temp_dir,
450 other_target_files_temp_dir,
451 output_target_files_temp_dir, system_misc_info_keys):
452 """Perform special processing for META/misc_info.txt.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800453
454 This function merges the contents of the META/misc_info.txt files from the
455 system directory and the other directory, placing the merged result in the
456 output directory. The precondition in that the files are already extracted.
457 The post condition is that the output META/misc_info.txt contains the merged
458 content.
459
460 Args:
Daniel Normane5b134a2019-04-17 14:54:06 -0700461 system_target_files_temp_dir: The name of a directory containing the special
462 items extracted from the system target files package.
463 other_target_files_temp_dir: The name of a directory containing the special
464 items extracted from the other target files package.
465 output_target_files_temp_dir: The name of a directory that will be used to
466 create the output target files package after all the special cases are
467 processed.
468 system_misc_info_keys: A list of keys to obtain from the system instance of
469 META/misc_info.txt. The remaining keys from the other instance.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800470 """
471
472 def read_helper(d):
473 misc_info_txt = os.path.join(d, 'META', 'misc_info.txt')
474 with open(misc_info_txt) as f:
475 return list(f.read().splitlines())
476
477 system_info_dict = common.LoadDictionaryFromLines(
478 read_helper(system_target_files_temp_dir))
479
480 # We take most of the misc info from the other target files.
481
482 merged_info_dict = common.LoadDictionaryFromLines(
483 read_helper(other_target_files_temp_dir))
484
485 # Replace certain values in merged_info_dict with values from
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800486 # system_info_dict.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800487
488 for key in system_misc_info_keys:
489 merged_info_dict[key] = system_info_dict[key]
490
Daniel Norman19b9fe92019-03-19 14:48:02 -0700491 # Merge misc info keys used for Dynamic Partitions.
492 if (merged_info_dict.get('use_dynamic_partitions') == 'true') and (
493 system_info_dict.get('use_dynamic_partitions') == 'true'):
Daniel Normana61cde02019-05-03 14:19:13 -0700494 merged_dynamic_partitions_dict = merge_dynamic_partition_info_dicts(
495 system_dict=system_info_dict,
496 other_dict=merged_info_dict,
497 size_prefix='super_',
498 size_suffix='_group_size',
499 list_prefix='super_',
500 list_suffix='_partition_list')
501 merged_info_dict.update(merged_dynamic_partitions_dict)
Daniel Norman19b9fe92019-03-19 14:48:02 -0700502
Daniel Norman72c626f2019-05-13 15:58:14 -0700503 # Replace <image>_selinux_fc values with system or other file_contexts.bin
504 # depending on which dictionary the key came from.
505 # Only the file basename is required because all selinux_fc properties are
506 # replaced with the full path to the file under META/ when misc_info.txt is
507 # loaded from target files for repacking. See common.py LoadInfoDict().
508 for key in merged_info_dict:
509 if key.endswith('_selinux_fc'):
510 merged_info_dict[key] = 'other_file_contexts.bin'
511 for key in system_info_dict:
512 if key.endswith('_selinux_fc'):
513 merged_info_dict[key] = 'system_file_contexts.bin'
514
Daniel Normane5b134a2019-04-17 14:54:06 -0700515 output_misc_info_txt = os.path.join(output_target_files_temp_dir, 'META',
516 'misc_info.txt')
Chris Grossfabf50a2019-05-02 12:42:09 -0700517 write_sorted_data(data=merged_info_dict, path=output_misc_info_txt)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800518
519
Daniel Normana61cde02019-05-03 14:19:13 -0700520def process_dynamic_partitions_info_txt(system_target_files_dir,
521 other_target_files_dir,
522 output_target_files_dir):
523 """Perform special processing for META/dynamic_partitions_info.txt.
524
525 This function merges the contents of the META/dynamic_partitions_info.txt
526 files from the system directory and the other directory, placing the merged
527 result in the output directory.
528
529 This function does nothing if META/dynamic_partitions_info.txt from the other
530 directory does not exist.
531
532 Args:
533 system_target_files_dir: The name of a directory containing the special
534 items extracted from the system target files package.
535 other_target_files_dir: The name of a directory containing the special items
536 extracted from the other target files package.
537 output_target_files_dir: The name of a directory that will be used to create
538 the output target files package after all the special cases are processed.
539 """
540
541 if not os.path.exists(
542 os.path.join(other_target_files_dir, 'META',
543 'dynamic_partitions_info.txt')):
544 return
545
546 def read_helper(d):
547 dynamic_partitions_info_txt = os.path.join(d, 'META',
548 'dynamic_partitions_info.txt')
549 with open(dynamic_partitions_info_txt) as f:
550 return list(f.read().splitlines())
551
552 system_dynamic_partitions_dict = common.LoadDictionaryFromLines(
553 read_helper(system_target_files_dir))
554 other_dynamic_partitions_dict = common.LoadDictionaryFromLines(
555 read_helper(other_target_files_dir))
556
557 merged_dynamic_partitions_dict = merge_dynamic_partition_info_dicts(
558 system_dict=system_dynamic_partitions_dict,
559 other_dict=other_dynamic_partitions_dict,
560 # META/dynamic_partitions_info.txt does not use dynamic_partition_list.
561 include_dynamic_partition_list=False,
562 size_suffix='_size',
563 list_suffix='_partition_list')
564
565 output_dynamic_partitions_info_txt = os.path.join(
566 output_target_files_dir, 'META', 'dynamic_partitions_info.txt')
Chris Grossfabf50a2019-05-02 12:42:09 -0700567 write_sorted_data(
568 data=merged_dynamic_partitions_dict,
569 path=output_dynamic_partitions_info_txt)
570
571
572def process_apex_keys_apk_certs_common(system_target_files_dir,
573 other_target_files_dir,
574 output_target_files_dir, file_name):
575 """Perform special processing for META/apexkeys.txt or META/apkcerts.txt.
576
577 This function merges the contents of the META/apexkeys.txt or
578 META/apkcerts.txt
579 files from the system directory and the other directory, placing the merged
580 result in the output directory. The precondition in that the files are already
581 extracted.
582 The post condition is that the output META/apexkeys.txt or META/apkcerts.txt
583 contains the merged content.
584
585 Args:
586 system_target_files_dir: The name of a directory containing the special
587 items extracted from the system target files package.
588 other_target_files_dir: The name of a directory containing the special items
589 extracted from the other target files package.
590 output_target_files_dir: The name of a directory that will be used to create
591 the output target files package after all the special cases are processed.
592 file_name: The name of the file to merge. One of apkcerts.txt or
593 apexkeys.txt.
594 """
595
596 def read_helper(d):
597 temp = {}
598 file_path = os.path.join(d, 'META', file_name)
599 with open(file_path) as f:
600 for line in f:
601 if line.strip():
602 temp[line.split()[0]] = line.strip()
603 return temp
604
605 system_dict = read_helper(system_target_files_dir)
606 other_dict = read_helper(other_target_files_dir)
607
608 for key in system_dict:
609 if key in other_dict and other_dict[key] != system_dict[key]:
610 raise ValueError('Conflicting entries found in %s:\n %s and\n %s' %
611 (file_name, system_dict[key], other_dict[key]))
612 other_dict[key] = system_dict[key]
613
614 output_file = os.path.join(output_target_files_dir, 'META', file_name)
615
616 write_sorted_data(data=other_dict.values(), path=output_file)
Daniel Normana61cde02019-05-03 14:19:13 -0700617
618
Daniel Norman72c626f2019-05-13 15:58:14 -0700619def copy_file_contexts(system_target_files_dir, other_target_files_dir,
620 output_target_files_dir):
621 """Creates named copies of each build's file_contexts.bin in output META/."""
622 system_fc_path = os.path.join(system_target_files_dir, 'META', 'system_file_contexts.bin')
623 if not os.path.exists(system_fc_path):
624 system_fc_path = os.path.join(system_target_files_dir, 'META', 'file_contexts.bin')
625 if not os.path.exists(system_fc_path):
626 raise ValueError('Missing system file_contexts.bin.')
627 shutil.copyfile(
628 system_fc_path,
629 os.path.join(output_target_files_dir, 'META', 'system_file_contexts.bin'))
630
631 other_fc_path = os.path.join(other_target_files_dir, 'META', 'other_file_contexts.bin')
632 if not os.path.exists(other_fc_path):
633 other_fc_path = os.path.join(other_target_files_dir, 'META', 'file_contexts.bin')
634 if not os.path.exists(other_fc_path):
635 raise ValueError('Missing other file_contexts.bin.')
636 shutil.copyfile(
637 other_fc_path,
638 os.path.join(output_target_files_dir, 'META', 'other_file_contexts.bin'))
639
640
Bill Peckham736b2232019-05-06 12:50:55 -0700641def process_special_cases(system_target_files_temp_dir,
Daniel Normane5b134a2019-04-17 14:54:06 -0700642 other_target_files_temp_dir,
643 output_target_files_temp_dir, system_misc_info_keys,
644 rebuild_recovery):
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800645 """Perform special-case processing for certain target files items.
646
647 Certain files in the output target files package require special-case
648 processing. This function performs all that special-case processing.
649
650 Args:
Daniel Normane5b134a2019-04-17 14:54:06 -0700651 system_target_files_temp_dir: The name of a directory containing the special
652 items extracted from the system target files package.
653 other_target_files_temp_dir: The name of a directory containing the special
654 items extracted from the other target files package.
655 output_target_files_temp_dir: The name of a directory that will be used to
656 create the output target files package after all the special cases are
657 processed.
658 system_misc_info_keys: A list of keys to obtain from the system instance of
659 META/misc_info.txt. The remaining keys from the other instance.
Bill Peckham364c1cc2019-03-29 18:27:23 -0700660 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
Daniel Normane5b134a2019-04-17 14:54:06 -0700661 devices and write it to the system image.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800662 """
663
Bill Peckham364c1cc2019-03-29 18:27:23 -0700664 if 'ab_update' in system_misc_info_keys:
665 process_ab_partitions_txt(
666 system_target_files_temp_dir=system_target_files_temp_dir,
667 other_target_files_temp_dir=other_target_files_temp_dir,
668 output_target_files_temp_dir=output_target_files_temp_dir)
669
670 if rebuild_recovery:
671 append_recovery_to_filesystem_config(
672 output_target_files_temp_dir=output_target_files_temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800673
Daniel Norman72c626f2019-05-13 15:58:14 -0700674 copy_file_contexts(
675 system_target_files_dir=system_target_files_temp_dir,
676 other_target_files_dir=other_target_files_temp_dir,
677 output_target_files_dir=output_target_files_temp_dir)
678
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800679 process_misc_info_txt(
680 system_target_files_temp_dir=system_target_files_temp_dir,
681 other_target_files_temp_dir=other_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800682 output_target_files_temp_dir=output_target_files_temp_dir,
683 system_misc_info_keys=system_misc_info_keys)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800684
Daniel Normana61cde02019-05-03 14:19:13 -0700685 process_dynamic_partitions_info_txt(
Daniel Norman714bd122019-05-08 16:20:02 -0700686 system_target_files_dir=system_target_files_temp_dir,
687 other_target_files_dir=other_target_files_temp_dir,
688 output_target_files_dir=output_target_files_temp_dir)
Daniel Normana61cde02019-05-03 14:19:13 -0700689
Chris Grossfabf50a2019-05-02 12:42:09 -0700690 process_apex_keys_apk_certs_common(
691 system_target_files_dir=system_target_files_temp_dir,
692 other_target_files_dir=other_target_files_temp_dir,
693 output_target_files_dir=output_target_files_temp_dir,
694 file_name='apkcerts.txt')
695
696 process_apex_keys_apk_certs_common(
697 system_target_files_dir=system_target_files_temp_dir,
698 other_target_files_dir=other_target_files_temp_dir,
699 output_target_files_dir=output_target_files_temp_dir,
700 file_name='apexkeys.txt')
701
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800702
Daniel Normane5b134a2019-04-17 14:54:06 -0700703def merge_target_files(temp_dir, system_target_files, system_item_list,
704 system_misc_info_keys, other_target_files,
705 other_item_list, output_target_files, output_dir,
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700706 output_item_list, output_ota, output_img,
707 output_super_empty, rebuild_recovery):
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800708 """Merge two target files packages together.
709
710 This function takes system and other target files packages as input, performs
711 various file extractions, special case processing, and finally creates a
712 merged zip archive as output.
713
714 Args:
715 temp_dir: The name of a directory we use when we extract items from the
Daniel Normane5b134a2019-04-17 14:54:06 -0700716 input target files packages, and also a scratch directory that we use for
717 temporary files.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800718 system_target_files: The name of the zip archive containing the system
Daniel Normane5b134a2019-04-17 14:54:06 -0700719 partial target files package.
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800720 system_item_list: The list of items to extract from the partial system
Daniel Normane5b134a2019-04-17 14:54:06 -0700721 target files package as is, meaning these items will land in the output
722 target files package exactly as they appear in the input partial system
723 target files package.
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800724 system_misc_info_keys: The list of keys to obtain from the system instance
Daniel Normane5b134a2019-04-17 14:54:06 -0700725 of META/misc_info.txt. The remaining keys from the other instance.
726 other_target_files: The name of the zip archive containing the other partial
727 target files package.
728 other_item_list: The list of items to extract from the partial other target
729 files package as is, meaning these items will land in the output target
730 files package exactly as they appear in the input partial other target
731 files package.
732 output_target_files: The name of the output zip archive target files package
733 created by merging system and other.
734 output_dir: The destination directory for saving merged files.
735 output_item_list: The list of items to copy into the output_dir.
Daniel Norman3b64ce12019-04-16 16:11:35 -0700736 output_ota: The name of the output zip archive ota package.
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700737 output_img: The name of the output zip archive img package.
Daniel Normanf0318252019-04-15 11:34:56 -0700738 output_super_empty: If provided, creates a super_empty.img file from the
Daniel Normane5b134a2019-04-17 14:54:06 -0700739 merged target files package and saves it at this path.
Daniel Normana4911da2019-03-15 14:36:21 -0700740 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
Daniel Normane5b134a2019-04-17 14:54:06 -0700741 devices and write it to the system image.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800742 """
743
Daniel Normane5b134a2019-04-17 14:54:06 -0700744 logger.info('starting: merge system %s and other %s into output %s',
745 system_target_files, other_target_files, output_target_files)
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800746
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800747 # Create directory names that we'll use when we extract files from system,
748 # and other, and for zipping the final output.
749
750 system_target_files_temp_dir = os.path.join(temp_dir, 'system')
751 other_target_files_temp_dir = os.path.join(temp_dir, 'other')
752 output_target_files_temp_dir = os.path.join(temp_dir, 'output')
753
754 # Extract "as is" items from the input system partial target files package.
755 # We extract them directly into the output temporary directory since the
756 # items do not need special case processing.
757
Bill Peckham889b0c62019-02-21 18:53:37 -0800758 extract_items(
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800759 target_files=system_target_files,
760 target_files_temp_dir=output_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800761 extract_item_list=system_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800762
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800763 # Extract "as is" items from the input other partial target files package. We
764 # extract them directly into the output temporary directory since the items
765 # do not need special case processing.
766
Bill Peckham889b0c62019-02-21 18:53:37 -0800767 extract_items(
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800768 target_files=other_target_files,
769 target_files_temp_dir=output_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800770 extract_item_list=other_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800771
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800772 # Extract "special" items from the input system partial target files package.
773 # We extract these items to different directory since they require special
774 # processing before they will end up in the output directory.
775
Bill Peckham889b0c62019-02-21 18:53:37 -0800776 extract_items(
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800777 target_files=system_target_files,
778 target_files_temp_dir=system_target_files_temp_dir,
779 extract_item_list=system_extract_special_item_list)
780
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800781 # Extract "special" items from the input other partial target files package.
782 # We extract these items to different directory since they require special
783 # processing before they will end up in the output directory.
784
Bill Peckham889b0c62019-02-21 18:53:37 -0800785 extract_items(
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800786 target_files=other_target_files,
787 target_files_temp_dir=other_target_files_temp_dir,
788 extract_item_list=other_extract_special_item_list)
789
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800790 # Now that the temporary directories contain all the extracted files, perform
791 # special case processing on any items that need it. After this function
792 # completes successfully, all the files we need to create the output target
793 # files package are in place.
794
Bill Peckham889b0c62019-02-21 18:53:37 -0800795 process_special_cases(
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800796 system_target_files_temp_dir=system_target_files_temp_dir,
797 other_target_files_temp_dir=other_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800798 output_target_files_temp_dir=output_target_files_temp_dir,
Bill Peckham364c1cc2019-03-29 18:27:23 -0700799 system_misc_info_keys=system_misc_info_keys,
800 rebuild_recovery=rebuild_recovery)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800801
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800802 # Regenerate IMAGES in the temporary directory.
803
Daniel Normana4911da2019-03-15 14:36:21 -0700804 add_img_args = ['--verbose']
805 if rebuild_recovery:
806 add_img_args.append('--rebuild_recovery')
807 add_img_args.append(output_target_files_temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800808
809 add_img_to_target_files.main(add_img_args)
810
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700811 # Create super_empty.img using the merged misc_info.txt.
812
813 misc_info_txt = os.path.join(output_target_files_temp_dir, 'META',
814 'misc_info.txt')
815
816 def read_helper():
817 with open(misc_info_txt) as f:
818 return list(f.read().splitlines())
819
820 use_dynamic_partitions = common.LoadDictionaryFromLines(
821 read_helper()).get('use_dynamic_partitions')
822
823 if use_dynamic_partitions != 'true' and output_super_empty:
824 raise ValueError(
825 'Building super_empty.img requires use_dynamic_partitions=true.')
826 elif use_dynamic_partitions == 'true':
827 super_empty_img = os.path.join(output_target_files_temp_dir, 'IMAGES',
828 'super_empty.img')
829 build_super_image_args = [
830 misc_info_txt,
831 super_empty_img,
832 ]
833 build_super_image.main(build_super_image_args)
834
835 # Copy super_empty.img to the user-provided output_super_empty location.
836 if output_super_empty:
837 shutil.copyfile(super_empty_img, output_super_empty)
838
Daniel Normanb8a2f9d2019-04-24 12:55:51 -0700839 # Create the IMG package from the merged target files (before zipping, in
840 # order to avoid an unnecessary unzip and copy).
841
842 if output_img:
843 img_from_target_files_args = [
844 output_target_files_temp_dir,
845 output_img,
846 ]
847 img_from_target_files.main(img_from_target_files_args)
848
Daniel Normanfdb38812019-04-15 09:47:24 -0700849 # Finally, create the output target files zip archive and/or copy the
850 # output items to the output target files directory.
851
852 if output_dir:
853 copy_items(output_target_files_temp_dir, output_dir, output_item_list)
854
855 if not output_target_files:
856 return
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800857
858 output_zip = os.path.abspath(output_target_files)
859 output_target_files_list = os.path.join(temp_dir, 'output.list')
Daniel Normane5b134a2019-04-17 14:54:06 -0700860 output_target_files_meta_dir = os.path.join(output_target_files_temp_dir,
861 'META')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800862
Bill Peckham9662cfb2019-04-24 17:59:01 -0700863 find_command = [
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800864 'find',
865 output_target_files_meta_dir,
866 ]
Bill Peckham9662cfb2019-04-24 17:59:01 -0700867 find_process = common.Run(find_command, stdout=subprocess.PIPE, verbose=False)
Daniel Normana61cde02019-05-03 14:19:13 -0700868 meta_content = common.RunAndCheckOutput(['sort'],
869 stdin=find_process.stdout,
Bill Peckham9662cfb2019-04-24 17:59:01 -0700870 verbose=False)
871
872 find_command = [
Daniel Normane5b134a2019-04-17 14:54:06 -0700873 'find', output_target_files_temp_dir, '-path',
874 output_target_files_meta_dir, '-prune', '-o', '-print'
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800875 ]
Bill Peckham9662cfb2019-04-24 17:59:01 -0700876 find_process = common.Run(find_command, stdout=subprocess.PIPE, verbose=False)
Daniel Normana61cde02019-05-03 14:19:13 -0700877 other_content = common.RunAndCheckOutput(['sort'],
878 stdin=find_process.stdout,
Bill Peckham9662cfb2019-04-24 17:59:01 -0700879 verbose=False)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800880
881 with open(output_target_files_list, 'wb') as f:
882 f.write(meta_content)
883 f.write(other_content)
884
885 command = [
Bill Peckhamf753e152019-02-19 18:02:46 -0800886 'soong_zip',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800887 '-d',
Daniel Normane5b134a2019-04-17 14:54:06 -0700888 '-o',
889 output_zip,
890 '-C',
891 output_target_files_temp_dir,
892 '-l',
893 output_target_files_list,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800894 ]
895 logger.info('creating %s', output_target_files)
Bill Peckham889b0c62019-02-21 18:53:37 -0800896 common.RunAndWait(command, verbose=True)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800897
Daniel Norman3b64ce12019-04-16 16:11:35 -0700898 # Create the OTA package from the merged target files package.
899
900 if output_ota:
901 ota_from_target_files_args = [
902 output_zip,
903 output_ota,
904 ]
905 ota_from_target_files.main(ota_from_target_files_args)
906
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700907
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800908def call_func_with_temp_dir(func, keep_tmp):
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800909 """Manage the creation and cleanup of the temporary directory.
910
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800911 This function calls the given function after first creating a temporary
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800912 directory. It also cleans up the temporary directory.
913
914 Args:
Daniel Normane5b134a2019-04-17 14:54:06 -0700915 func: The function to call. Should accept one parameter, the path to the
916 temporary directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800917 keep_tmp: Keep the temporary directory after processing is complete.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800918 """
919
920 # Create a temporary directory. This will serve as the parent of directories
921 # we use when we extract items from the input target files packages, and also
922 # a scratch directory that we use for temporary files.
923
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800924 temp_dir = common.MakeTempDir(prefix='merge_target_files_')
925
926 try:
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800927 func(temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800928 except:
929 raise
930 finally:
931 if keep_tmp:
932 logger.info('keeping %s', temp_dir)
933 else:
934 common.Cleanup()
935
936
937def main():
938 """The main function.
939
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800940 Process command line arguments, then call merge_target_files to
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800941 perform the heavy lifting.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800942 """
943
944 common.InitLogging()
945
Bill Peckhamf753e152019-02-19 18:02:46 -0800946 def option_handler(o, a):
947 if o == '--system-target-files':
948 OPTIONS.system_target_files = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800949 elif o == '--system-item-list':
950 OPTIONS.system_item_list = a
951 elif o == '--system-misc-info-keys':
952 OPTIONS.system_misc_info_keys = a
Bill Peckhamf753e152019-02-19 18:02:46 -0800953 elif o == '--other-target-files':
954 OPTIONS.other_target_files = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800955 elif o == '--other-item-list':
956 OPTIONS.other_item_list = a
Bill Peckhamf753e152019-02-19 18:02:46 -0800957 elif o == '--output-target-files':
958 OPTIONS.output_target_files = a
Daniel Normanfdb38812019-04-15 09:47:24 -0700959 elif o == '--output-dir':
960 OPTIONS.output_dir = a
961 elif o == '--output-item-list':
962 OPTIONS.output_item_list = a
Daniel Norman3b64ce12019-04-16 16:11:35 -0700963 elif o == '--output-ota':
964 OPTIONS.output_ota = a
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700965 elif o == '--output-img':
966 OPTIONS.output_img = a
Daniel Normanf0318252019-04-15 11:34:56 -0700967 elif o == '--output-super-empty':
968 OPTIONS.output_super_empty = a
Daniel Normana4911da2019-03-15 14:36:21 -0700969 elif o == '--rebuild_recovery':
970 OPTIONS.rebuild_recovery = True
Bill Peckham364c1cc2019-03-29 18:27:23 -0700971 elif o == '--keep-tmp':
Bill Peckhamf753e152019-02-19 18:02:46 -0800972 OPTIONS.keep_tmp = True
973 else:
974 return False
975 return True
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800976
Bill Peckhamf753e152019-02-19 18:02:46 -0800977 args = common.ParseOptions(
Daniel Normane5b134a2019-04-17 14:54:06 -0700978 sys.argv[1:],
979 __doc__,
Bill Peckhamf753e152019-02-19 18:02:46 -0800980 extra_long_opts=[
981 'system-target-files=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800982 'system-item-list=',
983 'system-misc-info-keys=',
Bill Peckhamf753e152019-02-19 18:02:46 -0800984 'other-target-files=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800985 'other-item-list=',
Bill Peckhamf753e152019-02-19 18:02:46 -0800986 'output-target-files=',
Daniel Normanfdb38812019-04-15 09:47:24 -0700987 'output-dir=',
988 'output-item-list=',
Daniel Norman3b64ce12019-04-16 16:11:35 -0700989 'output-ota=',
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700990 'output-img=',
Daniel Normanf0318252019-04-15 11:34:56 -0700991 'output-super-empty=',
Daniel Normana4911da2019-03-15 14:36:21 -0700992 'rebuild_recovery',
Bill Peckham364c1cc2019-03-29 18:27:23 -0700993 'keep-tmp',
Bill Peckhamf753e152019-02-19 18:02:46 -0800994 ],
995 extra_option_handler=option_handler)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800996
Daniel Normane5b134a2019-04-17 14:54:06 -0700997 if (args or OPTIONS.system_target_files is None or
998 OPTIONS.other_target_files is None or
999 (OPTIONS.output_target_files is None and OPTIONS.output_dir is None) or
1000 (OPTIONS.output_dir is not None and OPTIONS.output_item_list is None)):
Bill Peckhamf753e152019-02-19 18:02:46 -08001001 common.Usage(__doc__)
Bill Peckham889b0c62019-02-21 18:53:37 -08001002 sys.exit(1)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001003
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001004 if OPTIONS.system_item_list:
1005 system_item_list = read_config_list(OPTIONS.system_item_list)
1006 else:
1007 system_item_list = default_system_item_list
1008
1009 if OPTIONS.system_misc_info_keys:
1010 system_misc_info_keys = read_config_list(OPTIONS.system_misc_info_keys)
1011 else:
1012 system_misc_info_keys = default_system_misc_info_keys
1013
1014 if OPTIONS.other_item_list:
1015 other_item_list = read_config_list(OPTIONS.other_item_list)
1016 else:
1017 other_item_list = default_other_item_list
1018
Daniel Normanfdb38812019-04-15 09:47:24 -07001019 if OPTIONS.output_item_list:
1020 output_item_list = read_config_list(OPTIONS.output_item_list)
1021 else:
1022 output_item_list = None
1023
Daniel Normane5964522019-03-19 10:32:03 -07001024 if not validate_config_lists(
1025 system_item_list=system_item_list,
Daniel Norman19b9fe92019-03-19 14:48:02 -07001026 system_misc_info_keys=system_misc_info_keys,
Daniel Normane5964522019-03-19 10:32:03 -07001027 other_item_list=other_item_list):
1028 sys.exit(1)
1029
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001030 call_func_with_temp_dir(
1031 lambda temp_dir: merge_target_files(
1032 temp_dir=temp_dir,
1033 system_target_files=OPTIONS.system_target_files,
1034 system_item_list=system_item_list,
1035 system_misc_info_keys=system_misc_info_keys,
1036 other_target_files=OPTIONS.other_target_files,
1037 other_item_list=other_item_list,
Daniel Normana4911da2019-03-15 14:36:21 -07001038 output_target_files=OPTIONS.output_target_files,
Daniel Normanfdb38812019-04-15 09:47:24 -07001039 output_dir=OPTIONS.output_dir,
1040 output_item_list=output_item_list,
Daniel Norman3b64ce12019-04-16 16:11:35 -07001041 output_ota=OPTIONS.output_ota,
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001042 output_img=OPTIONS.output_img,
Daniel Normanf0318252019-04-15 11:34:56 -07001043 output_super_empty=OPTIONS.output_super_empty,
Daniel Normane5b134a2019-04-17 14:54:06 -07001044 rebuild_recovery=OPTIONS.rebuild_recovery), OPTIONS.keep_tmp)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001045
1046
1047if __name__ == '__main__':
Bill Peckham889b0c62019-02-21 18:53:37 -08001048 main()