Re: [RFC] Re: Convert 'git blame' to parse_options()

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

 




On Mon, 23 Jun 2008, Linus Torvalds wrote:
> 
> Or are we going to sit around discussing this for another five months?

So the gauntlet is thrown.

This is the trivial version that (on top of my original patch in this 
thread) makes

	git blame --since=April -b Makefile

work.

Does it handle all cases? No. In particular, because it still makes 
builtin-blame.c use PARSE_OPT_STOP_AT_NON_OPTION, and because cmd_blame.c 
simply doesn't do the sane thing (it took me more than five minutes just 
because I tried to make it do the same thing and not do any argument 
parsing at all, but I just gave up), you still cannot pass it things like

	--default HEAD

because it will stop at HEAD, and then do the exact wrong thing.

Could it be improved? I'm sure. And I didn't test it much at all. I also 
didn't change any existing users that could possibly use the new 
PARSE_OPT_STOP_AT_UNKNOWN thing. So this patch is an example patch only, 
to show what I'm talking about when I say "simple".

		Linus

---
 builtin-blame.c |    2 +-
 parse-options.c |   26 ++++++++++++++++++++++----
 parse-options.h |    2 ++
 3 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/builtin-blame.c b/builtin-blame.c
index f04bd93..059062c 100644
--- a/builtin-blame.c
+++ b/builtin-blame.c
@@ -2195,7 +2195,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
 	cmd_is_annotate = !strcmp(argv[0], "annotate");
 
 	argc = parse_options(argc, argv, options, blame_opt_usage,
-		PARSE_OPT_STOP_AT_NON_OPTION | PARSE_OPT_KEEP_DASHDASH);
+		PARSE_OPT_STOP_AT_NON_OPTION | PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_UNKNOWN);
 
 	/*
 	 * parse_options() offsets things by one - undo for now to make
diff --git a/parse-options.c b/parse-options.c
index acf3fe3..5b4653f 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -7,7 +7,7 @@
 struct optparse_t {
 	const char **argv;
 	const char **out;
-	int argc, cpidx;
+	int argc, cpidx, flags;
 	const char *opt;
 };
 
@@ -139,6 +139,8 @@ static int parse_short_opt(struct optparse_t *p, const struct option *options)
 			return get_value(p, options, OPT_SHORT);
 		}
 	}
+	if (p->flags & (PARSE_OPT_STOP_AT_UNKNOWN | PARSE_OPT_KEEP_UNKNOWN))
+		return -1;
 	return error("unknown switch `%c'", *p->opt);
 }
 
@@ -224,6 +226,8 @@ is_abbreviated:
 			abbrev_option->long_name);
 	if (abbrev_option)
 		return get_value(p, abbrev_option, abbrev_flags);
+	if (p->flags & (PARSE_OPT_STOP_AT_UNKNOWN | PARSE_OPT_KEEP_UNKNOWN))
+		return -1;
 	return error("unknown option `%s'", arg);
 }
 
@@ -253,7 +257,7 @@ static NORETURN void usage_with_options_internal(const char * const *,
 int parse_options(int argc, const char **argv, const struct option *options,
                   const char * const usagestr[], int flags)
 {
-	struct optparse_t args = { argv + 1, argv, argc - 1, 0, NULL };
+	struct optparse_t args = { argv + 1, argv, argc - 1, 0, flags, NULL };
 
 	for (; args.argc; args.argc--, args.argv++) {
 		const char *arg = args.argv[0];
@@ -269,8 +273,15 @@ int parse_options(int argc, const char **argv, const struct option *options,
 			args.opt = arg + 1;
 			if (*args.opt == 'h')
 				usage_with_options(usagestr, options);
-			if (parse_short_opt(&args, options) < 0)
+			if (parse_short_opt(&args, options) < 0) {
+				if (flags & PARSE_OPT_STOP_AT_UNKNOWN) 
+					break;
+				if (flags & PARSE_OPT_KEEP_UNKNOWN) {
+					args.out[args.cpidx++] = args.argv[0];
+					continue;
+				}
 				usage_with_options(usagestr, options);
+			}
 			if (args.opt)
 				check_typos(arg + 1, options);
 			while (args.opt) {
@@ -294,8 +305,15 @@ int parse_options(int argc, const char **argv, const struct option *options,
 			usage_with_options_internal(usagestr, options, 1);
 		if (!strcmp(arg + 2, "help"))
 			usage_with_options(usagestr, options);
-		if (parse_long_opt(&args, arg + 2, options))
+		if (parse_long_opt(&args, arg + 2, options)) {
+			if (flags & PARSE_OPT_STOP_AT_UNKNOWN)  
+				break;
+			if (flags & PARSE_OPT_KEEP_UNKNOWN) {
+				args.out[args.cpidx++] = args.argv[0];
+				continue;
+			}
 			usage_with_options(usagestr, options);
+		}
 	}
 
 	memmove(args.out + args.cpidx, args.argv, args.argc * sizeof(*args.out));
diff --git a/parse-options.h b/parse-options.h
index 4ee443d..a98f0ec 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -20,6 +20,8 @@ enum parse_opt_type {
 enum parse_opt_flags {
 	PARSE_OPT_KEEP_DASHDASH = 1,
 	PARSE_OPT_STOP_AT_NON_OPTION = 2,
+	PARSE_OPT_KEEP_UNKNOWN = 4,
+	PARSE_OPT_STOP_AT_UNKNOWN = 8,
 };
 
 enum parse_opt_option_flags {
--
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]

  Powered by Linux