Skip to content

Commit 7ce7ea2

Browse files
committed
Block reading notes sync deletions
1 parent 03dae04 commit 7ce7ea2

2 files changed

Lines changed: 66 additions & 0 deletions

File tree

deployments/desktop/shared/agents.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1368,6 +1368,33 @@ def _is_non_fast_forward_push(output: str) -> bool:
13681368
return "non-fast-forward" in normalized or "fetch first" in normalized
13691369

13701370

1371+
def _guard_reading_notes_deletions(repo_dir: Path, language: str) -> None:
1372+
deleted = [
1373+
line.strip()
1374+
for line in _git_output(["diff", "--cached", "--name-only", "--diff-filter=D"], repo_dir).splitlines()
1375+
if line.strip()
1376+
]
1377+
if not deleted:
1378+
return
1379+
_run_git(["checkout", "HEAD", "--", *deleted], repo_dir, check=False)
1380+
preview = "\n".join(f"- {path}" for path in deleted[:12])
1381+
if len(deleted) > 12:
1382+
preview += f"\n- ... and {len(deleted) - 12} more"
1383+
raise RuntimeError(
1384+
(
1385+
"GitHub sync blocked because it would delete reading-note files. "
1386+
"PaperFlow GUI sync is additive by default; delete files manually with Git if that is intended.\n"
1387+
f"{preview}"
1388+
)
1389+
if language == "en"
1390+
else (
1391+
"GitHub 同步已阻止:本次同步会删除阅读笔记文件。"
1392+
"PaperFlow GUI 同步默认只允许新增/修改;如果确实要删除文件,请手动用 Git 删除后提交。\n"
1393+
f"{preview}"
1394+
)
1395+
)
1396+
1397+
13711398
def _remote_first_sync_notes_worktree(repo_dir: Path, branch: str, language: str) -> Tuple[bool, bool, str]:
13721399
local_patch = ""
13731400
if _git_output(["status", "--short"], repo_dir):
@@ -1503,6 +1530,7 @@ def sync_reading_notes_github(user_id: str = "", response_language: str = "zh")
15031530
pull_warning = remote_first_message if remote_conflict_discarded else ""
15041531

15051532
_run_git(["add", "."], repo_dir)
1533+
_guard_reading_notes_deletions(repo_dir, language)
15061534
llm_review = _notes_llm_sync_review(
15071535
repo_dir,
15081536
branch,

tests/test_desktop_gui.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1368,6 +1368,44 @@ def test_desktop_github_sync_applies_local_changes_after_remote_first_sync(tmp_p
13681368
assert (clone_check / "Daily Note - Jun 2026.md").exists()
13691369

13701370

1371+
def test_desktop_github_sync_blocks_reading_note_deletions(tmp_path, monkeypatch: pytest.MonkeyPatch) -> None:
1372+
bare = tmp_path / "notes.git"
1373+
seed = tmp_path / "seed"
1374+
notes = tmp_path / "Daily Note 2026"
1375+
agents._run_git(["init", "--bare", str(bare)], tmp_path) # noqa: SLF001 - git sync contract
1376+
seed.mkdir()
1377+
agents._run_git(["init"], seed) # noqa: SLF001
1378+
agents._run_git(["checkout", "-b", "main"], seed) # noqa: SLF001
1379+
agents._run_git(["config", "user.email", "paperflow@example.com"], seed) # noqa: SLF001
1380+
agents._run_git(["config", "user.name", "PaperFlow Test"], seed) # noqa: SLF001
1381+
(seed / "Daily Note - Jan 2026.md").write_text("# Jan Note\n", encoding="utf-8")
1382+
(seed / "Daily Note - Jun 2026.md").write_text("# Jun Note\n", encoding="utf-8")
1383+
agents._run_git(["add", "."], seed) # noqa: SLF001
1384+
agents._run_git(["commit", "-m", "Initialize reading notes"], seed) # noqa: SLF001
1385+
agents._run_git(["remote", "add", "origin", str(bare)], seed) # noqa: SLF001
1386+
agents._run_git(["push", "-u", "origin", "main"], seed) # noqa: SLF001
1387+
1388+
agents._run_git(["clone", "-b", "main", str(bare), str(notes)], tmp_path) # noqa: SLF001
1389+
agents._run_git(["config", "user.email", "paperflow@example.com"], notes) # noqa: SLF001
1390+
agents._run_git(["config", "user.name", "PaperFlow Test"], notes) # noqa: SLF001
1391+
(notes / "Daily Note - Jan 2026.md").unlink()
1392+
(notes / "Daily Note - Jun 2026.md").write_text("# Jun Note\n\nNew local content.\n", encoding="utf-8")
1393+
1394+
monkeypatch.setattr(agents, "_configured_reading_notes_git_dir", lambda: notes)
1395+
monkeypatch.setattr(agents, "_configured_reading_notes_git_remote", lambda: str(bare))
1396+
monkeypatch.setattr(agents, "_configured_reading_notes_git_branch", lambda: "main")
1397+
monkeypatch.setenv("PAPERFLOW_READING_NOTES_GIT_LLM_REVIEW", "false")
1398+
1399+
with pytest.raises(RuntimeError, match="删除阅读笔记文件"):
1400+
agents.sync_reading_notes_github("user_test")
1401+
1402+
assert (notes / "Daily Note - Jan 2026.md").exists()
1403+
clone_check = tmp_path / "check-delete-guard"
1404+
agents._run_git(["clone", "-b", "main", str(bare), str(clone_check)], tmp_path) # noqa: SLF001
1405+
assert (clone_check / "Daily Note - Jan 2026.md").exists()
1406+
assert "New local content" not in (clone_check / "Daily Note - Jun 2026.md").read_text(encoding="utf-8")
1407+
1408+
13711409
def test_desktop_github_sync_keeps_remote_on_note_conflict_without_branch(
13721410
tmp_path, monkeypatch: pytest.MonkeyPatch
13731411
) -> None:

0 commit comments

Comments
 (0)