tests/functional: add a generalized archive_extract

There are many types of archives that the tests deal with. Provide
a generalized 'archive_extract' that can detect the format and
delegate to the appropriate helper for extraction. This ensures
that all archive extraction code follows the same design pattern.

Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Message-ID: <20241217155953.3950506-22-berrange@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
This commit is contained in:
Daniel P. Berrangé 2024-12-17 15:59:42 +00:00 committed by Thomas Huth
parent c055f1d26f
commit c283afbf65
2 changed files with 59 additions and 0 deletions

View file

@ -10,8 +10,10 @@
import os
from subprocess import check_call, run, DEVNULL
import tarfile
from urllib.parse import urlparse
import zipfile
from .asset import Asset
from .cmd import run_cmd
@ -56,3 +58,59 @@ def deb_extract(archive, dest_dir, member=None):
tar_extract(file_path, dest_dir, member)
finally:
os.chdir(cwd)
'''
@params archive: filename, Asset, or file-like object to extract
@params dest_dir: target directory to extract into
@params member: optional member file to limit extraction to
Extracts @archive into @dest_dir. All files are extracted
unless @member specifies a limit.
If @format is None, heuristics will be applied to guess the format
from the filename or Asset URL. @format must be non-None if @archive
is a file-like object.
'''
def archive_extract(archive, dest_dir, format=None, member=None):
if format is None:
format = guess_archive_format(archive)
if type(archive) == Asset:
archive = str(archive)
if format == "tar":
tar_extract(archive, dest_dir, member)
elif format == "zip":
zip_extract(archive, dest_dir, member)
elif format == "cpio":
if member is not None:
raise Exception("Unable to filter cpio extraction")
cpio_extract(archive, dest_dir)
elif format == "deb":
if type(archive) != str:
raise Exception("Unable to use file-like object with deb archives")
deb_extract(archive, dest_dir, "./" + member)
else:
raise Exception(f"Unknown archive format {format}")
'''
@params archive: filename, or Asset to guess
Guess the format of @compressed, raising an exception if
no format can be determined
'''
def guess_archive_format(archive):
if type(archive) == Asset:
archive = urlparse(archive.url).path
elif type(archive) != str:
raise Exception(f"Unable to guess archive format for {archive}")
if ".tar." in archive or archive.endswith("tgz"):
return "tar"
elif archive.endswith(".zip"):
return "zip"
elif archive.endswith(".cpio"):
return "cpio"
elif archive.endswith(".deb") or archive.endswith(".udeb"):
return "deb"
else:
raise Exception(f"Unknown archive format for {archive}")