diff src/hgext3rd/hggit_serve/_export.py @ 13:00bdfac5416c

Create Git SSH commands and add some documentation. Also cleanup. - Adds git-upload-pack and git-receive-pack as hg subcommands, to be run on the server side by git push/pull. - Starts on documentation. - Cleans up a lot of stuff.
author Paul Fisher <paul@pfish.zone>
date Thu, 19 Feb 2026 01:13:56 -0500
parents f630d9904ea7
children 959ef686193f
line wrap: on
line diff
--- a/src/hgext3rd/hggit_serve/_export.py	Wed Feb 18 16:17:05 2026 -0500
+++ b/src/hgext3rd/hggit_serve/_export.py	Thu Feb 19 01:13:56 2026 -0500
@@ -48,18 +48,18 @@
 """
 
 
-def importing_enter(repo: hgrepo.IRepo) -> None:
+def _importing_enter(repo: hgrepo.IRepo) -> None:
     """Call this before you start importing from Git."""
     level = getattr(repo, _ILEVEL_ATTR, 0) + 1
     setattr(repo, _ILEVEL_ATTR, level)
 
 
-def is_importing(repo: hgrepo.IRepo) -> bool:
+def _is_importing(repo: hgrepo.IRepo) -> bool:
     """Call this to check if you're currently importing."""
     return hasattr(repo, _ILEVEL_ATTR)
 
 
-def importing_exit(repo: hgrepo.IRepo) -> None:
+def _importing_exit(repo: hgrepo.IRepo) -> None:
     """Call this after you finish importing from Git."""
     level = getattr(repo, _ILEVEL_ATTR) - 1
     if level:
@@ -68,16 +68,31 @@
         delattr(repo, _ILEVEL_ATTR)
 
 
+def import_all(repo: GittyRepo, command: bytes = b'(unknown)') -> None:
+    _importing_enter(repo)
+    try:
+        gh = repo.githandler
+        gh.import_git_objects(
+            command, remote_names=(), refs=gh.git.refs.as_dict()
+        )
+    finally:
+        _importing_exit(repo)
+
+
 #
 # Export handling.
 #
 
 
-def clean_all_refs(refs: dulwich.refs.RefsContainer) -> None:
+def _clean_all_refs(refs: dulwich.refs.RefsContainer) -> None:
     """Removes all refs from the Git repository."""
+    # dump to allkeys so we explicitly are iterating over a snapshot
+    # and not over something while we mutate
+    for ref in refs.allkeys():
+        refs.remove_if_equals(ref, None)
 
 
-def set_head(ui: hgui.ui, repo: GittyRepo, at_name: bytes) -> None:
+def _set_head(ui: hgui.ui, repo: GittyRepo, at_name: bytes) -> None:
     """Creates a HEAD reference in Git referring to the current HEAD."""
     # By default, we use '@', since that's what will be auto checked out.
     current = b'@'
@@ -117,23 +132,19 @@
     refs.set_symbolic_ref(b'HEAD', git_branch)
 
 
-def fix_refs(ui: hgui.ui, repo: GittyRepo) -> None:
+def _fix_refs(ui: hgui.ui, repo: GittyRepo) -> None:
     """After a git export, fix up the refs.
 
     This ensures that there are no leftover refs from older, removed bookmarks
     and that there is a proper HEAD set so that cloning works.
     """
-    refs = repo.githandler.git.refs
-    # dump to allkeys so we explicitly are iterating over a snapshot
-    # and not over something while we mutate
-    for ref in refs.allkeys():
-        refs.remove_if_equals(ref, None)
+    _clean_all_refs(repo.githandler.git.refs)
     repo.githandler.export_hg_tags()
     repo.githandler.update_references()
     default_branch_name = ui.config(
         b'hggit-serve', b'default-branch', b'default'
     )
-    set_head(ui, repo, default_branch_name)
+    _set_head(ui, repo, default_branch_name)
 
 
 #
@@ -149,18 +160,18 @@
     if auto_export == b'never':
         return
     if auto_export == b'always' or git_handler.has_gitrepo(repo):
-        if is_importing(repo):
+        if _is_importing(repo):
             ui.note(b'currently importing revs from git; not exporting\n')
             return
         repo.githandler.export_commits()
-        fix_refs(ui, repo)
+        _fix_refs(ui, repo)
 
 
 def _fix_refs_hook(ui: hgui.ui, repo: hgrepo.IRepo, **__: object) -> None:
     """Exports to Git and sets up for serving.  See ``_fix_refs``."""
     if not is_gitty(repo):
         return
-    fix_refs(ui, repo)
+    _fix_refs(ui, repo)
 
 
 #
@@ -171,18 +182,28 @@
 def uipopulate(ui: hgui.ui) -> None:
     # Fix up our tags after a Git export.
     ui.setconfig(
-        b'hooks', b'post-git-export.__gitserve_add_tag__', _fix_refs_hook
+        b'hooks',
+        b'post-git-export.__gitserve_add_tag__',
+        _fix_refs_hook,
+        source=b'hggit_serve',
     )
     # Whenever we get new revisions, export them to the Git repository.
-    ui.setconfig(b'hooks', b'txnclose.__gitserve_export__', _export_hook)
+    ui.setconfig(
+        b'hooks',
+        b'txnclose.__gitserve_export__',
+        _export_hook,
+        source=b'hggit_serve',
+    )
     # Don't step on ourselves when importing data from Git.
     ui.setconfig(
         b'hooks',
         b'pre-git-import.__gitserve_suppress_export__',
-        lambda _, repo, **__: importing_enter(repo),
+        lambda _, repo, **__: _importing_enter(repo),
+        source=b'hggit_serve',
     )
     ui.setconfig(
         b'hooks',
         b'post-git-import.__gitserve_suppress_export__',
-        lambda _, repo, **__: importing_exit(repo),
+        lambda _, repo, **__: _importing_exit(repo),
+        source=b'hggit-serve',
     )