Use shutil.move() instead of os.rename()

Because os.rename() fails when renaming files across different
filesystems.

This issue can be easily triggered if we mount the "newver" file as a
volume in Docker, and then run nvchecker.

For example:

$ docker run -v ./source.toml:/source.toml \
             -v ./old.json:/old.json \
             -v ./new.json:/new.json \
             localhost/nvchecker -c /source.toml
[I 04-23 13:47:18.537 core:408] mysource: updated from 1.0.0 to 1.0.1 taskName=Task-2
Traceback (most recent call last):
  File "/usr/bin/nvchecker", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/lib/python3.12/site-packages/nvchecker/__main__.py", line 96, in main
    core.write_verfile(newverf, vers)
  File "/lib/python3.12/site-packages/nvchecker/core.py", line 167, in write_verfile
    safe_overwrite(file, data)
  File "/lib/python3.12/site-packages/nvchecker/core.py", line 128, in safe_overwrite
    os.rename(tmpname, resolved_path)
OSError: [Errno 16] Resource busy: '/new.json.tmp' -> '/new.json'
This commit is contained in:
guihkx 2024-04-23 04:41:02 -03:00
parent f1ff604b4c
commit 8546f6abd2
No known key found for this signature in database

View file

@ -4,6 +4,7 @@
from __future__ import annotations
import os
import shutil
import sys
import asyncio
from asyncio import Queue
@ -125,7 +126,7 @@ def safe_overwrite(file: Path, data: Union[bytes, str], *,
f.flush()
os.fsync(f.fileno())
# if the above write failed (because disk is full etc), the old data should be kept
os.rename(tmpname, resolved_path)
shutil.move(tmpname, resolved_path)
def read_verfile(file: Path) -> ResultData:
try: