serialize collection of refs that contain submodule changes
We are iterating over each pushed ref and want to check whether it contains changes to submodules. Instead of immediately checking each ref lets first collect them and then do the check for all of them in one revision walk. Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Heiko Voigt committed
Nov 16, 2016 at 16:11 UTC
9cfa1c260fd10dadb2dfbb62f8e120a10cabfd06
3 files changed
+44
-25
submodule.c
+20
-15
@@ -522,6 +522,13 @@ static int has_remote(const char *refname, const struct object_id *oid,
522
return 1;
523
}
524
525
+static int append_sha1_to_argv(const unsigned char sha1[20], void *data)
526
+{
527
+ struct argv_array *argv = data;
528
+ argv_array_push(argv, sha1_to_hex(sha1));
529
+ return 0;
530
+}
531
+
532
static int submodule_needs_pushing(const char *path, const unsigned char sha1[20])
533
{
534
if (add_submodule_odb(path) || !lookup_commit_reference(sha1))
@@ -621,25 +628,24 @@ static void free_submodules_sha1s(struct string_list *submodules)
628
string_list_clear(submodules, 1);
629
}
630
624
-int find_unpushed_submodules(unsigned char new_sha1[20],
631
+int find_unpushed_submodules(struct sha1_array *commits,
632
const char *remotes_name, struct string_list *needs_pushing)
633
{
634
struct rev_info rev;
635
struct commit *commit;
629
- const char *argv[] = {NULL, NULL, "--not", "NULL", NULL};
630
- int argc = ARRAY_SIZE(argv) - 1;
631
- char *sha1_copy;
636
struct string_list submodules = STRING_LIST_INIT_DUP;
637
struct string_list_item *submodule;
638
+ struct argv_array argv = ARGV_ARRAY_INIT;
639
635
- struct strbuf remotes_arg = STRBUF_INIT;
636
-
637
- strbuf_addf(&remotes_arg, "--remotes=%s", remotes_name);
640
init_revisions(&rev, NULL);
639
- sha1_copy = xstrdup(sha1_to_hex(new_sha1));
640
- argv[1] = sha1_copy;
641
- argv[3] = remotes_arg.buf;
642
- setup_revisions(argc, argv, &rev, NULL);
641
+
642
+ /* argv.argv[0] will be ignored by setup_revisions */
643
+ argv_array_push(&argv, "find_unpushed_submodules");
644
+ sha1_array_for_each_unique(commits, append_sha1_to_argv, &argv);
645
+ argv_array_push(&argv, "--not");
646
+ argv_array_pushf(&argv, "--remotes=%s", remotes_name);
647
+
648
+ setup_revisions(argv.argc, argv.argv, &rev, NULL);
649
if (prepare_revision_walk(&rev))
650
die("revision walk setup failed");
651
@@ -647,8 +653,7 @@ int find_unpushed_submodules(unsigned char new_sha1[20],
653
find_unpushed_submodule_commits(commit, &submodules);
654
655
reset_revision_walk();
650
- free(sha1_copy);
651
- strbuf_release(&remotes_arg);
656
+ argv_array_clear(&argv);
657
658
for_each_string_list_item(submodule, &submodules) {
659
struct collect_submodule_from_sha1s_data data;
@@ -685,12 +690,12 @@ static int push_submodule(const char *path)
690
return 1;
691
}
692
688
-int push_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_name)
693
+int push_unpushed_submodules(struct sha1_array *commits, const char *remotes_name)
694
{
695
int i, ret = 1;
696
struct string_list needs_pushing = STRING_LIST_INIT_DUP;
697
693
- if (!find_unpushed_submodules(new_sha1, remotes_name, &needs_pushing))
698
+ if (!find_unpushed_submodules(commits, remotes_name, &needs_pushing))
699
return 1;
700
701
for (i = 0; i < needs_pushing.nr; i++) {
submodule.h
+3
-2
@@ -3,6 +3,7 @@
3
4
struct diff_options;
5
struct argv_array;
6
+struct sha1_array;
7
8
enum {
9
RECURSE_SUBMODULES_CHECK = -4,
@@ -62,9 +63,9 @@ int submodule_uses_gitfile(const char *path);
63
int ok_to_remove_submodule(const char *path);
64
int merge_submodule(unsigned char result[20], const char *path, const unsigned char base[20],
65
const unsigned char a[20], const unsigned char b[20], int search);
65
-int find_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_name,
66
+int find_unpushed_submodules(struct sha1_array *commits, const char *remotes_name,
67
struct string_list *needs_pushing);
67
-int push_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_name);
68
+int push_unpushed_submodules(struct sha1_array *commits, const char *remotes_name);
69
void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir);
70
int parallel_submodules(void);
71
transport.c
+21
-8
@@ -915,23 +915,36 @@ int transport_push(struct transport *transport,
915
916
if ((flags & TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND) && !is_bare_repository()) {
917
struct ref *ref = remote_refs;
918
+ struct sha1_array commits = SHA1_ARRAY_INIT;
919
+
920
for (; ref; ref = ref->next)
919
- if (!is_null_oid(&ref->new_oid) &&
920
- !push_unpushed_submodules(ref->new_oid.hash,
921
- transport->remote->name))
922
- die ("Failed to push all needed submodules!");
921
+ if (!is_null_oid(&ref->new_oid))
922
+ sha1_array_append(&commits, ref->new_oid.hash);
923
+
924
+ if (!push_unpushed_submodules(&commits, transport->remote->name)) {
925
+ sha1_array_clear(&commits);
926
+ die("Failed to push all needed submodules!");
927
+ }
928
+ sha1_array_clear(&commits);
929
}
930
931
if ((flags & (TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND |
932
TRANSPORT_RECURSE_SUBMODULES_CHECK)) && !is_bare_repository()) {
933
struct ref *ref = remote_refs;
934
struct string_list needs_pushing = STRING_LIST_INIT_DUP;
935
+ struct sha1_array commits = SHA1_ARRAY_INIT;
936
937
for (; ref; ref = ref->next)
931
- if (!is_null_oid(&ref->new_oid) &&
932
- find_unpushed_submodules(ref->new_oid.hash,
933
- transport->remote->name, &needs_pushing))
934
- die_with_unpushed_submodules(&needs_pushing);
938
+ if (!is_null_oid(&ref->new_oid))
939
+ sha1_array_append(&commits, ref->new_oid.hash);
940
+
941
+ if (find_unpushed_submodules(&commits, transport->remote->name,
942
+ &needs_pushing)) {
943
+ sha1_array_clear(&commits);
944
+ die_with_unpushed_submodules(&needs_pushing);
945
+ }
946
+ string_list_clear(&needs_pushing, 0);
947
+ sha1_array_clear(&commits);
948
}
949
950
push_ret = transport->push_refs(transport, remote_refs, flags);