From: Daan De Meyer Date: Thu, 14 Mar 2024 13:30:25 +0000 (+0100) Subject: Introduce lock_repository_metadata() X-Git-Tag: v23~94^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8a1342e4c518957bb8c33f70cf04c28e9625d237;p=thirdparty%2Fmkosi.git Introduce lock_repository_metadata() --- diff --git a/mkosi/__init__.py b/mkosi/__init__.py index 3fb13b71a..c2f480e17 100644 --- a/mkosi/__init__.py +++ b/mkosi/__init__.py @@ -3316,6 +3316,18 @@ def setup_workspace(args: Args, config: Config) -> Iterator[Path]: raise +@contextlib.contextmanager +def lock_repository_metadata(config: Config) -> Iterator[None]: + subdir = config.distribution.package_manager(config).subdir(config) + + with contextlib.ExitStack() as stack: + for d in ("cache", "lib"): + if (src := config.package_cache_dir_or_default() / d / subdir).exists(): + stack.enter_context(flock(src)) + + yield + + def copy_repository_metadata(context: Context) -> None: if have_cache(context.config): return @@ -3330,29 +3342,32 @@ def copy_repository_metadata(context: Context) -> None: logging.debug(f"Found repository metadata in {context.package_cache_dir}, not copying repository metadata") return - for d in ("cache", "lib"): - src = context.config.package_cache_dir_or_default() / d / subdir - if not src.exists(): - logging.debug(f"{src} does not exist, not copying repository metadata from it") - continue + with lock_repository_metadata(context.config): + for d in ("cache", "lib"): + src = context.config.package_cache_dir_or_default() / d / subdir + if not src.exists(): + logging.debug(f"{src} does not exist, not copying repository metadata from it") + continue - caches = context.config.distribution.package_manager(context.config).cache_subdirs(src) if d == "cache" else [] + if d == "cache": + caches = context.config.distribution.package_manager(context.config).cache_subdirs(src) + else: + caches = [] - with tempfile.TemporaryDirectory() as tmp: - os.chmod(tmp, 0o755) + with tempfile.TemporaryDirectory() as tmp: + os.chmod(tmp, 0o755) - # cp doesn't support excluding directories but we can imitate it by bind mounting an empty directory over - # the directories we want to exclude. - exclude = flatten(["--ro-bind", tmp, os.fspath(p)] for p in caches) + # cp doesn't support excluding directories but we can imitate it by bind mounting an empty directory + # over the directories we want to exclude. + exclude = flatten(["--ro-bind", tmp, os.fspath(p)] for p in caches) - dst = context.package_cache_dir / d / subdir - with umask(~0o755): - dst.mkdir(parents=True, exist_ok=True) + dst = context.package_cache_dir / d / subdir + with umask(~0o755): + dst.mkdir(parents=True, exist_ok=True) - def sandbox(*, options: Sequence[PathString] = ()) -> list[PathString]: - return context.sandbox(options=[*options, *exclude]) + def sandbox(*, options: Sequence[PathString] = ()) -> list[PathString]: + return context.sandbox(options=[*options, *exclude]) - with flock(src): copy_tree( src, dst, tools=context.config.tools(), @@ -3965,7 +3980,10 @@ def run_clean(args: Args, config: Config, *, resources: Path) -> None: ): subdir = config.distribution.package_manager(config).subdir(config) - with complete_step(f"Clearing out package cache of {config.name()} image…"): + with ( + complete_step(f"Clearing out package cache of {config.name()} image…"), + lock_repository_metadata(config), + ): rmtree( *( config.package_cache_dir_or_default() / d / subdir @@ -3990,14 +4008,11 @@ def sync_repository_metadata(context: Context) -> None: if have_cache(context.config) or context.config.cacheonly != Cacheonly.none: return - with complete_step(f"Syncing package manager metadata for {context.config.name()} image"): - subdir = context.config.distribution.package_manager(context.config).subdir(context.config) - - with ( - flock(context.config.package_cache_dir_or_default() / "cache" / subdir), - flock(context.config.package_cache_dir_or_default() / "lib" / subdir), - ): - context.config.distribution.package_manager(context.config).sync(context) + with ( + complete_step(f"Syncing package manager metadata for {context.config.name()} image"), + lock_repository_metadata(context.config), + ): + context.config.distribution.package_manager(context.config).sync(context) def run_sync(args: Args, config: Config, *, resources: Path) -> None: