#!/usr/bin/env python
# Copyright 2023 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import optparse
import os
import shutil
import sys
import tarfile
import tempfile
from typing import List,Optional
# A python script that unpacks the supplied tar archive by:
# 1. Extracting the tar into a temporary directory
# 2. Copying the file contents from the temporary directory to the destination
# directory
# 3. Removing the temporary directory
#
# We need to do the extraction indirectly because of:
# 1. how tarfile.extractall() works
# 2. how ninja determines dirty/stale objects
#
# tarfile.extractall() hits errors if the extracted file already exists.
# If we wanted to extract directly into the destination directory, we'd need to
# clear the directory first. However, removing and creating new directories
# within this script would change object timestamps without ninja's
# knowledge. This would cause ninja to always think the pumpkin test files are
# out of date, and thus this script would run each time there is a build
# request, even if there is no work necessary. This is all important because the
# CQ builds all targets, then triggers the same build again and asserts that
# it was a no-op. Without this indirect extraction, we'd fail the CQ every time.
def main(argv: Optional[List[str]] = None) -> Optional[int]:
parser = optparse.OptionParser(description=__doc__)
parser.usage = '%prog [options] <tar-file_path>'
parser.add_option(
'--dest-dir',
action='store',
metavar='DEST_DIR',
help='Destination directory for extracted files.')
options, args = parser.parse_args()
if len(args) < 1 or not options.dest_dir:
print(
'Expected --dest-dir and the tar archive to unpack.',
file=sys.stderr)
print(str(args))
sys.exit(1)
tarArchive = args[0]
outputFiles = args[1].split(',')
stripFilePattern = args[2]
destDir = options.dest_dir
with tempfile.TemporaryDirectory() as tempDir:
# Update the file paths so that they're relative to the temporary directory.
for i in range(0, len(outputFiles)):
path = outputFiles[i]
outputFiles[i] = path.replace(stripFilePattern, "")
# Extract tar into temporary directory.
tar = tarfile.open(tarArchive)
tar.extractall(path=tempDir)
tar.close()
# Copy file contents from tempDir to destDir.
for file in outputFiles:
source = os.path.join(tempDir, file)
destination = os.path.join(destDir, file)
shutil.copyfile(source, destination)
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))