Browse Source
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> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
Emily Shaffer
5 years ago
committed by
Junio C Hamano
8 changed files with 224 additions and 0 deletions
@ -0,0 +1,46 @@
@@ -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 |
@ -0,0 +1,105 @@
@@ -0,0 +1,105 @@
|
||||
#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; |
||||
int report = -1; |
||||
time_t now = time(NULL); |
||||
char *option_output = NULL; |
||||
char *option_suffix = "%Y-%m-%d-%H%M"; |
||||
int nongit_ok = 0; |
||||
const char *prefix = NULL; |
||||
const char *user_relative_path = NULL; |
||||
|
||||
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() |
||||
}; |
||||
|
||||
prefix = setup_git_directory_gently(&nongit_ok); |
||||
|
||||
argc = parse_options(argc, argv, prefix, bugreport_options, |
||||
bugreport_usage, 0); |
||||
|
||||
/* Prepare the path to put the result */ |
||||
strbuf_addstr(&report_path, |
||||
prefix_filename(prefix, |
||||
option_output ? 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"); |
||||
|
||||
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); |
||||
} |
||||
|
||||
/* Prepare the report contents */ |
||||
get_bug_template(&buffer); |
||||
|
||||
/* fopen doesn't offer us an O_EXCL alternative, except with glibc. */ |
||||
report = open(report_path.buf, O_CREAT | O_EXCL | O_WRONLY, 0666); |
||||
|
||||
if (report < 0) { |
||||
UNLEAK(report_path); |
||||
die(_("couldn't create a new file at '%s'"), report_path.buf); |
||||
} |
||||
|
||||
strbuf_write_fd(&buffer, report); |
||||
close(report); |
||||
|
||||
/* |
||||
* We want to print the path relative to the user, but we still need the |
||||
* path relative to us to give to the editor. |
||||
*/ |
||||
if (!(prefix && skip_prefix(report_path.buf, prefix, &user_relative_path))) |
||||
user_relative_path = report_path.buf; |
||||
fprintf(stderr, _("Created new report at '%s'.\n"), |
||||
user_relative_path); |
||||
|
||||
UNLEAK(buffer); |
||||
UNLEAK(report_path); |
||||
return !!launch_editor(report_path.buf, NULL, NULL); |
||||
} |
@ -0,0 +1,61 @@
@@ -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' ' |
||||
test_when_finished rm git-bugreport-check-headers.txt && |
||||
git bugreport -s check-headers && |
||||
check_all_headers_populated <git-bugreport-check-headers.txt |
||||
' |
||||
|
||||
test_expect_success 'dies if file with same name as report already exists' ' |
||||
test_when_finished rm git-bugreport-duplicate.txt && |
||||
>>git-bugreport-duplicate.txt && |
||||
test_must_fail git bugreport --suffix duplicate |
||||
' |
||||
|
||||
test_expect_success '--output-directory puts the report in the provided dir' ' |
||||
test_when_finished rm -fr foo/ && |
||||
git bugreport -o foo/ && |
||||
test_path_is_file foo/git-bugreport-* |
||||
' |
||||
|
||||
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' ' |
||||
test_when_finished rm non-repo/git-bugreport-* && |
||||
nongit git bugreport |
||||
' |
||||
|
||||
test_expect_success 'can create leading directories outside of a git dir' ' |
||||
test_when_finished rm -fr foo/bar/baz && |
||||
nongit git bugreport -o foo/bar/baz |
||||
' |
||||
|
||||
|
||||
test_done |
Loading…
Reference in new issue