git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 3/6] Refactor --dirstat parsing; deprecate --cumulative and --dirstat-by-file

From
Junio C Hamano <gitster@pobox.com>
Date
Apr 27, 2011, 20:51 UTC
Message-ID
<7vaafb76zb.fsf@alter.siamese.dyndns.org>
In-Reply-To
<201104270402.10658.johan@herland.net>
Johan Herland <johan@herland.net> writes:
Show 7 quoted lines
>> Even better, probably they can be left to diff_opt_parse() without
>> calling this function, as you are deprecating them and do not have to
>> allow them to take the opt1,opt2,... form of parameter.
>
> I understand, but politely disagree: Patch 6/6 complicates the logic
> that DIFF_OPT_SET()/CLR() various bits in the diff options. I'd rather
> keep that logic in one place, than duplicate it into diff_opt_parse().

I've given a brief look at the v3. Looks better than the previous one; not using double is especailly a big and good thing.

There still are a few things I noticed, two of which I'd attempt to show how to fix in the attached patch (on top of the whole 6 patch series, as I don't have time to break it down and I know you are capable enough to do so yourself).

 * We eradicated the use of C99_FORMAT at 28bd70d (unbreak and eliminate
   NO_C99_FORMAT, 2011-03-16) and "%td" at 31d713d (mktag: avoid %td in
   format string, 2011-03-16).
 * parse_dirstat_params() can die when it sees an input that it does not
   understand, instead of silently returning and indicating an error by
   its return value, even when it is called from the codepath to read the
   configuration files.  Dying upon an erroneous command line argument is
   fine and diagnosing it is preferred, but the configuration parser
   should ignore values that it does not understand (may want to warn) so
   that you can keep using older git (i.e. the version resulting from your
   patch) in a repository you usually use newer git that supports even
   more features with its --dirstat option.
 * Temporary memory allocation in your dirstat_opt() to handle commonly
   used shorthand stands out as a sore thumb.
 * The parsing implemented in dirstat_opt() is a bit too loose.  For
   example, we never accepted "-X=3" nor "--dirstat40" but I suspect your
   parser would.  Accepting the former might not be such a big deal, but
   not the latter.

The attached is not a complete fix-up, but addresses the last two issues, and it also should be a good starting point for the second issue.

