Refactor submodule push check to use string list instead of integer

This allows us to tell the user which submodules have not been pushed. Additionally this is helpful when we want to automatically try to push submodules that have not been pushed. Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Heiko Voigt committed Mar 29, 2012 at 09:21 UTC a762e51ef2a39b0c326a1529dbe7f4cb303960db
3 files changed +35 -15
submodule.c
+11 -12
@@ -357,21 +357,19 @@ static void collect_submodules_from_diff(struct diff_queue_struct *q,
357 void *data)
358 {
359 int i;
360 - int *needs_pushing = data;
360 + struct string_list *needs_pushing = data;
361
362 for (i = 0; i < q->nr; i++) {
363 struct diff_filepair *p = q->queue[i];
364 if (!S_ISGITLINK(p->two->mode))
365 continue;
366 - if (submodule_needs_pushing(p->two->path, p->two->sha1)) {
367 - *needs_pushing = 1;
368 - break;
369 - }
366 + if (submodule_needs_pushing(p->two->path, p->two->sha1))
367 + string_list_insert(needs_pushing, p->two->path);
368 }
369 }
370
373 -
374 -static void commit_need_pushing(struct commit *commit, int *needs_pushing)
371 +static void find_unpushed_submodule_commits(struct commit *commit,
372 + struct string_list *needs_pushing)
373 {
374 struct rev_info rev;
375
@@ -382,14 +380,15 @@ static void commit_need_pushing(struct commit *commit, int *needs_pushing)
380 diff_tree_combined_merge(commit, 1, &rev);
381 }
382
385 -int check_submodule_needs_pushing(unsigned char new_sha1[20], const char *remotes_name)
383 +int find_unpushed_submodules(unsigned char new_sha1[20],
384 + const char *remotes_name, struct string_list *needs_pushing)
385 {
386 struct rev_info rev;
387 struct commit *commit;
388 const char *argv[] = {NULL, NULL, "--not", "NULL", NULL};
389 int argc = ARRAY_SIZE(argv) - 1;
390 char *sha1_copy;
392 - int needs_pushing = 0;
391 +
392 struct strbuf remotes_arg = STRBUF_INIT;
393
394 strbuf_addf(&remotes_arg, "--remotes=%s", remotes_name);
@@ -401,14 +400,14 @@ int check_submodule_needs_pushing(unsigned char new_sha1[20], const char *remote
400 if (prepare_revision_walk(&rev))
401 die("revision walk setup failed");
402
404 - while ((commit = get_revision(&rev)) && !needs_pushing)
405 - commit_need_pushing(commit, &needs_pushing);
403 + while ((commit = get_revision(&rev)) != NULL)
404 + find_unpushed_submodule_commits(commit, needs_pushing);
405
406 reset_revision_walk();
407 free(sha1_copy);
408 strbuf_release(&remotes_arg);
409
411 - return needs_pushing;
410 + return needs_pushing->nr;
411 }
412
413 static int is_submodule_commit_present(const char *path, unsigned char sha1[20])
submodule.h
+2 -1
@@ -29,6 +29,7 @@ int fetch_populated_submodules(int num_options, const char **options,
29 unsigned is_submodule_modified(const char *path, int ignore_untracked);
30 int merge_submodule(unsigned char result[20], const char *path, const unsigned char base[20],
31 const unsigned char a[20], const unsigned char b[20], int search);
32 -int check_submodule_needs_pushing(unsigned char new_sha1[20], const char *remotes_name);
32 +int find_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_name,
33 + struct string_list *needs_pushing);
34
35 #endif
transport.c
+22 -2
@@ -11,6 +11,7 @@
11 #include "branch.h"
12 #include "url.h"
13 #include "submodule.h"
14 +#include "string-list.h"
15
16 /* rsync support */
17
@@ -1000,6 +1001,20 @@ void transport_set_verbosity(struct transport *transport, int verbosity,
1001 transport->progress = force_progress || (verbosity >= 0 && isatty(2));
1002 }
1003
1004 +static void die_with_unpushed_submodules(struct string_list *needs_pushing)
1005 +{
1006 + int i;
1007 +
1008 + fprintf(stderr, "The following submodule paths contain changes that can\n"
1009 + "not be found on any remote:\n");
1010 + for (i = 0; i < needs_pushing->nr; i++)
1011 + printf(" %s\n", needs_pushing->items[i].string);
1012 +
1013 + string_list_clear(needs_pushing, 0);
1014 +
1015 + die("Aborting.");
1016 +}
1017 +
1018 int transport_push(struct transport *transport,
1019 int refspec_nr, const char **refspec, int flags,
1020 int *nonfastforward)
@@ -1040,10 +1055,15 @@ int transport_push(struct transport *transport,
1055
1056 if ((flags & TRANSPORT_RECURSE_SUBMODULES_CHECK) && !is_bare_repository()) {
1057 struct ref *ref = remote_refs;
1058 + struct string_list needs_pushing;
1059 +
1060 + memset(&needs_pushing, 0, sizeof(struct string_list));
1061 + needs_pushing.strdup_strings = 1;
1062 for (; ref; ref = ref->next)
1063 if (!is_null_sha1(ref->new_sha1) &&
1045 - check_submodule_needs_pushing(ref->new_sha1,transport->remote->name))
1046 - die("There are unpushed submodules, aborting.");
1064 + find_unpushed_submodules(ref->new_sha1,
1065 + transport->remote->name, &needs_pushing))
1066 + die_with_unpushed_submodules(&needs_pushing);
1067 }
1068
1069 push_ret = transport->push_refs(transport, remote_refs, flags);