Skip to content

Commit 7cc85e4

Browse files
hvoigtgitster
authored andcommitted
serialize collection of changed submodules
To check whether a submodule needs to be pushed we need to collect all changed submodules. Lets collect them first and then execute the possibly expensive test whether certain revisions are already pushed only once per submodule. There is further potential for optimization since we can assemble one command and only issued that instead of one call for each remote ref in the submodule. Signed-off-by: Heiko Voigt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 9194226 commit 7cc85e4

File tree

1 file changed

+62
-5
lines changed

1 file changed

+62
-5
lines changed

submodule.c

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -434,19 +434,38 @@ static int submodule_needs_pushing(const char *path, const unsigned char sha1[20
434434
return 0;
435435
}
436436

437+
static struct sha1_array *get_sha1s_from_list(struct string_list *submodules,
438+
const char *path)
439+
{
440+
struct string_list_item *item;
441+
struct sha1_array *hashes;
442+
443+
item = string_list_insert(submodules, path);
444+
if (item->util)
445+
return (struct sha1_array *) item->util;
446+
447+
hashes = (struct sha1_array *) xmalloc(sizeof(struct sha1_array));
448+
/* NEEDSWORK: should we add an initializer function for
449+
* sha1_array ? */
450+
memset(hashes, 0, sizeof(struct sha1_array));
451+
item->util = hashes;
452+
return hashes;
453+
}
454+
437455
static void collect_submodules_from_diff(struct diff_queue_struct *q,
438456
struct diff_options *options,
439457
void *data)
440458
{
441459
int i;
442-
struct string_list *needs_pushing = data;
460+
struct string_list *submodules = data;
443461

444462
for (i = 0; i < q->nr; i++) {
445463
struct diff_filepair *p = q->queue[i];
464+
struct sha1_array *hashes;
446465
if (!S_ISGITLINK(p->two->mode))
447466
continue;
448-
if (submodule_needs_pushing(p->two->path, p->two->oid.hash))
449-
string_list_insert(needs_pushing, p->two->path);
467+
hashes = get_sha1s_from_list(submodules, p->two->path);
468+
sha1_array_append(hashes, p->two->oid.hash);
450469
}
451470
}
452471

@@ -462,14 +481,41 @@ static void find_unpushed_submodule_commits(struct commit *commit,
462481
diff_tree_combined_merge(commit, 1, &rev);
463482
}
464483

484+
struct collect_submodule_from_sha1s_data {
485+
char *submodule_path;
486+
struct string_list *needs_pushing;
487+
};
488+
489+
static void collect_submodules_from_sha1s(const unsigned char sha1[20],
490+
void *data)
491+
{
492+
struct collect_submodule_from_sha1s_data *me =
493+
(struct collect_submodule_from_sha1s_data *) data;
494+
495+
if (submodule_needs_pushing(me->submodule_path, sha1))
496+
string_list_insert(me->needs_pushing, me->submodule_path);
497+
}
498+
499+
static void free_submodules_sha1s(struct string_list *submodules)
500+
{
501+
int i;
502+
for (i = 0; i < submodules->nr; i++) {
503+
struct string_list_item *item = &submodules->items[i];
504+
struct sha1_array *hashes = (struct sha1_array *) item->util;
505+
sha1_array_clear(hashes);
506+
}
507+
string_list_clear(submodules, 1);
508+
}
509+
465510
int find_unpushed_submodules(unsigned char new_sha1[20],
466511
const char *remotes_name, struct string_list *needs_pushing)
467512
{
468513
struct rev_info rev;
469514
struct commit *commit;
470515
const char *argv[] = {NULL, NULL, "--not", "NULL", NULL};
471-
int argc = ARRAY_SIZE(argv) - 1;
516+
int argc = ARRAY_SIZE(argv) - 1, i;
472517
char *sha1_copy;
518+
struct string_list submodules = STRING_LIST_INIT_DUP;
473519

474520
struct strbuf remotes_arg = STRBUF_INIT;
475521

@@ -483,12 +529,23 @@ int find_unpushed_submodules(unsigned char new_sha1[20],
483529
die("revision walk setup failed");
484530

485531
while ((commit = get_revision(&rev)) != NULL)
486-
find_unpushed_submodule_commits(commit, needs_pushing);
532+
find_unpushed_submodule_commits(commit, &submodules);
487533

488534
reset_revision_walk();
489535
free(sha1_copy);
490536
strbuf_release(&remotes_arg);
491537

538+
for (i = 0; i < submodules.nr; i++) {
539+
struct string_list_item *item = &submodules.items[i];
540+
struct collect_submodule_from_sha1s_data data;
541+
data.submodule_path = item->string;
542+
data.needs_pushing = needs_pushing;
543+
sha1_array_for_each_unique((struct sha1_array *) item->util,
544+
collect_submodules_from_sha1s,
545+
&data);
546+
}
547+
free_submodules_sha1s(&submodules);
548+
492549
return needs_pushing->nr;
493550
}
494551

0 commit comments

Comments
 (0)