Mercurial > hg-git-serve
changeset 6:7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
| author | Paul Fisher <paul@pfish.zone> |
|---|---|
| date | Sun, 15 Feb 2026 01:31:53 -0500 |
| parents | c43ce246240b |
| children | 4f42fdbb25f2 |
| files | src/git_serve/__init__.py |
| diffstat | 1 files changed, 59 insertions(+), 43 deletions(-) [+] |
line wrap: on
line diff
--- a/src/git_serve/__init__.py Sat Feb 14 21:39:54 2026 -0500 +++ b/src/git_serve/__init__.py Sun Feb 15 01:31:53 2026 -0500 @@ -141,7 +141,7 @@ refs.remove_if_equals(ref, None) -def _set_head(repo: GittyRepo) -> 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'@' @@ -152,76 +152,92 @@ git_current = current if current == b'@': # @ is a special keyword in Git, so we can't use it as a bookmark. - git_current = b'__default__' + git_current = at_name git_branch = dulwich.refs.LOCAL_BRANCH_PREFIX + git_current if not dulwich.refs.check_ref_format(git_branch): # We can't export this ref to Git. Give up. + ui.warn(f'{git_branch!r} is not a valid branch name for Git.'.encode()) + return + try: + # Maybe this is a real bookmark? + hgsha = repo._bookmarks[current] + except KeyError: + # Not a real bookmark. Assume we want the tip of the current branch. + branch = repo.dirstate.branch() + try: + tip = repo.branchtip(branch) + except hgerr.RepoLookupError: + # This branch somehow doesn't exist??? + ui.warn(f"{branch} doesn't seem to exist?".encode()) + return + hgsha = binascii.hexlify(tip) + gitsha = repo.githandler.map_git_get(hgsha) + if not gitsha: + # No Git SHA to match this Hg sha. Give up. + ui.warn(f'revision {hgsha} was not exported to Git'.encode()) return refs = repo.githandler.git.refs - if git_branch not in refs: - # This means our bookmark isn't actually in Git (usually because - # there's no real bookmark called '@'). We need to fake it. - try: - # Maybe this is a real bookmark? - hgsha = repo._bookmarks[current] - except KeyError: - # Not a real bookmark. Assume we want the tip of the current branch. - branch = repo.dirstate.branch() - try: - tip = repo.branchtip(branch) - except hgerr.RepoLookupError: - # This branch somehow doesn't exist??? - return - hgsha = binascii.hexlify(tip) - gitsha = repo.githandler.map_git_get(hgsha) - if not gitsha: - # No Git SHA to match this Hg sha. Give up. - return - refs.add_packed_refs({git_branch: gitsha}) + refs.add_packed_refs({git_branch: gitsha}) refs.set_symbolic_ref(b'HEAD', git_branch) -def _export_hook(ui: hgui.ui, repo: GittyRepo, **__: object) -> None: +def fix_refs_hook(ui: hgui.ui, repo: hgrepo.IRepo, **__: object) -> None: """Exports to Git and sets up for serving.""" - never_export = ui.configbool(b'git-serve', b'never-export') - if never_export: + if not _is_gitty(repo): return - always_export = ui.configbool(b'git-serve', b'always-export', False) - if always_export or os.path.isdir(repo.githandler.gitdir): - _export_repo(repo) + _fix_refs(ui, repo) -def _export_repo(repo: GittyRepo) -> None: - """Do the actual exporting.""" +def _fix_refs(ui: hgui.ui, repo: GittyRepo) -> None: + """After a git export, fix up the refs.""" _clean_all_refs(repo.githandler.git.refs) - repo.githandler.export_commits() - _set_head(repo) + 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) + + +def export_hook(ui: hgui.ui, repo: hgrepo.IRepo, **__: object) -> None: + if not _is_gitty(repo): + return + auto_export = ui.config(b'hggit-serve', b'auto-export') + if auto_export == b'never': + return + if auto_export == b'always' or os.path.isdir(repo.githandler.gitdir): + repo.githandler.export_commits() + _fix_refs(ui, repo) # Interfacing with Mercurial -__version__ = '0.1.3' +__version__ = '0.1.4' +testedwith = b'7.1 7.2' cmdtable: dict[bytes, object] = {} command = registrar.command(cmdtable) -@command(b'git-serve-export') -def git_serve_export(_: hgui.ui, repo: hgrepo.IRepo, **__: object) -> None: - if not _is_gitty(repo): - raise hgerr.Abort(b'this extension depends on the `hggit` extension') - _export_repo(repo) - - def uisetup(_: hgui.ui) -> None: extensions.wrapfunction( wireprotoserver, 'handlewsgirequest', _handle_git_protocol ) -def reposetup(ui: hgui.ui, _: hgrepo.IRepo) -> None: - ui.setconfig(b'hooks', b'txnclose.__gitserve_internal__', _export_hook) +def uipopulate(ui: hgui.ui) -> None: + ui.setconfig( + b'hooks', b'post-git-export.__gitserve_add_tag__', fix_refs_hook + ) + ui.setconfig(b'hooks', b'txnclose.__gitserve_export__', export_hook) -__all__ = ('__version__', 'cmdtable', 'command', 'uisetup', 'reposetup') +__all__ = ( + '__version__', + 'cmdtable', + 'command', + 'testedwith', + 'uipopulate', + 'uisetup', +)
