blob: 20806b802bb37ed91c30303dc36b3efa98ce9e51 [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.
16
17"""
18This script merges two partial target files packages (one of which contains
19system files, and the other contains non-system files) together, producing a
20complete target files package that can be used to generate an OTA package.
21
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
45 The output merged target files package. Also a zip archive.
Daniel Normana4911da2019-03-15 14:36:21 -070046
47 --rebuild_recovery
48 Rebuild the recovery patch used by non-A/B devices and write it to the
49 system image.
Bill Peckhame9eb5f92019-02-01 15:52:10 -080050"""
51
52from __future__ import print_function
53
Bill Peckhame9eb5f92019-02-01 15:52:10 -080054import fnmatch
55import logging
56import os
57import sys
58import zipfile
59
60import common
61import add_img_to_target_files
62
63logger = logging.getLogger(__name__)
64OPTIONS = common.OPTIONS
65OPTIONS.verbose = True
Bill Peckhamf753e152019-02-19 18:02:46 -080066OPTIONS.system_target_files = None
Daniel Norman2c99c5b2019-03-07 13:01:48 -080067OPTIONS.system_item_list = None
68OPTIONS.system_misc_info_keys = None
Bill Peckhamf753e152019-02-19 18:02:46 -080069OPTIONS.other_target_files = None
Daniel Norman2c99c5b2019-03-07 13:01:48 -080070OPTIONS.other_item_list = None
Bill Peckhamf753e152019-02-19 18:02:46 -080071OPTIONS.output_target_files = None
Daniel Normana4911da2019-03-15 14:36:21 -070072OPTIONS.rebuild_recovery = False
Bill Peckhamf753e152019-02-19 18:02:46 -080073OPTIONS.keep_tmp = False
Bill Peckhame9eb5f92019-02-01 15:52:10 -080074
Daniel Norman2c99c5b2019-03-07 13:01:48 -080075# default_system_item_list is a list of items to extract from the partial
Bill Peckhame9eb5f92019-02-01 15:52:10 -080076# system target files package as is, meaning these items will land in the
77# output target files package exactly as they appear in the input partial
78# system target files package.
79
Daniel Norman2c99c5b2019-03-07 13:01:48 -080080default_system_item_list = [
Bill Peckhame9eb5f92019-02-01 15:52:10 -080081 'META/apkcerts.txt',
82 'META/filesystem_config.txt',
83 'META/root_filesystem_config.txt',
84 'META/system_manifest.xml',
85 'META/system_matrix.xml',
86 'META/update_engine_config.txt',
87 'PRODUCT/*',
88 'ROOT/*',
89 'SYSTEM/*',
90]
91
92# system_extract_special_item_list is a list of items to extract from the
93# partial system target files package that need some special processing, such
94# as some sort of combination with items from the partial other target files
95# package.
96
97system_extract_special_item_list = [
98 'META/*',
99]
100
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800101# default_system_misc_info_keys is a list of keys to obtain from the system instance of
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800102# META/misc_info.txt. The remaining keys from the other instance.
103
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800104default_system_misc_info_keys = [
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800105 'avb_system_hashtree_enable',
106 'avb_system_add_hashtree_footer_args',
107 'avb_system_key_path',
108 'avb_system_algorithm',
109 'avb_system_rollback_index_location',
110 'avb_product_hashtree_enable',
111 'avb_product_add_hashtree_footer_args',
112 'avb_product_services_hashtree_enable',
113 'avb_product_services_add_hashtree_footer_args',
114 'system_root_image',
115 'root_dir',
116 'ab_update',
117 'default_system_dev_certificate',
118 'system_size',
119]
120
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800121# default_other_item_list is a list of items to extract from the partial
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800122# other target files package as is, meaning these items will land in the output
123# target files package exactly as they appear in the input partial other target
124# files package.
125
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800126default_other_item_list = [
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800127 'META/boot_filesystem_config.txt',
128 'META/otakeys.txt',
129 'META/releasetools.py',
130 'META/vendor_filesystem_config.txt',
131 'META/vendor_manifest.xml',
132 'META/vendor_matrix.xml',
133 'BOOT/*',
134 'DATA/*',
135 'ODM/*',
136 'OTA/android-info.txt',
137 'PREBUILT_IMAGES/*',
138 'RADIO/*',
139 'VENDOR/*',
140]
141
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800142# other_extract_special_item_list is a list of items to extract from the
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800143# partial other target files package that need some special processing, such as
144# some sort of combination with items from the partial system target files
145# package.
146
147other_extract_special_item_list = [
148 'META/*',
149]
150
151
152def extract_items(target_files, target_files_temp_dir, extract_item_list):
153 """Extract items from target files to temporary directory.
154
155 This function extracts from the specified target files zip archive into the
156 specified temporary directory, the items specified in the extract item list.
157
158 Args:
159 target_files: The target files zip archive from which to extract items.
160
161 target_files_temp_dir: The temporary directory where the extracted items
162 will land.
163
164 extract_item_list: A list of items to extract.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800165 """
166
167 logger.info('extracting from %s', target_files)
168
169 # Filter the extract_item_list to remove any items that do not exist in the
170 # zip file. Otherwise, the extraction step will fail.
171
172 with zipfile.ZipFile(
173 target_files,
174 'r',
175 allowZip64=True) as target_files_zipfile:
176 target_files_namelist = target_files_zipfile.namelist()
177
178 filtered_extract_item_list = []
179 for pattern in extract_item_list:
180 matching_namelist = fnmatch.filter(target_files_namelist, pattern)
181 if not matching_namelist:
182 logger.warning('no match for %s', pattern)
183 else:
184 filtered_extract_item_list.append(pattern)
185
Bill Peckham8ff3fbd2019-02-22 10:57:43 -0800186 # Extract from target_files into target_files_temp_dir the
187 # filtered_extract_item_list.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800188
Bill Peckham8ff3fbd2019-02-22 10:57:43 -0800189 common.UnzipToDir(
190 target_files,
191 target_files_temp_dir,
192 filtered_extract_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800193
194
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800195def read_config_list(config_file_path):
196 """Reads a config file into a list of strings.
197
198 Expects the file to be newline-separated.
199
200 Args:
201 config_file_path: The path to the config file to open and read.
202 """
203 with open(config_file_path) as config_file:
204 return config_file.read().splitlines()
205
206
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800207def process_ab_partitions_txt(
208 system_target_files_temp_dir,
209 other_target_files_temp_dir,
210 output_target_files_temp_dir):
211 """Perform special processing for META/ab_partitions.txt
212
213 This function merges the contents of the META/ab_partitions.txt files from
214 the system directory and the other directory, placing the merged result in
215 the output directory. The precondition in that the files are already
216 extracted. The post condition is that the output META/ab_partitions.txt
217 contains the merged content. The format for each ab_partitions.txt a one
218 partition name per line. The output file contains the union of the parition
219 names.
220
221 Args:
222 system_target_files_temp_dir: The name of a directory containing the
223 special items extracted from the system target files package.
224
225 other_target_files_temp_dir: The name of a directory containing the
226 special items extracted from the other target files package.
227
228 output_target_files_temp_dir: The name of a directory that will be used
229 to create the output target files package after all the special cases
230 are processed.
231 """
232
233 system_ab_partitions_txt = os.path.join(
234 system_target_files_temp_dir, 'META', 'ab_partitions.txt')
235
236 other_ab_partitions_txt = os.path.join(
237 other_target_files_temp_dir, 'META', 'ab_partitions.txt')
238
239 with open(system_ab_partitions_txt) as f:
240 system_ab_partitions = f.read().splitlines()
241
242 with open(other_ab_partitions_txt) as f:
243 other_ab_partitions = f.read().splitlines()
244
245 output_ab_partitions = set(system_ab_partitions + other_ab_partitions)
246
247 output_ab_partitions_txt = os.path.join(
248 output_target_files_temp_dir, 'META', 'ab_partitions.txt')
249
250 with open(output_ab_partitions_txt, 'w') as output:
251 for partition in sorted(output_ab_partitions):
252 output.write('%s\n' % partition)
253
254
255def process_misc_info_txt(
256 system_target_files_temp_dir,
257 other_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800258 output_target_files_temp_dir,
259 system_misc_info_keys):
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800260 """Perform special processing for META/misc_info.txt
261
262 This function merges the contents of the META/misc_info.txt files from the
263 system directory and the other directory, placing the merged result in the
264 output directory. The precondition in that the files are already extracted.
265 The post condition is that the output META/misc_info.txt contains the merged
266 content.
267
268 Args:
269 system_target_files_temp_dir: The name of a directory containing the
270 special items extracted from the system target files package.
271
272 other_target_files_temp_dir: The name of a directory containing the
273 special items extracted from the other target files package.
274
275 output_target_files_temp_dir: The name of a directory that will be used
276 to create the output target files package after all the special cases
277 are processed.
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800278
279 system_misc_info_keys: A list of keys to obtain from the system instance
280 of META/misc_info.txt. The remaining keys from the other instance.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800281 """
282
283 def read_helper(d):
284 misc_info_txt = os.path.join(d, 'META', 'misc_info.txt')
285 with open(misc_info_txt) as f:
286 return list(f.read().splitlines())
287
288 system_info_dict = common.LoadDictionaryFromLines(
289 read_helper(system_target_files_temp_dir))
290
291 # We take most of the misc info from the other target files.
292
293 merged_info_dict = common.LoadDictionaryFromLines(
294 read_helper(other_target_files_temp_dir))
295
296 # Replace certain values in merged_info_dict with values from
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800297 # system_info_dict.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800298
299 for key in system_misc_info_keys:
300 merged_info_dict[key] = system_info_dict[key]
301
302 output_misc_info_txt = os.path.join(
303 output_target_files_temp_dir,
304 'META', 'misc_info.txt')
305
306 sorted_keys = sorted(merged_info_dict.keys())
307
308 with open(output_misc_info_txt, 'w') as output:
309 for key in sorted_keys:
310 output.write('{}={}\n'.format(key, merged_info_dict[key]))
311
312
313def process_file_contexts_bin(temp_dir, output_target_files_temp_dir):
314 """Perform special processing for META/file_contexts.bin.
315
316 This function combines plat_file_contexts and vendor_file_contexts, which are
317 expected to already be extracted in temp_dir, to produce a merged
318 file_contexts.bin that will land in temp_dir at META/file_contexts.bin.
319
320 Args:
321 temp_dir: The name of a scratch directory that this function can use for
322 intermediate files generated during processing.
323
324 output_target_files_temp_dir: The name of the working directory that must
325 already contain plat_file_contexts and vendor_file_contexts (in the
326 appropriate sub directories), and to which META/file_contexts.bin will be
327 written.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800328 """
329
330 # To create a merged file_contexts.bin file, we use the system and vendor
331 # file contexts files as input, the m4 tool to combine them, the sorting tool
332 # to sort, and finally the sefcontext_compile tool to generate the final
333 # output. We currently omit a checkfc step since the files had been checked
334 # as part of the build.
335
336 # The m4 step concatenates the two input files contexts files. Since m4
337 # writes to stdout, we receive that into an array of bytes, and then write it
338 # to a file.
339
340 # Collect the file contexts that we're going to combine from SYSTEM, VENDOR,
341 # PRODUCT, and ODM. We require SYSTEM and VENDOR, but others are optional.
342
343 file_contexts_list = []
344
345 for partition in ['SYSTEM', 'VENDOR', 'PRODUCT', 'ODM']:
346 prefix = 'plat' if partition == 'SYSTEM' else partition.lower()
347
348 file_contexts = os.path.join(
349 output_target_files_temp_dir,
350 partition, 'etc', 'selinux', prefix + '_file_contexts')
351
352 mandatory = partition in ['SYSTEM', 'VENDOR']
353
354 if mandatory or os.path.isfile(file_contexts):
355 file_contexts_list.append(file_contexts)
356 else:
357 logger.warning('file not found: %s', file_contexts)
358
359 command = ['m4', '--fatal-warnings', '-s'] + file_contexts_list
360
361 merged_content = common.RunAndCheckOutput(command, verbose=False)
362
363 merged_file_contexts_txt = os.path.join(temp_dir, 'merged_file_contexts.txt')
364
365 with open(merged_file_contexts_txt, 'wb') as f:
366 f.write(merged_content)
367
368 # The sort step sorts the concatenated file.
369
370 sorted_file_contexts_txt = os.path.join(temp_dir, 'sorted_file_contexts.txt')
371 command = ['fc_sort', merged_file_contexts_txt, sorted_file_contexts_txt]
Bill Peckham889b0c62019-02-21 18:53:37 -0800372 common.RunAndWait(command, verbose=True)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800373
374 # Finally, the compile step creates the final META/file_contexts.bin.
375
376 file_contexts_bin = os.path.join(
377 output_target_files_temp_dir,
378 'META', 'file_contexts.bin')
379
380 command = [
381 'sefcontext_compile',
382 '-o', file_contexts_bin,
383 sorted_file_contexts_txt,
384 ]
385
Bill Peckham889b0c62019-02-21 18:53:37 -0800386 common.RunAndWait(command, verbose=True)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800387
388
389def process_special_cases(
390 temp_dir,
391 system_target_files_temp_dir,
392 other_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800393 output_target_files_temp_dir,
394 system_misc_info_keys):
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800395 """Perform special-case processing for certain target files items.
396
397 Certain files in the output target files package require special-case
398 processing. This function performs all that special-case processing.
399
400 Args:
401 temp_dir: The name of a scratch directory that this function can use for
402 intermediate files generated during processing.
403
404 system_target_files_temp_dir: The name of a directory containing the
405 special items extracted from the system target files package.
406
407 other_target_files_temp_dir: The name of a directory containing the
408 special items extracted from the other target files package.
409
410 output_target_files_temp_dir: The name of a directory that will be used
411 to create the output target files package after all the special cases
412 are processed.
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800413
414 system_misc_info_keys: A list of keys to obtain from the system instance
415 of META/misc_info.txt. The remaining keys from the other instance.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800416 """
417
418 process_ab_partitions_txt(
419 system_target_files_temp_dir=system_target_files_temp_dir,
420 other_target_files_temp_dir=other_target_files_temp_dir,
421 output_target_files_temp_dir=output_target_files_temp_dir)
422
423 process_misc_info_txt(
424 system_target_files_temp_dir=system_target_files_temp_dir,
425 other_target_files_temp_dir=other_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800426 output_target_files_temp_dir=output_target_files_temp_dir,
427 system_misc_info_keys=system_misc_info_keys)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800428
Bill Peckham889b0c62019-02-21 18:53:37 -0800429 process_file_contexts_bin(
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800430 temp_dir=temp_dir,
431 output_target_files_temp_dir=output_target_files_temp_dir)
432
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800433
434def merge_target_files(
435 temp_dir,
436 system_target_files,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800437 system_item_list,
438 system_misc_info_keys,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800439 other_target_files,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800440 other_item_list,
Daniel Normana4911da2019-03-15 14:36:21 -0700441 output_target_files,
442 rebuild_recovery):
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800443 """Merge two target files packages together.
444
445 This function takes system and other target files packages as input, performs
446 various file extractions, special case processing, and finally creates a
447 merged zip archive as output.
448
449 Args:
450 temp_dir: The name of a directory we use when we extract items from the
451 input target files packages, and also a scratch directory that we use for
452 temporary files.
453
454 system_target_files: The name of the zip archive containing the system
455 partial target files package.
456
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800457 system_item_list: The list of items to extract from the partial system
458 target files package as is, meaning these items will land in the output
459 target files package exactly as they appear in the input partial system
460 target files package.
461
462 system_misc_info_keys: The list of keys to obtain from the system instance
463 of META/misc_info.txt. The remaining keys from the other instance.
464
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800465 other_target_files: The name of the zip archive containing the other
466 partial target files package.
467
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800468 other_item_list: The list of items to extract from the partial other
469 target files package as is, meaning these items will land in the output
470 target files package exactly as they appear in the input partial other
471 target files package.
472
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800473 output_target_files: The name of the output zip archive target files
474 package created by merging system and other.
Daniel Normana4911da2019-03-15 14:36:21 -0700475
476 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
477 devices and write it to the system image.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800478 """
479
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800480 logger.info(
481 'starting: merge system %s and other %s into output %s',
482 system_target_files,
483 other_target_files,
484 output_target_files)
485
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800486 # Create directory names that we'll use when we extract files from system,
487 # and other, and for zipping the final output.
488
489 system_target_files_temp_dir = os.path.join(temp_dir, 'system')
490 other_target_files_temp_dir = os.path.join(temp_dir, 'other')
491 output_target_files_temp_dir = os.path.join(temp_dir, 'output')
492
493 # Extract "as is" items from the input system partial target files package.
494 # We extract them directly into the output temporary directory since the
495 # items do not need special case processing.
496
Bill Peckham889b0c62019-02-21 18:53:37 -0800497 extract_items(
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800498 target_files=system_target_files,
499 target_files_temp_dir=output_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800500 extract_item_list=system_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800501
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800502 # Extract "as is" items from the input other partial target files package. We
503 # extract them directly into the output temporary directory since the items
504 # do not need special case processing.
505
Bill Peckham889b0c62019-02-21 18:53:37 -0800506 extract_items(
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800507 target_files=other_target_files,
508 target_files_temp_dir=output_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800509 extract_item_list=other_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800510
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800511 # Extract "special" items from the input system partial target files package.
512 # We extract these items to different directory since they require special
513 # processing before they will end up in the output directory.
514
Bill Peckham889b0c62019-02-21 18:53:37 -0800515 extract_items(
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800516 target_files=system_target_files,
517 target_files_temp_dir=system_target_files_temp_dir,
518 extract_item_list=system_extract_special_item_list)
519
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800520 # Extract "special" items from the input other partial target files package.
521 # We extract these items to different directory since they require special
522 # processing before they will end up in the output directory.
523
Bill Peckham889b0c62019-02-21 18:53:37 -0800524 extract_items(
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800525 target_files=other_target_files,
526 target_files_temp_dir=other_target_files_temp_dir,
527 extract_item_list=other_extract_special_item_list)
528
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800529 # Now that the temporary directories contain all the extracted files, perform
530 # special case processing on any items that need it. After this function
531 # completes successfully, all the files we need to create the output target
532 # files package are in place.
533
Bill Peckham889b0c62019-02-21 18:53:37 -0800534 process_special_cases(
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800535 temp_dir=temp_dir,
536 system_target_files_temp_dir=system_target_files_temp_dir,
537 other_target_files_temp_dir=other_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800538 output_target_files_temp_dir=output_target_files_temp_dir,
539 system_misc_info_keys=system_misc_info_keys)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800540
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800541 # Regenerate IMAGES in the temporary directory.
542
Daniel Normana4911da2019-03-15 14:36:21 -0700543 add_img_args = ['--verbose']
544 if rebuild_recovery:
545 add_img_args.append('--rebuild_recovery')
546 add_img_args.append(output_target_files_temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800547
548 add_img_to_target_files.main(add_img_args)
549
550 # Finally, create the output target files zip archive.
551
552 output_zip = os.path.abspath(output_target_files)
553 output_target_files_list = os.path.join(temp_dir, 'output.list')
554 output_target_files_meta_dir = os.path.join(
555 output_target_files_temp_dir, 'META')
556
557 command = [
558 'find',
559 output_target_files_meta_dir,
560 ]
561 # TODO(bpeckham): sort this to be more like build.
562 meta_content = common.RunAndCheckOutput(command, verbose=False)
563 command = [
564 'find',
565 output_target_files_temp_dir,
566 '-path',
567 output_target_files_meta_dir,
568 '-prune',
569 '-o',
570 '-print'
571 ]
572 # TODO(bpeckham): sort this to be more like build.
573 other_content = common.RunAndCheckOutput(command, verbose=False)
574
575 with open(output_target_files_list, 'wb') as f:
576 f.write(meta_content)
577 f.write(other_content)
578
579 command = [
Bill Peckhamf753e152019-02-19 18:02:46 -0800580 'soong_zip',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800581 '-d',
582 '-o', output_zip,
583 '-C', output_target_files_temp_dir,
584 '-l', output_target_files_list,
585 ]
586 logger.info('creating %s', output_target_files)
Bill Peckham889b0c62019-02-21 18:53:37 -0800587 common.RunAndWait(command, verbose=True)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800588
589
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800590def call_func_with_temp_dir(func, keep_tmp):
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800591 """Manage the creation and cleanup of the temporary directory.
592
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800593 This function calls the given function after first creating a temporary
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800594 directory. It also cleans up the temporary directory.
595
596 Args:
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800597 func: The function to call. Should accept one parameter, the path to
598 the temporary directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800599
600 keep_tmp: Keep the temporary directory after processing is complete.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800601 """
602
603 # Create a temporary directory. This will serve as the parent of directories
604 # we use when we extract items from the input target files packages, and also
605 # a scratch directory that we use for temporary files.
606
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800607 temp_dir = common.MakeTempDir(prefix='merge_target_files_')
608
609 try:
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800610 func(temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800611 except:
612 raise
613 finally:
614 if keep_tmp:
615 logger.info('keeping %s', temp_dir)
616 else:
617 common.Cleanup()
618
619
620def main():
621 """The main function.
622
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800623 Process command line arguments, then call merge_target_files to
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800624 perform the heavy lifting.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800625 """
626
627 common.InitLogging()
628
Bill Peckhamf753e152019-02-19 18:02:46 -0800629 def option_handler(o, a):
630 if o == '--system-target-files':
631 OPTIONS.system_target_files = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800632 elif o == '--system-item-list':
633 OPTIONS.system_item_list = a
634 elif o == '--system-misc-info-keys':
635 OPTIONS.system_misc_info_keys = a
Bill Peckhamf753e152019-02-19 18:02:46 -0800636 elif o == '--other-target-files':
637 OPTIONS.other_target_files = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800638 elif o == '--other-item-list':
639 OPTIONS.other_item_list = a
Bill Peckhamf753e152019-02-19 18:02:46 -0800640 elif o == '--output-target-files':
641 OPTIONS.output_target_files = a
Daniel Normana4911da2019-03-15 14:36:21 -0700642 elif o == '--rebuild_recovery':
643 OPTIONS.rebuild_recovery = True
Bill Peckhamf753e152019-02-19 18:02:46 -0800644 elif o == '--keep_tmp':
645 OPTIONS.keep_tmp = True
646 else:
647 return False
648 return True
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800649
Bill Peckhamf753e152019-02-19 18:02:46 -0800650 args = common.ParseOptions(
651 sys.argv[1:], __doc__,
652 extra_long_opts=[
653 'system-target-files=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800654 'system-item-list=',
655 'system-misc-info-keys=',
Bill Peckhamf753e152019-02-19 18:02:46 -0800656 'other-target-files=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800657 'other-item-list=',
Bill Peckhamf753e152019-02-19 18:02:46 -0800658 'output-target-files=',
Daniel Normana4911da2019-03-15 14:36:21 -0700659 'rebuild_recovery',
Bill Peckhamf753e152019-02-19 18:02:46 -0800660 "keep_tmp",
661 ],
662 extra_option_handler=option_handler)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800663
Bill Peckham889b0c62019-02-21 18:53:37 -0800664 if (len(args) != 0 or
Bill Peckhamf753e152019-02-19 18:02:46 -0800665 OPTIONS.system_target_files is None or
666 OPTIONS.other_target_files is None or
667 OPTIONS.output_target_files is None):
668 common.Usage(__doc__)
Bill Peckham889b0c62019-02-21 18:53:37 -0800669 sys.exit(1)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800670
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800671 if OPTIONS.system_item_list:
672 system_item_list = read_config_list(OPTIONS.system_item_list)
673 else:
674 system_item_list = default_system_item_list
675
676 if OPTIONS.system_misc_info_keys:
677 system_misc_info_keys = read_config_list(OPTIONS.system_misc_info_keys)
678 else:
679 system_misc_info_keys = default_system_misc_info_keys
680
681 if OPTIONS.other_item_list:
682 other_item_list = read_config_list(OPTIONS.other_item_list)
683 else:
684 other_item_list = default_other_item_list
685
686 call_func_with_temp_dir(
687 lambda temp_dir: merge_target_files(
688 temp_dir=temp_dir,
689 system_target_files=OPTIONS.system_target_files,
690 system_item_list=system_item_list,
691 system_misc_info_keys=system_misc_info_keys,
692 other_target_files=OPTIONS.other_target_files,
693 other_item_list=other_item_list,
Daniel Normana4911da2019-03-15 14:36:21 -0700694 output_target_files=OPTIONS.output_target_files,
695 rebuild_recovery=OPTIONS.rebuild_recovery),
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800696 OPTIONS.keep_tmp)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800697
698
699if __name__ == '__main__':
Bill Peckham889b0c62019-02-21 18:53:37 -0800700 main()