1. 31 3月, 2017 1 次提交
    • B
      Rename sha1_array to oid_array · 910650d2
      brian m. carlson 提交于
      Since this structure handles an array of object IDs, rename it to struct
      oid_array.  Also rename the accessor functions and the initialization
      constant.
      
      This commit was produced mechanically by providing non-Documentation
      files to the following Perl one-liners:
      
          perl -pi -E 's/struct sha1_array/struct oid_array/g'
          perl -pi -E 's/\bsha1_array_/oid_array_/g'
          perl -pi -E 's/SHA1_ARRAY_INIT/OID_ARRAY_INIT/g'
      Signed-off-by: Nbrian m. carlson <sandals@crustytoothpaste.net>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      910650d2
  2. 29 3月, 2017 1 次提交
  3. 08 3月, 2017 5 次提交
    • J
      send-pack: report signal death of pack-objects · d1a13d3f
      Jeff King 提交于
      If our pack-objects sub-process dies of a signal, then it
      likely didn't have a chance to write anything useful to
      stderr. The user may be left scratching their head why the
      push failed. Let's detect this situation and write something
      to stderr.
      Signed-off-by: NJeff King <peff@peff.net>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      d1a13d3f
    • J
      send-pack: read "unpack" status even on pack-objects failure · ba69f92d
      Jeff King 提交于
      If the local pack-objects of a push fails, we'll tell the
      user about it. But one likely cause is that the remote
      index-pack stopped reading for some reason (because it
      didn't like our input, or encountered another error). In
      that case we'd expect the remote to report more details to
      us via the "unpack ..." status line. However, the current
      code just hangs up completely, and the user never sees it.
      
      Instead, let's call receive_unpack_status(), which will
      complain on stderr with whatever reason the remote told us.
      Note that if our pack-objects fails because the connection
      was severed or the remote just crashed entirely, then our
      packet_read_line() call may fail with "the remote end hung
      up unexpectedly". That's OK. It's a more accurate
      description than what we get now (which is just "some refs
      failed to push").
      
      This should be safe from any deadlocks. At the point we make
      this call we'll have closed the writing end of the
      connection to the server (either by handing it off to
      a pack-objects which exited, explicitly in the stateless_rpc
      case, or by doing a half-duplex shutdown for a socket). So
      there should be no chance that the other side is waiting
      for the rest of our pack-objects input.
      Signed-off-by: NJeff King <peff@peff.net>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      ba69f92d
    • J
      send-pack: improve unpack-status error messages · 40d05d04
      Jeff King 提交于
      When the remote tells us that the "unpack" step failed, we
      show an error message. However, unless you are familiar with
      the internals of send-pack and receive-pack, it was not
      clear that this represented an error on the remote side.
      Let's re-word to make that more obvious.
      
      Likewise, when we got an unexpected packet from the other
      end, we complained with a vague message but did not actually
      show the packet.  Let's fix that.
      
      And finally, neither message was marked for translation. The
      message from the remote probably won't be translated, but
      there's no reason we can't do better for the local half.
      Signed-off-by: NJeff King <peff@peff.net>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      40d05d04
    • J
      send-pack: use skip_prefix for parsing unpack status · f7cd74d1
      Jeff King 提交于
      This avoids repeating ourselves, and the use of magic
      numbers.
      Signed-off-by: NJeff King <peff@peff.net>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      f7cd74d1
    • J
      send-pack: extract parsing of "unpack" response · 7c39df29
      Jeff King 提交于
      After sending the pack, we call receive_status() which gets
      both the "unpack" line and the ref status. Let's break these
      into two functions so we can call the first part
      independently.
      Signed-off-by: NJeff King <peff@peff.net>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      7c39df29
  4. 13 10月, 2016 1 次提交
  5. 02 8月, 2016 1 次提交
  6. 15 7月, 2016 1 次提交
  7. 09 6月, 2016 1 次提交
    • J
      send-pack: use buffered I/O to talk to pack-objects · f0bca72d
      Jeff King 提交于
      We start a pack-objects process and then write all of the
      positive and negative sha1s to it over a pipe. We do so by
      formatting each item into a fixed-size buffer and then
      writing each individually. This has two drawbacks:
      
        1. There's some manual computation of the buffer size,
           which is not immediately obvious is correct (though it
           is).
      
        2. We write() once per sha1, which means a lot more system
           calls than are necessary.
      
      We can solve both by wrapping the pipe descriptor in a stdio
      handle; this is the same technique used by upload-pack when
      serving fetches.
      
      Note that we can also simplify and improve the error
      handling here. The original detected a single write error
      and broke out of the loop (presumably to avoid writing the
      error message over and over), but never actually acted on
      seeing an error; we just fed truncated input and took
      whatever pack-objects returned.
      
      In practice, this probably didn't matter, as the likely
      errors would be caused by pack-objects dying (and we'd
      probably just die with SIGPIPE anyway). But we can easily
      make this simpler and more robust; the stdio handle keeps an
      error flag, which we can check at the end.
      Signed-off-by: NJeff King <peff@peff.net>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      f0bca72d
  8. 21 4月, 2016 2 次提交
    • J
      send-pack: isolate sigpipe in demuxer thread · 3e8b06d0
      Jeff King 提交于
      If we get an error from pack-objects, we may exit
      send_pack() early, before reading the server's status
      response. In such a case, we may racily see SIGPIPE from our
      async demuxer (which is trying to write that status back to
      us), and we'd prefer to continue pushing the error up the
      call stack, rather than taking down the whole process with
      signal death.
      
      This is safe to do because our demuxer just calls
      recv_sideband, whose data writes are all done with
      write_or_die(), which will notice SIGPIPE.
      
      We do also write sideband 2 to stderr, and we would no
      longer die on SIGPIPE there (if it were piped in the first
      place, and if the piped program went away). But that's
      probably a good thing, as it likewise should not abort the
      push process at all (neither immediately by signal, nor
      eventually by reporting failure back to the main thread).
      Signed-off-by: NJeff King <peff@peff.net>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      3e8b06d0
    • J
      send-pack: close demux pipe before finishing async process · 739cf491
      Jeff King 提交于
      This fixes a deadlock on the client side when pushing a
      large number of refs from a corrupted repo.  There's a
      reproduction script below, but let's start with a
      human-readable explanation.
      
      The client side of a push goes something like this:
      
        1. Start an async process to demux sideband coming from
           the server.
      
        2. Run pack-objects to send the actual pack, and wait for
           its status via finish_command().
      
        3. If pack-objects failed, abort immediately.
      
        4. If pack-objects succeeded, read the per-ref status from
           the server, which is actually coming over a pipe from
           the demux process started in step 1.
      
      We run finish_async() to wait for and clean up the demux
      process in two places. In step 3, if we see an error, we
      want it to end early. And after step 4, it should be done
      writing any data and we are just cleaning it up.
      
      Let's focus on the error case first. We hand the output
      descriptor to the server over to pack-objects. So by the
      time it has returned an error to us, it has closed the
      descriptor and the server has gotten EOF. The server will
      mark all refs as failed with "unpacker error" and send us
      back the status for each (followed by EOF).
      
      This status goes to the demuxer thread, which relays it over
      a pipe to the main thread. But the main thread never even
      tries reading the status. It's trying to bail because of the
      pack-objects error, and is waiting for the demuxer thread to
      finish. If there are a small number of refs, that's OK; the
      demuxer thread writes into the pipe buffer, sees EOF from
      the server, and quits. But if there are a large number of
      refs, it may block on write() back to the main thread,
      leading to a deadlock (the main thread is waiting for the
      demuxer to finish, the demuxer is waiting for the main
      thread to read).
      
      We can break this deadlock by closing the pipe between the
      demuxer and the main thread before calling finish_async().
      Then the demuxer gets a write() error and exits.
      
      The non-error case usually just works, because we will have
      read all of the data from the other side. We do close
      demux.out already, but we only do so _after_ calling
      finish_async(). This is OK because there shouldn't be any
      more data coming from the server. But technically we've only
      read to a flush packet, and a broken or malicious server
      could be sending more cruft. In such a case, we would hit
      the same deadlock. Closing the pipe first doesn't affect the
      normal case, and means that for a cruft-sending server,
      we'll notice a write() error rather than deadlocking.
      
      Note that when write() sees this error, we'll actually
      deliver SIGPIPE to the thread, which will take down the
      whole process (unless we're compiled with NO_PTHREADS). This
      isn't ideal, but it's an improvement over the status quo,
      which is deadlocking. And SIGPIPE handling in async threads
      is a bigger problem that we can deal with separately.
      
      A simple reproduction for the error case is below. It's
      technically racy (we could exit the main process and take
      down the async thread with us before it even reads the
      status), though in practice it seems to fail pretty
      consistently.
      
          git init repo &&
          cd repo &&
      
          # make some commits; we need two so we can simulate corruption
          # in the history later.
          git commit --allow-empty -m one &&
          one=$(git rev-parse HEAD) &&
          git commit --allow-empty -m two &&
          two=$(git rev-parse HEAD) &&
      
          # now make a ton of refs; our goal here is to overflow the pipe buffer
          # when reporting the ref status, which will cause the demuxer to block
          # on write()
          for i in $(seq 20000); do
          	echo "create refs/heads/this-is-a-really-long-branch-name-$i $two"
          done |
          git update-ref --stdin &&
      
          # now make a corruption in the history such that pack-objects will fail
          rm -vf .git/objects/$(echo $one | sed 's}..}&/}') &&
      
          # and then push the result
          git init --bare dst.git &&
          git push --mirror dst.git
      Signed-off-by: NJeff King <peff@peff.net>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      739cf491
  9. 20 11月, 2015 1 次提交
  10. 20 8月, 2015 1 次提交
  11. 03 4月, 2015 2 次提交
  12. 14 3月, 2015 1 次提交
  13. 08 1月, 2015 2 次提交
    • R
      send-pack.c: add --atomic command line argument · 4ff17f10
      Ronnie Sahlberg 提交于
      This adds support to send-pack to negotiate and use atomic pushes
      iff the server supports it. Atomic pushes are activated by a new command
      line flag --atomic.
      
      In order to do this we also need to change the semantics for send_pack()
      slightly. The existing send_pack() function actually doesn't send all the
      refs back to the server when multiple refs are involved, for example
      when using --all. Several of the failure modes for pushes can already be
      detected locally in the send_pack client based on the information from the
      initial server side list of all the refs as generated by receive-pack.
      Any such refs that we thus know would fail to push are thus pruned from
      the list of refs we send to the server to update.
      
      For atomic pushes, we have to deal thus with both failures that are detected
      locally as well as failures that are reported back from the server. In order
      to do so we treat all local failures as push failures too.
      
      We introduce a new status code REF_STATUS_ATOMIC_PUSH_FAILED so we can
      flag all refs that we would normally have tried to push to the server
      but we did not due to local failures. This is to improve the error message
      back to the end user to flag that "these refs failed to update since the
      atomic push operation failed."
      Signed-off-by: NRonnie Sahlberg <sahlberg@google.com>
      Signed-off-by: NStefan Beller <sbeller@google.com>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      4ff17f10
    • S
      send-pack: rename ref_update_to_be_sent to check_to_send_update · 7582e939
      Stefan Beller 提交于
      This renames ref_update_to_be_sent to check_to_send_update and inverts
      the meaning of the return value. Having the return value inverted we
      can have different values for the error codes. This is useful in a
      later patch when we want to know if we hit the CHECK_REF_STATUS_REJECTED
      case.
      Signed-off-by: NStefan Beller <sbeller@google.com>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      7582e939
  14. 30 12月, 2014 1 次提交
    • B
      pack-objects: use --objects-edge-aggressive for shallow repos · 2dacf26d
      brian m. carlson 提交于
      When fetching into or pushing from a shallow repository, we want to
      aggressively mark edges as uninteresting, since this decreases the pack
      size.  However, aggressively marking edges can negatively affect
      performance on large non-shallow repositories with lots of refs.
      
      Teach pack-objects a --shallow option to indicate that we're pushing
      from or fetching into a shallow repository.  Use
      --objects-edge-aggressive only for shallow repositories and otherwise
      use --objects-edge, which performs better in the general case.  Update
      the callers to pass the --shallow option when they are dealing with a
      shallow repository.
      Signed-off-by: Nbrian m. carlson <sandals@crustytoothpaste.net>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      2dacf26d
  15. 18 9月, 2014 1 次提交
    • J
      signed push: fortify against replay attacks · b89363e4
      Junio C Hamano 提交于
      In order to prevent a valid push certificate for pushing into an
      repository from getting replayed in a different push operation, send
      a nonce string from the receive-pack process and have the signer
      include it in the push certificate.  The receiving end uses an HMAC
      hash of the path to the repository it serves and the current time
      stamp, hashed with a secret seed (the secret seed does not have to
      be per-repository but can be defined in /etc/gitconfig) to generate
      the nonce, in order to ensure that a random third party cannot forge
      a nonce that looks like it originated from it.
      
      The original nonce is exported as GIT_PUSH_CERT_NONCE for the hooks
      to examine and match against the value on the "nonce" header in the
      certificate to notice a replay, but returned "nonce" header in the
      push certificate is examined by receive-pack and the result is
      exported as GIT_PUSH_CERT_NONCE_STATUS, whose value would be "OK"
      if the nonce recorded in the certificate matches what we expect, so
      that the hooks can more easily check.
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      b89363e4
  16. 16 9月, 2014 11 次提交
    • J
      signed push: add "pushee" header to push certificate · 9be89160
      Junio C Hamano 提交于
      Record the URL of the intended recipient for a push (after
      anonymizing it if it has authentication material) on a new "pushee
      URL" header.  Because the networking configuration (SSH-tunnels,
      proxies, etc.) on the pushing user's side varies, the receiving
      repository may not know the single canonical URL all the pushing
      users would refer it as (besides, many sites allow pushing over
      ssh://host/path and https://host/path protocols to the same
      repository but with different local part of the path).  So this
      value may not be reliably used for replay-attack prevention
      purposes, but this will still serve as a human readable hint to
      identify the repository the certificate refers to.
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      9be89160
    • J
      signed push: remove duplicated protocol info · 4adf569d
      Junio C Hamano 提交于
      With the interim protocol, we used to send the update commands even
      though we already send a signed copy of the same information when
      push certificate is in use.  Update the send-pack/receive-pack pair
      not to do so.
      
      The notable thing on the receive-pack side is that it makes sure
      that there is no command sent over the traditional protocol packet
      outside the push certificate.  Otherwise a pusher can claim to be
      pushing one set of ref updates in the signed certificate while
      issuing commands to update unrelated refs, and such an update will
      evade later audits.
      
      Finally, start documenting the protocol.
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      4adf569d
    • J
      send-pack: send feature request on push-cert packet · 20a7558f
      Junio C Hamano 提交于
      We would want to update the interim protocol so that we do not send
      the usual update commands when the push certificate feature is in
      use, as the same information is in the certificate.  Once that
      happens, the push-cert packet may become the only protocol command,
      but then there is no packet to put the feature request behind, like
      we always did.
      
      As we have prepared the receiving end that understands the push-cert
      feature to accept the feature request on the first protocol packet
      (other than "shallow ", which was an unfortunate historical mistake
      that has to come before everything else), we can give the feature
      request on the push-cert packet instead of the first update protocol
      packet, in preparation for the next step to actually update to the
      final protocol.
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      20a7558f
    • J
      push: the beginning of "git push --signed" · a85b377d
      Junio C Hamano 提交于
      While signed tags and commits assert that the objects thusly signed
      came from you, who signed these objects, there is not a good way to
      assert that you wanted to have a particular object at the tip of a
      particular branch.  My signing v2.0.1 tag only means I want to call
      the version v2.0.1, and it does not mean I want to push it out to my
      'master' branch---it is likely that I only want it in 'maint', so
      the signature on the object alone is insufficient.
      
      The only assurance to you that 'maint' points at what I wanted to
      place there comes from your trust on the hosting site and my
      authentication with it, which cannot easily audited later.
      
      Introduce a mechanism that allows 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 mechanism goes like this:
      
       1. You push out your work with "git push --signed".
      
       2. The sending side learns where the remote refs are as usual,
          together with what protocol extension the receiving end
          supports.  If the receiving end does not advertise the protocol
          extension "push-cert", an attempt to "git push --signed" fails.
      
          Otherwise, a text file, that looks like the following, is
          prepared in core:
      
      	certificate version 0.1
      	pusher Junio C Hamano <gitster@pobox.com> 1315427886 -0700
      
      	7339ca65... 21580ecb... refs/heads/master
      	3793ac56... 12850bec... refs/heads/next
      
          The file begins with a few header lines, which may grow as we
          gain more experience.  The 'pusher' header records the name of
          the signer (the value of user.signingkey configuration variable,
          falling back to GIT_COMMITTER_{NAME|EMAIL}) and the time of the
          certificate generation.  After the header, a blank line follows,
          followed by a copy of the protocol message lines.
      
          Each 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 (by recording the "old" object
          name, the push certificate also protects against replaying).  It
          is expected that new command packet types other than the
          old-new-refname kind will be included in push certificate in the
          same way as would appear in the plain vanilla command packets in
          unsigned pushes.
      
          The user then is asked to sign this push certificate using GPG,
          formatted in a way similar to how signed tag objects are signed,
          and the result is sent 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.
      
       3. When the receiving end sees a push certificate, the certificate
          is written out as a blob.  The pre-receive hook can learn about
          the certificate by checking GIT_PUSH_CERT environment variable,
          which, if present, tells the object name of this blob, and make
          the decision to allow or reject this push.  Additionally, the
          post-receive hook can also look at the certificate, which may be
          a good place to log all the received certificates for later
          audits.
      
      Because a push certificate carry the same information as the usual
      command packets in the protocol exchange, we can omit the latter
      when a push certificate is in use and reduce the protocol overhead.
      This however is not included in this patch to make it easier to
      review (in other words, the series at this step should never be
      released without the remainder of the series, as it implements an
      interim protocol that will be incompatible with the final one).
      As such, the documentation update for the protocol is left out of
      this step.
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      a85b377d
    • J
      send-pack: clarify that cmds_sent is a boolean · c67072b9
      Junio C Hamano 提交于
      We use it to make sure that the feature request is sent only once on
      the very first request packet (ignoring the "shallow " line, which
      was an unfortunate mistake we cannot retroactively fix with existing
      receive-pack already deployed in the field) and we set it to "true"
      with cmds_sent++, not because we care about the actual number of
      updates sent but because it is merely an idiomatic way.
      
      Set it explicitly to one to clarify that the code that uses this
      variable only cares about its zero-ness.
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      c67072b9
    • J
      send-pack: refactor inspecting and resetting status and sending commands · b783aa71
      Junio C Hamano 提交于
      The main loop over remote_refs list inspects the ref status
      to see if we need to generate pack data (i.e. a delete-only push
      does not need to send any additional data), resets it to "expecting
      the status report" state, and formats the actual update commands
      to be sent.
      
      Split the former two out of the main loop, as it will become
      conditional in later steps.
      
      Besides, we should have code that does real thing here, before the
      "Finally, tell the other end!" part ;-)
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      b783aa71
    • J
      send-pack: rename "new_refs" to "need_pack_data" · ab2b0c90
      Junio C Hamano 提交于
      The variable counts how many non-deleting command is being sent, but
      is only checked with 0-ness to decide if we need to send the pack
      data.
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      ab2b0c90
    • J
      send-pack: factor out capability string generation · 887f3533
      Junio C Hamano 提交于
      A run of 'var ? " var" : ""' fed to a long printf string in a deeply
      nested block was hard to read.  Move it outside the loop and format
      it into a strbuf.
      
      As an added bonus, the trick to add "agent=<agent-name>" by using
      two conditionals is replaced by a more readable version.
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      887f3533
    • J
      send-pack: always send capabilities · 64de20a1
      Junio C Hamano 提交于
      We tried to avoid sending one extra byte, NUL and nothing behind it
      to signal there is no protocol capabilities being sent, on the first
      command packet on the wire, but it just made the code look ugly.
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      64de20a1
    • J
      send-pack: refactor decision to send update per ref · e40671a3
      Junio C Hamano 提交于
      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: NJunio C Hamano <gitster@pobox.com>
      e40671a3
    • J
      send-pack: move REF_STATUS_REJECT_NODELETE logic a bit higher · 621b0599
      Junio C Hamano 提交于
      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: NJunio C Hamano <gitster@pobox.com>
      621b0599
  17. 21 8月, 2014 1 次提交
  18. 07 1月, 2014 1 次提交
  19. 11 12月, 2013 3 次提交
  20. 06 12月, 2013 1 次提交
    • C
      replace {pre,suf}fixcmp() with {starts,ends}_with() · 59556548
      Christian Couder 提交于
      Leaving only the function definitions and declarations so that any
      new topic in flight can still make use of the old functions, replace
      existing uses of the prefixcmp() and suffixcmp() with new API
      functions.
      
      The change can be recreated by mechanically applying this:
      
          $ git grep -l -e prefixcmp -e suffixcmp -- \*.c |
            grep -v strbuf\\.c |
            xargs perl -pi -e '
              s|!prefixcmp\(|starts_with\(|g;
              s|prefixcmp\(|!starts_with\(|g;
              s|!suffixcmp\(|ends_with\(|g;
              s|suffixcmp\(|!ends_with\(|g;
            '
      
      on the result of preparatory changes in this series.
      Signed-off-by: NChristian Couder <chriscool@tuxfamily.org>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      59556548
  21. 26 11月, 2013 1 次提交