From e4fd6dae0fad2be998e3708856eabdfba90624dd Mon Sep 17 00:00:00 2001 From: Pavel Raiskup Date: Jun 28 2022 11:22:21 +0000 Subject: Extract source RPMs with rpm2archive if possible The output format from rpm2archive is not bound with the 4GB file size limit, like the rpm2cpio is. Unfortunately, rpm2archive doesn'ลง exist on EL7, and still doesn't support the -n option on EL8. Related: https://pagure.io/copr/copr/issue/2225 Signed-off-by: Pavel Raiskup --- diff --git a/pyrpkg/utils.py b/pyrpkg/utils.py index d754d78..d3f7877 100644 --- a/pyrpkg/utils.py +++ b/pyrpkg/utils.py @@ -245,6 +245,21 @@ def is_file_in_directory(file_path, dir_path): return +def check_rpm2archive(): + """ + Check if rpm2archive exists, and if it supports the required argument. + """ + + try: + popen = subprocess.Popen(["rpm2archive", "--help"], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + return "--nocompression" in popen.communicate()[0].decode("utf8") + except OSError: + pass + return False + + def extract_srpm(srpm_path, target_dir=None): """ Extract srpm file into target directory. Target directory is a current @@ -255,13 +270,24 @@ def extract_srpm(srpm_path, target_dir=None): if target_dir and not os.path.isdir(target_dir): raise IOError("Target directory doesn't exist: {0}".format(target_dir)) - # rpm2cpio | cpio -iud --quiet - cmd = ['rpm2cpio', srpm_path] - # We have to force cpio to copy out (u) because git messes with timestamps - cmd2 = ['cpio', '-iud', '--quiet'] - rpmcall = subprocess.Popen(cmd, stdout=subprocess.PIPE, universal_newlines=True) - cpiocall = subprocess.Popen(cmd2, stdin=rpmcall.stdout, universal_newlines=True, cwd=target_dir) - output, err = cpiocall.communicate() + # We prefer using the newer rpm2archive utility over rpm2cpio for extraction + # because it supports SRPMs >= 4GB (as long as it is available, i.e. epel8+) + use_rpm2archive = check_rpm2archive() + + # Use one of those: + # rpm2archive -n - < SRPM_PATH | tar xf - + # rpm2cpio - < SRPM_PATH | cpio -iud --quiet + cmd = ['rpm2archive', '-n', '-'] if use_rpm2archive else ['rpm2cpio', '-'] + # Overwrite existing files (tar's default, cpio -u), because git messes with + # timestamps. + cmd2 = ['tar', 'xf', '-'] if use_rpm2archive else ['cpio', '-iud', '--quiet'] + + with open(srpm_path, 'r') as stdin: + rpmcall = subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=stdin, + universal_newlines=True) + cpiocall = subprocess.Popen(cmd2, stdin=rpmcall.stdout, + universal_newlines=True, cwd=target_dir) + output, err = cpiocall.communicate() return output, err