copy_to_dir.py 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. import argparse
  2. import errno
  3. import sys
  4. import os
  5. import shutil
  6. import tarfile
  7. def parse_args():
  8. parser = argparse.ArgumentParser()
  9. parser.add_argument('--build-root', required=True)
  10. parser.add_argument('--dest-arch', default=None)
  11. parser.add_argument('--dest-dir', required=True)
  12. parser.add_argument('args', nargs='*')
  13. return parser.parse_args()
  14. def ensure_dir_exists(path):
  15. try:
  16. os.makedirs(path)
  17. except OSError as e:
  18. if e.errno == errno.EEXIST and os.path.isdir(path):
  19. pass
  20. else:
  21. raise
  22. def hardlink_or_copy(src, dst):
  23. if os.name == 'nt':
  24. shutil.copy(src, dst)
  25. else:
  26. try:
  27. os.link(src, dst)
  28. except OSError as e:
  29. if e.errno == errno.EEXIST:
  30. return
  31. elif e.errno == errno.EXDEV:
  32. sys.stderr.write("Can't make cross-device hardlink - fallback to copy: {} -> {}\n".format(src, dst))
  33. shutil.copy(src, dst)
  34. else:
  35. raise
  36. def main():
  37. opts = parse_args()
  38. dest_arch = None
  39. if opts.dest_arch:
  40. if opts.dest_arch.endswith('.tar'):
  41. dest_arch = tarfile.open(opts.dest_arch, 'w', dereference=True)
  42. elif opts.dest_arch.endswith('.tar.gz') or opts.dest_arch.endswith('.tgz'):
  43. dest_arch = tarfile.open(opts.dest_arch, 'w:gz', dereference=True)
  44. else:
  45. # TODO: move check to graph generation stage
  46. raise Exception(
  47. 'Unsopported archive type for {}. Use one of: tar, tar.gz, tgz.'.format(
  48. os.path.basename(opts.dest_arch)
  49. )
  50. )
  51. for arg in opts.args:
  52. dst = arg
  53. if dst.startswith(opts.build_root):
  54. dst = dst[len(opts.build_root) + 1 :]
  55. if dest_arch and not arg.endswith('.pkg.fake'):
  56. dest_arch.add(arg, arcname=dst)
  57. dst = os.path.join(opts.dest_dir, dst)
  58. ensure_dir_exists(os.path.dirname(dst))
  59. hardlink_or_copy(arg, dst)
  60. if dest_arch:
  61. dest_arch.close()
  62. if __name__ == '__main__':
  63. sys.exit(main())