Git-операции всегда над папкой данных, а не над корнем приложения
Приложение создавало GitSync от paths.app_root(). Пока база лежала внутри репозитория с кодом, это работало; после разделения репозиториев — нет. exe лежит в корне клона с исходниками, поэтому приложение распоряжалось репозиторием кода: переписало ему origin на food-records и попыталось отправить туда исходники. Пуш спас только отказ по fast-forward. Теперь GitSync создаётся в одном месте — MainWindow._git() — и всегда от paths.data_dir(). Тест проверяет и цель, и то, что других мест создания GitSync в файле не осталось. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
1a97fee872
commit
bc868f5af1
@ -168,6 +168,16 @@ class MainWindow(QMainWindow):
|
|||||||
def sync_status_text(self) -> str:
|
def sync_status_text(self) -> str:
|
||||||
return self._sync_text
|
return self._sync_text
|
||||||
|
|
||||||
|
def _git(self) -> GitSync:
|
||||||
|
"""Git всегда работает над папкой данных, а не над корнем приложения.
|
||||||
|
|
||||||
|
Единственная точка создания GitSync: если exe лежит внутри клона
|
||||||
|
с исходниками, ошибка в этом месте заставила бы приложение
|
||||||
|
распоряжаться репозиторием кода — переписать ему origin и запушить
|
||||||
|
исходники в репозиторий данных.
|
||||||
|
"""
|
||||||
|
return GitSync(paths.data_dir(), paths.vault_rel_posix(), self.vault.doc.settings.git)
|
||||||
|
|
||||||
# --- сохранение ---
|
# --- сохранение ---
|
||||||
|
|
||||||
def _autosave(self) -> None:
|
def _autosave(self) -> None:
|
||||||
@ -214,7 +224,7 @@ class MainWindow(QMainWindow):
|
|||||||
self._sync_text = "синхронизация…"
|
self._sync_text = "синхронизация…"
|
||||||
self._update_status()
|
self._update_status()
|
||||||
|
|
||||||
sync = GitSync(paths.app_root(), paths.vault_rel_posix(), git)
|
sync = self._git()
|
||||||
self._sync_task = SyncTask(sync, paths.remote_copy_path(), self)
|
self._sync_task = SyncTask(sync, paths.remote_copy_path(), self)
|
||||||
self._sync_task.done.connect(lambda *args: self._on_sync_done(*args, quiet=quiet))
|
self._sync_task.done.connect(lambda *args: self._on_sync_done(*args, quiet=quiet))
|
||||||
self._sync_task.start()
|
self._sync_task.start()
|
||||||
@ -267,8 +277,7 @@ class MainWindow(QMainWindow):
|
|||||||
# --- разрешение конфликта ---
|
# --- разрешение конфликта ---
|
||||||
|
|
||||||
def adopt_remote_version(self, _copy_path: Path) -> None:
|
def adopt_remote_version(self, _copy_path: Path) -> None:
|
||||||
git = self.vault.doc.settings.git
|
sync = self._git()
|
||||||
sync = GitSync(paths.app_root(), paths.vault_rel_posix(), git)
|
|
||||||
try:
|
try:
|
||||||
sync.reset_to_remote()
|
sync.reset_to_remote()
|
||||||
self.vault.reload()
|
self.vault.reload()
|
||||||
@ -289,9 +298,8 @@ class MainWindow(QMainWindow):
|
|||||||
self.changed()
|
self.changed()
|
||||||
|
|
||||||
def force_push_local(self) -> None:
|
def force_push_local(self) -> None:
|
||||||
git = self.vault.doc.settings.git
|
|
||||||
self.save_now()
|
self.save_now()
|
||||||
sync = GitSync(paths.app_root(), paths.vault_rel_posix(), git)
|
sync = self._git()
|
||||||
try:
|
try:
|
||||||
sync.force_push()
|
sync.force_push()
|
||||||
except GitError as exc:
|
except GitError as exc:
|
||||||
@ -325,7 +333,7 @@ class MainWindow(QMainWindow):
|
|||||||
# Последний пуш на выходе, с потолком по времени: висеть на закрытии
|
# Последний пуш на выходе, с потолком по времени: висеть на закрытии
|
||||||
# из-за пропавшей сети приложение не должно.
|
# из-за пропавшей сети приложение не должно.
|
||||||
self.status_label.setText("Отправляю базу на сервер…")
|
self.status_label.setText("Отправляю базу на сервер…")
|
||||||
sync = GitSync(paths.app_root(), paths.vault_rel_posix(), git)
|
sync = self._git()
|
||||||
task = SyncTask(sync, paths.remote_copy_path(), self)
|
task = SyncTask(sync, paths.remote_copy_path(), self)
|
||||||
task.start()
|
task.start()
|
||||||
task.wait(CLOSE_SYNC_WAIT_MS)
|
task.wait(CLOSE_SYNC_WAIT_MS)
|
||||||
|
|||||||
@ -107,6 +107,32 @@ def test_sync_is_skipped_without_a_remote(window):
|
|||||||
assert window._syncing is False
|
assert window._syncing is False
|
||||||
|
|
||||||
|
|
||||||
|
def test_git_always_targets_the_data_folder(window):
|
||||||
|
"""Приложение не должно распоряжаться репозиторием с исходниками.
|
||||||
|
|
||||||
|
exe обычно лежит в корне клона с кодом, и папка data — внутри него.
|
||||||
|
Если git начать с корня приложения, оно перепишет исходникам origin
|
||||||
|
и запушит их в репозиторий данных. Ровно это однажды и произошло.
|
||||||
|
"""
|
||||||
|
from app import paths
|
||||||
|
|
||||||
|
sync = window._git()
|
||||||
|
assert sync.repo_dir == paths.data_dir()
|
||||||
|
assert sync.repo_dir != paths.app_root()
|
||||||
|
assert sync.rel_path == "vault.fmdb"
|
||||||
|
assert "/" not in sync.rel_path # база лежит в корне своего репозитория
|
||||||
|
|
||||||
|
|
||||||
|
def test_no_other_place_builds_git_by_hand():
|
||||||
|
"""Единственная точка создания GitSync — MainWindow._git()."""
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
source = Path("app/ui/main_window.py").read_text(encoding="utf-8")
|
||||||
|
# Одно вхождение — внутри самого _git(); остальные зовут его.
|
||||||
|
assert source.count("GitSync(") == 1
|
||||||
|
assert "paths.app_root()" not in source
|
||||||
|
|
||||||
|
|
||||||
# --- таблицы наполняются --------------------------------------------------
|
# --- таблицы наполняются --------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user