[PATCH] log: convert to parse-options

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

 



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 <cmn@xxxxxxxx>
---

Carlos Martín Nieto <cmn@xxxxxxxx> writes:

>> 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.
>
>> +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.

>>  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.

>> +     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

--
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]