This commit is contained in:
2026-01-11 01:04:39 -08:00
parent 7c1959483f
commit 61ab690604
2 changed files with 32 additions and 14 deletions

View File

@@ -208,7 +208,7 @@ class API_folder_store:
Args:
library_root: Path to the local library root directory
"""
self.library_root = expand_path(library_root)
self.library_root = expand_path(library_root).resolve()
self.db_path = self.library_root / self.DB_NAME
self.connection: Optional[sqlite3.Connection] = None
# sqlite3 connections are not safe for concurrent use across threads.
@@ -218,14 +218,24 @@ class API_folder_store:
self._init_db()
def _normalize_input_path(self, file_path: Path) -> Path:
p = expand_path(file_path)
if not p.is_absolute():
# Check if it already seems to start with library_root but just wasn't absolute
# (e.g. library_root is "C:\foo" and p is "foo\bar" which might happen in some cases)
# though usually it's better to just join.
# But the recursive case happened because library_root was "$home/files" (not absolute)
# and p was "$home/files/..." (not absolute).
p = self.library_root / p
p = expand_path(file_path).resolve()
# If the path is relative to the current working directory, we check if it's meant to be in the library_root.
# However, because we call .resolve() above, it's already absolute relative to CWD if it was relative.
# But we want it to be absolute relative to library_root if it's not absolute or if it exists in library_root.
# If it's already under library_root, we are done.
try:
p.relative_to(self.library_root)
return p
except ValueError:
pass
# If it was a relative path (unresolved), we should have joined it before resolving.
# Let's re-expand without resolve to check if it's absolute.
raw_p = expand_path(file_path)
if not raw_p.is_absolute():
return (self.library_root / raw_p).resolve()
return p
def _to_db_file_path(self, file_path: Path) -> str:
@@ -2349,8 +2359,8 @@ class DatabaseAPI:
"""Query API wrapper for LocalLibraryDB providing specialized search methods."""
def __init__(self, search_dir: Path):
self.search_dir = search_dir
self.db = API_folder_store(search_dir)
self.search_dir = expand_path(search_dir).resolve()
self.db = API_folder_store(self.search_dir)
def __enter__(self):
self.db.__enter__()
@@ -2749,8 +2759,8 @@ class LocalLibraryInitializer:
def __init__(self, library_root: Path):
"""Initialize the database scanner."""
self.library_root = Path(library_root)
self.db = API_folder_store(library_root)
self.library_root = expand_path(library_root).resolve()
self.db = API_folder_store(self.library_root)
self.stats = {
"files_scanned": 0,
"files_new": 0,

View File

@@ -37,7 +37,15 @@ def expand_path(p: str | Path | None) -> Path:
"""Expand ~ and environment variables in path."""
if p is None:
return None # type: ignore
expanded = os.path.expandvars(str(p))
s = str(p)
# Courtesy check for $home -> $HOME if we're on a POSIX-like system
# (where env vars are case-sensitive)
if os.name != 'nt' and '$home' in s and '$HOME' not in os.environ:
# If $home is literally used in config but only HOME is defined
if 'HOME' in os.environ:
s = s.replace('$home', '$HOME')
expanded = os.path.expandvars(s)
return Path(expanded).expanduser()