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

[PATCH v2 2/4] run_builtin(): save "-h" detection result for later use

From
Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Date
Oct 20, 2010, 03:11 UTC
Message-ID
<1287544320-8499-2-git-send-email-pclouds@gmail.com>
In-Reply-To
<1287544320-8499-1-git-send-email-pclouds@gmail.com>
When run_builtin() sees "-h" as the first argument, it assumes:
 - this is the call for help usage
 - the real git command will only print help usage then exit

So it skips all setup in this case. Unfortunately, some commands do other things before calling parse_options(), which is often where the help usage is printed. Some of those things may try to access the repository unnecessarily. If a repository is broken, the command may die() before it prints help usage, not really helpful.

Make real commands aware of this fast path so that they can handle it properly (i.e., print help usage then exit immediately) if they were going to do more initialization than git_config().

Demonstrating "git foo -h" fails depends on individual commands and is generally difficult to do. Instead GIT_TRACE is used to check if a command does set repo. If it does, it is supposed to fail if repo setup code chokes.

"git upload-archive" fails for another reason, but will be fixed too when "git upload-archive -h" is converted to use startup_info->help

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 cache.h         |    1 +
 git.c           |   18 ++++++++++++++----
 t/t3905-help.sh |   24 ++++++++++++++++++++++++
 3 files changed, 39 insertions(+), 4 deletions(-)
 create mode 100755 t/t3905-help.sh
diff --git a/cache.h b/cache.h
index 33decd9..bb57e34 100644
--- a/cache.h
+++ b/cache.h
@@ -1117,6 +1117,7 @@ const char *split_cmdline_strerror(int cmdline_errno);
 /* git.c */
 struct startup_info {
 	int have_repository;
+	int help; /* git foo -h */
 };
 extern struct startup_info *startup_info;
 
