Skip to content

Commit 9491b1f

Browse files
Avoid reordering add-on repositories on Backup load (#5595)
* Avoid reordering add-on repositories on Backup load The `ensure_builtin_repositories` function uses a set to deduplicate items, which sometimes led to a change of order in elements. This is problematic when deduplicating Backups. Simply avoid mangling the list of add-on repositories on load. Instead rely on `update_repositories` which uses the same function to ensure built-in repositories when loading the store configuration and restoring a backup file. * Update tests * ruff format * ruff check * ruff check fixes * ruff format * Update tests/store/test_validate.py Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Simplify test --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
1 parent 30cbb03 commit 9491b1f

File tree

4 files changed

+42
-51
lines changed

4 files changed

+42
-51
lines changed

supervisor/backups/backup.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,12 +162,12 @@ def folders(self) -> list[str]:
162162

163163
@property
164164
def repositories(self) -> list[str]:
165-
"""Return backup date."""
165+
"""Return add-on store repositories."""
166166
return self._data[ATTR_REPOSITORIES]
167167

168168
@repositories.setter
169169
def repositories(self, value: list[str]) -> None:
170-
"""Set backup date."""
170+
"""Set add-on store repositories."""
171171
self._data[ATTR_REPOSITORIES] = value
172172

173173
@property
@@ -286,7 +286,7 @@ def __eq__(self, other: Any) -> bool:
286286
or k not in other._data
287287
or self._data[k] != other._data[k]
288288
):
289-
_LOGGER.debug(
289+
_LOGGER.info(
290290
"Backup %s and %s not equal because %s field has different value: %s and %s",
291291
self.slug,
292292
other.slug,

supervisor/store/validate.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,15 @@
2828
)
2929

3030

31+
def ensure_builtin_repositories(addon_repositories: list[str]) -> list[str]:
32+
"""Ensure builtin repositories are in list.
33+
34+
Note: This should not be used in validation as the resulting list is not
35+
stable. This can have side effects when comparing data later on.
36+
"""
37+
return list(set(addon_repositories) | BUILTIN_REPOSITORIES)
38+
39+
3140
def validate_repository(repository: str) -> str:
3241
"""Validate a valid repository."""
3342
if repository in [StoreType.CORE, StoreType.LOCAL]:
@@ -44,13 +53,7 @@ def validate_repository(repository: str) -> str:
4453
return repository
4554

4655

47-
def ensure_builtin_repositories(addon_repositories: list[str]) -> list[str]:
48-
"""Ensure builtin repositories are in list."""
49-
return list(set(addon_repositories) | BUILTIN_REPOSITORIES)
50-
51-
52-
# pylint: disable=no-value-for-parameter
53-
repositories = vol.All([validate_repository], vol.Unique(), ensure_builtin_repositories)
56+
repositories = vol.All([validate_repository], vol.Unique())
5457

5558
SCHEMA_STORE_FILE = vol.Schema(
5659
{

tests/backups/test_backup.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,30 @@ async def test_consolidate_conflict_varied_encryption(
4545
in caplog.text
4646
)
4747
assert enc_backup.all_locations == {None: {"path": unc_tar, "protected": False}}
48+
49+
50+
async def test_consolidate(
51+
coresys: CoreSys,
52+
tmp_path: Path,
53+
tmp_supervisor_data: Path,
54+
caplog: pytest.LogCaptureFixture,
55+
):
56+
"""Test consolidate with two backups in different location and varied encryption."""
57+
(mount_dir := coresys.config.path_mounts / "backup_test").mkdir()
58+
enc_tar = Path(copy(get_fixture_path("test_consolidate.tar"), tmp_path))
59+
enc_backup = Backup(coresys, enc_tar, "test", None)
60+
await enc_backup.load()
61+
62+
unc_tar = Path(copy(get_fixture_path("test_consolidate_unc.tar"), mount_dir))
63+
unc_backup = Backup(coresys, unc_tar, "test", "backup_test")
64+
await unc_backup.load()
65+
66+
enc_backup.consolidate(unc_backup)
67+
assert (
68+
"Backup in backup_test and None both have slug d9c48f8b but are not the same!"
69+
not in caplog.text
70+
)
71+
assert enc_backup.all_locations == {
72+
None: {"path": enc_tar, "protected": True},
73+
"backup_test": {"path": unc_tar, "protected": False},
74+
}

tests/store/test_validate.py

Lines changed: 2 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,14 @@
11
"""Test schema validation."""
22

3-
from typing import Any
4-
53
import pytest
64
from voluptuous import Invalid
75

8-
from supervisor.const import ATTR_REPOSITORIES
9-
from supervisor.store.validate import SCHEMA_STORE_FILE, repositories
10-
11-
12-
@pytest.mark.parametrize(
13-
"config",
14-
[
15-
{},
16-
{ATTR_REPOSITORIES: []},
17-
{ATTR_REPOSITORIES: ["https://github.com/esphome/home-assistant-addon"]},
18-
],
19-
)
20-
async def test_default_config(config: dict[Any]):
21-
"""Test built-ins included by default."""
22-
conf = SCHEMA_STORE_FILE(config)
23-
assert ATTR_REPOSITORIES in conf
24-
assert "core" in conf[ATTR_REPOSITORIES]
25-
assert "local" in conf[ATTR_REPOSITORIES]
26-
assert "https://github.com/hassio-addons/repository" in conf[ATTR_REPOSITORIES]
27-
assert (
28-
len(
29-
[
30-
repo
31-
for repo in conf[ATTR_REPOSITORIES]
32-
if repo == "https://github.com/esphome/home-assistant-addon"
33-
]
34-
)
35-
== 1
36-
)
6+
from supervisor.store.validate import repositories
377

388

399
@pytest.mark.parametrize(
4010
"repo_list,valid",
4111
[
42-
([], True),
4312
(["core", "local"], True),
4413
(["https://github.com/hassio-addons/repository"], True),
4514
(["not_a_url"], False),
@@ -49,15 +18,7 @@ async def test_default_config(config: dict[Any]):
4918
async def test_repository_validate(repo_list: list[str], valid: bool):
5019
"""Test repository list validate."""
5120
if valid:
52-
processed = repositories(repo_list)
53-
assert len(processed) == 5
54-
assert set(repositories(repo_list)) == {
55-
"core",
56-
"local",
57-
"https://github.com/hassio-addons/repository",
58-
"https://github.com/esphome/home-assistant-addon",
59-
"https://github.com/music-assistant/home-assistant-addon",
60-
}
21+
assert repositories(repo_list) == repo_list
6122
else:
6223
with pytest.raises(Invalid):
6324
repositories(repo_list)

0 commit comments

Comments
 (0)