Initial commit
Some checks failed
CI / test (push) Failing after 11s
CI / image (push) Has been skipped

This commit is contained in:
2026-08-01 21:03:35 -04:00
commit 8b5cd370ea
41 changed files with 5462 additions and 0 deletions

103
tests/test_globs.py Normal file
View File

@@ -0,0 +1,103 @@
"""Path filtering, including Syncthing-shaped vaults (SPEC 2.6)."""
from __future__ import annotations
from pathlib import Path
import pytest
from mdcaldav.config import Config
from mdcaldav.globs import matches
from mdcaldav.index import Index
CONFLICT = "daily/2026-01-05.sync-conflict-20260731-120000-ABCDEFG.md"
@pytest.mark.parametrize(
"path,pattern,expected",
[
# `**/` must mean "zero or more segments", so top-level files match.
("README.md", "**/*.md", True),
("daily/a.md", "**/*.md", True),
("a/b/c/d.md", "**/*.md", True),
# `*` must not cross a separator.
("a/b.tmp", "*.tmp", False),
("b.tmp", "*.tmp", True),
# Syncthing artefacts.
(".stversions/daily/2026-01-05.md", ".stversions/**", True),
(CONFLICT, "**/*.sync-conflict-*", True),
("daily/.syncthing.a.md.tmp", "**/.syncthing.*", True),
("daily/~syncthing~a.md.tmp", "**/~syncthing~*", True),
# Ordinary notes must survive all of the above.
("daily/2026-01-05.md", "**/*.sync-conflict-*", False),
("daily/2026-01-05.md", ".stversions/**", False),
],
)
def test_glob_semantics(path: str, pattern: str, expected: bool):
assert matches(path, pattern) is expected
@pytest.fixture
def syncthing_vault(vault: Path) -> Path:
"""A vault shaped like a live Syncthing folder."""
(vault / ".stfolder").mkdir()
(vault / ".stversions/daily").mkdir(parents=True)
# An old copy of a real note, exactly as Syncthing retains it.
(vault / ".stversions/daily/2026-01-07.md").write_text(
(vault / "daily/2026-01-07.md").read_text(), encoding="utf-8"
)
(vault / CONFLICT).write_text("- [ ] Book the soil test\n", encoding="utf-8")
(vault / "daily/.syncthing.2026-01-07.md.tmp").write_text("- [ ] partial\n")
(vault / "ROADMAP.md").write_text("- [ ] Top level task\n", encoding="utf-8")
return vault
@pytest.fixture
def index(syncthing_vault: Path, tmp_path: Path):
cfg = Config()
cfg.vault.path = syncthing_vault
cfg.index.db = tmp_path / "index.db"
idx = Index(cfg)
idx.rescan()
yield idx
idx.close()
def test_top_level_notes_are_indexed(index: Index):
"""Regression: `**/*.md` used to skip files at the vault root."""
assert "Top level task" in {t.title for t in index.tasks.values()}
def test_syncthing_artefacts_are_not_indexed(index: Index):
sources = {t.source.rel_path for t in index.tasks.values()}
assert not any(s.startswith(".stversions/") for s in sources)
assert not any(s.startswith(".stfolder/") for s in sources)
assert CONFLICT not in sources
assert not any(".syncthing." in s for s in sources)
def test_versioned_copies_do_not_duplicate_tasks(index: Index):
"""The failure mode that matters: one task per note, not one per version."""
titles = [t.title for t in index.tasks.values()]
assert titles.count("Book the soil test") == 1
def test_targeted_rescan_also_filters(index: Index):
"""The watcher path must filter too, or Syncthing writes poison the index."""
index.rescan([".stversions/daily/2026-01-07.md", CONFLICT])
titles = [t.title for t in index.tasks.values()]
assert titles.count("Book the soil test") == 1
sources = {t.source.rel_path for t in index.tasks.values()}
assert not any(s.startswith(".stversions/") for s in sources)
def test_doctor_reports_conflict_files(syncthing_vault: Path, tmp_path, capsys, monkeypatch):
from mdcaldav.cli import main
monkeypatch.setenv("HOME", str(tmp_path))
main(["--vault", str(syncthing_vault), "doctor"])
out = capsys.readouterr().out
assert "sync-conflict files present" in out
assert "merge and delete them" in out