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

Re: [PATCH] upload-pack.c: use of parse-options API

From
Jeff King <peff@peff.net>
Date
May 18, 2016, 18:08 UTC
Message-ID
<20160518180800.GC5796@sigill.intra.peff.net>
In-Reply-To
<20160518164019.26443-1-Antoine.Queru@ensimag.grenoble-inp.fr>
On Wed, May 18, 2016 at 06:40:19PM +0200, Antoine Queru wrote:
> Option parsing now uses the parser API instead of a local parser.
> Code is now more compact.
Sounds like a good goal.
Show 5 quoted lines
> -static const char upload_pack_usage[] = "git upload-pack [--strict] [--timeout=<n>] <dir>";
> +static const char * const upload_pack_usage[] = {
> +	N_("git upload-pack [--strict] [--timeout=<n>] <dir>"),
> +	NULL
> +};

Do we need to enumerate the options here now? The usage message should list the options from "struct options", which make these redundant.

Something like:
  git -upload-pack [options] <dir>
probably makes more sense.
Of course, it's hard to read the usage message because...
Show 7 quoted lines
> +	struct option options[] = {
> +		OPT_HIDDEN_BOOL(0, "stateless-rpc", &stateless_rpc, NULL),
> +		OPT_HIDDEN_BOOL(0, "advertise-refs", &advertise_refs, NULL),
> +		OPT_BOOL(0, "strict", &strict, NULL),
> +		OPT_INTEGER(0, "timeout", &timeout, NULL),
> +		OPT_END()
> +	};

You've left the description text for each of these options as NULL, so running "git-upload-pack -h" segfaults.

I'm not sure whether it is worth hiding the first two options. We typically hide "internal" options like this for user-facing programs, so as not to clutter the "-h" output. But upload-pack isn't a user-facing program. Anybody who is calling it directly with "-h" may be interested in even its more esoteric options.

Show 27 quoted lines
> -	for (i = 1; i < argc; i++) {
> -		char *arg = argv[i];
> -
> -		if (arg[0] != '-')
> -			break;
> -		if (!strcmp(arg, "--advertise-refs")) {
> -			advertise_refs = 1;
> -			continue;
> -		}
> -		if (!strcmp(arg, "--stateless-rpc")) {
> -			stateless_rpc = 1;
> -			continue;
> -		}
> -		if (!strcmp(arg, "--strict")) {
> -			strict = 1;
> -			continue;
> -		}
> -		if (starts_with(arg, "--timeout=")) {
> -			timeout = atoi(arg+10);
> -			daemon_mode = 1;
> -			continue;
> -		}
> -		if (!strcmp(arg, "--")) {
> -			i++;
> -			break;
> -		}
> -	}

A common pitfall in converting a for-loop to parse-options is when there is anything stateful in the parsing loop. But I don't see anything here. The trickiest thing is that --timeout implies daemon_mode. You've handled that below as:

> +	if (timeout != 0)
> +		daemon_mode = 1;

I think that is OK. It would not be correct if, for example, some other code set "timeout" to a non-zero value (e.g., a config option), but I don't see that here.

As a style nit, we usually spell comparison-with-zero as just:
  if (timeout)
	daemon_mode = 1;

Looking at at daemon_mode, though, it appears that it cannot be set in any other way except here. And it does nothing except to disable progress in some cases. Weird. There may be some opportunities for refactoring or simplification there, but I that is outside the scope of your patch.

> +	argc = parse_options(argc, (const char **)argv, NULL, options, upload_pack_usage, 0);

Perhaps this is a good opportunity to use "const" in the declaration of main(), as most other git programs do. Then you can drop this cast.

Show 7 quoted lines
>  	setup_path();
>  
> -	dir = argv[i];
> +	dir = argv[0];
>  
>  	if (!enter_repo(dir, strict))
>  		die("'%s' does not appear to be a git repository", dir);
Prior to your patch, we used to check:
  -       if (i != argc-1)
  -               usage(upload_pack_usage);

which ensured that "dir" was non-NULL. But with your patch, we may pass NULL to enter_repo. It fortunately catches this, but then we pass the NULL to die, which can segfault (though on glibc systems, stdio is kind enough to replace it with the "(null)").

Related, we silently accept extra arguments after your patch (whereas before we showed the usage message). You probably want to check "argc == 1", and otherwise show the usage message.

-Peff
Previous: Antoine QueruNext: Antoine Queru
Message 2 of 26 in “upload-pack.c: use of parse-options API”
  1. upload-pack.c: use of parse-options APIAntoine Queru, May 18, 2016
  2. Jeff KingMay 18, 2016
  3. Antoine QueruMay 19, 2016
  4. Jeff KingMay 19, 2016
  5. Matthieu MoyMay 19, 2016
  6. upload-pack.c: use of parse-options APIAntoine Queru, May 19, 2016
  7. Matthieu MoyMay 19, 2016
  8. Junio C HamanoMay 19, 2016
  9. Matthieu MoyMay 20, 2016
  10. Junio C HamanoMay 19, 2016
  11. Matthieu MoyMay 20, 2016
  12. Junio C HamanoMay 20, 2016
  13. upload-pack.c: use of parse-options APIAntoine Queru, May 23, 2016
  14. Matthieu MoyMay 23, 2016
  15. upload-pack.c: use of parse-options APIAntoine Queru, May 27, 2016
  16. Matthieu MoyMay 27, 2016
  17. Eric SunshineMay 27, 2016
  18. Antoine QueruMay 30, 2016
  19. upload-pack.c: use parse-options APIAntoine Queru, May 30, 2016
  20. Matthieu MoyMay 30, 2016
  21. Junio C HamanoMay 30, 2016
  22. Antoine QueruMay 31, 2016
  23. Matthieu MoyMay 31, 2016
  24. Junio C HamanoMay 31, 2016
  25. Antoine QueruJun 1, 2016
  26. upload-pack.c: use parse-options APIAntoine Queru, May 31, 2016

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.