send-pack: move REF_STATUS_REJECT_NODELETE logic a bit higher

20e8b465 (refactor ref status logic for pushing, 2010-01-08)
restructured the code to set status for each ref to be pushed, but
did not quite go far enough.  We inspect the status set earlier by
set_refs_status_for_push() and then perform yet another update to
the status of a ref with an otherwise OK status to be deleted to
mark it with REF_STATUS_REJECT_NODELETE when the protocol tells us
never to delete.

Split the latter into a separate loop that comes before we enter the
per-ref loop.  This way we would have one less condition to check in
the main loop.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
send-pack: refactor decision to send update per ref

A new helper function ref_update_to_be_sent() decides for each ref
if the update is to be sent based on the status previously set by
set_ref_status_for_push() and also if this is a mirrored push.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
push: the beginning of "signed push"

While signed tags and commits assert that the objects thusly signed
came from you, there is no good way to assert that you wanted to
have a particular object at the tip of a particular branch.

This introduces a skeletal framework to allow you to sign a "push
certificate" (for the lack of better name) every time you push,
asserting that what object you are pushing to update which ref that
used to point at what other object.

Think of it as a cryptographic protection for ref updates, similar
to signed tags/commits but working on an orthogonal axis.

The basic flow based on this idea would go like this:

 1. You push out your work with "git push -s".

 2. The sending side learns where the remote refs are and which refs
    are to be updated with this push, as usual, together with what
    protocol extension the receiving end supports.  If the receiving
    end does not advertise the protocol extension "push-cert", the
    sending side falls back to the normal push that is not signed.

    Otherwise, a text file in core, that looks like the following,
    is prepared:

	pushed-by Junio C Hamano <gitster@pobox.com>
	pushed-at 1315427886 -0700
	update 7339ca65... 21580ecb... refs/heads/master
	update 3793ac56... 12850bec... refs/heads/next

    Each "update" line shows the old and the new object name at the
    tip of the ref this push tries to update, in the way identical
    to how the underlying "git push" protocol exchange tells the ref
    updates to the receiving end.

    The user then is asked to sign this push certificate using GPG
    and the result is carried to the other side (i.e. receive-pack).

    In the protocol exchange, this step comes immediately before the
    sender tells what the result of the push should be, which in
    turn comes before it sends the pack data.

    Because "update" records in a push certificate carry the same
    information as the result packets in the protocol exchange, we
    could probably omit/shorten the latter when a push certificate
    is in use to reduce the protocol overhead.

 3. When the receiving end sees a push certificate, it checks the
    validity of its GPG signature (the receiving end needs to have
    GNUPGHOME configured for this), and makes sure that the signer
    matches the identity recorded on "pushed-by" record, before
    starting to accept the pack data stream.  The push is failed if
    the certificate verification fails.

 4. The pre-receive hook can inspect the push certificate and take
    it into account when it makes the decision to allow or reject
    this push.  In order to make the interface backward compatible,
    receive-pack would write the push certificate to a blob object
    and give its object name in an environment variable of the hook.

Signed-off-by: Junio C Hamano <gitster@pobox.com>