git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH v3 3/4] transport.c: introduce core.alternateRefsCommand

From
Jeff King <peff@peff.net>
Date
Sep 28, 2018, 05:26 UTC
Message-ID
<20180928052613.GC25850@sigill.intra.peff.net>
In-Reply-To
<2dbcd5419073f06def007be3746ce90fffaf6a6d.1538108385.git.me@ttaylorr.com>
On Thu, Sep 27, 2018 at 09:25:42PM -0700, Taylor Blau wrote:
Show 5 quoted lines
> Let the repository that has alternates configure this command to avoid
> trusting the alternate to provide us a safe command to run in the shell.
> To behave differently on each alternate (e.g., only list tags from
> alternate A, only heads from B) provide the path of the alternate as the
> first argument.

Well, you also need to pass the path so it knows which repo to look at. Which I think is the primary reason we do it, but behaving differently for each alternate is another option.

Show 5 quoted lines
> +core.alternateRefsCommand::
> +	When advertising tips of available history from an alternate, use the shell to
> +	execute the specified command instead of linkgit:git-for-each-ref[1]. The
> +	first argument is the absolute path of the alternate. Output must be of the
> +	form: `%(objectname)`, where multiple tips are separated by newlines.

I wonder if people may be confused about the %(objectname) syntax, since it's specific to for-each-ref. Now that we've simplified the output format to a single value, perhaps we should define it more directly. E.g., like:

  The output should contain one hex object id per line (i.e., the same
  as produced by `git for-each-ref --format='%(objectname)'`).

Now that we've dropped the refname requirement from the output, it is more clear that this really does not have to be about refs at all. In the most technical sense, what we really allow in the output is any object id X for which the alternate promises it has all objects reachable from X. Ref tips are a convenient and efficient way of providing that, but they are not the only possibility (and likewise, it is fine to omit duplicates or even tips that are ancestors of other tips).

I think that's probably getting _too_ technical, though. It probably makes sense to just keep thinking of these as "what are the ref tips".

> +This is useful when a repository only wishes to advertise some of its
> +alternate's references as ".have"'s. For example, to only advertise branch
Maybe put ".have" into backticks for formatting?
> +heads, configure `core.alternateRefsCommand` to the path of a script which runs
> +`git --git-dir="$1" for-each-ref --format='%(objectname)' refs/heads`.

Does that script actually work? Because of the way we invoke shell commands with arguments, I think we'd end up with:

  git --git-dir="$1" for-each-ref --format='%(objectname)' refs/heads "$@"

Possibly for-each-ref would ignore the extra path argument (thinking it's a ref pattern that just doesn't match), but it's definitely not what you intended. You'd have to write:

  f() { git --git-dir=$1 ...etc; } f

in the usual way. That's a minor pain, but it's what makes the more direct:

  /my/script
work.

The other alternative is to pass $GIT_DIR in the environment on behalf of the program. Then writing:

  git for-each-ref --format='%(objectname)' refs/heads

would Just Work. But it's a bit subtle, since it is not immediately obvious that the command is meant to run in a different repository.

Show 9 quoted lines
> diff --git a/t/t5410-receive-pack.sh b/t/t5410-receive-pack.sh
> new file mode 100755
> index 0000000000..503dde35a4
> --- /dev/null
> +++ b/t/t5410-receive-pack.sh
> @@ -0,0 +1,49 @@
> +#!/bin/sh
> +
> +test_description='git receive-pack test'

The name of this test file and the description are pretty vague. Can we say something like "test handling of receive-pack with alternate-refs config"?

Show 23 quoted lines
> +test_expect_success 'setup' '
> +	test_commit one &&
> +	git update-ref refs/heads/a HEAD &&
> +	test_commit two &&
> +	git update-ref refs/heads/b HEAD &&
> +	test_commit three &&
> +	git update-ref refs/heads/c HEAD &&
> +	git clone --bare . fork &&
> +	git clone fork pusher &&
> +	(
> +		cd fork &&
> +		git update-ref --stdin <<-\EOF &&
> +		delete refs/heads/a
> +		delete refs/heads/b
> +		delete refs/heads/c
> +		delete refs/heads/master
> +		delete refs/tags/one
> +		delete refs/tags/two
> +		delete refs/tags/three
> +		EOF
> +		echo "../../.git/objects" >objects/info/alternates
> +	)
> +'

