[BUGFIX] Invalid cross-device link workaround (#400)
This commit is contained in:
parent
beaa34a367
commit
c3d9d45c18
5 changed files with 36 additions and 15 deletions
|
|
@ -1,4 +1,3 @@
|
||||||
import shutil
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import tempfile
|
import tempfile
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
@ -7,6 +6,7 @@ from typing import Optional
|
||||||
|
|
||||||
from ytdl_sub.utils.chapters import Chapters
|
from ytdl_sub.utils.chapters import Chapters
|
||||||
from ytdl_sub.utils.exceptions import ValidationException
|
from ytdl_sub.utils.exceptions import ValidationException
|
||||||
|
from ytdl_sub.utils.file_handler import FileHandler
|
||||||
from ytdl_sub.utils.logger import Logger
|
from ytdl_sub.utils.logger import Logger
|
||||||
|
|
||||||
logger = Logger.get(name="ffmpeg")
|
logger = Logger.get(name="ffmpeg")
|
||||||
|
|
@ -132,8 +132,7 @@ def set_ffmpeg_metadata_chapters(
|
||||||
output_file_path,
|
output_file_path,
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
FileHandler.move(output_file_path, file_path)
|
||||||
shutil.move(src=output_file_path, dst=file_path)
|
|
||||||
|
|
||||||
|
|
||||||
def add_ffmpeg_metadata_key_values(file_path: str, key_values: Dict[str, str]) -> None:
|
def add_ffmpeg_metadata_key_values(file_path: str, key_values: Dict[str, str]) -> None:
|
||||||
|
|
@ -154,4 +153,4 @@ def add_ffmpeg_metadata_key_values(file_path: str, key_values: Dict[str, str]) -
|
||||||
ffmpeg_args.extend(["-codec", "copy", output_file_path])
|
ffmpeg_args.extend(["-codec", "copy", output_file_path])
|
||||||
|
|
||||||
FFMPEG.run(ffmpeg_args)
|
FFMPEG.run(ffmpeg_args)
|
||||||
shutil.move(src=output_file_path, dst=file_path)
|
FileHandler.move(output_file_path, file_path)
|
||||||
|
|
|
||||||
|
|
@ -353,8 +353,23 @@ class FileHandler:
|
||||||
Source file
|
Source file
|
||||||
dst_file_path
|
dst_file_path
|
||||||
Destination file
|
Destination file
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
OSError
|
||||||
|
Cross-device link workaround
|
||||||
"""
|
"""
|
||||||
shutil.move(src=src_file_path, dst=dst_file_path)
|
try:
|
||||||
|
shutil.move(src=src_file_path, dst=dst_file_path)
|
||||||
|
except OSError as os_error_exc:
|
||||||
|
# Invalid cross-device link
|
||||||
|
# Can happen from using os.rename under the hood, which requires the two file on the
|
||||||
|
# same filesystem. Work around it by copying and deleting the file
|
||||||
|
if os_error_exc.errno == 18:
|
||||||
|
cls.copy(src_file_path, dst_file_path)
|
||||||
|
cls.delete(src_file_path)
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def delete(cls, file_path: Union[str, Path]):
|
def delete(cls, file_path: Union[str, Path]):
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from e2e.conftest import mock_run_from_cli
|
from e2e.conftest import mock_run_from_cli
|
||||||
|
|
||||||
|
from ytdl_sub.utils.file_handler import FileMetadata
|
||||||
|
|
||||||
|
|
||||||
class TestView:
|
class TestView:
|
||||||
@pytest.mark.parametrize("split_chapters", [True, False])
|
@pytest.mark.parametrize("split_chapters", [True, False])
|
||||||
|
|
@ -22,12 +26,15 @@ class TestView:
|
||||||
# Ensure the video and thumbnail are recognized
|
# Ensure the video and thumbnail are recognized
|
||||||
assert len(transaction_log.files_created) == 2
|
assert len(transaction_log.files_created) == 2
|
||||||
|
|
||||||
file_name = f"avUT-zd9v68{'___0' if split_chapters else ''}.webm"
|
video_metadata: Optional[FileMetadata] = None
|
||||||
video_file = transaction_log.files_created.get(file_name)
|
for file_name, metadata in transaction_log.files_created.items():
|
||||||
assert video_file is not None
|
if file_name.endswith("webm"):
|
||||||
|
video_metadata = metadata
|
||||||
|
break
|
||||||
|
|
||||||
assert "Source Variables:" in video_file.metadata
|
assert video_metadata is not None
|
||||||
|
assert "Source Variables:" in video_metadata.metadata
|
||||||
if split_chapters:
|
if split_chapters:
|
||||||
assert " chapter_index: 1" in video_file.metadata
|
assert " chapter_index: 1" in video_metadata.metadata
|
||||||
else:
|
else:
|
||||||
assert " chapter_index: 1" not in video_file.metadata
|
assert " chapter_index: 1" not in video_metadata.metadata
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
".ytdl-sub-chapters_from_comments-download-archive.json": "122723ce8d257eebb05178daa26141f6",
|
".ytdl-sub-chapters_from_comments-download-archive.json": "122723ce8d257eebb05178daa26141f6",
|
||||||
"JMC/JMC - Move 78 - Automated Improvisation [Full Album]-thumb.jpg": "c12e6a6f242680d1096a1a99d74a62c6",
|
"JMC/JMC - Move 78 - Automated Improvisation [Full Album]-thumb.jpg": "c12e6a6f242680d1096a1a99d74a62c6",
|
||||||
"JMC/JMC - Move 78 - Automated Improvisation [Full Album].info.json": "228adc1dbc785852c8266457af0adadc",
|
"JMC/JMC - Move 78 - Automated Improvisation [Full Album].info.json": "ee8437e52186219ff510214138f00e28",
|
||||||
"JMC/JMC - Move 78 - Automated Improvisation [Full Album].mp4": "68c1c4b20b89511b26a92b967e54891e",
|
"JMC/JMC - Move 78 - Automated Improvisation [Full Album].mp4": "8b8a9a731a19bc37feb091559f97ebbc",
|
||||||
"JMC/JMC - Move 78 - Automated Improvisation [Full Album].nfo": "7a65b184d24c68fc0ec5380432250f5b"
|
"JMC/JMC - Move 78 - Automated Improvisation [Full Album].nfo": "7a65b184d24c68fc0ec5380432250f5b"
|
||||||
}
|
}
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
"Project ⧸ Zombie/Season 2011/s2011.e112101 - qbMJh2df1M4.mp4": "60c3221125afbef78990bdcead78a82d",
|
"Project ⧸ Zombie/Season 2011/s2011.e112101 - qbMJh2df1M4.mp4": "60c3221125afbef78990bdcead78a82d",
|
||||||
"Project ⧸ Zombie/Season 2011/s2011.e112101 - qbMJh2df1M4.nfo": "3c5e407a428161b75474eea13a82e009",
|
"Project ⧸ Zombie/Season 2011/s2011.e112101 - qbMJh2df1M4.nfo": "3c5e407a428161b75474eea13a82e009",
|
||||||
"Project ⧸ Zombie/Season 2012/s2012.e012301 - y5-3ovwQQ_U-thumb.jpg": "54ebe9df801b278fdd17b21afa8373a6",
|
"Project ⧸ Zombie/Season 2012/s2012.e012301 - y5-3ovwQQ_U-thumb.jpg": "54ebe9df801b278fdd17b21afa8373a6",
|
||||||
"Project ⧸ Zombie/Season 2012/s2012.e012301 - y5-3ovwQQ_U.mp4": "cdf5d458e148bbadba6dfed5b05e378b",
|
"Project ⧸ Zombie/Season 2012/s2012.e012301 - y5-3ovwQQ_U.mp4": "2141f0f928d55e94fef7f7d3c7a4aca0",
|
||||||
"Project ⧸ Zombie/Season 2012/s2012.e012301 - y5-3ovwQQ_U.nfo": "a0d59e102f06b93718ab20e0238b4f95",
|
"Project ⧸ Zombie/Season 2012/s2012.e012301 - y5-3ovwQQ_U.nfo": "a0d59e102f06b93718ab20e0238b4f95",
|
||||||
"Project ⧸ Zombie/Season 2013/s2013.e071901 - c_PZdc0Zi7M-thumb.jpg": "e29d49433175de8a761af35c5307791f",
|
"Project ⧸ Zombie/Season 2013/s2013.e071901 - c_PZdc0Zi7M-thumb.jpg": "e29d49433175de8a761af35c5307791f",
|
||||||
"Project ⧸ Zombie/Season 2013/s2013.e071901 - c_PZdc0Zi7M.mp4": "3fb239f0a646e515bbaaeb6f6d5cdd69",
|
"Project ⧸ Zombie/Season 2013/s2013.e071901 - c_PZdc0Zi7M.mp4": "3fb239f0a646e515bbaaeb6f6d5cdd69",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue