mirror of
https://github.com/esphome/esphome.git
synced 2026-08-30 17:46:01 +00:00
[core] Replace a damaged existing file in write_file_if_changed (#18665)
This commit is contained in:
+12
-1
@@ -552,7 +552,18 @@ def write_file_if_changed(path: Path, text: str) -> bool:
|
||||
"""
|
||||
src_content = None
|
||||
if path.is_file():
|
||||
src_content = read_file(path)
|
||||
try:
|
||||
src_content = path.read_text(encoding="utf-8")
|
||||
except UnicodeDecodeError as err:
|
||||
# Replace a damaged file rather than abort the regeneration that
|
||||
# fixes it; an OSError may hide an intact file, so it still raises
|
||||
_LOGGER.warning("Replacing damaged file %s: %s", path, err)
|
||||
with suppress(OSError):
|
||||
path.unlink(missing_ok=True)
|
||||
except OSError as err:
|
||||
from esphome.core import EsphomeError
|
||||
|
||||
raise EsphomeError(f"Error reading file {path}: {err}") from err
|
||||
if src_content == text:
|
||||
return False
|
||||
write_file(path, text)
|
||||
|
||||
@@ -253,6 +253,31 @@ class Test_write_file_if_changed:
|
||||
|
||||
assert dst.read_text() == text
|
||||
|
||||
def test_damaged_existing_file_is_replaced(
|
||||
self, tmp_path: Path, caplog: pytest.LogCaptureFixture
|
||||
):
|
||||
"""A non-UTF-8 existing file is logged and overwritten."""
|
||||
dst = tmp_path / "generated.txt"
|
||||
dst.write_bytes(b"\xff\xfe")
|
||||
|
||||
assert helpers.write_file_if_changed(dst, "fresh content") is True
|
||||
|
||||
assert dst.read_text(encoding="utf-8") == "fresh content"
|
||||
assert "Replacing damaged file" in caplog.text
|
||||
|
||||
def test_unreadable_existing_file_still_raises(self, tmp_path: Path):
|
||||
"""An OSError on the comparison read still raises EsphomeError."""
|
||||
dst = tmp_path / "generated.txt"
|
||||
dst.write_text("intact")
|
||||
|
||||
with (
|
||||
patch.object(Path, "read_text", side_effect=OSError("permission denied")),
|
||||
pytest.raises(EsphomeError, match="Error reading file"),
|
||||
):
|
||||
helpers.write_file_if_changed(dst, "fresh content")
|
||||
|
||||
assert dst.exists()
|
||||
|
||||
def test_dst_does_not_exist(self, tmp_path: Path):
|
||||
text = "A files are unique.\n"
|
||||
dst = tmp_path / "file-a.txt"
|
||||
|
||||
Reference in New Issue
Block a user