This setup is kind of convoluted. You're deleting those refs in the fork, I think, because we don't want them to suppress the duplicate .have lines from the alternate. Might it be easier to just create the .have lines we're interested in after the fact?

I think we can also use "clone -s" to make the setup of the alternate a little simpler.

I don't see the "pusher" repo being used for anything here. Leftover cruft from when you were using "git push" to test?

So all together, perhaps something like:
  # we have a fork which points back to us as an alternate
  test_commit base &&
  git clone -s . fork &&
  # the alternate has two refs with new tips, in two separate hierarchies
  git checkout -b public/branch master &&
  test_commit public &&
  git checkout -b private/branch master &&
  test_commit private
And then...
Show 7 quoted lines
> +test_expect_success 'with core.alternateRefsCommand' '
> +	write_script fork/alternate-refs <<-\EOF &&
> +		git --git-dir="$1" for-each-ref \
> +			--format="%(objectname)" \
> +			refs/heads/a \
> +			refs/heads/c
> +	EOF
...this can just look for refs/heads/public/, and...
> +	test_config -C fork core.alternateRefsCommand alternate-refs &&
> +	git rev-parse a c >expect &&
...we verify that we saw public/branch but not private/branch.

It's not that much shorter, but I had trouble understanding from the setup why we needed to delete all those refs (and why we cared about those tags in the first place).

