[PATCHv8 0/9] Expose submodule parallelism to the user

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]