Skip to content

Commit 5aec004

Browse files
author
Sergio Schvezov
authored
repo: consider virtual pkgs for cache invalidation (#3177)
Virtual packages were not considered when checking if all build-packages are satisfied between runs. Check and resolve with a warning to avoid use of virtual packages for deterministic results. LP: #1883546 Signed-off-by: Sergio Schvezov <sergio.schvezov@canonical.com>
1 parent fb967fe commit 5aec004

4 files changed

Lines changed: 18 additions & 4 deletions

File tree

snapcraft/internal/repo/_deb.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,9 @@ def _check_if_all_packages_installed(cls, package_names: List[str]) -> bool:
316316
with AptCache() as apt_cache:
317317
for package in package_names:
318318
pkg_name, pkg_version = get_pkg_name_parts(package)
319-
installed_version = apt_cache.get_installed_version(pkg_name)
319+
installed_version = apt_cache.get_installed_version(
320+
pkg_name, resolve_virtual_packages=True
321+
)
320322

321323
if installed_version is None or (
322324
pkg_version is not None and installed_version != pkg_version

snapcraft/internal/repo/apt_cache.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,19 @@ def _verify_marked_install(self, package: apt.Package):
140140
def is_package_valid(self, package_name: str) -> bool:
141141
return package_name in self.cache or self.cache.is_virtual_package(package_name)
142142

143-
def get_installed_version(self, package_name: str) -> Optional[str]:
143+
def get_installed_version(
144+
self, package_name: str, *, resolve_virtual_packages: bool = False
145+
) -> Optional[str]:
146+
if resolve_virtual_packages and self.cache.is_virtual_package(package_name):
147+
logger.warning(
148+
f"{package_name!r} is a virtual package, use non virtual packages for deterministic results."
149+
)
150+
# Recusrse until a "real" package is found.
151+
return self.get_installed_version(
152+
self.cache.get_providing_packages(package_name)[0].name,
153+
resolve_virtual_packages=resolve_virtual_packages,
154+
)
155+
144156
if package_name in self.cache:
145157
if self.cache[package_name].installed is not None:
146158
return self.cache[package_name].installed.version

tests/spread/general/virtual-packages/task.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ execute: |
2121
fi
2222
2323
cd "$SNAP_DIR"
24-
snapcraft build
24+
snapcraft build | MATCH "is a virtual package"
2525
2626
if [ ! -f "${test_file}" ]; then
2727
echo "failed to install uglifyjs build package"

tests/unit/repo/test_deb.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ def setUp(self):
183183
fixtures.MockPatch("subprocess.check_call")
184184
).mock
185185

186-
def get_installed_version(package_name):
186+
def get_installed_version(package_name, resolve_virtual_packages=False):
187187
return "1.0" if "installed" in package_name else None
188188

189189
self.fake_apt_cache.return_value.__enter__.return_value.get_installed_version.side_effect = (

0 commit comments

Comments
 (0)