diff --git a/git.c b/git.c
index 50a1401..bb67540 100644
--- a/git.c
+++ b/git.c
@@ -246,13 +246,23 @@ struct cmd_struct {
 
 static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
 {
-	int status, help;
+	int status;
 	struct stat st;
 	const char *prefix;
 
 	prefix = NULL;
-	help = argc == 2 && !strcmp(argv[1], "-h");
-	if (!help) {
+	startup_info->help = argc == 2 && !strcmp(argv[1], "-h");
+	if (startup_info->help) {
+		/*
+		 * Fast path for "git foo -h", no setup is done.
+		 * Other functions might set .git up automatically
+		 * and potentially die() along the way. It's best
+		 * to check this flag from the beginning, print its
+		 * help usage and exit, nothing more.
+		 */
+		;
+	}
+	else {
 		if (p->option & RUN_SETUP)
 			prefix = setup_git_directory();
 		if (p->option & RUN_SETUP_GENTLY) {
@@ -267,7 +277,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
 	}
 	commit_pager_choice();
 
-	if (!help && p->option & NEED_WORK_TREE)
+	if (!startup_info->help && p->option & NEED_WORK_TREE)
 		setup_work_tree();
 
 	trace_argv_printf(argv, "trace: built-in: git");
diff --git a/t/t3905-help.sh b/t/t3905-help.sh
new file mode 100755
index 0000000..0dcbedf
--- /dev/null
+++ b/t/t3905-help.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+test_description='tests that git foo -h should work even in potentially broken repos'
+
+. ./test-lib.sh
+
+test_help() {
+	test_expect_"$1" "$2 -h" "
+		GIT_TRACE=\"`pwd`\"/$2.log test_must_fail git $2 -h &&
+		test \$exit_code = 129 &&
+		! grep 'defaults to' $2.log
+	"
+}
+
+test_help failure branch
+test_help failure checkout-index
+test_help failure commit
+test_help failure gc
+test_help failure ls-files
+test_help failure merge
+test_help failure update-index
+test_help failure upload-archive
+
+test_done
-- 
1.7.0.2.445.gcbdb3
Previous: Nguyễn Thái Ngọc DuyNext: Junio C Hamano
Message 2 of 45 in “setup_git_env: print the true $GIT_DIR for debugging”
  1. 1/4 setup_git_env: print the true $GIT_DIR for debuggingNguyễn Thái Ngọc Duy, Oct 20, 2010
  2. 2/4 run_builtin(): save "-h" detection result for later useNguyễn Thái Ngọc Duy, Oct 20, 2010
  3. Junio C HamanoOct 21, 2010
  4. Nguyen Thai Ngoc DuyOct 22, 2010
  5. 3/4 builtins: utilize startup_info->help where possibleNguyễn Thái Ngọc Duy, Oct 20, 2010
  6. 4/4 builtins: check for startup_info->help, print and exit earlyNguyễn Thái Ngọc Duy, Oct 20, 2010
  7. 0/7 Jonathan Nieder, Oct 22, 2010
  8. 1/7 branch -h: show usage even in an invalid repositoryJonathan Nieder, Oct 22, 2010
  9. Junio C HamanoOct 22, 2010
  10. Jonathan NiederOct 24, 2010
  11. 0/4 update-index: migrate to parse-options APIJonathan Nieder, Oct 24, 2010
  12. 1/4 parse-options: allow git commands to invent new option typesJonathan Nieder, Oct 24, 2010
  13. Stephen BoydOct 25, 2010
  14. Jonathan NiederNov 29, 2010
  15. 2/4 parse-options: make resuming easier after PARSE_OPT_STOP_AT_NON_OPTIONJonathan Nieder, Oct 24, 2010
  16. 3/4 setup: save prefix (original cwd relative to toplevel) in startup_infoJonathan Nieder, Oct 24, 2010
  17. 4/4 update-index: migrate to parse-options APIJonathan Nieder, Oct 24, 2010
  18. Stephen BoydOct 25, 2010
  19. Jonathan NiederNov 30, 2010
  20. Nguyen Thai Ngoc DuyOct 24, 2010
  21. Junio C HamanoOct 27, 2010
  22. 0/6 update-index: migrate to parse-options APIJonathan Nieder, Nov 30, 2010
  23. 1/6 parse-options: sanity check PARSE_OPT_NOARG flagJonathan Nieder, Nov 30, 2010
  24. Stephen BoydNov 30, 2010
  25. Junio C HamanoDec 1, 2010
  26. Stephen BoydDec 3, 2010
  27. Junio C HamanoDec 1, 2010
  28. 2/6 parse-options: do not infer PARSE_OPT_NOARG from option typeJonathan Nieder, Nov 30, 2010
  29. Stephen BoydNov 30, 2010
  30. 3/6 parse-options: allow git commands to invent new option typesJonathan Nieder, Nov 30, 2010
  31. 4/6 parse-options: make resuming easier after PARSE_OPT_STOP_AT_NON_OPTIONJonathan Nieder, Nov 30, 2010
  32. 5/6 setup: save prefix (original cwd relative to toplevel) in startup_infoJonathan Nieder, Nov 30, 2010
  33. 6/6 update-index: migrate to parse-options APIJonathan Nieder, Nov 30, 2010
  34. Stephen BoydNov 30, 2010
  35. parse-options: always show arghelp when LITERAL_ARGHELP is setJonathan Nieder, Nov 30, 2010
  36. 2/7 checkout-index -h: show usage even in an invalid repositoryJonathan Nieder, Oct 22, 2010
  37. 3/7 commit/status -h: show usage even with broken configurationJonathan Nieder, Oct 22, 2010
  38. 4/7 gc -h: show usage even with broken configurationJonathan Nieder, Oct 22, 2010
  39. 5/7 ls-files -h: show usage even with corrupt indexJonathan Nieder, Oct 22, 2010
  40. Junio C HamanoOct 22, 2010
  41. 6/7 merge -h: show usage even with corrupt indexJonathan Nieder, Oct 22, 2010
  42. Junio C HamanoOct 22, 2010
  43. 7/7 update-index -h: show usage even with corrupt indexJonathan Nieder, Oct 22, 2010
  44. 0/7 avoid repository access during "git <foo> -h"Jonathan Nieder, Oct 22, 2010
  45. Nguyen Thai Ngoc DuyOct 22, 2010

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.