Skip to content

Commit

Permalink
builtin/bugreport.c: create '--diagnose' option
Browse files Browse the repository at this point in the history
Create a '--diagnose' option for 'git bugreport' to collect additional
information about the repository and write it to a zipped archive.

The '--diagnose' option behaves effectively as an alias for simultaneously
running 'git bugreport' and 'git diagnose'. In the documentation, users are
explicitly recommended to attach the diagnostics alongside a bug report to
provide additional context to readers, ideally reducing some back-and-forth
between reporters and those debugging the issue.

Note that '--diagnose' may take an optional string arg (either 'stats' or
'all'). If specified without the arg, the behavior corresponds to running
'git diagnose' without '--mode'. As with 'git diagnose', this default is
intended to help reduce unintentional leaking of sensitive information).
Users can also explicitly specify '--diagnose=(stats|all)' to generate the
respective archive created by 'git diagnose --mode=(stats|all)'.

Suggested-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Helped-by: Derrick Stolee <derrickstolee@github.com>
Signed-off-by: Victoria Dye <vdye@github.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
vdye authored and gitster committed Aug 12, 2022
1 parent 7ecf193 commit aac0e8f
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 3 deletions.
18 changes: 18 additions & 0 deletions Documentation/git-bugreport.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ SYNOPSIS
--------
[verse]
'git bugreport' [(-o | --output-directory) <path>] [(-s | --suffix) <format>]
[--diagnose[=<mode>]]

DESCRIPTION
-----------
Expand All @@ -31,6 +32,10 @@ The following information is captured automatically:
- A list of enabled hooks
- $SHELL

Additional information may be gathered into a separate zip archive using the
`--diagnose` option, and can be attached alongside the bugreport document to
provide additional context to readers.

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
Expand All @@ -49,6 +54,19 @@ OPTIONS
named 'git-bugreport-<formatted suffix>'. This should take the form of a
strftime(3) format string; the current local time will be used.

--no-diagnose::
--diagnose[=<mode>]::
Create a zip archive of supplemental information about the user's
machine, Git client, and repository state. The archive is written to the
same output directory as the bug report and is named
'git-diagnostics-<formatted suffix>'.
+
Without `mode` specified, the diagnostic archive will contain the default set of
statistics reported by `git diagnose`. An optional `mode` value may be specified
to change which information is included in the archive. See
linkgit:git-diagnose[1] for the list of valid values for `mode` and details
about their usage.

GIT
---
Part of the linkgit:git[1] suite
27 changes: 24 additions & 3 deletions builtin/bugreport.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "compat/compiler.h"
#include "hook.h"
#include "hook-list.h"
#include "diagnose.h"


static void get_system_info(struct strbuf *sys_info)
Expand Down Expand Up @@ -59,7 +60,7 @@ static void get_populated_hooks(struct strbuf *hook_info, int nongit)
}

static const char * const bugreport_usage[] = {
N_("git bugreport [-o|--output-directory <file>] [-s|--suffix <format>]"),
N_("git bugreport [-o|--output-directory <file>] [-s|--suffix <format>] [--diagnose[=<mode>]"),
NULL
};

Expand Down Expand Up @@ -98,16 +99,21 @@ int cmd_bugreport(int argc, const char **argv, const char *prefix)
int report = -1;
time_t now = time(NULL);
struct tm tm;
enum diagnose_mode diagnose = DIAGNOSE_NONE;
char *option_output = NULL;
char *option_suffix = "%Y-%m-%d-%H%M";
const char *user_relative_path = NULL;
char *prefixed_filename;
size_t output_path_len;

const struct option bugreport_options[] = {
OPT_CALLBACK_F(0, "diagnose", &diagnose, N_("mode"),
N_("create an additional zip archive of detailed diagnostics (default 'stats')"),
PARSE_OPT_OPTARG, option_parse_diagnose),
OPT_STRING('o', "output-directory", &option_output, N_("path"),
N_("specify a destination for the bugreport file")),
N_("specify a destination for the bugreport file(s)")),
OPT_STRING('s', "suffix", &option_suffix, N_("format"),
N_("specify a strftime format suffix for the filename")),
N_("specify a strftime format suffix for the filename(s)")),
OPT_END()
};

Expand All @@ -119,6 +125,7 @@ int cmd_bugreport(int argc, const char **argv, const char *prefix)
option_output ? option_output : "");
strbuf_addstr(&report_path, prefixed_filename);
strbuf_complete(&report_path, '/');
output_path_len = report_path.len;

strbuf_addstr(&report_path, "git-bugreport-");
strbuf_addftime(&report_path, option_suffix, localtime_r(&now, &tm), 0, 0);
Expand All @@ -133,6 +140,20 @@ int cmd_bugreport(int argc, const char **argv, const char *prefix)
report_path.buf);
}

/* Prepare diagnostics, if requested */
if (diagnose != DIAGNOSE_NONE) {
struct strbuf zip_path = STRBUF_INIT;
strbuf_add(&zip_path, report_path.buf, output_path_len);
strbuf_addstr(&zip_path, "git-diagnostics-");
strbuf_addftime(&zip_path, option_suffix, localtime_r(&now, &tm), 0, 0);
strbuf_addstr(&zip_path, ".zip");

if (create_diagnostics_archive(&zip_path, diagnose))
die_errno(_("unable to create diagnostics archive %s"), zip_path.buf);

strbuf_release(&zip_path);
}

/* Prepare the report contents */
get_bug_template(&buffer);

Expand Down
48 changes: 48 additions & 0 deletions t/t0091-bugreport.sh
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,52 @@ test_expect_success 'indicates populated hooks' '
test_cmp expect actual
'

test_expect_success UNZIP '--diagnose creates diagnostics zip archive' '
test_when_finished rm -rf report &&
git bugreport --diagnose -o report -s test >out &&
zip_path=report/git-diagnostics-test.zip &&
grep "Available space" out &&
test_path_is_file "$zip_path" &&
# Check zipped archive content
"$GIT_UNZIP" -p "$zip_path" diagnostics.log >out &&
test_file_not_empty out &&
"$GIT_UNZIP" -p "$zip_path" packs-local.txt >out &&
grep ".git/objects" out &&
"$GIT_UNZIP" -p "$zip_path" objects-local.txt >out &&
grep "^Total: [0-9][0-9]*" out &&
# Should not include .git directory contents by default
! "$GIT_UNZIP" -l "$zip_path" | grep ".git/"
'

test_expect_success UNZIP '--diagnose=stats excludes .git dir contents' '
test_when_finished rm -rf report &&
git bugreport --diagnose=stats -o report -s test >out &&
# Includes pack quantity/size info
"$GIT_UNZIP" -p "$zip_path" packs-local.txt >out &&
grep ".git/objects" out &&
# Does not include .git directory contents
! "$GIT_UNZIP" -l "$zip_path" | grep ".git/"
'

test_expect_success UNZIP '--diagnose=all includes .git dir contents' '
test_when_finished rm -rf report &&
git bugreport --diagnose=all -o report -s test >out &&
# Includes .git directory contents
"$GIT_UNZIP" -l "$zip_path" | grep ".git/" &&
"$GIT_UNZIP" -p "$zip_path" .git/HEAD >out &&
test_file_not_empty out
'

test_done

0 comments on commit aac0e8f

Please sign in to comment.