copy_to_dir.py 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  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('Unsopported archive type for {}. Use one of: tar, tar.gz, tgz.'.format(os.path.basename(opts.dest_arch)))
  47. for arg in opts.args:
  48. dst = arg
  49. if dst.startswith(opts.build_root):
  50. dst = dst[len(opts.build_root) + 1:]
  51. if dest_arch and not arg.endswith('.pkg.fake'):
  52. dest_arch.add(arg, arcname=dst)
  53. dst = os.path.join(opts.dest_dir, dst)
  54. ensure_dir_exists(os.path.dirname(dst))
  55. hardlink_or_copy(arg, dst)
  56. if dest_arch:
  57. dest_arch.close()
  58. if __name__ == '__main__':
  59. sys.exit(main())