copy_to_dir.py 2.0 KB

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