text: #!/usr/bin/env python
  #
  # Copyright 2013 The Flutter Authors. All rights reserved.
  # Use of this source code is governed by a BSD-style license that can be
  # found in the LICENSE file.
  """ Merges the debug symbols and uploads them to cipd.
  """
  
  import argparse
  import collections
  import json
  import os
  import platform
  import shutil
  import subprocess
  import sys
  import tarfile
  
  
  def IsLinux():
    return platform.system() == 'Linux'
  
  
  def GetPackagingDir(out_dir):
    return os.path.abspath(os.path.join(out_dir, os.pardir))
  
  
  def CreateCIPDDefinition(target_arch, out_dir):
    dir_name = os.path.basename(os.path.normpath(out_dir))
    return """
  package: flutter/fuchsia-debug-symbols-%s
  description: Flutter and Dart runner debug symbols for Fuchsia. Target architecture %s.
  install_mode: copy
  data:
    - dir: %s
  """ % (target_arch, target_arch, dir_name)
  
  
  # CIPD CLI needs the definition and data directory to be relative to each other.
  def WriteCIPDDefinition(target_arch, out_dir):
    _packaging_dir = GetPackagingDir(out_dir)
    yaml_file = os.path.join(_packaging_dir, 'debug_symbols.cipd.yaml')
    with open(yaml_file, 'w') as f:
      cipd_def = CreateCIPDDefinition(target_arch, out_dir)
      f.write(cipd_def)
    return yaml_file
  
  
  def ProcessCIPDPackage(upload, cipd_yaml, engine_version, out_dir, target_arch):
    _packaging_dir = GetPackagingDir(out_dir)
    if upload and IsLinux():
      command = [
          'cipd', 'create', '-pkg-def', cipd_yaml, '-ref', 'latest', '-tag',
          'git_revision:%s' % engine_version
      ]
    else:
      command = [
          'cipd', 'pkg-build', '-pkg-def', cipd_yaml, '-out',
          os.path.join(_packaging_dir,
                       'fuchsia-debug-symbols-%s.cipd' % target_arch)
      ]
  
    # Retry up to three times.  We've seen CIPD fail on verification in some
    # instances. Normally verification takes slightly more than 1 minute when
    # it succeeds.
    num_tries = 3
    for tries in range(num_tries):
      try:
        subprocess.check_call(command, cwd=_packaging_dir)
        break
      except subprocess.CalledProcessError:
        print('Failed %s times' % tries + 1)
        if tries == num_tries - 1:
          raise
  
  def CreateTarFile(folder_path, base_dir):
    archive_name = os.path.basename(folder_path)
    tar_file_path = os.path.join(base_dir, archive_name + '.tar.bz2')
    with tarfile.open(tar_file_path, "w:bz2") as archive:
      for root, dirs, _ in os.walk(folder_path):
        for dir_name in dirs:
          dir_path = os.path.join(root, dir_name)
          archive.add(dir_path, arcname=dir_name)
    return tar_file_path
  
  
  def main():
    parser = argparse.ArgumentParser()
  
    parser.add_argument(
        '--symbol-dirs',
        required=True,
        nargs='+',
        help='Space separated list of directories that contain the debug symbols.'
    )
    parser.add_argument(
        '--out-dir',
        required=True,
        action='store',
        dest='out_dir',
        help='Output directory where the executables will be placed.')
    parser.add_argument(
        '--target-arch', type=str, choices=['x64', 'arm64'], required=True)
    parser.add_argument(
        '--engine-version',
        required=True,
        help='Specifies the flutter engine SHA.')
  
    parser.add_argument('--upload', default=False, action='store_true')
  
    args = parser.parse_args()
  
    symbol_dirs = args.symbol_dirs
    for symbol_dir in symbol_dirs:
      assert os.path.exists(symbol_dir) and os.path.isdir(symbol_dir)
  
    arch = args.target_arch
    out_dir = os.path.join(args.out_dir,
                           'flutter-fuchsia-debug-symbols-%s' % arch)
    if os.path.exists(out_dir):
      print 'Directory: %s is not empty, deleting it.' % out_dir
      shutil.rmtree(out_dir)
    os.makedirs(out_dir)
  
    for symbol_dir in symbol_dirs:
      archive_path = CreateTarFile(symbol_dir, out_dir)
      print('Created archive: ' + archive_path)
  
    cipd_def = WriteCIPDDefinition(arch, out_dir)
    ProcessCIPDPackage(args.upload, cipd_def, args.engine_version, out_dir, arch)
    return 0
  
  
  if __name__ == '__main__':
    sys.exit(main())
  