def create_archive(self, scm_object, **kwargs): """Create an OBS cpio archive of repodir in destination directory. """ basename = kwargs['basename'] dstname = kwargs['dstname'] version = kwargs['version'] args = kwargs['cli'] commit = scm_object.get_current_commit() package_metadata = args.package_meta (workdir, topdir) = os.path.split(scm_object.arch_dir) extension = 'obscpio' cwd = os.getcwd() os.chdir(workdir) archivefilename = os.path.join(args.outdir, dstname + '.' + extension) archivefile = open(archivefilename, "w") # detect reproducible support params = ['cpio', '--create', '--format=newc', '--owner', '0:0'] chkcmd = "cpio --create --format=newc --reproducible " chkcmd += "/dev/null 2>&1" if os.system(chkcmd) == 0: params.append('--reproducible') proc = subprocess.Popen( params, shell=False, stdin=subprocess.PIPE, stdout=archivefile, stderr=subprocess.STDOUT ) # transform glob patterns to regular expressions includes = '' excludes = r'$.' topdir_re = '(' + topdir + '/)(' if args.include: incl_arr = [fnmatch.translate(x + '*') for x in args.include] match_list = r'|'.join(incl_arr) includes = topdir_re + match_list + ')' if args.exclude: excl_arr = [fnmatch.translate(x) for x in args.exclude] excludes = topdir_re + r'|'.join(excl_arr) + ')' # add topdir without filtering for now cpiolist = [] for root, dirs, files in os.walk(topdir, topdown=False): # excludes dirs[:] = [os.path.join(root, d) for d in dirs] dirs[:] = [d for d in dirs if not re.match(excludes, d)] dirs[:] = [d for d in dirs if re.match(includes, d)] # exclude/include files files = [os.path.join(root, f) for f in files] files = [f for f in files if not re.match(excludes, f)] files = [f for f in files if re.match(includes, f)] for name in dirs: if not METADATA_PATTERN.match(name) or package_metadata: cpiolist.append(name) for name in files: if not METADATA_PATTERN.match(name) or package_metadata: cpiolist.append(name) tstamp = self.helpers.get_timestamp(scm_object, args, topdir) for name in sorted(cpiolist): try: os.utime(name, (tstamp, tstamp)) except OSError: pass # bytes() break in python2 with a TypeError as it expects only 1 # arg try: proc.stdin.write(name.encode('UTF-8', 'surrogateescape')) except (TypeError, UnicodeDecodeError): proc.stdin.write(name) proc.stdin.write(b"\n") proc.stdin.close() ret_code = proc.wait() if ret_code != 0: raise SystemExit("Creating the cpio archive failed!") archivefile.close() # write meta data infofile = os.path.join(args.outdir, basename + '.obsinfo') logging.debug("Writing to obsinfo file '%s'", infofile) metafile = open(infofile, "w") metafile.write("name: " + basename + "\n") metafile.write("version: " + version + "\n") metafile.write("mtime: " + str(tstamp) + "\n") if commit: metafile.write("commit: " + commit + "\n") metafile.close() self.archivefile = archivefile.name self.metafile = metafile.name os.chdir(cwd)