git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [PATCH] submodule-config: Untangle logic in parse_config
@ 2015-10-12 17:58 Stefan Beller
  2015-10-12 19:24 ` Junio C Hamano
  0 siblings, 1 reply; 3+ messages in thread
From: Stefan Beller @ 2015-10-12 17:58 UTC (permalink / raw)
  To: gitster; +Cc: git, Stefan Beller, Eric Sunshine, Heiko Voigt

This improves readability of the parse_config logic by making it more concise.

CC: Eric Sunshine <sunshine@sunshineco.com>
CC: Heiko Voigt <hvoigt@hvoigt.net>
Signed-off-by: Stefan Beller <sbeller@google.com>
---
 Eric commented on this during the long series for parallelizing 
 fetching submodules. I realized this can be added as an independant patch
 as it doesn't interfere with the series at all, but rather was needed for the
 next series I planned to put on top (parallelize git submodule). I need to
 rethink the next series anyway, so I extracted this patch as a useful
 readability improvement. 
 
 submodule-config.c | 74 +++++++++++++++++++++---------------------------------
 1 file changed, 29 insertions(+), 45 deletions(-)

diff --git a/submodule-config.c b/submodule-config.c
index 393de53..afe0ea8 100644
--- a/submodule-config.c
+++ b/submodule-config.c
@@ -257,78 +257,62 @@ static int parse_config(const char *var, const char *value, void *data)
 	if (!name_and_item_from_var(var, &name, &item))
 		return 0;
 
-	submodule = lookup_or_create_by_name(me->cache, me->gitmodules_sha1,
-			name.buf);
+	submodule = lookup_or_create_by_name(me->cache,
+					     me->gitmodules_sha1,
+					     name.buf);
 
 	if (!strcmp(item.buf, "path")) {
-		struct strbuf path = STRBUF_INIT;
-		if (!value) {
+		if (!value)
 			ret = config_error_nonbool(var);
-			goto release_return;
-		}
-		if (!me->overwrite && submodule->path != NULL) {
+		else if (!me->overwrite && submodule->path != NULL)
 			warn_multiple_config(me->commit_sha1, submodule->name,
 					"path");
-			goto release_return;
+		else {
+			if (submodule->path)
+				cache_remove_path(me->cache, submodule);
+			free((void *) submodule->path);
+			submodule->path = xstrdup(value);
+			cache_put_path(me->cache, submodule);
 		}
-
-		if (submodule->path)
-			cache_remove_path(me->cache, submodule);
-		free((void *) submodule->path);
-		strbuf_addstr(&path, value);
-		submodule->path = strbuf_detach(&path, NULL);
-		cache_put_path(me->cache, submodule);
 	} else if (!strcmp(item.buf, "fetchrecursesubmodules")) {
 		/* when parsing worktree configurations we can die early */
 		int die_on_error = is_null_sha1(me->gitmodules_sha1);
 		if (!me->overwrite &&
-		    submodule->fetch_recurse != RECURSE_SUBMODULES_NONE) {
+		    submodule->fetch_recurse != RECURSE_SUBMODULES_NONE)
 			warn_multiple_config(me->commit_sha1, submodule->name,
 					"fetchrecursesubmodules");
-			goto release_return;
-		}
-
-		submodule->fetch_recurse = parse_fetch_recurse(var, value,
+		else
+			submodule->fetch_recurse = parse_fetch_recurse(
+								var, value,
 								die_on_error);
 	} else if (!strcmp(item.buf, "ignore")) {
-		struct strbuf ignore = STRBUF_INIT;
-		if (!me->overwrite && submodule->ignore != NULL) {
+		if (!value)
+			ret = config_error_nonbool(var);
+		else if (!me->overwrite && submodule->ignore != NULL)
 			warn_multiple_config(me->commit_sha1, submodule->name,
 					"ignore");
-			goto release_return;
-		}
-		if (!value) {
-			ret = config_error_nonbool(var);
-			goto release_return;
-		}
-		if (strcmp(value, "untracked") && strcmp(value, "dirty") &&
-		    strcmp(value, "all") && strcmp(value, "none")) {
+		else if (strcmp(value, "untracked") &&
+			 strcmp(value, "dirty") &&
+			 strcmp(value, "all") &&
+			 strcmp(value, "none"))
 			warning("Invalid parameter '%s' for config option "
 					"'submodule.%s.ignore'", value, var);
-			goto release_return;
+		else {
+			free((void *) submodule->ignore);
+			submodule->ignore = xstrdup(value);
 		}
-
-		free((void *) submodule->ignore);
-		strbuf_addstr(&ignore, value);
-		submodule->ignore = strbuf_detach(&ignore, NULL);
 	} else if (!strcmp(item.buf, "url")) {
-		struct strbuf url = STRBUF_INIT;
 		if (!value) {
 			ret = config_error_nonbool(var);
-			goto release_return;
-		}
-		if (!me->overwrite && submodule->url != NULL) {
+		} else if (!me->overwrite && submodule->url != NULL) {
 			warn_multiple_config(me->commit_sha1, submodule->name,
 					"url");
-			goto release_return;
+		} else {
+			free((void *) submodule->url);
+			submodule->url = xstrdup(value);
 		}
-
-		free((void *) submodule->url);
-		strbuf_addstr(&url, value);
-		submodule->url = strbuf_detach(&url, NULL);
 	}
 
-release_return:
 	strbuf_release(&name);
 	strbuf_release(&item);
 
-- 
2.5.0.274.g94829aa.dirty

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] submodule-config: Untangle logic in parse_config
  2015-10-12 17:58 [PATCH] submodule-config: Untangle logic in parse_config Stefan Beller
@ 2015-10-12 19:24 ` Junio C Hamano
  2015-10-13  0:02   ` [PATCHv2] submodule-config: Shorten " Stefan Beller
  0 siblings, 1 reply; 3+ messages in thread
From: Junio C Hamano @ 2015-10-12 19:24 UTC (permalink / raw)
  To: Stefan Beller; +Cc: git, Eric Sunshine, Heiko Voigt

Stefan Beller <sbeller@google.com> writes:

> This improves readability of the parse_config logic by making it more concise.

This does make it shorter, but "improve readability" is highly
subjective and "untangle logic" is content-free without explaining
what aspect of the logic is being untangled into what other shape.

> @@ -257,78 +257,62 @@ static int parse_config(const char *var, const char *value, void *data)
>  	if (!name_and_item_from_var(var, &name, &item))
>  		return 0;
>  
> -	submodule = lookup_or_create_by_name(me->cache, me->gitmodules_sha1,
> -			name.buf);
> +	submodule = lookup_or_create_by_name(me->cache,
> +					     me->gitmodules_sha1,
> +					     name.buf);

Just a formatting change, which does make it easier to follow, but
does not untangle the logic.

> ...
>  	} else if (!strcmp(item.buf, "ignore")) {
> -		struct strbuf ignore = STRBUF_INIT;
> -		if (!me->overwrite && submodule->ignore != NULL) {
> +		if (!value)
> +			ret = config_error_nonbool(var);
> +		else if (!me->overwrite && submodule->ignore != NULL)
>  			warn_multiple_config(me->commit_sha1, submodule->name,
>  					"ignore");
> -			goto release_return;
> -		}
> -		if (!value) {
> -			ret = config_error_nonbool(var);
> -			goto release_return;
> -		}

This is not a faithful conversion, in that we used to complain and
abort when seeing multiple values with or without value but now we
complain about malformed boolean first.  I do not think the
difference matters, but it is worth noting in the log, as it is a
clean-up that makes the order of checks consistent between ignore
and url, if I am reading the patch correctly.

> -		if (strcmp(value, "untracked") && strcmp(value, "dirty") &&
> -		    strcmp(value, "all") && strcmp(value, "none")) {
> +		else if (strcmp(value, "untracked") &&
> +			 strcmp(value, "dirty") &&
> +			 strcmp(value, "all") &&
> +			 strcmp(value, "none"))
>  			warning("Invalid parameter '%s' for config option "
>  					"'submodule.%s.ignore'", value, var);
> -			goto release_return;
> +		else {
> +			free((void *) submodule->ignore);
> +			submodule->ignore = xstrdup(value);
>  		}
> -
> -		free((void *) submodule->ignore);
> -		strbuf_addstr(&ignore, value);
> -		submodule->ignore = strbuf_detach(&ignore, NULL);
>  	} else if (!strcmp(item.buf, "url")) {
> -		struct strbuf url = STRBUF_INIT;
>  		if (!value) {
>  			ret = config_error_nonbool(var);
> -			goto release_return;
> -		}
> -		if (!me->overwrite && submodule->url != NULL) {
> +		} else if (!me->overwrite && submodule->url != NULL) {
>  			warn_multiple_config(me->commit_sha1, submodule->name,
>  					"url");
> -			goto release_return;
> +		} else {
> +			free((void *) submodule->url);
> +			submodule->url = xstrdup(value);
>  		}
> -
> -		free((void *) submodule->url);
> -		strbuf_addstr(&url, value);
> -		submodule->url = strbuf_detach(&url, NULL);
>  	}
>  
> -release_return:

So overall, I think there is not much "untangled", but its primary
effect is that a forward "goto" to the clean-up is removed by making
each component in if/else if/... cascade more independently complete.

Generally, a large piece of code is _easier_ to read with forward
"goto"s that jump to the shared clean-up code, as they serve as
visual cues that tell the reader "you can stop reading here and
ignore the remainder of this if/else if/... cascade".  But this
function is no too large and removing them does not make the
result harder to read, so I am not opposed to this change.  If each
individual component in if/else if/... cascade grows too large in
the future, it can easily become its own helper function.

So the patch looks OK to me, except for the "hmm, the order of
checks are made uniform without being documented?" comment above.

Thanks.


>  	strbuf_release(&name);
>  	strbuf_release(&item);

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCHv2] submodule-config: Shorten logic in parse_config
  2015-10-12 19:24 ` Junio C Hamano
