Thread (4 messages) flat view 4 messages, 3 authors, 2016-06-15
DORMANTno replies

[PATCH] log: convert to parse-options

From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= <hidden>
Date: 2016-06-15 22:51:04
Subsystem: the rest · Maintainer: Linus Torvalds

Possibly related (same subject, not in this thread)

Use parse-options in cmd_log_init instead of manually iterating
through them. This makes the code a bit cleaner but more importantly
allows us to catch the "--quiet" option which causes some of the
log-related commands to misbehave as it would otherwise get passed on
to the diff.

Also take this opportinity to add 'whatchanged' to the help output.

Signed-off-by: Carlos Martín Nieto <redacted>
---

Carlos Martín Nieto [off-list ref] writes:
quoted
diff --git a/builtin/log.c b/builtin/log.c
index 9a15d69..5316be3 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -25,6 +25,7 @@ static const char *default_date_mode =3D3D NULL;

 static int default_show_root =3D3D 1;
 static int decoration_style;
+static int decoration_given =3D3D 0;
We prefer to leave zero-initialization of statics to the linker, similarly
to how we initialize decoration_style to zero in the line above.
quoted
+static int decorate_callback(const struct option *opt, const char *arg, int unset)
+{
+     if (unset) {
+             decoration_style = 0;
+             return 0;
+     }
This is not a new issue, but I do not think the original code did not
mean to keep decoration_given unmodified when --no-decorate was given
from the command line.  The variable is about "did we get any
--decorate related options from the command line to override whatever
log.decorate variable says?", and when we saw --no-decorate, we did
get such an override from the command line.  We should consistently
set _given variable to 1 here.
It is immaterial that it happens not to matter to the current user of the
variable that sets decoration_style to zero.  The next user of _given may
want to do other things.
Ok, I've changed this to use the version in your fixup patch.
+     if (arg == NULL) {
+             decoration_style = DECORATE_SHORT_REFS;
+             decoration_given = 1;
+             return 0;
+     }
+
+     /* First arg is irrelevant, as it just tries to parse arg */
+     decoration_style = parse_decoration_style("decorate", arg);
It is used in the error message in git_config_long() in the callchain from
here, primarily meant to report which configuration variable had a bad
value, so it is in no way irrelevant.  We need to say that a bad value
comes not from a configuration but from the command line; get_color() in
builtin/config.c passes "command line" for this exact reason.
git_config_long doesn't die with an error (though git_config_int does,
if git_config_long isn't successful) but returns 0 if it can't parse
the value. git_config_maybe_bool notices this and returns -1, which
parse_decoration_style interprets as "was not boolean" and tries to
match "short" or "full". If it can't, then it returns -1 and
decoration_callback dies with the error message.

Be it as it may, gt_config_long doesn't output any error message at
all, so what we pass is irrelevant, unless we want to future-proof it
because we don't trust the git_config_maybe_bool call to let us handle
the error ourselves in the future.
quoted
 static void cmd_log_init(int argc, const char **argv, const char *prefix,
                       struct rev_info *rev, struct setup_revision_opt *opt)
 {
-     int i;
-     int decoration_given = 0;
      struct userformat_want w;
+     int help, quiet, source;
+
+     const struct option builtin_log_options[] = {
+             OPT_BOOLEAN(0, "h", &help, "show help"),
+             OPT_BOOLEAN(0, "quiet", &quiet, "supress diff output"),
+             OPT_BOOLEAN(0, "source", &source, "show source"),
+             { OPTION_CALLBACK, 0, "decorate", NULL, NULL, "decorate options",
+               PARSE_OPT_OPTARG, decorate_callback},
+             OPT_END()
+     };
+
+     argc = parse_options(argc, argv, prefix, builtin_log_options,
+                                              builtin_log_usage,
+                                              PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |
+                                              PARSE_OPT_KEEP_DASHDASH);
The 5th parameter is an array of strings terminated with a NULL element.
Done.
quoted
+     if (help)
+             usage(builtin_log_usage);
I think parse_options() handles -h and --help itself, so there is no
longer need for this.
Indeed, removed.

As the help is generated from the option struct, I've changed the
comment a bit to me more helpful and I've added 'whatchanged' to the
usage message, as it looks bad if 'git whatchanged -h' doesn't tell
you about itself.

I'm not completely sure what "show source" is meant to be, I think
it's the source of merges, which could be added to that explanation, I guess.

 Documentation/git-format-patch.txt |    5 ++-
 builtin/log.c                      |   77 ++++++++++++++++++++++--------------
 2 files changed, 51 insertions(+), 31 deletions(-)
diff --git a/builtin/log.c b/builtin/log.c
index 9a15d69..d1b0861 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -25,12 +25,16 @@ static const char *default_date_mode = NULL;
 
 static int default_show_root = 1;
 static int decoration_style;
+static int decoration_given;
 static const char *fmt_patch_subject_prefix = "PATCH";
 static const char *fmt_pretty;
 
-static const char * const builtin_log_usage =
+static const char * const builtin_log_usage[] = {
 	"git log [<options>] [<since>..<until>] [[--] <path>...]\n"
-	"   or: git show [options] <object>...";
+	"   or: git show [options] <object>...\n"
+	"   or: git whatchanged [options] <object>...",
+	NULL
+};
 
 static int parse_decoration_style(const char *var, const char *value)
 {
@@ -49,12 +53,44 @@ static int parse_decoration_style(const char *var, const char *value)
 	return -1;
 }
 
+static int decorate_callback(const struct option *opt, const char *arg, int unset)
+{
+	if (unset)
+		decoration_style = 0;
+	else if (arg)
+		decoration_style = parse_decoration_style("decorate", arg);
+	else
+		decoration_style = DECORATE_SHORT_REFS;
+
+	if (decoration_style < 0)
+		die("invalid --decorate option: %s", arg);
+
+	decoration_given = 1;
+
+	return 0;
+}
+
 static void cmd_log_init(int argc, const char **argv, const char *prefix,
 			 struct rev_info *rev, struct setup_revision_opt *opt)
 {
-	int i;
-	int decoration_given = 0;
 	struct userformat_want w;
+	int dummy, source;
+
+	/*
+	 * The 'quiet' option is a dummy no-op to stop it from propagating
+	 * to the diff option parsing.
+	 */
+	const struct option builtin_log_options[] = {
+		OPT_BOOLEAN(0, "quiet", &dummy, "no-op, provided for compatability"),
+		OPT_BOOLEAN(0, "source", &source, "show source"),
+		{ OPTION_CALLBACK, 0, "decorate", NULL, NULL, "decoration options (default: short)",
+		  PARSE_OPT_OPTARG, decorate_callback},
+		OPT_END()
+	};
+
+	argc = parse_options(argc, argv, prefix, builtin_log_options, builtin_log_usage,
+						 PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |
+						 PARSE_OPT_KEEP_DASHDASH);
 
 	rev->abbrev = DEFAULT_ABBREV;
 	rev->commit_format = CMIT_FMT_DEFAULT;
@@ -69,14 +105,12 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,
 	if (default_date_mode)
 		rev->date_mode = parse_date_format(default_date_mode);
 
-	/*
-	 * Check for -h before setup_revisions(), or "git log -h" will
-	 * fail when run without a git directory.
-	 */
-	if (argc == 2 && !strcmp(argv[1], "-h"))
-		usage(builtin_log_usage);
 	argc = setup_revisions(argc, argv, rev, opt);
 
+	/* Any arguments at this point are not recognized */
+	if (argc > 1)
+		die("unrecognized argument: %s", argv[1]);
+
 	memset(&w, 0, sizeof(w));
 	userformat_find_requirements(NULL, &w);
 
@@ -92,26 +126,9 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,
 		if (rev->diffopt.nr_paths != 1)
 			usage("git logs can only follow renames on one pathname at a time");
 	}
-	for (i = 1; i < argc; i++) {
-		const char *arg = argv[i];
-		if (!strcmp(arg, "--decorate")) {
-			decoration_style = DECORATE_SHORT_REFS;
-			decoration_given = 1;
-		} else if (!prefixcmp(arg, "--decorate=")) {
-			const char *v = skip_prefix(arg, "--decorate=");
-			decoration_style = parse_decoration_style(arg, v);
-			if (decoration_style < 0)
-				die("invalid --decorate option: %s", arg);
-			decoration_given = 1;
-		} else if (!strcmp(arg, "--no-decorate")) {
-			decoration_style = 0;
-		} else if (!strcmp(arg, "--source")) {
-			rev->show_source = 1;
-		} else if (!strcmp(arg, "-h")) {
-			usage(builtin_log_usage);
-		} else
-			die("unrecognized argument: %s", arg);
-	}
+
+	if (source)
+		rev->show_source = 1;
 
 	/*
 	 * defeat log.decorate configuration interacting with --pretty=raw
-- 
1.7.4.2.437.g4fc7e.dirty
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help