This replaces sb/submodule-parallel-update.
(which is based on sb/submodule-parallel-fetch,
but this series also applies cleanly on master)

* using a "more" correct version of parsing the section title
* fixed the memleaks, free-after-use in
  "git submodule update: have a dedicated helper for cloning"
* reworded documentation.
* another additional patch snuck in, which makes code a bit more readable
  (0004-submodule-config-slightly-simplify-lookup_or_create_.patch)

Thanks,
Stefan

Interdiff to v7:

diff --git a/Documentation/config.txt b/Documentation/config.txt
index eda3276..3b02732 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -2647,11 +2647,10 @@ submodule.<name>.ignore::
        affected by this setting.
 
 submodule.fetchJobs::
-       This is used to determine how many submodules will be
-       fetched/cloned at the same time. Specifying a positive integer
-       allows up to that number of submodules being fetched in parallel.
-       This is used in fetch and clone operations only. A value of 0 will
-       give some reasonable configuration. It defaults to 1.
+       Specifies how many submodules are fetched/cloned at the same time.
+       A positive integer allows up to that number of submodules fetched
+       in parallel. A value of 0 will give some reasonable default.
+       If unset, it defaults to 1.
 
 tag.sort::
        This variable controls the sort ordering of tags when displayed by
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 8002187..7e01b85 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -312,33 +312,31 @@ static int update_clone_get_next_task(struct 
child_process *cp,
 
        for (; pp->count < pp->list.nr; pp->count++) {
                const struct submodule *sub = NULL;
-               const char *displaypath = NULL;
                const struct cache_entry *ce = pp->list.entries[pp->count];
+               struct strbuf displaypath_sb = STRBUF_INIT;
                struct strbuf sb = STRBUF_INIT;
+               const char *displaypath = NULL;
                const char *update_module = NULL;
                char *url = NULL;
                int needs_cloning = 0;
 
                if (ce_stage(ce)) {
                        if (pp->recursive_prefix)
-                               strbuf_addf(err, "Skipping unmerged submodule 
%s/%s\n",
+                               strbuf_addf(err,
+                                       "Skipping unmerged submodule %s/%s\n",
                                        pp->recursive_prefix, ce->name);
                        else
-                               strbuf_addf(err, "Skipping unmerged submodule 
%s\n",
+                               strbuf_addf(err,
+                                       "Skipping unmerged submodule %s\n",
                                        ce->name);
-                       continue;
+                       goto cleanup_and_continue;
                }
 
                sub = submodule_from_path(null_sha1, ce->name);
-               if (!sub) {
-                       strbuf_addf(err, "BUG: internal error managing 
submodules. "
-                                   "The cache could not locate '%s'", 
ce->name);
-                       pp->print_unmatched = 1;
-                       continue;
-               }
 
                if (pp->recursive_prefix)
-                       displaypath = relative_path(pp->recursive_prefix, 
ce->name, &sb);
+                       displaypath = relative_path(pp->recursive_prefix,
+                                                   ce->name, &displaypath_sb);
                else
                        displaypath = ce->name;
 
@@ -349,14 +347,15 @@ static int update_clone_get_next_task(struct 
child_process *cp,
                if (!update_module)
                        update_module = "checkout";
                if (!strcmp(update_module, "none")) {
-                       strbuf_addf(err, "Skipping submodule '%s'\n", 
displaypath);
-                       continue;
+                       strbuf_addf(err, "Skipping submodule '%s'\n",
+                                   displaypath);
+                       goto cleanup_and_continue;
                }
 
                /*
                 * Looking up the url in .git/config.
-                * We must not fall back to .gitmodules as we only want to 
process
-                * configured submodules.
+                * We must not fall back to .gitmodules as we only want
+                * to process configured submodules.
                 */
                strbuf_reset(&sb);
                strbuf_addf(&sb, "submodule.%s.url", sub->name);
@@ -367,9 +366,11 @@ static int update_clone_get_next_task(struct child_process 
*cp,
                         * path have been specified
                         */
                        if (pp->pathspec.nr)
-                               strbuf_addf(err, _("Submodule path '%s' not 
initialized\n"
-                                       "Maybe you want to use 'update 
--init'?"), displaypath);
-                       continue;
+                               strbuf_addf(err,
+                                           _("Submodule path '%s' not 
initialized\n"
+                                           "Maybe you want to use 'update 
--init'?"),
+                                           displaypath);
+                       goto cleanup_and_continue;
                }
 
                strbuf_reset(&sb);
@@ -383,13 +384,19 @@ static int update_clone_get_next_task(struct 
child_process *cp,
                string_list_append(&pp->projectlines, sb.buf);
 
                if (needs_cloning) {
-                       fill_clone_command(cp, pp->quiet, pp->prefix, ce->name,
-                                          sub->name, url, pp->reference, 
pp->depth);
+                       fill_clone_command(cp, pp->quiet, pp->prefix,
+                                          ce->name, sub->name, strdup(url),
+                                          pp->reference, pp->depth);
                        pp->count++;
-                       free(url);
+               }
+
+cleanup_and_continue:
+               free(url);
+               strbuf_reset(&displaypath_sb);
+               strbuf_reset(&sb);
+
+               if (needs_cloning)
                        return 1;
-               } else
-                       free(url);
        }
        return 0;
 }
diff --git a/submodule-config.c b/submodule-config.c
index a32259e..339b59d 100644
--- a/submodule-config.c
+++ b/submodule-config.c
@@ -32,7 +32,7 @@ enum lookup_type {
 
 static struct submodule_cache cache;
 static int is_cache_init;
-static int parallel_jobs = -1;
+static unsigned long parallel_jobs = -1;
 
 static int config_path_cmp(const struct submodule_entry *a,
                           const struct submodule_entry *b,
@@ -163,22 +163,17 @@ static struct submodule *cache_lookup_name(struct 
submodule_cache *cache,
 }
 
 static struct submodule *lookup_or_create_by_name(struct submodule_cache 
*cache,
-                                                 const unsigned char 
*gitmodules_sha1,
-                                                 const char *name_ptr, int 
name_len)
+               const unsigned char *gitmodules_sha1, const char *name)
 {
        struct submodule *submodule;
-       struct strbuf name_buf = STRBUF_INIT;
-       char *name = xmemdupz(name_ptr, name_len);
 
        submodule = cache_lookup_name(cache, gitmodules_sha1, name);
        if (submodule)
-               goto out;
+               return submodule;
 
        submodule = xmalloc(sizeof(*submodule));
 
-       strbuf_addstr(&name_buf, name);
-       submodule->name = strbuf_detach(&name_buf, NULL);
-
+       submodule->name = xstrdup(name);
        submodule->path = NULL;
        submodule->url = NULL;
        submodule->update = NULL;
@@ -188,8 +183,7 @@ static struct submodule *lookup_or_create_by_name(struct 
submodule_cache *cache,
        hashcpy(submodule->gitmodules_sha1, gitmodules_sha1);
 
        cache_add(cache, submodule);
-out:
-       free(name);
+
        return submodule;
 }
 
@@ -241,18 +235,16 @@ static int parse_generic_submodule_config(const char *key,
                                          struct parse_config_parameter *me)
 {
        if (!strcmp(key, "fetchjobs")) {
-               parallel_jobs = strtol(value, NULL, 10);
-               if (parallel_jobs < 0) {
-                       warning("submodule.fetchJobs not allowed to be 
negative.");
+               if (!git_parse_ulong(value, &parallel_jobs)) {
+                       warning(_("Error parsing submodule.fetchJobs; 
Defaulting to 1."));
                        parallel_jobs = 1;
-                       return 1;
                }
        }
 
        return 0;
 }
 
-static int parse_specific_submodule_config(const char *subsection, int 
subsection_len,
+static int parse_specific_submodule_config(const char *subsection,
                                           const char *key,
                                           const char *var,
                                           const char *value,
@@ -262,7 +254,7 @@ static int parse_specific_submodule_config(const char 
*subsection, int subsectio
        struct submodule *submodule;
        submodule = lookup_or_create_by_name(me->cache,
                                             me->gitmodules_sha1,
-                                            subsection, subsection_len);
+                                            subsection);
 
        if (!strcmp(key, "path")) {
                if (!value)
@@ -332,19 +324,22 @@ static int parse_specific_submodule_config(const char 
*subsection, int subsectio
 static int parse_config(const char *var, const char *value, void *data)
 {
        struct parse_config_parameter *me = data;
-       int subsection_len;
+       int subsection_len, ret;
        const char *subsection, *key;
+       char *sub;
 
        if (parse_config_key(var, "submodule", &subsection,
                             &subsection_len, &key) < 0)
                return 0;
 
-       if (!subsection_len)
+       if (!subsection)
                return parse_generic_submodule_config(key, var, value, me);
-       else
-               return parse_specific_submodule_config(subsection,
-                                                      subsection_len, key,
-                                                      var, value, me);
+
+       sub = xmemdupz(subsection, subsection_len);
+       ret = parse_specific_submodule_config(sub, key,
+                                             var, value, me);
+       free(sub);
+       return ret;
 }
 
 static int gitmodule_sha1_from_commit(const unsigned char *commit_sha1,
@@ -493,7 +488,7 @@ void submodule_free(void)
        is_cache_init = 0;
 }
 
-int config_parallel_submodules(void)
+unsigned long config_parallel_submodules(void)
 {
        return parallel_jobs;
 }
diff --git a/submodule-config.h b/submodule-config.h
index d9bbf9a..bab1e8d 100644
--- a/submodule-config.h
+++ b/submodule-config.h
@@ -27,6 +27,6 @@ const struct submodule *submodule_from_path(const unsigned 
char *commit_sha1,
                const char *path);
 void submodule_free(void);
 
-int config_parallel_submodules(void);
+unsigned long config_parallel_submodules(void);
 
 #endif /* SUBMODULE_CONFIG_H */


Stefan Beller (9):
  submodule-config: keep update strategy around
  submodule-config: drop check against NULL
  submodule-config: remove name_and_item_from_var
  submodule-config: slightly simplify lookup_or_create_by_name
  submodule-config: introduce parse_generic_submodule_config
  fetching submodules: respect `submodule.fetchJobs` config option
  git submodule update: have a dedicated helper for cloning
  submodule update: expose parallelism to the user
  clone: allow an explicit argument for parallel submodule clones

 Documentation/config.txt        |   6 +
 Documentation/git-clone.txt     |   6 +-
 Documentation/git-submodule.txt |   7 +-
 builtin/clone.c                 |  19 +++-
 builtin/fetch.c                 |   2 +-
 builtin/submodule--helper.c     | 246 ++++++++++++++++++++++++++++++++++++++++
 git-submodule.sh                |  54 ++++-----
 submodule-config.c              | 104 ++++++++++-------
 submodule-config.h              |   3 +
 submodule.c                     |   5 +
 t/t5526-fetch-submodules.sh     |  14 +++
 t/t7400-submodule-basic.sh      |   4 +-
 t/t7406-submodule-update.sh     |  27 +++++
 13 files changed, 414 insertions(+), 83 deletions(-)

-- 
2.7.0.rc0.41.gd102984.dirty

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to