Avoid using non-atomic shutil.move

This commit is contained in:
Blallo 2021-09-15 22:02:12 +02:00
parent bb8e4cdbfa
commit c788289567
No known key found for this signature in database
GPG key ID: 0CBE577C9B72DC3F

View file

@ -3,7 +3,6 @@ import logging
import tempfile import tempfile
import os import os
from datetime import datetime, timedelta from datetime import datetime, timedelta
import shutil
from subprocess import Popen from subprocess import Popen
from time import sleep from time import sleep
from typing import Callable, Optional from typing import Callable, Optional
@ -25,8 +24,7 @@ async def get_timefile_exact(time) -> str:
remote_repo, time.strftime(get_config()["AUDIO_INPUT_FORMAT"]) remote_repo, time.strftime(get_config()["AUDIO_INPUT_FORMAT"])
) )
if remote_path.startswith("http://") or remote_path.startswith("https://"): if remote_path.startswith("http://") or remote_path.startswith("https://"):
logger.info(f"downloading {remote_path}") logger.info(f"downloading: {remote_path}")
print(f"DOWNLOADING -> {remote_path}")
local = await download(remote_path) local = await download(remote_path)
return local return local
return local_path return local_path
@ -125,7 +123,8 @@ async def create_mp3(
raise OSError("file '%s' already exists" % outfile) raise OSError("file '%s' already exists" % outfile)
for path, _s, _e in intervals: for path, _s, _e in intervals:
if not os.path.exists(path): if not os.path.exists(path):
raise OSError("file '%s' does not exist; recording system broken?" % path) raise OSError(
"file '%s' does not exist; recording system broken?" % path)
# metadata date/time formatted according to # metadata date/time formatted according to
# https://wiki.xiph.org/VorbisComment#Date_and_time # https://wiki.xiph.org/VorbisComment#Date_and_time
@ -133,7 +132,8 @@ async def create_mp3(
if outfile.endswith(".mp3"): if outfile.endswith(".mp3"):
metadata["TRDC"] = start.replace(microsecond=0).isoformat() metadata["TRDC"] = start.replace(microsecond=0).isoformat()
metadata["RECORDINGTIME"] = metadata["TRDC"] metadata["RECORDINGTIME"] = metadata["TRDC"]
metadata["ENCODINGTIME"] = datetime.now().replace(microsecond=0).isoformat() metadata["ENCODINGTIME"] = datetime.now().replace(
microsecond=0).isoformat()
else: else:
metadata["DATE"] = start.replace(microsecond=0).isoformat() metadata["DATE"] = start.replace(microsecond=0).isoformat()
metadata["ENCODER"] = "https://git.lattuga.net/techbloc/techrec" metadata["ENCODER"] = "https://git.lattuga.net/techbloc/techrec"
@ -154,7 +154,11 @@ async def create_mp3(
prefix, suffix = os.path.basename(outfile).split(".", 1) prefix, suffix = os.path.basename(outfile).split(".", 1)
tmp_file = tempfile.NamedTemporaryFile( tmp_file = tempfile.NamedTemporaryFile(
suffix=".%s" % suffix, prefix="forge-%s" % prefix, delete=False suffix=".%s" % suffix,
prefix="forge-%s" % prefix,
delete=False,
# This is needed to avoid errors with the rename across different mounts
dir=os.path.dirname(outfile),
) )
cmd = ( cmd = (
mp3_join(intervals) mp3_join(intervals)
@ -187,10 +191,7 @@ async def create_mp3(
if not validator(start, end, tmp_file.name): if not validator(start, end, tmp_file.name):
os.unlink(tmp_file.name) os.unlink(tmp_file.name)
return False return False
try: os.rename(tmp_file.name, outfile)
os.rename(tmp_file.name, outfile)
except OSError:
shutil.move(tmp_file.name, outfile)
return True return True