Subject: [PATCH v3 0/6] transport: catch non-fast forwards

From: Tay Ray Chuan <[email-masked]>
Date: Thu, 24 Dec 2009 15:40:05 +0800

Junio, this is re-roll of the 'tr/http-push-ref-status' branch in 'pu'.

Summary:
  This patch series applies on top of 'next', and deals with alerting
  the user to rejected non-fast-forward pushes when using helpers
  (smart).

  Previously, git silently exited. This situation involves the curl
  helper and the smart protocol. The non-fast-forward push is only
  detected when curl executes the rpc client (git-send-pack). Now, we
  detect it before telling the helper to push.

Changes from v2:
 - add tests
 - modify commit messages to mention tests
 - report rejected non-fast-forward pushes for unmatched refs
   (without an explicit refspec) by the remote helper (see patches #2
   and #5).

   This remedies the scenario where a user would not be aware of
   rejected non-fast-forward pushes.

   It occurs when
     1) there are one or more pushes that succeed and
     2) there are one or more rejected non-fast-forward pushes that
	    involve refs that cannot be matched without explicit refspecs.

   This is due to the re-marking of ref status in transport-helper.c::
   push_refs() when interacting with the remote helper.

   If only non-matched, non-fast-forward refs are involved (ie.
   condition #2 is present without #1), then the situtation does not
   occur - no 'push' commands are passed to the remote helper, no
   interaction with the helper takes place, and no re-marking of ref
   status takes place. The user will be alerted to the rejected
   non-fast-forward push.

   If both are present, re-marking occurs. Even if a ref was not part
   of a 'push' command to the helper, 'ok'/'error' status reports might
   be made for it, since the remote helper does ref matching on its
   side. This led to refs that cannot be matched without an explicit
   refspec marked as REF_STATUS_REJECT_NONFASTFORWARD to be re-marked
   REF_STATUS_NONE.

   (Note: helpers fail to match refs as explicit refspecs are always
   available to the top-level transport mechanism, but only on a need-
   to-know basis to the remote helper via a 'push' command when a ref
   is to be pushed.)

   Interestingly, it is possible for a user to be forever unaware of
   the rejected push if the user relies on information from git push
   alone. As long as the user ensures that one or more other pushes are
   successful (eg. change a tracked ref fast-forwardedly) between the
   execution of git push, the rejected non-fast-forward push won't be
   reported.

Tay Ray Chuan (6):
  t5541-http-push.sh: add tests for non-fast-forward pushes
  t5541-http-push.sh: add test for unmatched, non-fast-forwarded refs
  refactor ref status logic for pushing
  transport.c::transport_push(): make ref status affect return value
  transport-helper.c::push_refs(): ignore helper-reported status if ref
    is not to be pushed
  transport-helper.c::push_refs(): emit "no refs" error message

 builtin-send-pack.c  |   50 +++++++++++---------------------------------------
 remote.c             |   50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 remote.h             |    2 ++
 t/t5541-http-push.sh |   43 +++++++++++++++++++++++++++++++++++++++++++
 transport-helper.c   |   32 ++++++++++++++++++++++----------
 transport.c          |   11 +++++++++--
 6 files changed, 137 insertions(+), 51 deletions(-)

--
Cheers,
Ray Chuan