@ 2015-10-13  0:02   ` Stefan Beller
  0 siblings, 0 replies; 3+ messages in thread
From: Stefan Beller @ 2015-10-13  0:02 UTC (permalink / raw)
  To: gitster; +Cc: git, jens.lehmann, Stefan Beller, Eric Sunshine, Heiko Voigt

This makes the parsing more concise by removing the forward goto as well
as unifying the structure of parsing the {ignore, url, path} options.
By unifying we introduce subtle changes in the error cases. We notice
non-boolean variables before noticing duplicate variables now.

CC: Eric Sunshine <sunshine@sunshineco.com>
CC: Heiko Voigt <hvoigt@hvoigt.net>
Signed-off-by: Stefan Beller <sbeller@google.com>
---
 submodule-config.c | 69 ++++++++++++++++++++----------------------------------
 1 file changed, 26 insertions(+), 43 deletions(-)

diff --git a/submodule-config.c b/submodule-config.c
index 393de53..96f1a0b 100644
--- a/submodule-config.c
+++ b/submodule-config.c
@@ -261,74 +261,57 @@ static int parse_config(const char *var, const char *value, void *data)
 			name.buf);
 
 	if (!strcmp(item.buf, "path")) {
-		struct strbuf path = STRBUF_INIT;
-		if (!value) {
+		if (!value)
 			ret = config_error_nonbool(var);
-			goto release_return;
-		}
-		if (!me->overwrite && submodule->path != NULL) {
+		else if (!me->overwrite && submodule->path != NULL)
 			warn_multiple_config(me->commit_sha1, submodule->name,
 					"path");
-			goto release_return;
+		else {
+			if (submodule->path)
+				cache_remove_path(me->cache, submodule);
+			free((void *) submodule->path);
+			submodule->path = xstrdup(value);
+			cache_put_path(me->cache, submodule);
 		}
-
-		if (submodule->path)
-			cache_remove_path(me->cache, submodule);
-		free((void *) submodule->path);
-		strbuf_addstr(&path, value);
-		submodule->path = strbuf_detach(&path, NULL);
-		cache_put_path(me->cache, submodule);
 	} else if (!strcmp(item.buf, "fetchrecursesubmodules")) {
 		/* when parsing worktree configurations we can die early */
 		int die_on_error = is_null_sha1(me->gitmodules_sha1);
 		if (!me->overwrite &&
-		    submodule->fetch_recurse != RECURSE_SUBMODULES_NONE) {
+		    submodule->fetch_recurse != RECURSE_SUBMODULES_NONE)
 			warn_multiple_config(me->commit_sha1, submodule->name,
 					"fetchrecursesubmodules");
-			goto release_return;
-		}
-
-		submodule->fetch_recurse = parse_fetch_recurse(var, value,
+		else
+			submodule->fetch_recurse = parse_fetch_recurse(
+								var, value,
 								die_on_error);
 	} else if (!strcmp(item.buf, "ignore")) {
-		struct strbuf ignore = STRBUF_INIT;
-		if (!me->overwrite && submodule->ignore != NULL) {
+		if (!value)
+			ret = config_error_nonbool(var);
+		else if (!me->overwrite && submodule->ignore != NULL)
 			warn_multiple_config(me->commit_sha1, submodule->name,
 					"ignore");
-			goto release_return;
-		}
-		if (!value) {
-			ret = config_error_nonbool(var);
-			goto release_return;
-		}
-		if (strcmp(value, "untracked") && strcmp(value, "dirty") &&
-		    strcmp(value, "all") && strcmp(value, "none")) {
+		else if (strcmp(value, "untracked") &&
+			 strcmp(value, "dirty") &&
+			 strcmp(value, "all") &&
+			 strcmp(value, "none"))
 			warning("Invalid parameter '%s' for config option "
 					"'submodule.%s.ignore'", value, var);
-			goto release_return;
+		else {
+			free((void *) submodule->ignore);
+			submodule->ignore = xstrdup(value);
 		}
-
-		free((void *) submodule->ignore);
-		strbuf_addstr(&ignore, value);
-		submodule->ignore = strbuf_detach(&ignore, NULL);
 	} else if (!strcmp(item.buf, "url")) {
-		struct strbuf url = STRBUF_INIT;
 		if (!value) {
 			ret = config_error_nonbool(var);
-			goto release_return;
-		}
-		if (!me->overwrite && submodule->url != NULL) {
+		} else if (!me->overwrite && submodule->url != NULL) {
 			warn_multiple_config(me->commit_sha1, submodule->name,
 					"url");
-			goto release_return;
+		} else {
+			free((void *) submodule->url);
+			submodule->url = xstrdup(value);
 		}
-
-		free((void *) submodule->url);
-		strbuf_addstr(&url, value);
-		submodule->url = strbuf_detach(&url, NULL);
 	}
 
-release_return:
 	strbuf_release(&name);
 	strbuf_release(&item);
 
-- 
2.5.0.267.g8d6e698.dirty

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2015-10-13  0:02 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-12 17:58 [PATCH] submodule-config: Untangle logic in parse_config Stefan Beller
2015-10-12 19:24 ` Junio C Hamano
2015-10-13  0:02   ` [PATCHv2] submodule-config: Shorten " Stefan Beller

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).