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:
@@ -219,11 +219,18 @@ class RepositoryLocal(RepositoryBuiltin):
|
|||||||
super().__init__(coresys, BuiltinRepository.LOCAL.value, local_path, slug)
|
super().__init__(coresys, BuiltinRepository.LOCAL.value, local_path, slug)
|
||||||
self._latest_mtime: float | None = None
|
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:
|
async def load(self) -> None:
|
||||||
"""Load addon repository."""
|
"""Load addon repository."""
|
||||||
self._latest_mtime, _ = await self.sys_run_in_executor(
|
self._latest_mtime, _ = await self._get_latest_mtime()
|
||||||
get_latest_mtime, self.local_path
|
|
||||||
)
|
|
||||||
|
|
||||||
async def update(self) -> bool:
|
async def update(self) -> bool:
|
||||||
"""Update add-on repository.
|
"""Update add-on repository.
|
||||||
@@ -231,9 +238,8 @@ class RepositoryLocal(RepositoryBuiltin):
|
|||||||
Returns True if the repository was updated.
|
Returns True if the repository was updated.
|
||||||
"""
|
"""
|
||||||
# Check local modifications
|
# Check local modifications
|
||||||
latest_mtime, modified_path = await self.sys_run_in_executor(
|
latest_mtime, modified_path = await self._get_latest_mtime()
|
||||||
get_latest_mtime, self.local_path
|
|
||||||
)
|
|
||||||
if self._latest_mtime != latest_mtime:
|
if self._latest_mtime != latest_mtime:
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"Local modifications detected in %s repository: %s",
|
"Local modifications detected in %s repository: %s",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
"""Tools file for Supervisor."""
|
"""Tools file for Supervisor."""
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import errno
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
from ipaddress import IPv4Address
|
from ipaddress import IPv4Address
|
||||||
import logging
|
import logging
|
||||||
@@ -146,10 +147,11 @@ def get_latest_mtime(directory: Path) -> tuple[float, Path]:
|
|||||||
if mtime > latest_mtime:
|
if mtime > latest_mtime:
|
||||||
latest_mtime = mtime
|
latest_mtime = mtime
|
||||||
latest_path = path
|
latest_path = path
|
||||||
except FileNotFoundError:
|
except OSError as err:
|
||||||
# File might disappear between listing and stat. Parent
|
if err.errno in (errno.ENOENT, errno.ELOOP):
|
||||||
# directory modification date will flag such a change.
|
_LOGGER.debug("Could not stat %s, skipping", path)
|
||||||
continue
|
continue
|
||||||
|
raise
|
||||||
return latest_mtime, latest_path
|
return latest_mtime, latest_path
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user