diff --git a/src/python/txtai/archive/zip.py b/src/python/txtai/archive/zip.py index a068a5764..1b0cb7da6 100644 --- a/src/python/txtai/archive/zip.py +++ b/src/python/txtai/archive/zip.py @@ -18,12 +18,17 @@ def pack(self, path, output): with ZipFile(output, "w", ZIP_DEFLATED) as zfile: for root, _, files in sorted(os.walk(path)): for f in files: - zfile.write(os.path.join(root, f), arcname=f) + # Generate archive name with relative path, if necessary + name = os.path.join(os.path.relpath(root, path), f) + + # Write file to zip + zfile.write(os.path.join(root, f), arcname=name) def unpack(self, path, output): with ZipFile(path, "r") as zfile: # Validate path if directory specified for fullpath in zfile.namelist(): + fullpath = os.path.join(path, fullpath) if os.path.dirname(fullpath) and not self.validate(path, fullpath): raise IOError(f"Invalid zip entry: {fullpath}") diff --git a/test/python/testarchive.py b/test/python/testarchive.py index b199586d5..dd1466e74 100644 --- a/test/python/testarchive.py +++ b/test/python/testarchive.py @@ -20,6 +20,35 @@ class TestArchive(unittest.TestCase): Archive tests. """ + def testDirectory(self): + """ + Test directory included in compressed files + """ + + for extension in ["tar", "zip"]: + # Create archive instance + archive = ArchiveFactory.create() + + # Create subdirectory in archive working path + path = os.path.join(archive.path(), "dir") + os.makedirs(path, exist_ok=True) + + # Create file in archive working path + with open(os.path.join(path, "test"), "w", encoding="utf-8") as f: + f.write("test") + + # Save archive + path = os.path.join(tempfile.gettempdir(), f"subdir.{extension}") + archive.save(path) + + # Extract files from archive + archive = ArchiveFactory.create() + archive.load(path) + + # Check if file properly extracted + path = os.path.join(archive.path(), "dir", "test") + self.assertTrue(os.path.exists(path)) + def testInvalidTar(self): """ Test invalid tar file