mirror of
https://github.com/beetbox/beets.git
synced 2025-12-06 16:42:42 +01:00
Handle missing reflink dependency in the business logic
This commit is contained in:
parent
255ac4bc2f
commit
fee959c500
2 changed files with 21 additions and 20 deletions
|
|
@ -13,6 +13,7 @@
|
|||
# included in all copies or substantial portions of the Software.
|
||||
|
||||
"""Miscellaneous utility functions."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import errno
|
||||
|
|
@ -29,6 +30,7 @@ import traceback
|
|||
from collections import Counter
|
||||
from contextlib import suppress
|
||||
from enum import Enum
|
||||
from importlib import import_module
|
||||
from logging import Logger
|
||||
from multiprocessing.pool import ThreadPool
|
||||
from pathlib import Path
|
||||
|
|
@ -615,31 +617,33 @@ def reflink(
|
|||
Raise an `OSError` if `dest` already exists, unless `replace` is
|
||||
True. If `path` == `dest`, then do nothing.
|
||||
|
||||
If reflinking fails and `fallback` is enabled, try copying the file
|
||||
instead. Otherwise, raise an error without trying a plain copy.
|
||||
|
||||
May raise an `ImportError` if the `reflink` module is not available.
|
||||
If `fallback` is enabled, ignore errors and copy the file instead.
|
||||
Otherwise, errors are re-raised as FilesystemError with an explanation.
|
||||
"""
|
||||
import reflink as pyreflink
|
||||
|
||||
if samefile(path, dest):
|
||||
return
|
||||
|
||||
if os.path.exists(syspath(dest)) and not replace:
|
||||
raise FilesystemError("file exists", "rename", (path, dest))
|
||||
|
||||
try:
|
||||
pyreflink.reflink(path, dest)
|
||||
except (NotImplementedError, pyreflink.ReflinkImpossibleError):
|
||||
if fallback:
|
||||
copy(path, dest, replace)
|
||||
else:
|
||||
with suppress(Exception):
|
||||
return import_module("reflink").reflink(path, dest)
|
||||
return copy(path, dest, replace)
|
||||
|
||||
try:
|
||||
import_module("reflink").reflink(path, dest)
|
||||
except (ImportError, OSError):
|
||||
raise
|
||||
except Exception as exc:
|
||||
msg = {
|
||||
"EXDEV": "Cannot reflink across devices",
|
||||
"EOPNOTSUPP": "Device does not support reflinks",
|
||||
}.get(str(exc), "OS does not support reflinks")
|
||||
|
||||
raise FilesystemError(
|
||||
"OS/filesystem does not support reflinks.",
|
||||
"link",
|
||||
(path, dest),
|
||||
traceback.format_exc(),
|
||||
)
|
||||
msg, "reflink", (path, dest), traceback.format_exc()
|
||||
) from exc
|
||||
|
||||
|
||||
def unique_path(path: bytes) -> bytes:
|
||||
|
|
|
|||
|
|
@ -86,12 +86,10 @@ class MoveTest(BeetsTestCase):
|
|||
self.i.move(operation=MoveOperation.COPY)
|
||||
self.assertExists(self.path)
|
||||
|
||||
@NEEDS_REFLINK
|
||||
def test_reflink_arrives(self):
|
||||
self.i.move(operation=MoveOperation.REFLINK_AUTO)
|
||||
self.assertExists(self.dest)
|
||||
|
||||
@NEEDS_REFLINK
|
||||
def test_reflink_does_not_depart(self):
|
||||
self.i.move(operation=MoveOperation.REFLINK_AUTO)
|
||||
self.assertExists(self.path)
|
||||
|
|
@ -584,7 +582,6 @@ class SafeMoveCopyTest(BeetsTestCase):
|
|||
with pytest.raises(util.FilesystemError):
|
||||
util.copy(self.path, self.otherpath)
|
||||
|
||||
@NEEDS_REFLINK
|
||||
def test_unsuccessful_reflink(self):
|
||||
with pytest.raises(util.FilesystemError):
|
||||
util.reflink(self.path, self.otherpath)
|
||||
|
|
|
|||
Loading…
Reference in a new issue