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

[PATCH v8 03/15] bugreport: add tool to generate debugging info

From
Emily Shaffer <emilyshaffer@google.com>
Date
Feb 20, 2020, 01:58 UTC
Message-ID
<20200220015858.181086-4-emilyshaffer@google.com>
In-Reply-To
<20200220015858.181086-1-emilyshaffer@google.com>

Teach Git how to prompt the user for a good bug report: reproduction steps, expected behavior, and actual behavior. Later, Git can learn how to collect some diagnostic information from the repository.

If users can send us a well-written bug report which contains diagnostic information we would otherwise need to ask the user for, we can reduce the number of question-and-answer round trips between the reporter and the Git contributor.

Users may also wish to send a report like this to their local "Git expert" if they have put their repository into a state they are confused by.

Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
---
 .gitignore                      |  1 +
 Documentation/git-bugreport.txt | 46 ++++++++++++++++
 Makefile                        |  5 ++
 bugreport.c                     | 94 +++++++++++++++++++++++++++++++++
 command-list.txt                |  1 +
 t/t0091-bugreport.sh            | 61 +++++++++++++++++++++
 6 files changed, 208 insertions(+)
 create mode 100644 Documentation/git-bugreport.txt
 create mode 100644 bugreport.c
 create mode 100755 t/t0091-bugreport.sh
diff --git a/.gitignore b/.gitignore
index ea97de83f3..d89bf9e11e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,6 +25,7 @@
 /git-bisect--helper
 /git-blame
 /git-branch
+/git-bugreport
 /git-bundle
 /git-cat-file
 /git-check-attr
diff --git a/Documentation/git-bugreport.txt b/Documentation/git-bugreport.txt
new file mode 100644
index 0000000000..1f9fde5cde
--- /dev/null
+++ b/Documentation/git-bugreport.txt
@@ -0,0 +1,46 @@
+git-bugreport(1)
+================
+
+NAME
+----
+git-bugreport - Collect information for user to file a bug report
+
+SYNOPSIS
+--------
+[verse]
+'git bugreport' [(-o | --output-directory) <path>] [(-s | --suffix) <format>]
+
+DESCRIPTION
+-----------
+Captures information about the user's machine, Git client, and repository state,
+as well as a form requesting information about the behavior the user observed,
+into a single text file which the user can then share, for example to the Git
+mailing list, in order to report an observed bug.
+
+The following information is requested from the user:
+
+ - Reproduction steps
+ - Expected behavior
+ - Actual behavior
+
+This tool is invoked via the typical Git setup process, which means that in some
+cases, it might not be able to launch - for example, if a relevant config file
+is unreadable. In this kind of scenario, it may be helpful to manually gather
+the kind of information listed above when manually asking for help.
+
+OPTIONS
+-------
+-o <path>::
+--output-directory <path>::
+	Place the resulting bug report file in `<path>` instead of the root of
+	the Git repository.
+
+-s <format>::
+--suffix <format>::
+	Specify an alternate suffix for the bugreport name, to create a file
+	named 'git-bugreport-<formatted suffix>'. This should take the form of a
+	link:strftime[3] format string; the current local time will be used.
+
+GIT
+---
+Part of the linkgit:git[1] suite
diff --git a/Makefile b/Makefile
index c552312d3f..9e6705061d 100644
--- a/Makefile
+++ b/Makefile
@@ -681,6 +681,7 @@ EXTRA_PROGRAMS =
 # ... and all the rest that could be moved out of bindir to gitexecdir
 PROGRAMS += $(EXTRA_PROGRAMS)
 
+PROGRAM_OBJS += bugreport.o
 PROGRAM_OBJS += credential-store.o
 PROGRAM_OBJS += daemon.o
 PROGRAM_OBJS += fast-import.o
@@ -2461,6 +2462,10 @@ endif
 git-%$X: %.o GIT-LDFLAGS $(GITLIBS)
 	$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
 
