chromium/chrome/browser/resources/chromeos/accessibility/tools/unpack_tar_archive.py

#!/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:]))