glandium / git-cinnabar

git remote helper to interact with mercurial repositories
GNU General Public License v2.0
288 stars 61 forks source link

Mirror pushes back to hg #335

Open riastradh opened 2 days ago

riastradh commented 2 days ago

Suppose I have an hg repository, say ssh://hg.example.com/src.

Developers who have installed git-cinnabar can interact with it that way. Can it be exposed to developers who don't have git-cinnabar installed, for push and pull access, say via an intermediate ssh://git.example.com/src.git?

Obviously a cron job or notify hook can trigger git fetch --mirror in ssh://git.example.com/src.git, and developers can git clone and pull from ssh://git.example.com/src.git to get and track a normal git repository, modulo the unconventional refnames. But what about push?

  1. I tried creating a pre-receive hook in ssh://git.example.com that does git push, but that fails because with git-cinnabar, git push to a remote hg repo updates some local refs too (presumably to store the hg hash <-> git hash correspondence):

    remote: error: update_ref failed for ref 'refs/cinnabar/refs/heads/branches/default/tip': ref updates forbidden inside quarantine environment

  2. I tried creating a post-receive hook in ssh://git.example.com that does git push, and while that allows the push to proceed, it's wrong because the git repo has already committed the ref updates before the hg repo has had a chance to review, and possibly reject, the push. So the git repo may wind up falsely accepting a push that it should have rejected, and committing ref updates for the errant changes. (Same problem with post-update, of course.)

Is there another approach that could make this work, or is there a fundamental reason blocking it?

glandium commented 2 days ago

remote: error: update_ref failed for ref 'refs/cinnabar/refs/heads/branches/default/tip': ref updates forbidden inside quarantine environment Where does this error message come from exactly?

riastradh commented 2 days ago

remote: error: update_ref failed for ref 'refs/cinnabar/refs/heads/branches/default/tip': ref updates forbidden inside quarantine environment Where does this error message come from exactly?

Here's the pre-receive hook I used:

#!/bin/sh

set -Ceu
set -x

cmd="git push origin"
while read old new ref stuff; do
    # XXX require fast-forward
    cmd="${cmd} ${new}:${ref}"
done
$cmd

Here's the output when I push to a git repository with that pre-receive hook, which had been cloned from an origin of hg::/path/to/hg/repo:

Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 335 bytes | 335.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
remote: + cmd='git push origin'
remote: + read old new ref stuff
remote: + cmd='git push origin c882229d437b3afd2f2d5f1d9a5b1f6bfc04b10e:refs/heads/branches/default/tip'
remote: + read old new ref stuff
remote: + git push origin 'c882229d437b3afd2f2d5f1d9a5b1f6bfc04b10e:refs/heads/branches/default/tip'
remote: remote: adding changesets
remote: remote: adding manifests
remote: remote: adding file changes
remote: remote: added 1 changesets with 1 changes to 1 files
remote: error: update_ref failed for ref 'refs/cinnabar/refs/heads/branches/default/tip': ref updates forbidden inside quarantine environment
remote: To hg::/path/to/hg/repo
remote:    be0de8f..c882229  c882229d437b3afd2f2d5f1d9a5b1f6bfc04b10e -> branches/default/tip
remote: error: update_ref failed for ref 'refs/heads/branches/default/tip': ref updates forbidden inside quarantine environment
remote: fatal: called `Result::unwrap()` on an `Err` value: "ref updates forbidden inside quarantine environment"
remote: Run the command again with `git -c cinnabar.check=traceback <command>` to see the full traceback.
remote: error: git-remote-hg died of signal 6
To /path/to/git/repo
 ! [remote rejected] branches/default/tip -> branches/default/tip (pre-receive hook declined)
error: failed to push some refs to '/path/to/git/repo'
glandium commented 2 days ago

Presumably, even if git-cinnabar didn't do a ref update, your push would too, and that would be rejected as well. That is, if your origin was a git repo rather than a mercurial remote, I would expect you to get a similar error when the push tries to update a ref under refs/remotes/origin/. That it fails on refs/cinnabar/ stuff first, is kind of incidental. You should probably try to get your setup working with a pure git repo first (possibly asking for the recommended setup on the git mailing list)