refactor argv_array into generic code

The submodule code recently grew generic code to build a
dynamic argv array. Many other parts of the code can reuse
this, too, so let's make it generically available.

There are two enhancements not found in the original code:

  1. We now handle the NULL-termination invariant properly,
     even when no strings have been pushed (before, you
     could have an empty, NULL argv). This was not a problem
     for the submodule code, which always pushed at least
     one argument, but was not sufficiently safe for
     generic code.

  2. There is a formatted variant of the "push" function.
     This is a convenience function which was not needed by
     the submodule code, but will make it easier to port
     other users to the new code.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Jeff King
2011-09-13 17:57:57 -04:00
committed by Junio C Hamano
parent 7878b07c0d
commit c1189caeaf
5 changed files with 125 additions and 35 deletions

View File

@ -9,6 +9,7 @@
#include "refs.h"
#include "string-list.h"
#include "sha1-array.h"
#include "argv-array.h"
static struct string_list config_name_for_path;
static struct string_list config_fetch_recurse_submodules_for_name;
@ -388,52 +389,22 @@ void check_for_new_submodule_commits(unsigned char new_sha1[20])
sha1_array_append(&ref_tips_after_fetch, new_sha1);
}
struct argv_array {
const char **argv;
unsigned int argc;
unsigned int alloc;
};
static void init_argv(struct argv_array *array)
{
array->argv = NULL;
array->argc = 0;
array->alloc = 0;
}
static void push_argv(struct argv_array *array, const char *value)
{
ALLOC_GROW(array->argv, array->argc + 2, array->alloc);
array->argv[array->argc++] = xstrdup(value);
array->argv[array->argc] = NULL;
}
static void clear_argv(struct argv_array *array)
{
int i;
for (i = 0; i < array->argc; i++)
free((char **)array->argv[i]);
free(array->argv);
init_argv(array);
}
static void add_sha1_to_argv(const unsigned char sha1[20], void *data)
{
push_argv(data, sha1_to_hex(sha1));
argv_array_push(data, sha1_to_hex(sha1));
}
static void calculate_changed_submodule_paths(void)
{
struct rev_info rev;
struct commit *commit;
struct argv_array argv;
struct argv_array argv = ARGV_ARRAY_INIT;
init_revisions(&rev, NULL);
init_argv(&argv);
push_argv(&argv, "--"); /* argv[0] program name */
argv_array_push(&argv, "--"); /* argv[0] program name */
sha1_array_for_each_unique(&ref_tips_after_fetch,
add_sha1_to_argv, &argv);
push_argv(&argv, "--not");
argv_array_push(&argv, "--not");
sha1_array_for_each_unique(&ref_tips_before_fetch,
add_sha1_to_argv, &argv);
setup_revisions(argv.argc, argv.argv, &rev, NULL);
@ -460,7 +431,7 @@ static void calculate_changed_submodule_paths(void)
}
}
clear_argv(&argv);
argv_array_clear(&argv);
sha1_array_clear(&ref_tips_before_fetch);
sha1_array_clear(&ref_tips_after_fetch);
initialized_fetch_ref_tips = 0;