Taylor Blau <me@xxxxxxxxxxxx> writes: > +core.alternateRefsCommand:: > + When listing references from an alternate (e.g., in the case of ".have"), use It is not clear how (e.g.,...) connects to what is said in the sentence. "When advertising tips of available history from an alternate, use ..." without saying ".have" may be less cryptic. I dunno. > + the shell to execute the specified command instead of > + linkgit:git-for-each-ref[1]. The first argument is the path of the alternate. "The path" meaning the absolute path? Relative to the original object store? Something else? > + Output must be of the form: `%(objectname) SPC %(refname)`. > ++ > +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 > +heads, configure `core.alternateRefsCommand` to the path of a script which runs > +`git --git-dir="$1" for-each-ref refs/heads`. > + > core.bare:: > If true this repository is assumed to be 'bare' and has no > working directory associated with it. If this is the case a > diff --git a/t/t5410-receive-pack.sh b/t/t5410-receive-pack.sh > new file mode 100755 > index 0000000000..2f21f1cb8f > --- /dev/null > +++ b/t/t5410-receive-pack.sh > @@ -0,0 +1,54 @@ > +#!/bin/sh > + > +test_description='git receive-pack test' > + > +. ./test-lib.sh > + > +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 config receive.advertisealternates true && Hmph. Do we have code to support this configuration variable? > + cat <<-EOF | git update-ref --stdin && Style: writing "<<-\EOF" instead would allow readers' eyes to coast over without having to look for $variable_references in the here-doc. > + 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 So, the original created one/two/three/a/b/c/master, fork is a bare clone of it and has all these things, and then you deleted all of these? What does fork have after this is done? HEAD that is dangling? > + EOF > + echo "../../.git/objects" >objects/info/alternates When viewed from fork/objects, ../../.git is the GIT_DIR of the primary test repository, so that is where we borrow objects from. If we pruned the objects from fork's object store before this echo, we would have an almost empty repository that borrows from its alternates everything, which may make a more realistic sample case, but because you are only focusing on the ref advertisement, it does not matter that your fork is full of duplicate objects that are available from the alternates. > +expect_haves () { > + printf "%s .have\n" $(git rev-parse $@) >expect Quote $@ inside dq pair, like $(git rev-parse "$@"). > +extract_haves () { > + depacketize - | grep '\.have' | sed -e 's/\\0.*$//g' > +} Don't pipe grep into sed, especially when both the pattern to filter and the operation to perform are simple. I am not sure what you are trying to achive with 'g' in s/pattern$//g; The anchor at the rightmost end of the pattern makes sure that the pattern matches only once per line at the end anyway, so "do this howmanyever times as we have match on each line" would not make any difference, no? > diff --git a/transport.c b/transport.c > index 24ae3f375d..e7d2cdf00b 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) > { > - cmd->git_cmd = 1; > - argv_array_pushf(&cmd->args, "--git-dir=%s", repo_path); > - argv_array_push(&cmd->args, "for-each-ref"); > - argv_array_push(&cmd->args, "--format=%(objectname) %(refname)"); > + const char *value; > + > + if (!git_config_get_value("core.alternateRefsCommand", &value)) { > + cmd->use_shell = 1; > + > + argv_array_push(&cmd->args, value); > + argv_array_push(&cmd->args, repo_path); > + } else { > + cmd->git_cmd = 1; > + > + argv_array_pushf(&cmd->args, "--git-dir=%s", repo_path); > + argv_array_push(&cmd->args, "for-each-ref"); > + argv_array_push(&cmd->args, "--format=%(objectname) %(refname)"); > + } > + > cmd->env = local_repo_env; > cmd->out = -1; > }