{"thread":{"id":"24899","subject":"remote-helpers: http-push protocol","startedAt":"2010-08-29T04:57:31Z","lastAt":"2010-09-07T22:14:01Z","messageCount":2,"participants":["Sverre Rabbelier","Jonathan Nieder"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"149202","messageId":"AANLkTim=HKiQ-25QEAPPRcH6wwLLAsDdoRqTsanM67SK@mail.gmail.com","threadId":"24899","inReplyTo":null,"subject":"remote-helpers: http-push protocol","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2010-08-29T04:57:31Z","receivedAt":"2010-08-29T04:57:31Z","isPatch":false,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"Heya,\n\nI'm trying to figure out how the current http push protocol is\nimplemented. What I've been able to deduce on my own:\n\nWhen fetching from the remote, the helper is called with 'list', after\nwhich it will give back a list of refs, 'remote' style. That is, the\nremote master branch will be listed as '<remote sha>\nrefs/heads/master'.\nWhen pushing to the remote, the helper is called with 'list for-push',\nit will again list all refs in the same manner (omitting 'HEAD' if the\nsmart protocol is used).\n\nWhat happens next is the part that confuses me, a certain set of refs\nis pushed, by calling the helper with 'push <refspec>'. I am unclear\nhow this set of refs is chosen, I see that only refs that have a\npeer_ref are sent, unless mirror is also set (I don't think I\nunderstand the significance)? After the push, the helper write a set\nof 'ok/error' messages, sometimes for refs that were not asked to be\npushed in the first place, errors for those are ignored though (the\nerror parsing code ignores an error if the ref was not scheduled to be\npushed).\n\nCan you clarify the behavior I described? How can I best hook into the\n'refs that need to be pushed selection' in the 'export' command [0]?\n\n[0] The export command currently tries to export all refs it gets from\npush_refs, which seems to be everything that the helper got from the\n'list' command. The only reason this has worked so far it seems is\nthat all branches listed by 'list' were present as local branches.\n\n-- \nCheers,\n\nSverre Rabbelier\n"},{"id":"150257","messageId":"20100907221401.GA29102@capella.cs.uchicago.edu","threadId":"24899","inReplyTo":"AANLkTim=HKiQ-25QEAPPRcH6wwLLAsDdoRqTsanM67SK@mail.gmail.com","subject":"Re: remote-helpers: http-push protocol","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-09-07T22:14:01Z","receivedAt":"2010-09-07T22:14:01Z","isPatch":false,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Hi,\n\nHere's a know-nothing view (and I assume you have already done this\nlegwork; just summarizing for myself).  Following along in do_push().\n\nSverre Rabbelier wrote:\n\n> When fetching from the remote, the helper is called with 'list',\n\nget_ref_map() -> transport_get_remote_refs() ->\ntransport::get_refs_list()\n\n[...]\n> What happens next is the part that confuses me, a certain set of refs\n> is pushed, by calling the helper with 'push <refspec>'.\n\nThe transport_push() codepath in transport.c.  For remote helpers, it\nrelies on the push_refs() method, calling:\n\n - transport::get_refs_list() to get the list of remote refs\n - get_local_heads() for the local refs\n - match_refs() to list remote refs matching the refspec/--all/\n   --mirror\n - transport::push_refs() to push the list of refs chosen\n - transport_print_push_status() for a nice message\n - set_upstreams() to handle --set-upstream requests\n - transport_update_tracking_ref() to update the local remote-tracking\n   refs.\n\n> I am unclear\n> how this set of refs is chosen\n\nremote.c's match_refs() calls:\n\n - parse_push_refspec() to convert the refspec strings to\n   structs refspec, separating src, dest, and +/*/no-dest-specified\n   flags\n - match_explicit_refs() to build a linked list of struct ref\n   explicitly requested with non-wildcard refspecs (the easy ones)\n - check_pattern_match() for each remote ref, to figure out which\n   refspec, if any, it corresponds to.  If any:\n    - Refs outside the refs/heads/ hierarchy are excluded (unless\n      --mirror as used) when not named by a refspec, as you mentioned.\n    - Where actual refspecs are concerned, though, they can match.\n    - A local peer is determined with find_ref_by_name().\n    - Enforces the \"push matching\" rule: do not push a new branch\n      unless it was explicitly requested by naming it, --all, or\n      --mirror.\n \n> I see that only refs that have a\n> peer_ref are sent, unless mirror is also set (I don't think I\n> understand the significance)?\n\n$ git log -S'\"matching refs\"; traditionally we pushed everything' remote.c\ncommit 098e711e6c0d123dff2f38d6b804ec632ad7dd78\nAuthor: Junio C Hamano <gitster@pobox.com>\nDate:   Sun Jul 1 19:00:08 2007 -0700\n\n    \"git-push $URL\" without refspecs pushes only matching branches\n\n    When \"git push\" is run without any refspec (neither on the\n    command line nor in the config), we used to push \"matching refs\"\n    in the sense that anything under refs/ hierarchy that exist on\n    both ends were updated.  This used to be a sane default for\n    publishing your repository to another back when we did not have\n    refs/remotes/ hierarchy, but it does not make much sense these\n    days.\n\n    This changes the semantics to push only \"matching branches\".\n\nSo I suspect this is to ensure that with \"[push] default = matching\",\n\n $ git push\n\npushes branches and not remote-tracking refs, but\n\n $ git push --mirror\n\npushes everything.\n\n> After the push, the helper write a set\n> of 'ok/error' messages sometimes for refs that were not asked to be\n> pushed in the first place\n\nPart of transport::push_refs().  I think it only allows status\nmessages for refs that were actually pushed; otherwise it will print\n\n\twarning: helper reported unexpected status of <ref>\n\n> Can you clarify the behavior I described? How can I best hook into the\n> 'refs that need to be pushed selection' in the 'export' command [0]?\n\nHmm --- do you want some other hierarchy than refs/heads/* for the\n\"push matching\" rule?\n\nThanks for the nice introduction.\n"}]}