From: Michael Tremer Date: Wed, 8 Mar 2023 11:05:40 +0000 (+0000) Subject: repositories: Compose them seperately and atomically swap X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=10aaca72cdb9a52cc66d0577c2f771f1245b82e4;p=pbs.git repositories: Compose them seperately and atomically swap We will now create the repositories in our temporary space, which will allow us to be sure that we generated a consistent repository. We will then swap the new directory with the former one atomically so that the repository is accessible at all times. Signed-off-by: Michael Tremer --- diff --git a/src/buildservice/repository.py b/src/buildservice/repository.py index 58d44210..6ea60abe 100644 --- a/src/buildservice/repository.py +++ b/src/buildservice/repository.py @@ -6,6 +6,8 @@ import datetime import io import logging import os.path +import shutil +import tempfile import pakfire @@ -614,17 +616,40 @@ class Repository(base.DataObject): def _write(self): log.info("Writing repository %s..." % self) + # Write any new repositories to the temporary space first + tmp = self.backend.path("tmp") + # Create a new pakfire instance - with self.pakfire() as p: - for arch in self.arches: + with tempfile.TemporaryDirectory(dir=tmp, prefix="pakfire-repo-") as t: + with self.pakfire() as p: + for arch in self.arches: + # Destination path for this architecture + path = os.path.join(t, arch) + + # Fetch packages + packages = self.get_packages(arch) + + # Make filelist (if they exist) + files = [p.path for p in packages if os.path.exists(p.path)] + + # Write repository metadata + p.repo_compose(path=path, files=files) + + # Mark the repository as read-only + os.chmod(t, 0o755) + + # Perform an atomic replace of the repository directory + with tempfile.TemporaryDirectory(dir=tmp, prefix="pakfire-repo-") as bin: # Local path - path = self.local_path(arch) + path = self.local_path() - # Fetch packages - packages = self.get_packages(arch) + # Move the old data to the temporary space + try: + shutil.move(path, bin) - # Make filelist (if they exist) - files = [p.path for p in packages if os.path.exists(p.path)] + # Ignore if this repository is being created for the first time + except FileNotFoundError: + pass - # Write repository metadata - p.repo_compose(path=path, files=files) + # Move the new repository data to its destination + shutil.move(t, path)