From: Junio C Hamano <hidden> Date: 2016-06-15 22:54:37
Dan Johnson [off-list ref] writes:
I believe that is bad interaction with "--all" (probably a bug). If I
am remembering correctly, --no-tags is internally a per-remote
setting, so I'm guessing it's not getting set on all remotes here.
I'll look into this more a bit later tonight. Does fetch --no-tags
work when you specify a remote?
From: Dan Johnson <hidden> Date: 2016-06-15 22:54:37
Reported-by: Oswald Buddenhagen <redacted>
Signed-off-by: Dan Johnson <redacted>
---
Junio C Hamano [off-list ref] writes:
Dan Johnson [off-list ref] writes:
quoted
I believe that is bad interaction with "--all" (probably a bug). If I
am remembering correctly, --no-tags is internally a per-remote
setting, so I'm guessing it's not getting set on all remotes here.
I'll look into this more a bit later tonight. Does fetch --no-tags
work when you specify a remote?
Thanks.
And here it is. Apparently we just don't pass those options through. I didn't
look to see if there are any other options we should consider passing through;
it's quite possible there are. I also have not written a test to ensure that
this doesn't break in the future. I will hopefully have time for these things
tomorrow. It's getting too late for me to be able to put sentences together,
so hopefully this mail comes out readable ;)
builtin/fetch.c | 4 ++++
1 file changed, 4 insertions(+)
Hmm. We allocate argv in fetch_multiple like this:
const char *argv[12] = { "fetch", "--append" };
and then add a bunch of options to it, along with the name of the
remote. By my count, the current code can hit exactly 12 (including the
terminating NULL) if all options are set. Your patch would make it
possible to overflow. Of course, I may be miscounting since it is
extremely error-prone to figure out the right number by tracing each
possible conditional.
Maybe we should switch it to a dynamic argv_array? Like this:
[1/2]: argv-array: add pop function
[2/2]: fetch: use argv_array instead of hand-building arrays
-Peff
From: Jeff King <hidden> Date: 2016-06-15 22:54:37
Sometimes we build a set of similar command lines, differing
only in the final arguments (e.g., "fetch --multiple"). To
use argv_array for this, you have to either push the same
set of elements repeatedly, or break the abstraction by
manually manipulating the array's internal members.
Instead, let's provide a sanctioned "pop" function to remove
elements from the end.
Signed-off-by: Jeff King <redacted>
---
Documentation/technical/api-argv-array.txt | 4 ++++
argv-array.c | 9 +++++++++
argv-array.h | 1 +
3 files changed, 14 insertions(+)
@@ -46,6 +46,10 @@ Functions Format a string and push it onto the end of the array. This is a convenience wrapper combining `strbuf_addf` and `argv_array_push`.+`argv_array_pop`::+ Remove the final element from the array. If there are no+ elements in the array, do nothing.+ `argv_array_clear`:: Free all memory associated with the array and return it to the initial, empty state.
From: Jeff King <hidden> Date: 2016-06-15 22:54:37
Fetch invokes itself recursively when recursing into
submodules or handling "fetch --multiple". In both cases, it
builds the child's command line by pushing options onto a
statically-sized array. In both cases, the array is
currently just big enough to handle the largest possible
case. However, this technique is brittle and error-prone, so
let's replace it with a dynamic argv_array.
Signed-off-by: Jeff King <redacted>
---
Not very well tested by me, but hopefully it is simple enough that I
managed not to screw it up.
It may be that fetch_populated_submodules would also benefit from
conversion (here I just pass in the argc and argv separately), but I
didn't look.
builtin/fetch.c | 47 +++++++++++++++++++++++++----------------------
1 file changed, 25 insertions(+), 22 deletions(-)
@@ -841,38 +842,35 @@ static int fetch_multiple(struct string_list *list)return1;}-staticvoidadd_options_to_argv(int*argc,constchar**argv)+staticvoidadd_options_to_argv(structargv_array*argv){if(dry_run)-argv[(*argc)++]="--dry-run";+argv_array_push(argv,"--dry-run");if(prune)-argv[(*argc)++]="--prune";+argv_array_push(argv,"--prune");if(update_head_ok)-argv[(*argc)++]="--update-head-ok";+argv_array_push(argv,"--update-head-ok");if(force)-argv[(*argc)++]="--force";+argv_array_push(argv,"--force");if(keep)-argv[(*argc)++]="--keep";+argv_array_push(argv,"--keep");if(recurse_submodules==RECURSE_SUBMODULES_ON)-argv[(*argc)++]="--recurse-submodules";+argv_array_push(argv,"--recurse-submodules");elseif(recurse_submodules==RECURSE_SUBMODULES_ON_DEMAND)-argv[(*argc)++]="--recurse-submodules=on-demand";+argv_array_push(argv,"--recurse-submodules=on-demand");if(verbosity>=2)-argv[(*argc)++]="-v";+argv_array_push(argv,"-v");if(verbosity>=1)-argv[(*argc)++]="-v";+argv_array_push(argv,"-v");elseif(verbosity<0)-argv[(*argc)++]="-q";+argv_array_push(argv,"-q");}staticintfetch_multiple(structstring_list*list){inti,result=0;-constchar*argv[12]={"fetch","--append"};-intargc=2;--add_options_to_argv(&argc,argv);+structargv_arrayargv=ARGV_ARRAY_INIT;if(!append&&!dry_run){interrcode=truncate_fetch_head();
@@ -880,18 +878,22 @@ static int fetch_multiple(struct string_list *list)returnerrcode;}+argv_array_pushl(&argv,"fetch","--append",NULL);+add_options_to_argv(&argv);+for(i=0;i<list->nr;i++){constchar*name=list->items[i].string;-argv[argc]=name;-argv[argc+1]=NULL;+argv_array_push(&argv,name);if(verbosity>=0)printf(_("Fetching %s\n"),name);-if(run_command_v_opt(argv,RUN_GIT_CMD)){+if(run_command_v_opt(argv.argv,RUN_GIT_CMD)){error(_("Could not fetch %s"),name);result=1;}+argv_array_pop(&argv);}+argv_array_clear(&argv);returnresult;}
@@ -1007,13 +1009,14 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)}if(!result&&(recurse_submodules!=RECURSE_SUBMODULES_OFF)){-constchar*options[10];-intnum_options=0;-add_options_to_argv(&num_options,options);-result=fetch_populated_submodules(num_options,options,+structargv_arrayoptions=ARGV_ARRAY_INIT;++add_options_to_argv(&options);+result=fetch_populated_submodules(options.argc,options.argv,submodule_prefix,recurse_submodules,verbosity<0);+argv_array_clear(&options);}/* All names were strdup()ed or strndup()ed */
From: Jeff King <hidden> Date: 2016-06-15 22:54:37
Since the array struct stores a "const char **" argv member
(for compatibility with most of our argv-taking functions),
we have to cast away the const-ness when freeing its
elements.
However, we used the wrong type when doing so. It doesn't
make a difference since free() take a void pointer anyway,
but it can be slightly confusing to a reader.
Signed-off-by: Jeff King <redacted>
---
Noticed this while I was adding the other free in argv_array_pop...
argv-array.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
From: Jeff King <hidden> Date: 2016-06-15 22:54:37
On Sat, Sep 01, 2012 at 07:32:07AM -0400, Jeff King wrote:
Since the array struct stores a "const char **" argv member
(for compatibility with most of our argv-taking functions),
we have to cast away the const-ness when freeing its
elements.
However, we used the wrong type when doing so. It doesn't
make a difference since free() take a void pointer anyway,
but it can be slightly confusing to a reader.
Signed-off-by: Jeff King <redacted>
---
Noticed this while I was adding the other free in argv_array_pop...
Argh, managed to botch the subject line. Here it is for real.
-- >8 --
Since the array struct stores a "const char **" argv member
(for compatibility with most of our argv-taking functions),
we have to cast away the const-ness when freeing its
elements.
However, we used the wrong type when doing so. It doesn't
make a difference since free() take a void pointer anyway,
but it can be slightly confusing to a reader.
Signed-off-by: Jeff King <redacted>
---
argv-array.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Fetch invokes itself recursively when recursing into
submodules or handling "fetch --multiple". In both cases, it
builds the child's command line by pushing options onto a
statically-sized array. In both cases, the array is
currently just big enough to handle the largest possible
case. However, this technique is brittle and error-prone, so
let's replace it with a dynamic argv_array.
Signed-off-by: Jeff King <redacted>
---
Not very well tested by me, but hopefully it is simple enough that I
managed not to screw it up.
This is definitely an improvement, and I can't spot any problems
either.
It may be that fetch_populated_submodules would also benefit from
conversion (here I just pass in the argc and argv separately), but I
didn't look.
Yes, it does some similar brittle stuff and should be changed to use
the argv-array too. I'll look into that.
fetch_populated_submodules() allocates the full argv array it uses to
recurse into the submodules from the number of given options plus the six
argv values it is going to add. It then initializes it with those values
which won't change during the iteration and copies the given options into
it. Inside the loop the two argv values different for each submodule get
replaced with those currently valid.
However, this technique is brittle and error-prone (as the comment to
explain the magic number 6 indicates), so let's replace it with an
argv_array. Instead of replacing the argv values, push them to the
argv_array just before the run_command() call (including the option
separating them) and pop them from the argv_array right after that.
Signed-off-by: Jens Lehmann <redacted>
---
Am 01.09.2012 16:34, schrieb Jens Lehmann:
Am 01.09.2012 13:27, schrieb Jeff King:
quoted
It may be that fetch_populated_submodules would also benefit from
conversion (here I just pass in the argc and argv separately), but I
didn't look.
Yes, it does some similar brittle stuff and should be changed to use
the argv-array too. I'll look into that.
Maybe something like this on top of your two patches?
I thought about adding an argv_array_cat() function to replace the
for() loop copying the option values into the argv-array built inside
fetch_populated_submodules(), but I suspect saving one line from the
code is not worth it. Yet I didn't check if others would benefit from
such a function too.
builtin/fetch.c | 2 +-
submodule.c | 31 ++++++++++++++++---------------
submodule.h | 3 ++-
3 files changed, 19 insertions(+), 17 deletions(-)
From: Dan Johnson <hidden> Date: 2016-06-15 22:54:38
When fetch is invoked with --all, we need to pass the tag-following
preference to each individual fetch; without this, we will always
auto-follow tags, preventing us from fetching the remote tags into a
remote-specific namespace, for example.
Reported-by: Oswald Buddenhagen <redacted>
Signed-off-by: Dan Johnson <redacted>
---
On Sat, Sep 1, 2012 at 7:22 AM, Jeff King [off-list ref] wrote:
Hmm. We allocate argv in fetch_multiple like this:
const char *argv[12] = { "fetch", "--append" };
and then add a bunch of options to it, along with the name of the
remote. By my count, the current code can hit exactly 12 (including the
terminating NULL) if all options are set. Your patch would make it
possible to overflow. Of course, I may be miscounting since it is
extremely error-prone to figure out the right number by tracing each
possible conditional.
Maybe we should switch it to a dynamic argv_array? Like this:
[1/2]: argv-array: add pop function
[2/2]: fetch: use argv_array instead of hand-building arrays
This version is re-rolled to be on top of jk/argv-array, avoiding the issue of
the fixed-size array entirely. If needed, we could of course use the old
version of this patch and bump the number, but I figure this is preferable.
I've also added some test cases to cover this behavior, but I'm not entirely
happy with them. I'm not sure if/how we should be testing the pass-through
behavior of various arguments with fetch --all, but if so, we should probably do
so more thouroughly than I have here, but that just seems like combining
together tests of two unrelated things. It might just make more sense to ignore
it and drop these tests, I don't know.
Sorry this took me a few days to send, I just kept not getting around to it.
builtin/fetch.c | 4 ++++
t/t5514-fetch-multiple.sh | 29 +++++++++++++++++++++++++++++
2 files changed, 33 insertions(+)