mirror of
https://github.com/lrnselfreliance/wrolpi.git
synced 2026-10-25 18:40:06 -04:00
Ignored directories: match whole directories, and check where a link points
An ignored directory was matched as a string prefix, so ignoring `private` also ignored `private-notes`. A file is now ignored only when it is the ignored directory or inside it. Viewing a file, or saving its progress, checked only the path it was given, so a link outside an ignored directory to a file inside it was tracked. is_ignored_file checks the link and its target. Refresh does not follow links, so the bulk paths keep the cheaper lexical check. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
9588af2601
commit
9a565e19ee
3 changed files with 45 additions and 5 deletions
|
|
@ -146,9 +146,7 @@ async def set_file_viewed(session: Session, file: pathlib.Path):
|
|||
|
||||
Files in ignored directories are not tracked.
|
||||
"""
|
||||
# Check if file is in an ignored directory
|
||||
remaining = remove_files_in_ignored_directories([file])
|
||||
if not remaining:
|
||||
if is_ignored_file(file):
|
||||
return
|
||||
|
||||
try:
|
||||
|
|
@ -170,7 +168,7 @@ def _trackable_path(file: pathlib.Path) -> pathlib.Path | None:
|
|||
file = pathlib.Path(os.path.normpath(file))
|
||||
if not get_paths_in_media_directory([file]):
|
||||
raise InvalidFile('File must be in the media directory')
|
||||
if not remove_files_in_ignored_directories([file]):
|
||||
if is_ignored_file(file):
|
||||
return None
|
||||
return file
|
||||
|
||||
|
|
@ -880,12 +878,21 @@ def _upsert_files(files: List[pathlib.Path],
|
|||
progress_callback(processed_count, total_files)
|
||||
|
||||
|
||||
def is_ignored_file(file: pathlib.Path) -> bool:
|
||||
"""Is `file`, or the file it links to, in an ignored directory?
|
||||
|
||||
Refresh does not follow links, but a link can be viewed directly."""
|
||||
return len(remove_files_in_ignored_directories([file, file.resolve()])) < 2
|
||||
|
||||
|
||||
def remove_files_in_ignored_directories(files: List[pathlib.Path]) -> List[pathlib.Path]:
|
||||
"""Return a new list which does not contain any file paths that are in ignored directories."""
|
||||
from wrolpi.db import get_db_file
|
||||
|
||||
ignored_directories = get_normalized_ignored_directories()
|
||||
files = [i for i in files if not any(str(i).startswith(j) for j in ignored_directories)]
|
||||
# `private` must not hide `private-notes`.
|
||||
files = [i for i in files
|
||||
if not any(str(i) == j or str(i).startswith(f'{j}{os.sep}') for j in ignored_directories)]
|
||||
# Never index the database (or its WAL sidecars), even if the user un-ignores `config`.
|
||||
db_file = str(get_db_file())
|
||||
files = [i for i in files if not str(i).startswith(db_file)]
|
||||
|
|
|
|||
|
|
@ -1896,3 +1896,18 @@ def test_bulk_update_file_groups_reorganize_updates_stem(test_session, test_dire
|
|||
fg = test_session.query(FileGroup).filter_by(id=fg_id).one()
|
||||
assert fg.stem == '2024-01-01 New Title'
|
||||
assert fg.primary_path == new_path
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_remove_files_in_ignored_directories(async_client, test_directory, test_wrolpi_config, await_switches):
|
||||
"""An ignored directory hides its own files only, not those of a sibling which shares its name as a prefix."""
|
||||
get_wrolpi_config().ignored_directories = [str(test_directory / 'private')]
|
||||
await await_switches()
|
||||
|
||||
private = test_directory / 'private/movie.mp4'
|
||||
nested = test_directory / 'private/deeper/movie.mp4'
|
||||
sibling = test_directory / 'private-notes/notes.txt'
|
||||
other = test_directory / 'videos/movie.mp4'
|
||||
assert lib.remove_files_in_ignored_directories([private, nested, sibling, other]) == [sibling, other]
|
||||
# The ignored directory itself is ignored.
|
||||
assert lib.remove_files_in_ignored_directories([test_directory / 'private']) == []
|
||||
|
|
|
|||
|
|
@ -415,3 +415,21 @@ async def test_recently_viewed_import_outside_media_directory(test_session, asyn
|
|||
assert [i['path'] for i in read_recently_viewed(test_directory)] == ['videos/movie.mp4']
|
||||
finally:
|
||||
outside.unlink()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_progress_symlink_into_ignored_directory(test_session, async_client, test_directory,
|
||||
make_files_structure, test_wrolpi_config, await_switches,
|
||||
await_background_tasks):
|
||||
"""A link outside an ignored directory, to a file in it, is not tracked (viewed or progress)."""
|
||||
from wrolpi.common import get_wrolpi_config
|
||||
movie, _ = make_files_structure(['private/movie.mp4', 'videos/other.mp4'])
|
||||
(test_directory / 'videos/link.mp4').symlink_to(movie)
|
||||
get_wrolpi_config().ignored_directories = [str(test_directory / 'private')]
|
||||
await await_switches()
|
||||
|
||||
body = dict(file='videos/link.mp4', progress=0.4, position=dict(kind='time', seconds=480))
|
||||
await async_client.post('/api/files/progress', content=json.dumps(body))
|
||||
await async_client.post('/api/files/file', content=json.dumps(dict(file='videos/link.mp4')))
|
||||
await await_background_tasks()
|
||||
assert test_session.query(FileGroup).count() == 0
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue