Reproduce stale upstream configuration with real local Git repositories, including the already-matching pin fast path. Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
+9
-4
@@ -73,13 +73,12 @@ def engine_identity() -> str:
|
||||
def fork():
|
||||
"""Initialize the exact gitlink; never replace a modified developer checkout."""
|
||||
expected = engine_commit()
|
||||
matched = False
|
||||
if (FORK / ".git").exists():
|
||||
current = subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=FORK, text=True).strip()
|
||||
if current == expected:
|
||||
print(f"horizon/: закреплённый коммит {expected}")
|
||||
return
|
||||
matched = current == expected
|
||||
dirty = subprocess.check_output(["git", "status", "--porcelain"], cwd=FORK, text=True).strip()
|
||||
if dirty:
|
||||
if not matched and dirty:
|
||||
sys.exit("horizon/: есть изменения при другом закреплённом SHA; сохраните их перед обновлением сабмодуля")
|
||||
if (FORK / ".git").is_dir():
|
||||
# Migrate the old standalone clone without deleting it or any local branches.
|
||||
@@ -88,6 +87,12 @@ def fork():
|
||||
run(["git", "remote", "set-url", "origin", url], cwd=FORK)
|
||||
elif FORK.exists() and any(FORK.iterdir()):
|
||||
sys.exit("horizon/: непустой каталог без Git; сохраните его перед инициализацией сабмодуля")
|
||||
# Existing clones cache the previous upstream URL in local Git configuration.
|
||||
# Synchronize even when HEAD already matches: the next pin may exist only in our fork.
|
||||
run(["git", "submodule", "sync", "--recursive", "--", "horizon"], cwd=ROOT)
|
||||
if matched:
|
||||
print(f"horizon/: закреплённый коммит {expected}")
|
||||
return
|
||||
run(["git", "submodule", "update", "--init", "--recursive", "--", "horizon"], cwd=ROOT)
|
||||
current = subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=FORK, text=True).strip()
|
||||
if current != expected:
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
"""Real Git migration regression; no network, user settings or player data."""
|
||||
import importlib.util
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import tempfile
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
SPEC = importlib.util.spec_from_file_location("airdef_build", Path(__file__).with_name("airdef.py"))
|
||||
airdef = importlib.util.module_from_spec(SPEC)
|
||||
SPEC.loader.exec_module(airdef)
|
||||
|
||||
|
||||
def git(at, *args):
|
||||
return subprocess.check_output(["git", "-C", str(at), *args], text=True, stderr=subprocess.STDOUT).strip()
|
||||
|
||||
|
||||
def init(at):
|
||||
at.mkdir()
|
||||
git(at, "init", "-q")
|
||||
git(at, "config", "user.name", "Test")
|
||||
git(at, "config", "user.email", "test@example.invalid")
|
||||
|
||||
|
||||
def commit(at, text):
|
||||
(at / "engine.txt").write_text(text)
|
||||
git(at, "add", "engine.txt")
|
||||
git(at, "commit", "-qm", text)
|
||||
return git(at, "rev-parse", "HEAD")
|
||||
|
||||
|
||||
class ForkMigrationTests(unittest.TestCase):
|
||||
def test_stale_local_url_is_synced_before_fetching_new_pin(self):
|
||||
with tempfile.TemporaryDirectory(prefix="airdef-fork-test-") as tmp, patch.dict(os.environ, {"GIT_ALLOW_PROTOCOL": "file"}):
|
||||
root = Path(tmp)
|
||||
source, parent = root / "source", root / "airdef"
|
||||
init(source)
|
||||
old = commit(source, "old")
|
||||
canonical = root / "canonical.git"
|
||||
git(root, "clone", "--bare", str(source), str(canonical))
|
||||
init(parent)
|
||||
git(parent, "submodule", "add", str(canonical), "horizon")
|
||||
child = parent / "horizon"
|
||||
new = commit(source, "new-fork-only-pin")
|
||||
git(source, "push", str(canonical), "HEAD")
|
||||
git(parent, "update-index", "--cacheinfo", f"160000,{new},horizon")
|
||||
stale = str(root / "missing-upstream.git")
|
||||
git(parent, "config", "submodule.horizon.url", stale)
|
||||
git(child, "remote", "set-url", "origin", stale)
|
||||
self.assertEqual(git(child, "rev-parse", "HEAD"), old)
|
||||
with patch.object(airdef, "ROOT", parent), patch.object(airdef, "FORK", child):
|
||||
airdef.fork()
|
||||
self.assertEqual(git(child, "rev-parse", "HEAD"), new)
|
||||
self.assertEqual(git(child, "remote", "get-url", "origin"), str(canonical))
|
||||
# The fast path must also repair stale configuration for the next update.
|
||||
git(child, "remote", "set-url", "origin", stale)
|
||||
airdef.fork()
|
||||
self.assertEqual(git(child, "remote", "get-url", "origin"), str(canonical))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user