+git-bugreport$X: bugreport.o GIT-LDFLAGS $(GITLIBS)
+	$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
+		$(LIBS)
+
 git-imap-send$X: imap-send.o $(IMAP_SEND_BUILDDEPS) GIT-LDFLAGS $(GITLIBS)
 	$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
 		$(IMAP_SEND_LDFLAGS) $(LIBS)
diff --git a/bugreport.c b/bugreport.c
new file mode 100644
index 0000000000..8d4a76fdac
--- /dev/null
+++ b/bugreport.c
@@ -0,0 +1,94 @@
+#include "builtin.h"
+#include "parse-options.h"
+#include "stdio.h"
+#include "strbuf.h"
+#include "time.h"
+
+static const char * const bugreport_usage[] = {
+	N_("git bugreport [-o|--output-directory <file>] [-s|--suffix <format>]"),
+	NULL
+};
+
+static int get_bug_template(struct strbuf *template)
+{
+	const char template_text[] = N_(
+"Thank you for filling out a Git bug report!\n"
+"Please answer the following questions to help us understand your issue.\n"
+"\n"
+"What did you do before the bug happened? (Steps to reproduce your issue)\n"
+"\n"
+"What did you expect to happen? (Expected behavior)\n"
+"\n"
+"What happened instead? (Actual behavior)\n"
+"\n"
+"What's different between what you expected and what actually happened?\n"
+"\n"
+"Anything else you want to add:\n"
+"\n"
+"Please review the rest of the bug report below.\n"
+"You can delete any lines you don't wish to share.\n");
+
+	strbuf_addstr(template, template_text);
+	return 0;
+}
+
+int cmd_main(int argc, const char **argv)
+{
+	struct strbuf buffer = STRBUF_INIT;
+	struct strbuf report_path = STRBUF_INIT;
+	FILE *report;
+	time_t now = time(NULL);
+	char *option_output = NULL;
+	char *option_suffix = "%F-%H%M";
+	struct stat statbuf;
+
+	const struct option bugreport_options[] = {
+		OPT_STRING('o', "output-directory", &option_output, N_("path"),
+			   N_("specify a destination for the bugreport file")),
+		OPT_STRING('s', "suffix", &option_suffix, N_("format"),
+			   N_("specify a strftime format suffix for the filename")),
+		OPT_END()
+	};
+	argc = parse_options(argc, argv, "", bugreport_options,
+			     bugreport_usage, 0);
+
+	if (option_output) {
+		strbuf_addstr(&report_path, option_output);
+		strbuf_complete(&report_path, '/');
+	}
+
+
+	strbuf_addstr(&report_path, "git-bugreport-");
+	strbuf_addftime(&report_path, option_suffix, localtime(&now), 0, 0);
+	strbuf_addstr(&report_path, ".txt");
+
+	if (!stat(report_path.buf, &statbuf))
+		die("'%s' already exists", report_path.buf);
+
+	switch (safe_create_leading_directories(report_path.buf)) {
+	case SCLD_OK:
+	case SCLD_EXISTS:
+		break;
+	default:
+		die(_("could not create leading directories for '%s'"),
+		    report_path.buf);
+	}
+
+	get_bug_template(&buffer);
+
+	report = fopen_for_writing(report_path.buf);
+
+	if (report == NULL) {
+		strbuf_release(&report_path);
+		die("couldn't open '%s' for writing", report_path.buf);
+	}
+
+	strbuf_write(&buffer, report);
+	fclose(report);
+
+	fprintf(stderr, _("Created new report at '%s'.\n"), report_path.buf);
+
+	UNLEAK(buffer);
+	UNLEAK(report_path);
+	return !!launch_editor(report_path.buf, NULL, NULL);
+}
diff --git a/command-list.txt b/command-list.txt
index 2087894655..185e5e3f05 100644
--- a/command-list.txt
+++ b/command-list.txt
@@ -54,6 +54,7 @@ git-archive                             mainporcelain
 git-bisect                              mainporcelain           info
 git-blame                               ancillaryinterrogators          complete
 git-branch                              mainporcelain           history