I tried not to fix style issues, but parse_dirstat_params() should follow
	if (...) {
            ... compound ...
	} else if (...) {
            ... compound ...
	} else if (...) {
	    ...
i.e. close brace just before the "else if" on the same line.
 diff.c |   94 +++++++++++++++++++++++++++++----------------------------------
 1 files changed, 43 insertions(+), 51 deletions(-)
diff --git a/diff.c b/diff.c
index 9008e88..7c6a8d1 100644
--- a/diff.c
+++ b/diff.c
@@ -73,9 +73,14 @@ static int parse_diff_color_slot(const char *var, int ofs)
 #define PD_FMT "%td"
 #endif
 
-static void parse_dirstat_params(struct diff_options *options, const char *params)
+static int parse_dirstat_params(struct diff_options *options, const char *params,
+				int die_on_error)
 {
 	const char *p = params;
+	const char *unknown_param_error = "Unknown --dirstat parameter '%s'";
+	const char *missing_comma_error = "Missing comma separator at char " PD_FMT
+		" of '%s'";
+
 	while (*p) {
 		if (!prefixcmp(p, "changes")) {
 			p += 7;
@@ -109,19 +114,27 @@ static void parse_dirstat_params(struct diff_options *options, const char *param
 				options->dirstat_permille += *p - '0';
 				/* .. and ignore any further digits */
 				while (isdigit(*++p))
-					/* nothing */;
+					; /* nothing */
 			}
+		} else if (die_on_error) {
+			die(unknown_param_error, p);
+		} else {
+			return error(unknown_param_error, p);
 		}
-		else
-			die("Unknown --dirstat parameter '%s'", p);
 
-		if (*p) { /* more parameters, swallow separator */
-			if (*p != ',')
-				die("Missing comma separator at char " PD_FMT
-				    " of '%s'", p - params, params);
-			p++;
+		if (*p) {
+			/* more parameters, swallow separator */
+			if (*p == ',') {
+				p++;
+				continue;
+			}
+			if (die_on_error)
+				die(missing_comma_error, p - params, params);
+			else
+				return error(missing_comma_error, p - params, params);
 		}
 	}
+	return 0;
 }
 
 static int git_config_rename(const char *var, const char *value)
@@ -205,7 +218,7 @@ int git_diff_basic_config(const char *var, const char *value, void *cb)
 
 	if (!strcmp(var, "diff.dirstat")) {
 		default_diff_options.dirstat_permille = diff_dirstat_permille_default;
-		parse_dirstat_params(&default_diff_options, value);
+		(void) parse_dirstat_params(&default_diff_options, value, 0);
 		diff_dirstat_permille_default = default_diff_options.dirstat_permille;
 		return 0;
 	}
@@ -3252,45 +3265,14 @@ static int stat_opt(struct diff_options *options, const char **av)
 	return argcount;
 }
 
-/*
- * Parse dirstat-related options and any parameters given to those options.
- * Returns 1 if the option in 'arg' is a recognized dirstat-related option;
- * otherwise returns 0.
- */
-static int dirstat_opt(struct diff_options *options, const char *arg)
+static int parse_dirstat_opt(struct diff_options *options, const char *params)
 {
-	const char *p;
-	char *mangled = NULL;
-
-	if (!strcmp(arg, "--cumulative")) /* deprecated */
-		/* handle '--cumulative' like '--dirstat=cumulative' */
-		p = "cumulative";
-	else if (!strcmp(arg, "--dirstat-by-file") ||
-		 !prefixcmp(arg, "--dirstat-by-file=")) { /* deprecated */
-		/* handle '--dirstat-by-file=*' like '--dirstat=files,*' */
-		mangled = xstrdup(arg + 12);
-		memcpy(mangled, "files", 5);
-		if (mangled[5]) {
-			assert(mangled[5] == '=');
-			mangled[5] = ',';
-		}
-		p = mangled;
-	}
-	else if (!prefixcmp(arg, "-X"))
-		p = arg + 2;
-	else if (!prefixcmp(arg, "--dirstat"))
-		p = arg + 9;
-	else
-		return 0;
-
+	parse_dirstat_params(options, params, 1);
+	/*
+	 * The caller knows a dirstat-related option is given from the command
+	 * line; allow it to say "return this_function();"
+	 */
 	options->output_format |= DIFF_FORMAT_DIRSTAT;
-
-	if (*p)
-		if (*p == '=')
-			p++;
-		parse_dirstat_params(options, p);
-
-	free(mangled);
 	return 1;
 }
 
@@ -3313,10 +3295,20 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
 		options->output_format |= DIFF_FORMAT_NUMSTAT;
 	else if (!strcmp(arg, "--shortstat"))
 		options->output_format |= DIFF_FORMAT_SHORTSTAT;
-	else if (!prefixcmp(arg, "-X") || !prefixcmp(arg, "--dirstat") ||
-		 !strcmp(arg, "--cumulative"))
-		/* -X, --dirstat[=<args>], --dirstat-by-file, or --cumulative */
-		return dirstat_opt(options, arg);
+	else if (!strcmp(arg, "-X") || !strcmp(arg, "--dirstat"))
+		return parse_dirstat_opt(options, "");
+	else if (!prefixcmp(arg, "-X"))
+		return parse_dirstat_opt(options, arg + 2);
+	else if (!prefixcmp(arg, "--dirstat="))
+		return parse_dirstat_opt(options, arg + 10);
+	else if (!strcmp(arg, "--cumulative"))
+		return parse_dirstat_opt(options, "cumulative");
+	else if (!strcmp(arg, "--dirstat-by-file"))
+		return parse_dirstat_opt(options, "files");
+	else if (!prefixcmp(arg, "--dirstat-by-file=")) {
+		parse_dirstat_opt(options, "files");
+		return parse_dirstat_opt(options, arg + 18);
+	}
 	else if (!strcmp(arg, "--check"))
 		options->output_format |= DIFF_FORMAT_CHECKDIFF;
 	else if (!strcmp(arg, "--summary"))
Previous: Junio C HamanoNext: Junio C Hamano
Message 36 of 91 in “BUG? in --dirstat when rearranging lines in a file”
  1. Johan HerlandApr 7, 2011
  2. Linus TorvaldsApr 7, 2011
  3. Junio C HamanoApr 7, 2011
  4. Linus TorvaldsApr 7, 2011
  5. Johan HerlandApr 8, 2011
  6. 1/3 --dirstat: Document shortcomings compared to --stat or regular diffJohan Herland, Apr 8, 2011
  7. Junio C HamanoApr 8, 2011
  8. 2/3 --dirstat-by-file: Make it faster and more correctJohan Herland, Apr 8, 2011
  9. 3/3 Teach --dirstat to not completely ignore rearranged linesJohan Herland, Apr 8, 2011
  10. Linus TorvaldsApr 8, 2011
  11. Junio C HamanoApr 8, 2011
  12. 0/3 --dirstat fixesJohan Herland, Apr 10, 2011
  13. 1/3 --dirstat: Describe non-obvious differences relative to --stat or regular diffJohan Herland, Apr 10, 2011
  14. 2/3 --dirstat-by-file: Make it faster and more correctJohan Herland, Apr 10, 2011
  15. Junio C HamanoApr 11, 2011
  16. 3/3 Teach --dirstat to not completely ignore rearranged lines within a fileJohan Herland, Apr 10, 2011
  17. Junio C HamanoApr 11, 2011
  18. Johan HerlandApr 11, 2011
  19. Junio C HamanoApr 11, 2011
  20. Johan HerlandApr 12, 2011
  21. 4/3 --dirstat: In case of renames, use target filename instead of source filenameJohan Herland, Apr 12, 2011
  22. Linus TorvaldsApr 12, 2011
  23. 5/3 Alternative --dirstat implementation, based on diffstat analysisJohan Herland, Apr 12, 2011
  24. Linus TorvaldsApr 12, 2011
  25. Linus TorvaldsApr 12, 2011
  26. Johan HerlandApr 12, 2011
  27. Linus TorvaldsApr 12, 2011
  28. Junio C HamanoApr 12, 2011
  29. 0/6 --dirstat fixes, part 2Johan Herland, Apr 26, 2011
  30. 1/6 Add several testcases for --dirstat and friendsJohan Herland, Apr 26, 2011
  31. 2/6 Make --dirstat=0 output directories that contribute < 0.1% of changesJohan Herland, Apr 26, 2011
  32. 3/6 Refactor --dirstat parsing; deprecate --cumulative and --dirstat-by-fileJohan Herland, Apr 26, 2011
  33. Junio C HamanoApr 26, 2011
  34. Johan HerlandApr 27, 2011
  35. Junio C HamanoApr 27, 2011
  36. Junio C HamanoApr 27, 2011
  37. Junio C HamanoApr 27, 2011
  38. 4/6 Add config variable for specifying default --dirstat behaviorJohan Herland, Apr 26, 2011
  39. Junio C HamanoApr 26, 2011
  40. Johan HerlandApr 27, 2011
  41. 5/6 Use floating point for --dirstat percentagesJohan Herland, Apr 26, 2011
  42. Junio C HamanoApr 26, 2011
  43. Johan HerlandApr 27, 2011
  44. Junio C HamanoApr 27, 2011
  45. Linus TorvaldsApr 27, 2011
  46. Junio C HamanoApr 27, 2011
  47. 6/6 New --dirstat=lines mode, doing dirstat analysis based on diffstatJohan Herland, Apr 26, 2011
  48. Junio C HamanoApr 26, 2011
  49. Johan HerlandApr 27, 2011
  50. Linus TorvaldsApr 26, 2011
  51. 0/6 --dirstat fixes, part 2Johan Herland, Apr 27, 2011
  52. 1/6 Add several testcases for --dirstat and friendsJohan Herland, Apr 27, 2011
  53. 2/6 Make --dirstat=0 output directories that contribute < 0.1% of changesJohan Herland, Apr 27, 2011
  54. 3/6 Refactor --dirstat parsing; deprecate --cumulative and --dirstat-by-fileJohan Herland, Apr 27, 2011
  55. 4/6 Add config variable for specifying default --dirstat behaviorJohan Herland, Apr 27, 2011
  56. 5/6 Use floating point for --dirstat percentagesJohan Herland, Apr 27, 2011
  57. Linus TorvaldsApr 27, 2011
  58. 6/6 New --dirstat=lines mode, doing dirstat analysis based on diffstatJohan Herland, Apr 27, 2011
  59. 0/6 --dirstat fixes, part 2Johan Herland, Apr 27, 2011
  60. 1/6 Add several testcases for --dirstat and friendsJohan Herland, Apr 27, 2011
  61. 2/6 Make --dirstat=0 output directories that contribute < 0.1% of changesJohan Herland, Apr 27, 2011
  62. 3/6 Refactor --dirstat parsing; deprecate --cumulative and --dirstat-by-fileJohan Herland, Apr 27, 2011
  63. 4/6 Add config variable for specifying default --dirstat behaviorJohan Herland, Apr 27, 2011
  64. 5/6 Allow specifying --dirstat cut-off percentage as a floating point numberJohan Herland, Apr 27, 2011
  65. Linus TorvaldsApr 27, 2011
  66. 5/6 Allow specifying --dirstat cut-off percentage as a floating point numberJohan Herland, Apr 27, 2011
  67. 6/6 New --dirstat=lines mode, doing dirstat analysis based on diffstatJohan Herland, Apr 27, 2011
  68. 0/7 --dirstat fixes, part 2Johan Herland, Apr 28, 2011
  69. 1/7 Add several testcases for --dirstat and friendsJohan Herland, Apr 28, 2011
  70. 2/7 Make --dirstat=0 output directories that contribute < 0.1% of changesJohan Herland, Apr 28, 2011
  71. 3/7 Refactor --dirstat parsing; deprecate --cumulative and --dirstat-by-fileJohan Herland, Apr 28, 2011
  72. 4/7 Add config variable for specifying default --dirstat behaviorJohan Herland, Apr 28, 2011
  73. 5/7 Allow specifying --dirstat cut-off percentage as a floating point numberJohan Herland, Apr 28, 2011
  74. 6/7 New --dirstat=lines mode, doing dirstat analysis based on diffstatJohan Herland, Apr 28, 2011
  75. 7/7 Improve error handling when parsing dirstat parametersJohan Herland, Apr 28, 2011
  76. Junio C HamanoApr 28, 2011
  77. Junio C HamanoApr 28, 2011
  78. Johan HerlandApr 28, 2011
  79. Johan HerlandApr 28, 2011
  80. Junio C HamanoApr 29, 2011
  81. 0/8 --dirstat fixes, part 2Johan Herland, Apr 29, 2011
  82. 1/8 Add several testcases for --dirstat and friendsJohan Herland, Apr 29, 2011
  83. 2/8 Make --dirstat=0 output directories that contribute < 0.1% of changesJohan Herland, Apr 29, 2011
  84. 3/8 Refactor --dirstat parsing; deprecate --cumulative and --dirstat-by-fileJohan Herland, Apr 29, 2011
  85. 4/8 Add config variable for specifying default --dirstat behaviorJohan Herland, Apr 29, 2011
  86. 5/8 Allow specifying --dirstat cut-off percentage as a floating point numberJohan Herland, Apr 29, 2011
  87. 6/8 New --dirstat=lines mode, doing dirstat analysis based on diffstatJohan Herland, Apr 29, 2011
  88. 7/8 Improve error handling when parsing dirstat parametersJohan Herland, Apr 29, 2011
  89. 8/8 Mark dirstat error messages for translationJohan Herland, Apr 29, 2011
  90. Junio C HamanoApr 12, 2011
  91. Linus TorvaldsApr 10, 2011

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.