Merge branch 'dj/fetch-all-tags' into maint

"git fetch --all", when passed "--no-tags", did not honor the
"--no-tags" option while fetching from individual remotes (the same
issue existed with "--tags", but combination "--all --tags" makes
much less sense than "--all --no-tags").

* dj/fetch-all-tags:
  fetch --all: pass --tags/--no-tags through to each remote
  submodule: use argv_array instead of hand-building arrays
  fetch: use argv_array instead of hand-building arrays
  argv-array: fix bogus cast when freeing array
  argv-array: add pop function
This commit is contained in:
Junio C Hamano 2012-09-24 12:39:21 -07:00
commit 8144049d79
7 changed files with 92 additions and 39 deletions

View File

@ -46,6 +46,10 @@ Functions
Format a string and push it onto the end of the array. This is a Format a string and push it onto the end of the array. This is a
convenience wrapper combining `strbuf_addf` and `argv_array_push`. 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`:: `argv_array_clear`::
Free all memory associated with the array and return it to the Free all memory associated with the array and return it to the
initial, empty state. initial, empty state.

View File

@ -49,12 +49,21 @@ void argv_array_pushl(struct argv_array *array, ...)
va_end(ap); va_end(ap);
} }
void argv_array_pop(struct argv_array *array)
{
if (!array->argc)
return;
free((char *)array->argv[array->argc - 1]);
array->argv[array->argc - 1] = NULL;
array->argc--;
}
void argv_array_clear(struct argv_array *array) void argv_array_clear(struct argv_array *array)
{ {
if (array->argv != empty_argv) { if (array->argv != empty_argv) {
int i; int i;
for (i = 0; i < array->argc; i++) for (i = 0; i < array->argc; i++)
free((char **)array->argv[i]); free((char *)array->argv[i]);
free(array->argv); free(array->argv);
} }
argv_array_init(array); argv_array_init(array);

View File

@ -16,6 +16,7 @@ void argv_array_push(struct argv_array *, const char *);
__attribute__((format (printf,2,3))) __attribute__((format (printf,2,3)))
void argv_array_pushf(struct argv_array *, const char *fmt, ...); void argv_array_pushf(struct argv_array *, const char *fmt, ...);
void argv_array_pushl(struct argv_array *, ...); void argv_array_pushl(struct argv_array *, ...);
void argv_array_pop(struct argv_array *);
void argv_array_clear(struct argv_array *); void argv_array_clear(struct argv_array *);
#endif /* ARGV_ARRAY_H */ #endif /* ARGV_ARRAY_H */

View File

@ -14,6 +14,7 @@
#include "transport.h" #include "transport.h"
#include "submodule.h" #include "submodule.h"
#include "connected.h" #include "connected.h"
#include "argv-array.h"
static const char * const builtin_fetch_usage[] = { static const char * const builtin_fetch_usage[] = {
"git fetch [<options>] [<repository> [<refspec>...]]", "git fetch [<options>] [<repository> [<refspec>...]]",
@ -841,38 +842,39 @@ static int add_remote_or_group(const char *name, struct string_list *list)
return 1; return 1;
} }
static void add_options_to_argv(int *argc, const char **argv) static void add_options_to_argv(struct argv_array *argv)
{ {
if (dry_run) if (dry_run)
argv[(*argc)++] = "--dry-run"; argv_array_push(argv, "--dry-run");
if (prune) if (prune)
argv[(*argc)++] = "--prune"; argv_array_push(argv, "--prune");
if (update_head_ok) if (update_head_ok)
argv[(*argc)++] = "--update-head-ok"; argv_array_push(argv, "--update-head-ok");
if (force) if (force)
argv[(*argc)++] = "--force"; argv_array_push(argv, "--force");
if (keep) if (keep)
argv[(*argc)++] = "--keep"; argv_array_push(argv, "--keep");
if (recurse_submodules == RECURSE_SUBMODULES_ON) if (recurse_submodules == RECURSE_SUBMODULES_ON)
argv[(*argc)++] = "--recurse-submodules"; argv_array_push(argv, "--recurse-submodules");
else if (recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND) else if (recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND)
argv[(*argc)++] = "--recurse-submodules=on-demand"; argv_array_push(argv, "--recurse-submodules=on-demand");
if (tags == TAGS_SET)
argv_array_push(argv, "--tags");
else if (tags == TAGS_UNSET)
argv_array_push(argv, "--no-tags");
if (verbosity >= 2) if (verbosity >= 2)
argv[(*argc)++] = "-v"; argv_array_push(argv, "-v");
if (verbosity >= 1) if (verbosity >= 1)
argv[(*argc)++] = "-v"; argv_array_push(argv, "-v");
else if (verbosity < 0) else if (verbosity < 0)
argv[(*argc)++] = "-q"; argv_array_push(argv, "-q");
} }
static int fetch_multiple(struct string_list *list) static int fetch_multiple(struct string_list *list)
{ {
int i, result = 0; int i, result = 0;
const char *argv[12] = { "fetch", "--append" }; struct argv_array argv = ARGV_ARRAY_INIT;
int argc = 2;
add_options_to_argv(&argc, argv);
if (!append && !dry_run) { if (!append && !dry_run) {
int errcode = truncate_fetch_head(); int errcode = truncate_fetch_head();
@ -880,18 +882,22 @@ static int fetch_multiple(struct string_list *list)
return errcode; return errcode;
} }
argv_array_pushl(&argv, "fetch", "--append", NULL);
add_options_to_argv(&argv);
for (i = 0; i < list->nr; i++) { for (i = 0; i < list->nr; i++) {
const char *name = list->items[i].string; const char *name = list->items[i].string;
argv[argc] = name; argv_array_push(&argv, name);
argv[argc + 1] = NULL;
if (verbosity >= 0) if (verbosity >= 0)
printf(_("Fetching %s\n"), name); 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); error(_("Could not fetch %s"), name);
result = 1; result = 1;
} }
argv_array_pop(&argv);
} }
argv_array_clear(&argv);
return result; return result;
} }
@ -1007,13 +1013,14 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
} }
if (!result && (recurse_submodules != RECURSE_SUBMODULES_OFF)) { if (!result && (recurse_submodules != RECURSE_SUBMODULES_OFF)) {
const char *options[10]; struct argv_array options = ARGV_ARRAY_INIT;
int num_options = 0;
add_options_to_argv(&num_options, options); add_options_to_argv(&options);
result = fetch_populated_submodules(num_options, options, result = fetch_populated_submodules(&options,
submodule_prefix, submodule_prefix,
recurse_submodules, recurse_submodules,
verbosity < 0); verbosity < 0);
argv_array_clear(&options);
} }
/* All names were strdup()ed or strndup()ed */ /* All names were strdup()ed or strndup()ed */

View File

@ -588,13 +588,13 @@ static void calculate_changed_submodule_paths(void)
initialized_fetch_ref_tips = 0; initialized_fetch_ref_tips = 0;
} }
int fetch_populated_submodules(int num_options, const char **options, int fetch_populated_submodules(const struct argv_array *options,
const char *prefix, int command_line_option, const char *prefix, int command_line_option,
int quiet) int quiet)
{ {
int i, result = 0, argc = 0, default_argc; int i, result = 0;
struct child_process cp; struct child_process cp;
const char **argv; struct argv_array argv = ARGV_ARRAY_INIT;
struct string_list_item *name_for_path; struct string_list_item *name_for_path;
const char *work_tree = get_git_work_tree(); const char *work_tree = get_git_work_tree();
if (!work_tree) if (!work_tree)
@ -604,17 +604,13 @@ int fetch_populated_submodules(int num_options, const char **options,
if (read_cache() < 0) if (read_cache() < 0)
die("index file corrupt"); die("index file corrupt");
/* 6: "fetch" (options) --recurse-submodules-default default "--submodule-prefix" prefix NULL */ argv_array_push(&argv, "fetch");
argv = xcalloc(num_options + 6, sizeof(const char *)); for (i = 0; i < options->argc; i++)
argv[argc++] = "fetch"; argv_array_push(&argv, options->argv[i]);
for (i = 0; i < num_options; i++) argv_array_push(&argv, "--recurse-submodules-default");
argv[argc++] = options[i]; /* default value, "--submodule-prefix" and its value are added later */
argv[argc++] = "--recurse-submodules-default";
default_argc = argc++;
argv[argc++] = "--submodule-prefix";
memset(&cp, 0, sizeof(cp)); memset(&cp, 0, sizeof(cp));
cp.argv = argv;
cp.env = local_repo_env; cp.env = local_repo_env;
cp.git_cmd = 1; cp.git_cmd = 1;
cp.no_stdin = 1; cp.no_stdin = 1;
@ -674,16 +670,21 @@ int fetch_populated_submodules(int num_options, const char **options,
if (!quiet) if (!quiet)
printf("Fetching submodule %s%s\n", prefix, ce->name); printf("Fetching submodule %s%s\n", prefix, ce->name);
cp.dir = submodule_path.buf; cp.dir = submodule_path.buf;
argv[default_argc] = default_argv; argv_array_push(&argv, default_argv);
argv[argc] = submodule_prefix.buf; argv_array_push(&argv, "--submodule-prefix");
argv_array_push(&argv, submodule_prefix.buf);
cp.argv = argv.argv;
if (run_command(&cp)) if (run_command(&cp))
result = 1; result = 1;
argv_array_pop(&argv);
argv_array_pop(&argv);
argv_array_pop(&argv);
} }
strbuf_release(&submodule_path); strbuf_release(&submodule_path);
strbuf_release(&submodule_git_dir); strbuf_release(&submodule_git_dir);
strbuf_release(&submodule_prefix); strbuf_release(&submodule_prefix);
} }
free(argv); argv_array_clear(&argv);
out: out:
string_list_clear(&changed_submodule_paths, 1); string_list_clear(&changed_submodule_paths, 1);
return result; return result;

View File

@ -2,6 +2,7 @@
#define SUBMODULE_H #define SUBMODULE_H
struct diff_options; struct diff_options;
struct argv_array;
enum { enum {
RECURSE_SUBMODULES_ON_DEMAND = -1, RECURSE_SUBMODULES_ON_DEMAND = -1,
@ -23,7 +24,7 @@ void show_submodule_summary(FILE *f, const char *path,
const char *del, const char *add, const char *reset); const char *del, const char *add, const char *reset);
void set_config_fetch_recurse_submodules(int value); void set_config_fetch_recurse_submodules(int value);
void check_for_new_submodule_commits(unsigned char new_sha1[20]); void check_for_new_submodule_commits(unsigned char new_sha1[20]);
int fetch_populated_submodules(int num_options, const char **options, int fetch_populated_submodules(const struct argv_array *options,
const char *prefix, int command_line_option, const char *prefix, int command_line_option,
int quiet); int quiet);
unsigned is_submodule_modified(const char *path, int ignore_untracked); unsigned is_submodule_modified(const char *path, int ignore_untracked);

View File

@ -151,4 +151,34 @@ test_expect_success 'git fetch --multiple (ignoring skipFetchAll)' '
test_cmp ../expect output) test_cmp ../expect output)
' '
test_expect_success 'git fetch --all --no-tags' '
>expect &&
git clone one test5 &&
git clone test5 test6 &&
(cd test5 && git tag test-tag) &&
(
cd test6 &&
git fetch --all --no-tags &&
git tag >output
) &&
test_cmp expect test6/output
'
test_expect_success 'git fetch --all --tags' '
echo test-tag >expect &&
git clone one test7 &&
git clone test7 test8 &&
(
cd test7 &&
test_commit test-tag &&
git reset --hard HEAD^
) &&
(
cd test8 &&
git fetch --all --tags &&
git tag >output
) &&
test_cmp expect test8/output
'
test_done test_done