+git-bugreport                           ancillaryinterrogators
 git-bundle                              mainporcelain
 git-cat-file                            plumbinginterrogators
 git-check-attr                          purehelpers
diff --git a/t/t0091-bugreport.sh b/t/t0091-bugreport.sh
new file mode 100755
index 0000000000..65f664fdac
--- /dev/null
+++ b/t/t0091-bugreport.sh
@@ -0,0 +1,61 @@
+#!/bin/sh
+
+test_description='git bugreport'
+
+. ./test-lib.sh
+
+# Headers "[System Info]" will be followed by a non-empty line if we put some
+# information there; we can make sure all our headers were followed by some
+# information to check if the command was successful.
+HEADER_PATTERN="^\[.*\]$"
+
+check_all_headers_populated () {
+	while read -r line
+	do
+		if test "$(grep "$HEADER_PATTERN" "$line")"
+		then
+			echo "$line"
+			read -r nextline
+			if test -z "$nextline"; then
+				return 1;
+			fi
+		fi
+	done
+}
+
+test_expect_success 'creates a report with content in the right places' '
+	git bugreport -s check-headers &&
+	check_all_headers_populated <git-bugreport-check-headers.txt &&
+	test_when_finished rm git-bugreport-check-headers.txt
+'
+
+test_expect_success 'dies if file with same name as report already exists' '
+	>>git-bugreport-duplicate.txt &&
+	test_must_fail git bugreport --suffix duplicate &&
+	test_when_finished rm git-bugreport-duplicate.txt
+'
+
+test_expect_success '--output-directory puts the report in the provided dir' '
+	git bugreport -o foo/ &&
+	test_path_is_file foo/git-bugreport-* &&
+	test_when_finished rm -fr foo/
+'
+
+test_expect_success 'incorrect arguments abort with usage' '
+	test_must_fail git bugreport --false 2>output &&
+	test_i18ngrep usage output &&
+	test_path_is_missing git-bugreport-*
+'
+
+test_expect_success 'runs outside of a git dir' '
+	nongit git bugreport &&
+	test_when_finished rm non-repo/git-bugreport-*
+'
+
+test_expect_success 'can create leading directories outside of a git dir' '
+	nongit git bugreport -o foo/bar/baz &&
+	test_when_finished rm -fr foo/bar/baz
+'
+
+
+test_done
-- 
2.25.0.265.gbab2e86ba0-goog
Previous: Emily ShafferNext: Junio C Hamano
Message 6 of 87 in “add git-bugreport tool”
  1. 00/15 add git-bugreport toolEmily Shaffer, Feb 20, 2020
  2. 02/15 help: add shell-path to --build-optionsEmily Shaffer, Feb 20, 2020
  3. Junio C HamanoFeb 20, 2020
  4. Emily ShafferFeb 20, 2020
  5. 01/15 help: move list_config_help to builtin/helpEmily Shaffer, Feb 20, 2020
  6. 03/15 bugreport: add tool to generate debugging infoEmily Shaffer, Feb 20, 2020
  7. Junio C HamanoFeb 20, 2020
  8. Emily ShafferFeb 20, 2020
  9. Johannes SchindelinFeb 26, 2020
  10. 04/15 bugreport: gather git version and build infoEmily Shaffer, Feb 20, 2020
  11. Junio C HamanoFeb 20, 2020
  12. Emily ShafferFeb 20, 2020
  13. Junio C HamanoFeb 20, 2020
  14. 05/15 bugreport: add uname infoEmily Shaffer, Feb 20, 2020
  15. Junio C HamanoFeb 20, 2020
  16. Emily ShafferFeb 20, 2020
  17. 06/15 bugreport: add compiler infoEmily Shaffer, Feb 20, 2020
  18. Danh DoanFeb 20, 2020
  19. Emily ShafferFeb 20, 2020
  20. Junio C HamanoFeb 20, 2020
  21. Junio C HamanoFeb 21, 2020
  22. 07/15 bugreport: add git-remote-https versionEmily Shaffer, Feb 20, 2020
  23. Junio C HamanoFeb 20, 2020
  24. Emily ShafferFeb 20, 2020
  25. Junio C HamanoFeb 21, 2020
  26. Emily ShafferFeb 25, 2020
  27. Junio C HamanoFeb 25, 2020
  28. Emily ShafferFeb 25, 2020
  29. Junio C HamanoFeb 25, 2020
  30. Emily ShafferFeb 25, 2020
  31. 08/15 bugreport: include user interactive shellEmily Shaffer, Feb 20, 2020
  32. 09/15 bugreport: generate config safelist based on docsEmily Shaffer, Feb 20, 2020
  33. Junio C HamanoFeb 20, 2020
  34. Johannes SchindelinFeb 26, 2020
  35. Junio C HamanoFeb 26, 2020
  36. 10/15 bugreport: add config values from safelistEmily Shaffer, Feb 20, 2020
  37. Junio C HamanoFeb 20, 2020
  38. 11/15 bugreport: collect list of populated hooksEmily Shaffer, Feb 20, 2020
  39. Junio C HamanoFeb 20, 2020
  40. Emily ShafferFeb 25, 2020
  41. 12/15 bugreport: count loose objectsEmily Shaffer, Feb 20, 2020
  42. Junio C HamanoFeb 20, 2020
  43. Emily ShafferFeb 25, 2020
  44. Emily ShafferFeb 25, 2020
  45. 13/15 bugreport: add packed object summaryEmily Shaffer, Feb 20, 2020
  46. Junio C HamanoFeb 20, 2020
  47. Emily ShafferFeb 25, 2020
  48. 14/15 bugreport: list contents of $OBJDIR/infoEmily Shaffer, Feb 20, 2020
  49. Junio C HamanoFeb 20, 2020
  50. 15/15 bugreport: summarize contents of alternates fileEmily Shaffer, Feb 20, 2020
  51. Johannes SchindelinFeb 20, 2020
  52. Junio C HamanoFeb 20, 2020
  53. 0/5 add git-bugreport toolEmily Shaffer, Mar 2, 2020
  54. 1/5 help: move list_config_help to builtin/helpEmily Shaffer, Mar 2, 2020
  55. 2/5 bugreport: add tool to generate debugging infoEmily Shaffer, Mar 2, 2020
  56. Johannes SchindelinMar 3, 2020
  57. Johannes SchindelinMar 4, 2020
  58. Jeff HostetlerMar 5, 2020
  59. Johannes SchindelinMar 6, 2020
  60. Junio C HamanoMar 6, 2020
  61. Junio C HamanoMar 6, 2020
  62. Jeff HostetlerMar 6, 2020
  63. Johannes SchindelinMar 8, 2020
  64. Junio C HamanoMar 9, 2020
  65. Johannes SchindelinMar 9, 2020
  66. Junio C HamanoMar 9, 2020
  67. Johannes SchindelinMar 10, 2020
  68. Junio C HamanoMar 10, 2020
  69. Johannes SchindelinMar 10, 2020
  70. Emily ShafferMar 19, 2020
  71. Junio C HamanoMar 20, 2020
  72. Johannes SchindelinMar 20, 2020
  73. Emily ShafferMar 23, 2020
  74. Johannes SchindelinMar 20, 2020
  75. Emily ShafferMar 23, 2020
  76. Junio C HamanoMar 20, 2020
  77. Johannes SchindelinMar 20, 2020
  78. Junio C HamanoMar 20, 2020
  79. Johannes SchindelinMar 21, 2020
  80. 3/5 bugreport: gather git version and build infoEmily Shaffer, Mar 2, 2020
  81. Junio C HamanoMar 23, 2020
  82. 4/5 bugreport: add uname infoEmily Shaffer, Mar 2, 2020
  83. 5/5 bugreport: add compiler infoEmily Shaffer, Mar 2, 2020
  84. Danh DoanMar 3, 2020
  85. Junio C HamanoMar 3, 2020
  86. Johannes SchindelinMar 4, 2020
  87. Emily ShafferMar 23, 2020

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.