archiver_3_3.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. def create_archive(self, scm_object, **kwargs):
  2. """Create an OBS cpio archive of repodir in destination directory.
  3. """
  4. basename = kwargs['basename']
  5. dstname = kwargs['dstname']
  6. version = kwargs['version']
  7. args = kwargs['cli']
  8. commit = scm_object.get_current_commit()
  9. package_metadata = args.package_meta
  10. (workdir, topdir) = os.path.split(scm_object.arch_dir)
  11. extension = 'obscpio'
  12. cwd = os.getcwd()
  13. os.chdir(workdir)
  14. archivefilename = os.path.join(args.outdir, dstname + '.' + extension)
  15. archivefile = open(archivefilename, "w")
  16. # detect reproducible support
  17. params = ['cpio', '--create', '--format=newc', '--owner', '0:0']
  18. chkcmd = "cpio --create --format=newc --reproducible "
  19. chkcmd += "</dev/null >/dev/null 2>&1"
  20. if os.system(chkcmd) == 0:
  21. params.append('--reproducible')
  22. proc = subprocess.Popen(
  23. params,
  24. shell=False,
  25. stdin=subprocess.PIPE,
  26. stdout=archivefile,
  27. stderr=subprocess.STDOUT
  28. )
  29. # transform glob patterns to regular expressions
  30. includes = ''
  31. excludes = r'$.'
  32. topdir_re = '(' + topdir + '/)('
  33. if args.include:
  34. incl_arr = [fnmatch.translate(x + '*') for x in args.include]
  35. match_list = r'|'.join(incl_arr)
  36. includes = topdir_re + match_list + ')'
  37. if args.exclude:
  38. excl_arr = [fnmatch.translate(x) for x in args.exclude]
  39. excludes = topdir_re + r'|'.join(excl_arr) + ')'
  40. # add topdir without filtering for now
  41. cpiolist = []
  42. for root, dirs, files in os.walk(topdir, topdown=False):
  43. # excludes
  44. dirs[:] = [os.path.join(root, d) for d in dirs]
  45. dirs[:] = [d for d in dirs if not re.match(excludes, d)]
  46. dirs[:] = [d for d in dirs if re.match(includes, d)]
  47. # exclude/include files
  48. files = [os.path.join(root, f) for f in files]
  49. files = [f for f in files if not re.match(excludes, f)]
  50. files = [f for f in files if re.match(includes, f)]
  51. for name in dirs:
  52. if not METADATA_PATTERN.match(name) or package_metadata:
  53. cpiolist.append(name)
  54. for name in files:
  55. if not METADATA_PATTERN.match(name) or package_metadata:
  56. cpiolist.append(name)
  57. tstamp = self.helpers.get_timestamp(scm_object, args, topdir)
  58. for name in sorted(cpiolist):
  59. try:
  60. os.utime(name, (tstamp, tstamp))
  61. except OSError:
  62. pass
  63. # bytes() break in python2 with a TypeError as it expects only 1
  64. # arg
  65. try:
  66. proc.stdin.write(name.encode('UTF-8', 'surrogateescape'))
  67. except (TypeError, UnicodeDecodeError):
  68. proc.stdin.write(name)
  69. proc.stdin.write(b"\n")
  70. proc.stdin.close()
  71. ret_code = proc.wait()
  72. if ret_code != 0:
  73. raise SystemExit("Creating the cpio archive failed!")
  74. archivefile.close()
  75. # write meta data
  76. infofile = os.path.join(args.outdir, basename + '.obsinfo')
  77. logging.debug("Writing to obsinfo file '%s'", infofile)
  78. metafile = open(infofile, "w")
  79. metafile.write("name: " + basename + "\n")
  80. metafile.write("version: " + version + "\n")
  81. metafile.write("mtime: " + str(tstamp) + "\n")
  82. if commit:
  83. metafile.write("commit: " + commit + "\n")
  84. metafile.close()
  85. self.archivefile = archivefile.name
  86. self.metafile = metafile.name
  87. os.chdir(cwd)