1
0
mirror of https://github.com/home-assistant/supervisor.git synced 2026-04-02 00:07:16 +01:00

Handle certain OSError in get_latest_mtime during directory walk (#6632)

Besides file not found also catch "Too many levels of symbolic links"
which can happen when there are symbolic link loops in the add-on/apps
repository.

Also improve error handling in the repository update process to catch
OSError when checking for local modifications and raise a specific
error that can be handled appropriately.

Fixes SUPERVISOR-1FJ0

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Stefan Agner
2026-03-27 09:13:48 +01:00
committed by GitHub
parent e2db2315b3
commit 713354bf56
2 changed files with 18 additions and 10 deletions

View File

@@ -219,11 +219,18 @@ class RepositoryLocal(RepositoryBuiltin):
super().__init__(coresys, BuiltinRepository.LOCAL.value, local_path, slug)
self._latest_mtime: float | None = None
async def _get_latest_mtime(self) -> tuple[float, Path]:
"""Get latest modification time of repository."""
try:
return await self.sys_run_in_executor(get_latest_mtime, self.local_path)
except OSError as err:
self.coresys.resolution.check_oserror(err)
_LOGGER.error("Can't check local repository for modifications: %s", err)
raise StoreRepositoryUnknownError(repo=self.slug) from err
async def load(self) -> None:
"""Load addon repository."""
self._latest_mtime, _ = await self.sys_run_in_executor(
get_latest_mtime, self.local_path
)
self._latest_mtime, _ = await self._get_latest_mtime()
async def update(self) -> bool:
"""Update add-on repository.
@@ -231,9 +238,8 @@ class RepositoryLocal(RepositoryBuiltin):
Returns True if the repository was updated.
"""
# Check local modifications
latest_mtime, modified_path = await self.sys_run_in_executor(
get_latest_mtime, self.local_path
)
latest_mtime, modified_path = await self._get_latest_mtime()
if self._latest_mtime != latest_mtime:
_LOGGER.debug(
"Local modifications detected in %s repository: %s",

View File

@@ -1,6 +1,7 @@
"""Tools file for Supervisor."""
import asyncio
import errno
from functools import lru_cache
from ipaddress import IPv4Address
import logging
@@ -146,10 +147,11 @@ def get_latest_mtime(directory: Path) -> tuple[float, Path]:
if mtime > latest_mtime:
latest_mtime = mtime
latest_path = path
except FileNotFoundError:
# File might disappear between listing and stat. Parent
# directory modification date will flag such a change.
continue
except OSError as err:
if err.errno in (errno.ENOENT, errno.ELOOP):
_LOGGER.debug("Could not stat %s, skipping", path)
continue
raise
return latest_mtime, latest_path