fix(update): preserve archive metadata in git checkouts
- Skip expanded archive metadata when updating Git worktrees - Retain commit metadata for archive-only installations - Cover repositories, linked worktrees, and packaged installs
This commit is contained in:
parent
0a618c5608
commit
33038978cc
2 changed files with 64 additions and 1 deletions
20
gui/main.py
20
gui/main.py
|
|
@ -131,6 +131,20 @@ class UpdateThread(QThread):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def should_install_to_root(cls, rel: Path, root: Path) -> bool:
|
||||||
|
"""Return True when *rel* may be copied into the selected install root.
|
||||||
|
|
||||||
|
Git expands ``.git_archival.txt`` while creating a source archive. Keep
|
||||||
|
that expanded file in archive-only installs, but do not copy it back
|
||||||
|
into a live checkout where it would dirty the worktree on every update.
|
||||||
|
"""
|
||||||
|
if not cls.should_install(rel):
|
||||||
|
return False
|
||||||
|
if rel.as_posix() == ".git_archival.txt" and (root / ".git").exists():
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def resolve_archive_root(cls, extract_dir: Path) -> Path:
|
def resolve_archive_root(cls, extract_dir: Path) -> Path:
|
||||||
"""Locate the single top-level folder inside an extracted archive.
|
"""Locate the single top-level folder inside an extracted archive.
|
||||||
|
|
@ -281,7 +295,11 @@ class UpdateThread(QThread):
|
||||||
install_files = [
|
install_files = [
|
||||||
src
|
src
|
||||||
for src in extracted.rglob("*")
|
for src in extracted.rglob("*")
|
||||||
if src.is_file() and self.should_install(src.relative_to(extracted))
|
if src.is_file()
|
||||||
|
and self.should_install_to_root(
|
||||||
|
src.relative_to(extracted),
|
||||||
|
root,
|
||||||
|
)
|
||||||
]
|
]
|
||||||
if not install_files:
|
if not install_files:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,51 @@ class UpdateThreadInstallFilterTests(unittest.TestCase):
|
||||||
with self.subTest(rel=rel):
|
with self.subTest(rel=rel):
|
||||||
self.assertFalse(UpdateThread.should_install(Path(rel)))
|
self.assertFalse(UpdateThread.should_install(Path(rel)))
|
||||||
|
|
||||||
|
def test_preserves_archive_metadata_in_git_checkout(self):
|
||||||
|
from gui.main import UpdateThread
|
||||||
|
|
||||||
|
with tempfile.TemporaryDirectory() as raw:
|
||||||
|
root = Path(raw)
|
||||||
|
(root / ".git").mkdir()
|
||||||
|
|
||||||
|
self.assertFalse(
|
||||||
|
UpdateThread.should_install_to_root(
|
||||||
|
Path(".git_archival.txt"),
|
||||||
|
root,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.assertTrue(
|
||||||
|
UpdateThread.should_install_to_root(Path("gui/main.py"), root)
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_preserves_archive_metadata_with_git_file(self):
|
||||||
|
"""Linked worktrees and submodules use a .git file, not a directory."""
|
||||||
|
from gui.main import UpdateThread
|
||||||
|
|
||||||
|
with tempfile.TemporaryDirectory() as raw:
|
||||||
|
root = Path(raw)
|
||||||
|
(root / ".git").write_text("gitdir: elsewhere\n", encoding="utf-8")
|
||||||
|
|
||||||
|
self.assertFalse(
|
||||||
|
UpdateThread.should_install_to_root(
|
||||||
|
Path(".git_archival.txt"),
|
||||||
|
root,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_installs_archive_metadata_outside_git_checkout(self):
|
||||||
|
from gui.main import UpdateThread
|
||||||
|
|
||||||
|
with tempfile.TemporaryDirectory() as raw:
|
||||||
|
root = Path(raw)
|
||||||
|
|
||||||
|
self.assertTrue(
|
||||||
|
UpdateThread.should_install_to_root(
|
||||||
|
Path(".git_archival.txt"),
|
||||||
|
root,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class UpdateThreadArchiveRootTests(unittest.TestCase):
|
class UpdateThreadArchiveRootTests(unittest.TestCase):
|
||||||
"""Gitea zips nest files under a single top folder (repo display name)."""
|
"""Gitea zips nest files under a single top folder (repo display name)."""
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue