Subject: Re: git.c option parsing

From: Pierre Habouzit <[email-masked]>
Date: Mon, 17 Dec 2007 10:20:13 +0100

On Mon, Dec 17, 2007 at 09:01:56AM +0000, Wincent Colaiuta wrote:
> El 17/12/2007, a las 9:48, Junio C Hamano escribió:
> 
> >Wincent Colaiuta <[email-masked]> writes:
> >
> >>Of course, the above plan will only work for builtins, not for
> >>scripts. An additional step would be needed to enable scripts to
> >>handle these options; perhaps teaching "git rev-parse" something...
> >
> >As long as special options stay special and we make a rule not to allow
> >any subcommand to assign its own meaning to them, the git wrapper can
> >lookahead and reorder, when seeing a command line:
> >
> >	git scripted-command --special
> >
> >into
> >
> >	git --special scripted-command
> >
> >And that approach would work well for built-ins as well, I would
> >imagine.
> 
> Yes, and it would be simpler to implement also. The only downside is that 
> without all the other proposed changes things like "git-dashed --special" 
> wouldn't work; only teaching the builtins to actually handle the special 
> options would work in that case. And in the interests of consistency I 
> think it's pretty important that "git subcommand --special" and 
> "git-subcommand --special" both work the same as the user would 
> (reasonably) expect them to...

  There is a simple way to do that, that wouldn't conflict with the git
grep -e one, that would be to define an array of "Special" flags, in a
macro, and have every builtin using parseopt adding that macro at the
end.

  Then in git.c, you would have to scan for the command name when called
through `git --opt1 --opt2 foo`, and pass it to parseopt with as argc
the position of `foo` in the argument array. Parseopt will trust you for
it, and if it returns a non zero count, you have to barf, then you just
need to work on the rest of the array. That would mean in pseudo code
that this would work like:

    // ...
    /* when in `git --opt1 --opt2 foo -a -b -c` mode: */
    int cmd_pos = git_find_builtin_command_name(argc, argv);
    int count = parse_options(cmd_pos, argv, git_generic_options,
	"git [special-options] cmd [options]", 0);
    if (count)
	die("unknown git command: `%s`", argv[0]);
    argv += cmd_pos;
    argc -= cmd_pos;
    /* here we simulate an argv of {"foo", "-a", "-b", "-c"} */

  Of course this only works on builtins that do support parseopt other
ones will need the massage you describe. For them the sole thing to
change would be to replace the OPT_END() with a GIT_SPECIAL_OPTS() or
sth alike.

-- 
·O·  Pierre Habouzit
··O                                                [email-masked]
OOO                                                http://www.madism.org