mirror of
https://github.com/beetbox/beets.git
synced 2026-03-26 07:15:34 +01:00
Fix paths for Windows
This commit is contained in:
parent
81dac7e64a
commit
5eee28bb5c
5 changed files with 22 additions and 20 deletions
|
|
@ -8,6 +8,15 @@ from beets import context, util
|
|||
MaybeBytes = TypeVar("MaybeBytes", bytes, None)
|
||||
|
||||
|
||||
def _is_same_path_or_child(path: bytes, music_dir: bytes) -> bool:
|
||||
"""Check if path is the music directory itself or resides within it."""
|
||||
path_cmp = os.path.normcase(os.fsdecode(path))
|
||||
music_dir_cmp = os.path.normcase(os.fsdecode(music_dir))
|
||||
return path_cmp == music_dir_cmp or path_cmp.startswith(
|
||||
os.path.join(music_dir_cmp, "")
|
||||
)
|
||||
|
||||
|
||||
def normalize_path_for_db(path: MaybeBytes) -> MaybeBytes:
|
||||
"""Convert an absolute library path to its database representation."""
|
||||
if not path or not os.path.isabs(path):
|
||||
|
|
@ -17,10 +26,7 @@ def normalize_path_for_db(path: MaybeBytes) -> MaybeBytes:
|
|||
if not music_dir:
|
||||
return path
|
||||
|
||||
if path == music_dir:
|
||||
return os.path.relpath(path, music_dir)
|
||||
|
||||
if path.startswith(os.path.join(music_dir, b"")):
|
||||
if _is_same_path_or_child(path, music_dir):
|
||||
return os.path.relpath(path, music_dir)
|
||||
|
||||
return path
|
||||
|
|
|
|||
|
|
@ -12,8 +12,9 @@ from typing import TYPE_CHECKING, ClassVar
|
|||
from mediafile import MediaFile, UnreadableFileError
|
||||
|
||||
import beets
|
||||
from beets import context, dbcore, logging, plugins, util
|
||||
from beets import dbcore, logging, plugins, util
|
||||
from beets.dbcore import types
|
||||
from beets.dbcore.pathutils import normalize_path_for_db
|
||||
from beets.util import (
|
||||
MoveOperation,
|
||||
bytestring_path,
|
||||
|
|
@ -104,19 +105,15 @@ class LibModel(dbcore.Model["Library"]):
|
|||
if (
|
||||
cls._type(field).query is dbcore.query.PathQuery
|
||||
and query_cls is not dbcore.query.PathQuery
|
||||
and (music_dir := context.get_music_dir())
|
||||
):
|
||||
# Regex, exact, and string queries operate on the raw DB value, so
|
||||
# strip the library prefix to match the stored relative path.
|
||||
if isinstance(pattern, bytes):
|
||||
prefix = os.path.join(music_dir, b"")
|
||||
if pattern.startswith(prefix):
|
||||
pattern = os.path.relpath(pattern, music_dir)
|
||||
pattern = normalize_path_for_db(pattern)
|
||||
else:
|
||||
music_dir_str = os.fsdecode(music_dir)
|
||||
prefix = music_dir_str + os.sep
|
||||
if pattern.startswith(prefix):
|
||||
pattern = pattern.removeprefix(prefix)
|
||||
pattern = os.fsdecode(
|
||||
normalize_path_for_db(util.bytestring_path(pattern))
|
||||
)
|
||||
if field in cls.shared_db_fields:
|
||||
# This field exists in both tables, so SQLite will encounter
|
||||
# an OperationalError if we try to use it in a query.
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ class TestRelativePathMigration:
|
|||
helper.teardown_beets()
|
||||
|
||||
def test_migrate(self, helper: TestHelper):
|
||||
relative_path = "foo/bar/baz.mp3"
|
||||
relative_path = os.path.join("foo", "bar", "baz.mp3")
|
||||
absolute_path = os.fsencode(helper.lib_path / relative_path)
|
||||
|
||||
# need to insert the path directly into the database to bypass the path setter
|
||||
|
|
|
|||
|
|
@ -15,9 +15,9 @@
|
|||
import os
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
from beets import util
|
||||
from beets.test import _common
|
||||
from beets.test.helper import PluginTestCase
|
||||
from beets.util import bytestring_path
|
||||
from beetsplug.ipfs import IPFSPlugin
|
||||
|
||||
|
||||
|
|
@ -37,10 +37,9 @@ class IPFSPluginTest(PluginTestCase):
|
|||
try:
|
||||
if check_item.get("ipfs", with_album=False):
|
||||
ipfs_item = os.fsdecode(os.path.basename(want_item.path))
|
||||
want_path = os.path.normpath(
|
||||
f"/ipfs/{test_album.ipfs}/{ipfs_item}"
|
||||
want_path = util.normpath(
|
||||
os.path.join("/ipfs", test_album.ipfs, ipfs_item)
|
||||
)
|
||||
want_path = bytestring_path(want_path)
|
||||
assert check_item.path == want_path
|
||||
assert (
|
||||
check_item.get("ipfs", with_album=False)
|
||||
|
|
|
|||
|
|
@ -1094,7 +1094,7 @@ class PathStringTest(BeetsTestCase):
|
|||
assert isinstance(dest, bytes)
|
||||
|
||||
def test_artpath_stores_special_chars(self):
|
||||
path = b"b\xe1r"
|
||||
path = bytestring_path("b\xe1r")
|
||||
alb = self.lib.add_album([self.i])
|
||||
alb.artpath = path
|
||||
alb.store()
|
||||
|
|
@ -1131,7 +1131,7 @@ class PathStringTest(BeetsTestCase):
|
|||
assert isinstance(alb.artpath, bytes)
|
||||
|
||||
def test_relative_path_is_stored(self):
|
||||
relative_path = b"abc/foo.mp3"
|
||||
relative_path = os.path.join(b"abc", b"foo.mp3")
|
||||
absolute_path = os.path.join(self.libdir, relative_path)
|
||||
self.i.path = absolute_path
|
||||
self.i.store()
|
||||
|
|
|
|||
Loading…
Reference in a new issue