Skip to content

Commit 99747cf

Browse files
Reopen named files also before saving (#470)
Reopen named files also before saving The underlying file could have been deleted or replaced and its inode may be different, reopening it just before writing should ensure the content is written where it's supposed to. Reviewed-by: Matej Focko Reviewed-by: Laura Barcziová
2 parents e059c30 + a67e12e commit 99747cf

File tree

3 files changed

+32
-10
lines changed

3 files changed

+32
-10
lines changed

plans/packit-integration.fmf

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ adjust:
2626
- how: shell
2727
script: pip3 install build 'deepdiff < 8.0.0' # version 8.0.0 depends on numpy, avoid it
2828

29-
- when: "distro == rhel-8 or distro == centos-8 or distro == centos-stream-8"
29+
- when: >
30+
distro == rhel-8 or distro == centos-8 or distro == centos-stream-8 or
31+
distro == rhel-9 or distro == centos-9 or distro == centos-stream-9
3032
because: "packit doesn't support EL 8"
3133
enabled: false

specfile/specfile.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,12 @@ def _read_lines(cls, file: IO) -> Tuple[List[str], bool]:
202202
content = raw_content.decode(**cls.ENCODING_ARGS)
203203
return content.splitlines(), content.endswith("\n")
204204

205+
def _reopen_named_file(self) -> None:
206+
if not self.path:
207+
return
208+
self._file.close()
209+
self._file = self.path.open("r+", **self.ENCODING_ARGS)
210+
205211
@property
206212
def path(self) -> Optional[Path]:
207213
"""Path to the spec file."""
@@ -263,21 +269,17 @@ def rpm_spec(self) -> rpm.spec:
263269

264270
def reload(self) -> None:
265271
"""Reloads the spec file content."""
266-
try:
267-
path = Path(cast(FileIO, self._file).name)
268-
except AttributeError:
269-
pass
270-
else:
271-
# reopen the path in case the original file has been deleted/replaced
272-
self._file.close()
273-
self._file = path.open("r+", **self.ENCODING_ARGS)
272+
# reopen the path in case the original file has been deleted/replaced
273+
self._reopen_named_file()
274274
self._lines, self._trailing_newline = self._read_lines(self._file)
275275

276276
def save(self) -> None:
277277
"""Saves the spec file content."""
278+
content = str(self)
279+
# reopen the path in case the original file has been deleted/replaced
280+
self._reopen_named_file()
278281
self._file.seek(0)
279282
self._file.truncate(0)
280-
content = str(self)
281283
try:
282284
self._file.write(content)
283285
except TypeError:

tests/integration/test_specfile.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,3 +710,21 @@ def test_reload(specfile_factory, spec_minimal, spec_traditional, remove_spec):
710710
after_reload = spec
711711

712712
assert str(before_reload) != str(after_reload)
713+
714+
715+
def test_save_after_inode_change(specfile_factory, spec_minimal):
716+
spec = specfile_factory(spec_minimal)
717+
if spec.path is None:
718+
return
719+
inode = spec_minimal.stat().st_ino
720+
content = spec_minimal.read_bytes()
721+
spec_minimal.unlink()
722+
spec_minimal.write_bytes(content)
723+
assert spec_minimal.stat().st_ino != inode
724+
spec.version = "0.2"
725+
spec.save()
726+
assert all(
727+
line.endswith("0.2")
728+
for line in spec_minimal.read_text().splitlines()
729+
if line.startswith("Version:")
730+
)

0 commit comments

Comments
 (0)