Show 7 quoted lines
> diff --git a/transport.c b/transport.c
> index 2825debac5..e271b66603 100644
> --- a/transport.c
> +++ b/transport.c
> @@ -1328,10 +1328,21 @@ char *transport_anonymize_url(const char *url)
>  static void fill_alternate_refs_command(struct child_process *cmd,
>  					const char *repo_path)
The code change itself looks good to me.
-Peff
Previous: Taylor BlauNext: Taylor Blau
Message 69 of 94 in “Filter alternate references”
  1. 0/3 Filter alternate referencesTaylor Blau, Sep 20, 2018
  2. 1/3 transport.c: extract 'fill_alternate_refs_command'Taylor Blau, Sep 20, 2018
  3. 2/3 transport.c: introduce core.alternateRefsCommandTaylor Blau, Sep 20, 2018
  4. Jeff KingSep 20, 2018
  5. Taylor BlauSep 20, 2018
  6. Jeff KingSep 20, 2018
  7. Junio C HamanoSep 21, 2018
  8. Taylor BlauSep 21, 2018
  9. Taylor BlauSep 21, 2018
  10. Junio C HamanoSep 21, 2018
  11. Taylor BlauSep 26, 2018
  12. 3/3 transport.c: introduce core.alternateRefsPrefixesTaylor Blau, Sep 20, 2018
  13. Jeff KingSep 20, 2018
  14. Taylor BlauSep 20, 2018
  15. Eric SunshineSep 21, 2018
  16. Taylor BlauSep 21, 2018
  17. Junio C HamanoSep 21, 2018
  18. Taylor BlauSep 21, 2018
  19. Junio C HamanoSep 21, 2018
  20. Stefan BellerSep 20, 2018
  21. Taylor BlauSep 20, 2018
  22. Jeff KingSep 20, 2018
  23. Jeff KingSep 20, 2018
  24. 0/3 Filter alternate referencesTaylor Blau, Sep 21, 2018
  25. 1/3 transport.c: extract 'fill_alternate_refs_command'Taylor Blau, Sep 21, 2018
  26. 2/3 transport.c: introduce core.alternateRefsCommandTaylor Blau, Sep 21, 2018
  27. Eric SunshineSep 21, 2018
  28. Taylor BlauSep 26, 2018
  29. Junio C HamanoSep 21, 2018
  30. Jeff KingSep 21, 2018
  31. Junio C HamanoSep 21, 2018
  32. Jeff KingSep 21, 2018
  33. Taylor BlauSep 26, 2018
  34. Jeff KingSep 26, 2018
  35. Eric SunshineSep 21, 2018
  36. brian m. carlsonSep 22, 2018
  37. Jeff KingSep 22, 2018
  38. brian m. carlsonSep 23, 2018
  39. Taylor BlauSep 26, 2018
  40. Jeff KingSep 26, 2018
  41. Taylor BlauSep 26, 2018
  42. Jeff KingSep 26, 2018
  43. Taylor BlauSep 28, 2018
  44. 3/3 transport.c: introduce core.alternateRefsPrefixesTaylor Blau, Sep 21, 2018
  45. Junio C HamanoSep 21, 2018
  46. Jeff KingSep 21, 2018
  47. Junio C HamanoSep 21, 2018
  48. Jeff KingSep 21, 2018
  49. Stefan BellerSep 21, 2018
  50. Junio C HamanoSep 24, 2018
  51. Jeff KingSep 24, 2018
  52. Junio C HamanoSep 24, 2018
  53. Jeff KingSep 24, 2018
  54. Jeff KingSep 24, 2018
  55. Junio C HamanoSep 24, 2018
  56. Jeff KingSep 24, 2018
  57. Junio C HamanoSep 25, 2018
  58. Taylor BlauSep 25, 2018
  59. Junio C HamanoSep 25, 2018
  60. Taylor BlauSep 26, 2018
  61. Jeff KingSep 26, 2018
  62. 0/4 Filter alternate referencesTaylor Blau, Sep 28, 2018
  63. 1/4 transport: drop refnames from for_each_alternate_refJeff King, Sep 28, 2018
  64. Jeff KingSep 28, 2018
  65. Taylor BlauSep 28, 2018
  66. 2/4 transport.c: extract 'fill_alternate_refs_command'Taylor Blau, Sep 28, 2018
  67. Jeff KingSep 28, 2018
  68. 3/4 transport.c: introduce core.alternateRefsCommandTaylor Blau, Sep 28, 2018
  69. Jeff KingSep 28, 2018
  70. Taylor BlauSep 28, 2018
  71. Jeff KingSep 29, 2018
  72. Taylor BlauOct 2, 2018
  73. 4/4 transport.c: introduce core.alternateRefsPrefixesTaylor Blau, Sep 28, 2018
  74. Jeff KingSep 28, 2018
  75. Taylor BlauSep 28, 2018
  76. Jeff KingSep 29, 2018
  77. Taylor BlauOct 2, 2018
  78. Taylor BlauOct 2, 2018
  79. 0/4 Filter alternate referencesTaylor Blau, Oct 2, 2018
  80. 1/4 transport: drop refnames from for_each_alternate_refTaylor Blau, Oct 2, 2018
  81. 3/4 transport.c: introduce core.alternateRefsCommandTaylor Blau, Oct 2, 2018
  82. Jeff KingOct 2, 2018
  83. Taylor BlauOct 4, 2018
  84. 2/4 transport.c: extract 'fill_alternate_refs_command'Taylor Blau, Oct 2, 2018
  85. 4/4 transport.c: introduce core.alternateRefsPrefixesTaylor Blau, Oct 2, 2018
  86. Ramsay JonesOct 2, 2018
  87. 4/4 transport.c: introduce core.alternateRefsPrefixesTaylor Blau, Oct 2, 2018
  88. 0/4 Filter alternate referencesTaylor Blau, Oct 8, 2018
  89. 1/4 transport: drop refnames from for_each_alternate_refTaylor Blau, Oct 8, 2018
  90. 2/4 transport.c: extract 'fill_alternate_refs_command'Taylor Blau, Oct 8, 2018
  91. 3/4 transport.c: introduce core.alternateRefsCommandTaylor Blau, Oct 8, 2018
  92. 4/4 transport.c: introduce core.alternateRefsPrefixesTaylor Blau, Oct 8, 2018
  93. Jeff KingOct 9, 2018
  94. Taylor BlauOct 9, 2018

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.