fix: use git fetch from Gitea side to transfer objects + update refs without triggering pre-receive hook
This commit is contained in:
+37
-35
@@ -4,7 +4,7 @@ import logging
|
||||
import os
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from typing import Dict, Optional
|
||||
from typing import Optional
|
||||
|
||||
from .mirror import Mirror
|
||||
|
||||
@@ -52,10 +52,11 @@ def _git(*args: str, timeout: int = 300, check: bool = True) -> str:
|
||||
|
||||
|
||||
def push_to_gitea(mirror: Mirror) -> bool:
|
||||
"""Sync canonical refs to Gitea's bare repo via direct ref updates.
|
||||
"""Sync canonical → Gitea via ``git fetch`` from Gitea's side.
|
||||
|
||||
Uses ``git update-ref`` to bypass Gitea's pre-receive hook, then
|
||||
fires Gitea's ``post-receive`` hook manually so the UI refreshes.
|
||||
``git fetch`` transfers objects + updates refs without triggering
|
||||
Gitea's ``pre-receive`` hook, then fires ``post-receive`` manually
|
||||
for the UI to refresh.
|
||||
|
||||
Returns True if anything changed.
|
||||
"""
|
||||
@@ -66,49 +67,50 @@ def push_to_gitea(mirror: Mirror) -> bool:
|
||||
|
||||
canonical = str(mirror.canonical_dir)
|
||||
|
||||
# Collect canonical refs
|
||||
out = _git("--git-dir", canonical, "for-each-ref",
|
||||
# Grab old refs so we can detect what changed
|
||||
old_refs: Dict[str, str] = {}
|
||||
out = _git("--git-dir", str(gitea_path), "for-each-ref",
|
||||
"--format=%(objectname) %(refname)",
|
||||
"refs/heads/", "refs/tags/",
|
||||
timeout=30, check=False)
|
||||
canonical_refs: Dict[str, str] = {}
|
||||
for line in (out or "").splitlines():
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
obj_hash, ref = line.split(None, 1)
|
||||
canonical_refs[ref] = obj_hash
|
||||
h, r = line.split(None, 1)
|
||||
old_refs[r] = h
|
||||
|
||||
# Gitea fetches from canonical — this transfers objects + refs,
|
||||
# and DOES NOT trigger Gitea's pre-receive hook.
|
||||
_git(
|
||||
"--git-dir", str(gitea_path), "fetch", "--prune",
|
||||
canonical,
|
||||
"+refs/heads/*:refs/heads/*",
|
||||
"+refs/tags/*:refs/tags/*",
|
||||
timeout=300,
|
||||
)
|
||||
|
||||
# Build the changelist for post-receive
|
||||
changed: list = []
|
||||
for ref, obj_hash in canonical_refs.items():
|
||||
gitea_hash = _git("--git-dir", str(gitea_path), "rev-parse",
|
||||
"--verify", "--quiet", ref,
|
||||
timeout=15, check=False)
|
||||
if obj_hash != gitea_hash:
|
||||
if gitea_hash:
|
||||
_git("--git-dir", str(gitea_path), "update-ref", ref,
|
||||
obj_hash, gitea_hash, timeout=15)
|
||||
else:
|
||||
_git("--git-dir", str(gitea_path), "update-ref", ref,
|
||||
obj_hash, timeout=15)
|
||||
changed.append((gitea_hash or "0" * 40, obj_hash, ref))
|
||||
logger.debug("Updated %s in Gitea", ref)
|
||||
|
||||
# Prune refs in Gitea not in canonical
|
||||
gitea_out = _git("--git-dir", str(gitea_path), "for-each-ref",
|
||||
"--format=%(objectname) %(refname)",
|
||||
"refs/heads/", "refs/tags/",
|
||||
timeout=30, check=False)
|
||||
for line in (gitea_out or "").splitlines():
|
||||
cur_refs: dict = {}
|
||||
out = _git("--git-dir", str(gitea_path), "for-each-ref",
|
||||
"--format=%(objectname) %(refname)",
|
||||
"refs/heads/", "refs/tags/",
|
||||
timeout=30, check=False)
|
||||
for line in (out or "").splitlines():
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
obj_hash, ref = line.split(None, 1)
|
||||
if ref not in canonical_refs:
|
||||
_git("--git-dir", str(gitea_path), "update-ref", "-d", ref,
|
||||
obj_hash, timeout=15)
|
||||
changed.append((obj_hash, "0" * 40, ref))
|
||||
logger.debug("Pruned %s from Gitea", ref)
|
||||
h, r = line.split(None, 1)
|
||||
cur_refs[r] = h
|
||||
old = old_refs.get(r, "0" * 40)
|
||||
if h != old:
|
||||
changed.append((old, h, r))
|
||||
|
||||
# Detect deletions (refs present before fetch but gone now)
|
||||
for r, old_h in old_refs.items():
|
||||
if r not in cur_refs:
|
||||
changed.append((old_h, "0" * 40, r))
|
||||
|
||||
if not changed:
|
||||
logger.debug("No new commits to push to Gitea")
|
||||
|
||||
Reference in New Issue
Block a user