@@ -4712,6 +4712,7 @@ def run_clean(args: Args, config: Config, repository_metadata_needs_sync: bool =
47124712 # be able to remove various files from the rootfs.
47134713 sandbox = functools .partial (config .sandbox , tools = False )
47144714
4715+ remove_image_cache_reason : Optional [str ] = None
47154716 if args .verb == Verb .clean :
47164717 remove_outputs = True
47174718 remove_build_cache = args .force > 0 or args .wipe_build_dir
@@ -4723,7 +4724,17 @@ def run_clean(args: Args, config: Config, repository_metadata_needs_sync: bool =
47234724 config .is_incremental () and not have_cache (config )
47244725 )
47254726 remove_build_cache = args .force > 1 or args .wipe_build_dir
4726- remove_image_cache = args .force > 1 or not have_cache (config ) or repository_metadata_needs_sync
4727+ if args .force > 1 :
4728+ remove_image_cache = True
4729+ remove_image_cache_reason = "'--force' was passed at least twice"
4730+ elif not have_cache (config ):
4731+ remove_image_cache = True
4732+ remove_image_cache_reason = "the cached image is out of date"
4733+ elif repository_metadata_needs_sync :
4734+ remove_image_cache = True
4735+ remove_image_cache_reason = "package manager metadata is being re-synced"
4736+ else :
4737+ remove_image_cache = False
47274738 remove_package_cache = args .force > 2
47284739
47294740 if remove_outputs :
@@ -4762,6 +4773,8 @@ def run_clean(args: Args, config: Config, repository_metadata_needs_sync: bool =
47624773 rmtree (* config .build_subdir .iterdir (), sandbox = sandbox )
47634774
47644775 if remove_image_cache and config .cache_dir and any (p .exists () for p in cache_tree_paths (config )):
4776+ if remove_image_cache_reason is not None :
4777+ logging .info (f"Removing cache entries of { config .image } image: { remove_image_cache_reason } " )
47654778 with complete_step (f"Removing cache entries of { config .image } image…" ):
47664779 rmtree (* (p for p in cache_tree_paths (config ) if p .exists ()), sandbox = sandbox )
47674780
@@ -4797,11 +4810,18 @@ def ensure_directories_exist(config: Config) -> None:
47974810 config .build_subdir .chmod (stat .S_IMODE (st .st_mode ) & ~ (stat .S_ISGID | stat .S_ISUID ))
47984811
47994812
4800- def repository_metadata_needs_sync (images : Sequence [Config ]) -> bool :
4801- if any (c .cacheonly == Cacheonly .never for c in images ):
4813+ def repository_metadata_needs_sync (images : Sequence [Config ], log : bool = False ) -> bool :
4814+ if never := [c .image for c in images if c .cacheonly == Cacheonly .never ]:
4815+ if log :
4816+ logging .info (
4817+ "Syncing package manager metadata: images with 'Cacheonly=never' present "
4818+ f"({ ', ' .join (sorted (never ))} )"
4819+ )
48024820 return True
48034821
48044822 if not (auto := [c for c in images if c .cacheonly == Cacheonly .auto ]):
4823+ if log :
4824+ logging .info ("Skipping package manager metadata sync: no images with 'Cacheonly=auto'" )
48054825 return False
48064826
48074827 # If there are no incremental images at all, we have no caches to preserve, so
@@ -4811,6 +4831,8 @@ def repository_metadata_needs_sync(images: Sequence[Config]) -> bool:
48114831 # metadata, but that's the cost of mixing them with incremental images we want
48124832 # to preserve.
48134833 if not (incremental := [c for c in auto if c .is_incremental ()]):
4834+ if log :
4835+ logging .info ("Syncing package manager metadata: no incremental images, no caches to preserve" )
48144836 return True
48154837
48164838 # Use the manifest file as the "previously cached" marker: it's written when an
@@ -4825,11 +4847,35 @@ def repository_metadata_needs_sync(images: Sequence[Config]) -> bool:
48254847 # metadata is by construction consistent with the caches that do exist, so we
48264848 # don't need to re-sync.
48274849 if all (not cache_tree_paths (c )[2 ].exists () for c in incremental ):
4850+ if log :
4851+ logging .info ("Syncing package manager metadata: no incremental image has a cache manifest" )
48284852 return True
48294853
4830- return all (cache_tree_paths (c )[2 ].exists () for c in incremental ) and not all (
4831- have_cache (c ) for c in incremental
4832- )
4854+ if all (cache_tree_paths (c )[2 ].exists () for c in incremental ):
4855+ if all (have_cache (c ) for c in incremental ):
4856+ if log :
4857+ logging .info (
4858+ "Skipping package manager metadata sync: all incremental image caches are up to date"
4859+ )
4860+ return False
4861+ if log :
4862+ stale = sorted (c .image for c in incremental if not have_cache (c ))
4863+ logging .info (
4864+ f"Syncing package manager metadata: cached images are out of date: ({ ', ' .join (stale )} )"
4865+ )
4866+ return True
4867+
4868+ if log :
4869+ with_manifest = sorted (c .image for c in incremental if cache_tree_paths (c )[2 ].exists ())
4870+ without_manifest = sorted (c .image for c in incremental if not cache_tree_paths (c )[2 ].exists ())
4871+ logging .info (
4872+ "Skipping package manager metadata sync: assuming mid-build-failure recovery "
4873+ f"(images with cache manifest: { ', ' .join (with_manifest )} ; "
4874+ f"without: { ', ' .join (without_manifest )} )"
4875+ )
4876+ logging .info ("If package installation fails because of stale metadata, re-run with '-ff'" )
4877+
4878+ return False
48334879
48344880
48354881def sync_repository_metadata (
@@ -4880,7 +4926,7 @@ def sync_repository_metadata(
48804926 (last .package_cache_dir_or_default () / "cache" / subdir ).mkdir (parents = True , exist_ok = True )
48814927
48824928 # Sync repository metadata unless explicitly disabled.
4883- if repository_metadata_needs_sync (images ):
4929+ if repository_metadata_needs_sync (images , log = True ):
48844930 with setup_workspace (args , last ) as workspace :
48854931 context = Context (
48864932 args ,
0 commit comments