{"thread":{"id":"45942","subject":"Re: [Git 2.13.0] BUG: setup_git_env called without repository","startedAt":"2017-05-12T18:44:22Z","lastAt":"2018-05-07T09:08:11Z","messageCount":25,"participants":["Johannes Schindelin","Josh Hagins","Jeff King","Ævar Arnfjörð Bjarmason","Jonathan Nieder","Junio C Hamano","Duy Nguyen"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"319496","messageId":"alpine.DEB.2.21.1.1705121643180.146734@virtualbox","threadId":"45942","inReplyTo":"CANuW5x0pBwfQeha50mxN8pVQKm67u_b3UKTCQ8ZbJA6FUGvYbw@mail.gmail.com","subject":"Re: [Git 2.13.0] BUG: setup_git_env called without repository","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2017-05-12T14:48:52Z","receivedAt":"2017-05-12T18:44:22Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Josh,\n\nOn Fri, 12 May 2017, Josh Hagins wrote:\n\n> Since upgrading to Git 2.13.0 I'm seeing this error message whenever\n> `git config --local <whatever>` is called outside a Git repository.\n> For example, note the difference in behavior between Git 2.13 and\n> Apple Git:\n> \n>     $ pwd\n>     /Users/jhagins\n>     $ /usr/bin/git --version\n>     git version 2.11.0 (Apple Git-81)\n>     $ /usr/bin/git config --local --get user.name\n>     $ /usr/local/bin/git --version\n>     git version 2.13.0\n>     $ /usr/local/bin/git config --local --get user.name\n>     fatal: BUG: setup_git_env called without repository\n> \n> Apple Git outputs nothing, as expected. The summarized release notes\n> published by GitHub specifically mentioned that instances of this\n> error message should be reported, so here you go!\n> \n> Please let me know if I can provide any more information that would be\n> helpful.\n\nSince this is in /usr/local/bin/, there are two possibilities:\n\n1) you built and installed it yourself (but then it would be more likely\n   in your $HOME/bin), or\n\n2) you installed it via HomeBrew.\n\nI guess it is the latter.\n\nIn both cases, however, you have XCode installed, so you can dig further.\nYay.\n\nThe thing I would do in your case would be to clone Git:\n\n\tgit clone https://github.com/git/git\n\nthen check out v2.13.0:\n\n\tgit checkout v2.13.0\n\nthen edit the Makefile to remove the -O2 from the CFLAGS (the next step is\nto use the GNU debugger, and in my hands the -O2 optimization made that\npretty useless), and then build with\n\n\tmake\n\nAfter that, you should be able to start the command in your local GNU\ndebugger:\n\n\tgdb -args ./git config --local --get user.name\n\nYou will then want to set a breakpoint on the die_builtin() function:\n\n\tb die_builtin\n\nNow run it with the `r` command, and it should stop in the die_builtin\nroutine, in which case a backtrace would be most helpful to figure out\nwhat is going wrong:\n\n\tbt\n\nIf the output is not enlightening on its own, it would be nice to paste it\ninto a reply to this mail so that the entire Git developer community can\nhave a look.\n\nCiao,\nJohannes\n"},{"id":"319552","messageId":"CANuW5x0pBwfQeha50mxN8pVQKm67u_b3UKTCQ8ZbJA6FUGvYbw@mail.gmail.com","threadId":"45942","inReplyTo":null,"subject":"[Git 2.13.0] BUG: setup_git_env called without repository","fromName":"Josh Hagins","fromEmail":"hagins.josh@gmail.com","sentAt":"2017-05-12T14:19:59Z","receivedAt":"2017-05-12T18:46:07Z","isPatch":false,"sender":{"key":"hagins.josh@gmail.com","avatar":null},"body":"Hey Git people,\n\nSince upgrading to Git 2.13.0 I'm seeing this error message whenever\n`git config --local <whatever>` is called outside a Git repository.\nFor example, note the difference in behavior between Git 2.13 and\nApple Git:\n\n    $ pwd\n    /Users/jhagins\n    $ /usr/bin/git --version\n    git version 2.11.0 (Apple Git-81)\n    $ /usr/bin/git config --local --get user.name\n    $ /usr/local/bin/git --version\n    git version 2.13.0\n    $ /usr/local/bin/git config --local --get user.name\n    fatal: BUG: setup_git_env called without repository\n\nApple Git outputs nothing, as expected. The summarized release notes\npublished by GitHub specifically mentioned that instances of this\nerror message should be reported, so here you go!\n\nPlease let me know if I can provide any more information that would be helpful.\n\nCheers!\n\n-- \nJosh Hagins\n"},{"id":"319562","messageId":"20170512203436.fcoqauphzvox2sgv@sigill.intra.peff.net","threadId":"45942","inReplyTo":"CANuW5x0pBwfQeha50mxN8pVQKm67u_b3UKTCQ8ZbJA6FUGvYbw@mail.gmail.com","subject":"[PATCH] config: complain about --local outside of a git repo","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2017-05-12T20:34:36Z","receivedAt":"2017-05-12T20:34:47Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, May 12, 2017 at 10:19:59AM -0400, Josh Hagins wrote:\n\n> Since upgrading to Git 2.13.0 I'm seeing this error message whenever\n> `git config --local <whatever>` is called outside a Git repository.\n> For example, note the difference in behavior between Git 2.13 and\n> Apple Git:\n> \n>     $ pwd\n>     /Users/jhagins\n>     $ /usr/bin/git --version\n>     git version 2.11.0 (Apple Git-81)\n>     $ /usr/bin/git config --local --get user.name\n>     $ /usr/local/bin/git --version\n>     git version 2.13.0\n>     $ /usr/local/bin/git config --local --get user.name\n>     fatal: BUG: setup_git_env called without repository\n> \n> Apple Git outputs nothing, as expected. The summarized release notes\n> published by GitHub specifically mentioned that instances of this\n> error message should be reported, so here you go!\n\nThanks for reporting. All the developers have been running with this\nchange for months, but I knew as soon as it was released into the wild\nthat somebody would find a new corner case. :)\n\nI think dying is the right thing here; you are asking for \"--local\" but\nthere is no local repository. But we should never hit a BUG assertion.\nPatch is below.\n\nI'm not sure exactly what you wanted to accomplish with --local. If you\njust want to know if user.name is set anywhere (and you may or may not\nbe in a git repo), then just \"git config --get user.name\" would work. If\nyou want to know if you're in a local repo and if so whether the\nvariable is set, you'd need to use two commands, like:\n\n  git rev-parse --git-dir >/dev/null 2>&1 &&\n  git config --local --get user.name\n\n-- >8 --\nSubject: [PATCH] config: complain about --local outside of a git repo\n\nThe \"--local\" option instructs git-config to read or modify\nthe repository-level config. This doesn't make any sense if\nyou're not actually in a repository.\n\nOlder versions of Git would blindly try to read or write\n\".git/config\". For reading, this would result in a quiet\nfailure, since there was no config to read (and thus no\nmatching config value). Writing would generally fail\nnoisily, since \".git\" was unlikely to exist. But since\nb1ef400ee (setup_git_env: avoid blind fall-back to \".git\",\n2016-10-20), we catch this in the call to git_pathdup() and\ndie(\"BUG\").\n\nDying is the right thing to do, but we should catch the\nproblem early and give a more human-friendly error message.\n\nNote that even without --local, git-config will sometimes\ndefault to using local repository config. These cases are\nalready protected by a similar check.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\n builtin/config.c | 3 +++\n 1 file changed, 3 insertions(+)\n\ndiff --git a/builtin/config.c b/builtin/config.c\nindex 3a554ad50..ad7c6a19c 100644\n--- a/builtin/config.c\n+++ b/builtin/config.c\n@@ -496,6 +496,9 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\tusage_with_options(builtin_config_usage, builtin_config_options);\n \t}\n \n+\tif (use_local_config && nongit)\n+\t\tdie(_(\"--local only be used inside a git repository\"));\n+\n \tif (given_config_source.file &&\n \t\t\t!strcmp(given_config_source.file, \"-\")) {\n \t\tgiven_config_source.file = NULL;\n-- \n2.13.0.452.g0afc8e12b\n\n"},{"id":"319576","messageId":"CACBZZX5rasExB9jN0RmZ9zcSTbc9qOEZ2VoqRFt8C09vW9mkfQ@mail.gmail.com","threadId":"45942","inReplyTo":"20170512203436.fcoqauphzvox2sgv@sigill.intra.peff.net","subject":"Re: [PATCH] config: complain about --local outside of a git repo","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2017-05-12T22:31:31Z","receivedAt":"2017-05-12T22:31:57Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"On Fri, May 12, 2017 at 10:34 PM, Jeff King <peff@peff.net> wrote:\n> On Fri, May 12, 2017 at 10:19:59AM -0400, Josh Hagins wrote:\n>\n>> Since upgrading to Git 2.13.0 I'm seeing this error message whenever\n>> `git config --local <whatever>` is called outside a Git repository.\n>> For example, note the difference in behavior between Git 2.13 and\n>> Apple Git:\n>>\n>>     $ pwd\n>>     /Users/jhagins\n>>     $ /usr/bin/git --version\n>>     git version 2.11.0 (Apple Git-81)\n>>     $ /usr/bin/git config --local --get user.name\n>>     $ /usr/local/bin/git --version\n>>     git version 2.13.0\n>>     $ /usr/local/bin/git config --local --get user.name\n>>     fatal: BUG: setup_git_env called without repository\n>>\n>> Apple Git outputs nothing, as expected. The summarized release notes\n>> published by GitHub specifically mentioned that instances of this\n>> error message should be reported, so here you go!\n>\n> Thanks for reporting. All the developers have been running with this\n> change for months, but I knew as soon as it was released into the wild\n> that somebody would find a new corner case. :)\n>\n> I think dying is the right thing here; you are asking for \"--local\" but\n> there is no local repository. But we should never hit a BUG assertion.\n> Patch is below.\n>\n> I'm not sure exactly what you wanted to accomplish with --local. If you\n> just want to know if user.name is set anywhere (and you may or may not\n> be in a git repo), then just \"git config --get user.name\" would work. If\n> you want to know if you're in a local repo and if so whether the\n> variable is set, you'd need to use two commands, like:\n>\n>   git rev-parse --git-dir >/dev/null 2>&1 &&\n>   git config --local --get user.name\n>\n> -- >8 --\n> Subject: [PATCH] config: complain about --local outside of a git repo\n>\n> The \"--local\" option instructs git-config to read or modify\n> the repository-level config. This doesn't make any sense if\n> you're not actually in a repository.\n>\n> Older versions of Git would blindly try to read or write\n> \".git/config\". For reading, this would result in a quiet\n> failure, since there was no config to read (and thus no\n> matching config value). Writing would generally fail\n> noisily, since \".git\" was unlikely to exist. But since\n> b1ef400ee (setup_git_env: avoid blind fall-back to \".git\",\n> 2016-10-20), we catch this in the call to git_pathdup() and\n> die(\"BUG\").\n>\n> Dying is the right thing to do, but we should catch the\n> problem early and give a more human-friendly error message.\n>\n> Note that even without --local, git-config will sometimes\n> default to using local repository config. These cases are\n> already protected by a similar check.\n>\n> Signed-off-by: Jeff King <peff@peff.net>\n> ---\n>  builtin/config.c | 3 +++\n>  1 file changed, 3 insertions(+)\n>\n> diff --git a/builtin/config.c b/builtin/config.c\n> index 3a554ad50..ad7c6a19c 100644\n> --- a/builtin/config.c\n> +++ b/builtin/config.c\n> @@ -496,6 +496,9 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n>                 usage_with_options(builtin_config_usage, builtin_config_options);\n>         }\n>\n> +       if (use_local_config && nongit)\n> +               die(_(\"--local only be used inside a git repository\"));\n> +\n>         if (given_config_source.file &&\n>                         !strcmp(given_config_source.file, \"-\")) {\n>                 given_config_source.file = NULL;\n> --\n> 2.13.0.452.g0afc8e12b\n\nIt would be better to have a test for edge cases that are currently\nonly being discovered by users in the wild.\n"},{"id":"319586","messageId":"20170513000442.GH27400@aiede.svl.corp.google.com","threadId":"45942","inReplyTo":"20170512203436.fcoqauphzvox2sgv@sigill.intra.peff.net","subject":"Re: [PATCH] config: complain about --local outside of a git repo","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2017-05-13T00:04:42Z","receivedAt":"2017-05-13T00:04:49Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Jeff King wrote:\n\n> Subject: [PATCH] config: complain about --local outside of a git repo\n>\n> The \"--local\" option instructs git-config to read or modify\n> the repository-level config. This doesn't make any sense if\n> you're not actually in a repository.\n>\n> Older versions of Git would blindly try to read or write\n> \".git/config\". For reading, this would result in a quiet\n> failure, since there was no config to read (and thus no\n> matching config value). Writing would generally fail\n> noisily, since \".git\" was unlikely to exist. But since\n> b1ef400ee (setup_git_env: avoid blind fall-back to \".git\",\n> 2016-10-20), we catch this in the call to git_pathdup() and\n> die(\"BUG\").\n>\n> Dying is the right thing to do, but we should catch the\n> problem early and give a more human-friendly error message.\n>\n> Note that even without --local, git-config will sometimes\n> default to using local repository config. These cases are\n> already protected by a similar check.\n>\n> Signed-off-by: Jeff King <peff@peff.net>\n> ---\n>  builtin/config.c | 3 +++\n>  1 file changed, 3 insertions(+)\n\nMakes sense.\n\n> diff --git a/builtin/config.c b/builtin/config.c\n> index 3a554ad50..ad7c6a19c 100644\n> --- a/builtin/config.c\n> +++ b/builtin/config.c\n> @@ -496,6 +496,9 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n>  \t\tusage_with_options(builtin_config_usage, builtin_config_options);\n>  \t}\n> \n> +\tif (use_local_config && nongit)\n> +\t\tdie(_(\"--local only be used inside a git repository\"));\n> +\n\nThe output would be\n\n\tfatal: --local only be used inside a git repository\n\nIs that missing a \"should\" before \"only\"?\n\nWith that change,\nReviewed-by: Jonathan Nieder <jrnieder@gmail.com>\n"},{"id":"319589","messageId":"20170513020346.25ijajgtwffh7g4b@sigill.intra.peff.net","threadId":"45942","inReplyTo":"CACBZZX5rasExB9jN0RmZ9zcSTbc9qOEZ2VoqRFt8C09vW9mkfQ@mail.gmail.com","subject":"Re: [PATCH] config: complain about --local outside of a git repo","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2017-05-13T02:03:46Z","receivedAt":"2017-05-13T02:03:55Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, May 13, 2017 at 12:31:31AM +0200, Ævar Arnfjörð Bjarmason wrote:\n\n> > +       if (use_local_config && nongit)\n> > +               die(_(\"--local only be used inside a git repository\"));\n> > +\n> \n> It would be better to have a test for edge cases that are currently\n> only being discovered by users in the wild.\n\nI actually started on one earlier, but what would it check? We already\ndie() in this case. Should we be grepping for the message? It seems more\nlikely to me that we would change the message and cause a false positive\nthan that there would be an actual regression.\n\nWhat I think might be more interesting is if die(\"BUG\") could learn to\nexit with some error code that the test suite considered invalid. Like\ncalling abort(), which would kill us with SIGABRT and cause\ntest_must_fail to complain.\n\nOn many systems that would also generate a coredump. Which is handy\nsometimes, but I wonder if it would be inconvenient for others. I guess\nthat is no different than what a raised assert() would do.\n\nBut if we were to do that, then the test could easily demonstrate that\nwe expect a clean die().\n\n-Peff\n"},{"id":"319590","messageId":"20170513020409.kyqglojregge44mt@sigill.intra.peff.net","threadId":"45942","inReplyTo":"20170513000442.GH27400@aiede.svl.corp.google.com","subject":"Re: [PATCH] config: complain about --local outside of a git repo","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2017-05-13T02:04:10Z","receivedAt":"2017-05-13T02:04:17Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, May 12, 2017 at 05:04:42PM -0700, Jonathan Nieder wrote:\n\n> > diff --git a/builtin/config.c b/builtin/config.c\n> > index 3a554ad50..ad7c6a19c 100644\n> > --- a/builtin/config.c\n> > +++ b/builtin/config.c\n> > @@ -496,6 +496,9 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n> >  \t\tusage_with_options(builtin_config_usage, builtin_config_options);\n> >  \t}\n> > \n> > +\tif (use_local_config && nongit)\n> > +\t\tdie(_(\"--local only be used inside a git repository\"));\n> > +\n> \n> The output would be\n> \n> \tfatal: --local only be used inside a git repository\n> \n> Is that missing a \"should\" before \"only\"?\n\nUrgh, I meant \"can\" (I had originally written \"only makes sense\" but\nchanged it at the list minute).\n\nI'll re-roll after thinking about the test issues raised in the other\npart of the thread.\n\n-Peff\n"},{"id":"319593","messageId":"20170513032414.mfrwabt4hovujde2@sigill.intra.peff.net","threadId":"45942","inReplyTo":"20170513020346.25ijajgtwffh7g4b@sigill.intra.peff.net","subject":"[PATCH 0/3] BUG() and \"config --local\" outside of repo","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2017-05-13T03:24:14Z","receivedAt":"2017-05-13T03:24:24Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, May 12, 2017 at 10:03:46PM -0400, Jeff King wrote:\n\n> On Sat, May 13, 2017 at 12:31:31AM +0200, Ævar Arnfjörð Bjarmason wrote:\n> \n> > > +       if (use_local_config && nongit)\n> > > +               die(_(\"--local only be used inside a git repository\"));\n> > > +\n> > \n> > It would be better to have a test for edge cases that are currently\n> > only being discovered by users in the wild.\n> \n> I actually started on one earlier, but what would it check? We already\n> die() in this case. Should we be grepping for the message? It seems more\n> likely to me that we would change the message and cause a false positive\n> than that there would be an actual regression.\n> \n> What I think might be more interesting is if die(\"BUG\") could learn to\n> exit with some error code that the test suite considered invalid. Like\n> calling abort(), which would kill us with SIGABRT and cause\n> test_must_fail to complain.\n> \n> On many systems that would also generate a coredump. Which is handy\n> sometimes, but I wonder if it would be inconvenient for others. I guess\n> that is no different than what a raised assert() would do.\n> \n> But if we were to do that, then the test could easily demonstrate that\n> we expect a clean die().\n\nSo here's a series which does that (and fixes the gramm-o that Jonathan\npointed out). The SIGABRT/coredump thing may seem like overkill, but\nit's actually something I've found useful before (while developing this\nvery same setup_git_env assertion, in fact).\n\n  [1/3]: usage.c: add BUG() function\n  [2/3]: setup_git_env: convert die(\"BUG\") to BUG()\n  [3/3]: config: complain about --local outside of a git repo\n\n builtin/config.c       |  3 +++\n environment.c          |  2 +-\n git-compat-util.h      |  9 +++++++++\n t/t1300-repo-config.sh |  6 ++++++\n usage.c                | 32 ++++++++++++++++++++++++++++++++\n 5 files changed, 51 insertions(+), 1 deletion(-)\n"},{"id":"319594","messageId":"20170513032850.zeru4cm2l7i23rkc@sigill.intra.peff.net","threadId":"45942","inReplyTo":"20170513032414.mfrwabt4hovujde2@sigill.intra.peff.net","subject":"[PATCH 1/3] usage.c: add BUG() function","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2017-05-13T03:28:50Z","receivedAt":"2017-05-13T03:28:58Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"There's a convention in Git's code base to write assertions\nas:\n\n  if (...some_bad_thing...)\n\tdie(\"BUG: the terrible thing happened\");\n\nwith the idea that users should never see a \"BUG:\" message\n(but if they, it at least gives a clue what happened).  We\nuse die() here because it's convenient, but there are a few\ndraw-backs:\n\n  1. Without parsing the messages, it's hard for callers to\n     distinguish BUG assertions from regular errors.\n\n     For instance, it would be nice if the test suite could\n     check that we don't hit any assertions, but\n     test_must_fail will pass BUG deaths as OK.\n\n  2. It would be useful to add more debugging features to\n     BUG assertions, like file/line numbers or dumping core.\n\n  3. The die() handler can be replaced, and might not\n     actually exit the whole program (e.g., it may just\n     pthread_exit()). This is convenient for normal errors,\n     but for an assertion failure (which is supposed to\n     never happen), we're probably better off taking down\n     the whole process as quickly and cleanly as possible.\n\nWe could address these by checking in die() whether the\nerror message starts with \"BUG\", and behaving appropriately.\nBut there's little advantage at that point to sharing the\ndie() code, and only downsides (e.g., we can't change the\nBUG() interface independently). Moreover, converting all of\nthe existing BUG calls reveals that the test suite does\nindeed trigger a few of them.\n\nInstead, this patch introduces a new BUG() function, which\nprints an error before dying via SIGABRT. This gives us test\nsuite checking and core dumps.  The function is actually a\nmacro (when supported) so that we can show the file/line\nnumber.\n\nWe can convert die(\"BUG\") invocations to BUG() in further\npatches, dealing with any test fallouts individually.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nI actually don't care that much about the file/line thing\npersonally. The messages are generally unique, which lets\nyou find them in the code base easily. And it does introduce\na lot of complexity due to the variadic macro fallback. So\nwe could just drop it and have a much simpler patch\n(basically just die() without the abstracted handler, and\nwith abort() instead of exit()).\n\n git-compat-util.h |  9 +++++++++\n usage.c           | 32 ++++++++++++++++++++++++++++++++\n 2 files changed, 41 insertions(+)\n\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex bd04564a6..4575b3890 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -1064,6 +1064,15 @@ static inline int regexec_buf(const regex_t *preg, const char *buf, size_t size,\n #define HAVE_VARIADIC_MACROS 1\n #endif\n \n+#ifdef HAVE_VARIADIC_MACROS\n+__attribute__((format (printf, 3, 4))) NORETURN\n+void BUG_fl(const char *file, int line, const char *fmt, ...);\n+#define BUG(...) BUG_fl(__FILE__, __LINE__, __VA_ARGS__)\n+#else\n+__attribute__((format (printf, 1, 2))) NORETURN\n+void BUG(const char *fmt, ...);\n+#endif\n+\n /*\n  * Preserves errno, prints a message, but gives no warning for ENOENT.\n  * Returns 0 on success, which includes trying to unlink an object that does\ndiff --git a/usage.c b/usage.c\nindex ad6d2910f..7e6cb2028 100644\n--- a/usage.c\n+++ b/usage.c\n@@ -201,3 +201,35 @@ void warning(const char *warn, ...)\n \twarn_routine(warn, params);\n \tva_end(params);\n }\n+\n+static NORETURN void BUG_vfl(const char *file, int line, const char *fmt, va_list params)\n+{\n+\tchar prefix[256];\n+\n+\t/* truncation via snprintf is OK here */\n+\tif (file)\n+\t\tsnprintf(prefix, sizeof(prefix), \"BUG: %s:%d: \", file, line);\n+\telse\n+\t\tsnprintf(prefix, sizeof(prefix), \"BUG: \");\n+\n+\tvreportf(prefix, fmt, params);\n+\tabort();\n+}\n+\n+#ifdef HAVE_VARIADIC_MACROS\n+void BUG_fl(const char *file, int line, const char *fmt, ...)\n+{\n+\tva_list ap;\n+\tva_start(ap, fmt);\n+\tBUG_vfl(file, line, fmt, ap);\n+\tva_end(ap);\n+}\n+#else\n+void BUG(const char *fmt, ...)\n+{\n+\tva_list ap;\n+\tva_start(ap, fmt);\n+\tBUG_vfl(NULL, 0, fmt, ap);\n+\tva_end(ap);\n+}\n+#endif\n-- \n2.13.0.452.g0afc8e12b\n\n"},{"id":"319595","messageId":"20170513032918.cisxuwoi6lvswetg@sigill.intra.peff.net","threadId":"45942","inReplyTo":"20170513032414.mfrwabt4hovujde2@sigill.intra.peff.net","subject":"[PATCH 2/3] setup_git_env: convert die(\"BUG\") to BUG()","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2017-05-13T03:29:18Z","receivedAt":"2017-05-13T03:29:26Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"Converting to BUG() makes it easier to detect and debug\ncases where we hit this assertion. Coupled with a new test\nin t1300, this shows that the test suite can detect such\ncorner cases.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\n environment.c          | 2 +-\n t/t1300-repo-config.sh | 6 ++++++\n 2 files changed, 7 insertions(+), 1 deletion(-)\n\ndiff --git a/environment.c b/environment.c\nindex ff6e4f06e..1f0bda5af 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -169,7 +169,7 @@ static void setup_git_env(void)\n \tgit_dir = getenv(GIT_DIR_ENVIRONMENT);\n \tif (!git_dir) {\n \t\tif (!startup_info->have_repository)\n-\t\t\tdie(\"BUG: setup_git_env called without repository\");\n+\t\t\tBUG(\"setup_git_env called without repository\");\n \t\tgit_dir = DEFAULT_GIT_DIR_ENVIRONMENT;\n \t}\n \tgitfile = read_gitfile(git_dir);\ndiff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh\nindex afcca0d52..867704a64 100755\n--- a/t/t1300-repo-config.sh\n+++ b/t/t1300-repo-config.sh\n@@ -1539,4 +1539,10 @@ test_expect_success !MINGW '--show-origin blob ref' '\n \ttest_cmp expect output\n '\n \n+test_expect_failure '--local requires a repo' '\n+\t# we expect 128 to ensure that we do not simply\n+\t# fail to find anything and return code \"1\"\n+\ttest_expect_code 128 nongit git config --local foo.bar\n+'\n+\n test_done\n-- \n2.13.0.452.g0afc8e12b\n\n"},{"id":"319596","messageId":"20170513032931.uyvhfw6fgju36ovf@sigill.intra.peff.net","threadId":"45942","inReplyTo":"20170513032414.mfrwabt4hovujde2@sigill.intra.peff.net","subject":"[PATCH 3/3] config: complain about --local outside of a git repo","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2017-05-13T03:29:31Z","receivedAt":"2017-05-13T03:29:38Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"The \"--local\" option instructs git-config to read or modify\nthe repository-level config. This doesn't make any sense if\nyou're not actually in a repository.\n\nOlder versions of Git would blindly try to read or write\n\".git/config\". For reading, this would result in a quiet\nfailure, since there was no config to read (and thus no\nmatching config value). Writing would generally fail\nnoisily, since \".git\" was unlikely to exist. But since\nb1ef400ee (setup_git_env: avoid blind fall-back to \".git\",\n2016-10-20), we catch this in the call to git_pathdup() and\ndie with an assertion.\n\nDying is the right thing to do, but we should catch the\nproblem early and give a more human-friendly error message.\n\nNote that even without --local, git-config will sometimes\ndefault to using local repository config (e.g., when\nwriting). These cases are already protected by similar\nchecks, and covered by a test in t1308.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\n builtin/config.c       | 3 +++\n t/t1300-repo-config.sh | 2 +-\n 2 files changed, 4 insertions(+), 1 deletion(-)\n\ndiff --git a/builtin/config.c b/builtin/config.c\nindex 3a554ad50..7f6c25d4d 100644\n--- a/builtin/config.c\n+++ b/builtin/config.c\n@@ -496,6 +496,9 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\tusage_with_options(builtin_config_usage, builtin_config_options);\n \t}\n \n+\tif (use_local_config && nongit)\n+\t\tdie(_(\"--local can only be used inside a git repository\"));\n+\n \tif (given_config_source.file &&\n \t\t\t!strcmp(given_config_source.file, \"-\")) {\n \t\tgiven_config_source.file = NULL;\ndiff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh\nindex 867704a64..13b7851f7 100755\n--- a/t/t1300-repo-config.sh\n+++ b/t/t1300-repo-config.sh\n@@ -1539,7 +1539,7 @@ test_expect_success !MINGW '--show-origin blob ref' '\n \ttest_cmp expect output\n '\n \n-test_expect_failure '--local requires a repo' '\n+test_expect_success '--local requires a repo' '\n \t# we expect 128 to ensure that we do not simply\n \t# fail to find anything and return code \"1\"\n \ttest_expect_code 128 nongit git config --local foo.bar\n-- \n2.13.0.452.g0afc8e12b\n"},{"id":"319598","messageId":"20170513035503.cubqhzcvhifp54yg@sigill.intra.peff.net","threadId":"45942","inReplyTo":"20170513032850.zeru4cm2l7i23rkc@sigill.intra.peff.net","subject":"Re: [PATCH 1/3] usage.c: add BUG() function","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2017-05-13T03:55:03Z","receivedAt":"2017-05-13T03:55:10Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, May 12, 2017 at 11:28:50PM -0400, Jeff King wrote:\n\n> +static NORETURN void BUG_vfl(const char *file, int line, const char *fmt, va_list params)\n> +{\n> +\tchar prefix[256];\n> +\n> +\t/* truncation via snprintf is OK here */\n> +\tif (file)\n> +\t\tsnprintf(prefix, sizeof(prefix), \"BUG: %s:%d: \", file, line);\n> +\telse\n> +\t\tsnprintf(prefix, sizeof(prefix), \"BUG: \");\n> +\n> +\tvreportf(prefix, fmt, params);\n> +\tabort();\n> +}\n\nI used vreportf() here to match die(). But the two things that function\ndoes are:\n\n  1. Respect error_handle. But after bw/forking-and-threading is merged,\n     nobody will ever set error_handle (and I just sent a patch to drop\n     it entirely).\n\n  2. Quotes non-printable characters. I don't know how useful this is.\n     Most of the assertion messages are pretty vanilla (because anything\n     that relies on user input probably should be a regular die, not an\n     assertion failure). But a few of them do actually print arbitrary\n     strings in a reasonable way (e.g., a BUG() which is handling user\n     string which was supposed to be vetted by an earlier function is\n     still a reasonable assertion, but it's useful to show the string).\n\nSo an alternative would be just:\n\n  fprintf(stderr, \"BUG: \");\n  if (file)\n\tfprintf(stderr, \"%s:%d \", file, line);\n  vfprintf(stderr, fmt, params);\n  fputc('\\n', stderr);\n\nwhich is perhaps a bit simpler (not much in lines of code, but there's\nno extra buffer to reason about). But given the discussion in (2) above,\nit's probably worth continuing to use vreportf.\n\n-Peff\n"},{"id":"319732","messageId":"CANuW5x0rOKm29SDR_jF9ZydAA5UPyjmvnoH9At+M_uXUzdV5HA@mail.gmail.com","threadId":"45942","inReplyTo":"alpine.DEB.2.21.1.1705121643180.146734@virtualbox","subject":"Re: [Git 2.13.0] BUG: setup_git_env called without repository","fromName":"Josh Hagins","fromEmail":"hagins.josh@gmail.com","sentAt":"2017-05-15T00:22:33Z","receivedAt":"2017-05-15T00:23:11Z","isPatch":false,"sender":{"key":"hagins.josh@gmail.com","avatar":null},"body":"Hi Johannes,\n\nHere's the full text of the gdb session, including backtrace. Hope it helps!\n\n$ pwd\n/Users/jhagins/dev/github\n$ gdb -args ./git/git config --local --get user.name\nGNU gdb (GDB) 7.12.1\nCopyright (C) 2017 Free Software Foundation, Inc.\nLicense GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.  Type \"show copying\"\nand \"show warranty\" for details.\nThis GDB was configured as \"x86_64-apple-darwin16.4.0\".\nType \"show configuration\" for configuration details.\nFor bug reporting instructions, please see:\n<http://www.gnu.org/software/gdb/bugs/>.\nFind the GDB manual and other documentation resources online at:\n<http://www.gnu.org/software/gdb/documentation/>.\nFor help, type \"help\".\nType \"apropos word\" to search for commands related to \"word\"...\nReading symbols from ./git/git...done.\n(gdb) b die_builtin\nBreakpoint 1 at 0x100210757: file usage.c, line 33.\n(gdb) r\nStarting program: /Volumes/git/github/git/git config --local --get user.name\n[New Thread 0x1403 of process 64101]\nwarning: unhandled dyld version (15)\n\nThread 2 hit Breakpoint 1, die_builtin (err=0x100270d95 \"BUG:\nsetup_git_env called without repository\", params=0x7fff5fbfdbe0) at\nusage.c:33\n33 vreportf(\"fatal: \", err, params);\n(gdb) bt\n#0  die_builtin (err=0x100270d95 \"BUG: setup_git_env called without\nrepository\", params=0x7fff5fbfdbe0) at usage.c:33\n#1  0x000000010020fc80 in die (err=0x100270d95 \"BUG: setup_git_env\ncalled without repository\") at usage.c:120\n#2  0x000000010012cb2b in setup_git_env () at environment.c:172\n#3  0x000000010012cab7 in get_git_dir () at environment.c:214\n#4  0x0000000100214e9c in get_worktree_git_dir (wt=0x0) at worktree.c:215\n#5  0x000000010017968c in do_git_path (wt=0x0, buf=0x7fff5fbfde50,\nfmt=0x10024c24d \"config\", args=0x7fff5fbfde70) at path.c:395\n#6  0x0000000100179c78 in git_pathdup (fmt=0x10024c24d \"config\") at path.c:437\n#7  0x0000000100030449 in cmd_config (argc=1, argv=0x7fff5fbfe180,\nprefix=0x0) at builtin/config.c:527\n#8  0x0000000100001ac5 in run_builtin (p=0x10028c3a8, argc=4,\nargv=0x7fff5fbfe180) at git.c:371\n#9  0x0000000100000cc6 in handle_builtin (argc=4, argv=0x7fff5fbfe180)\nat git.c:572\n#10 0x0000000100001883 in run_argv (argcp=0x7fff5fbfe12c,\nargv=0x7fff5fbfe120) at git.c:624\n#11 0x0000000100000a4f in cmd_main (argc=4, argv=0x7fff5fbfe180) at git.c:701\n#12 0x00000001000c3772 in main (argc=5, argv=0x7fff5fbfe178) at common-main.c:43\n\nCheers,\nJosh\n\nOn Fri, May 12, 2017 at 10:48 AM, Johannes Schindelin\n<Johannes.Schindelin@gmx.de> wrote:\n> Hi Josh,\n>\n> On Fri, 12 May 2017, Josh Hagins wrote:\n>\n>> Since upgrading to Git 2.13.0 I'm seeing this error message whenever\n>> `git config --local <whatever>` is called outside a Git repository.\n>> For example, note the difference in behavior between Git 2.13 and\n>> Apple Git:\n>>\n>>     $ pwd\n>>     /Users/jhagins\n>>     $ /usr/bin/git --version\n>>     git version 2.11.0 (Apple Git-81)\n>>     $ /usr/bin/git config --local --get user.name\n>>     $ /usr/local/bin/git --version\n>>     git version 2.13.0\n>>     $ /usr/local/bin/git config --local --get user.name\n>>     fatal: BUG: setup_git_env called without repository\n>>\n>> Apple Git outputs nothing, as expected. The summarized release notes\n>> published by GitHub specifically mentioned that instances of this\n>> error message should be reported, so here you go!\n>>\n>> Please let me know if I can provide any more information that would be\n>> helpful.\n>\n> Since this is in /usr/local/bin/, there are two possibilities:\n>\n> 1) you built and installed it yourself (but then it would be more likely\n>    in your $HOME/bin), or\n>\n> 2) you installed it via HomeBrew.\n>\n> I guess it is the latter.\n>\n> In both cases, however, you have XCode installed, so you can dig further.\n> Yay.\n>\n> The thing I would do in your case would be to clone Git:\n>\n>         git clone https://github.com/git/git\n>\n> then check out v2.13.0:\n>\n>         git checkout v2.13.0\n>\n> then edit the Makefile to remove the -O2 from the CFLAGS (the next step is\n> to use the GNU debugger, and in my hands the -O2 optimization made that\n> pretty useless), and then build with\n>\n>         make\n>\n> After that, you should be able to start the command in your local GNU\n> debugger:\n>\n>         gdb -args ./git config --local --get user.name\n>\n> You will then want to set a breakpoint on the die_builtin() function:\n>\n>         b die_builtin\n>\n> Now run it with the `r` command, and it should stop in the die_builtin\n> routine, in which case a backtrace would be most helpful to figure out\n> what is going wrong:\n>\n>         bt\n>\n> If the output is not enlightening on its own, it would be nice to paste it\n> into a reply to this mail so that the entire Git developer community can\n> have a look.\n>\n> Ciao,\n> Johannes\n\n\n\n-- \nJosh Hagins\n"},{"id":"319733","messageId":"CANuW5x2-gzHuPN9ox8hEgNUiTsEKeAqeZQXZZ=SMFbsfabXd1w@mail.gmail.com","threadId":"45942","inReplyTo":"20170512203436.fcoqauphzvox2sgv@sigill.intra.peff.net","subject":"Re: [PATCH] config: complain about --local outside of a git repo","fromName":"Josh Hagins","fromEmail":"hagins.josh@gmail.com","sentAt":"2017-05-15T00:31:54Z","receivedAt":"2017-05-15T00:32:31Z","isPatch":true,"sender":{"key":"hagins.josh@gmail.com","avatar":null},"body":"Hi Jeff,\n\nFor context, the \"user.name\" bit was purely notional; I just wanted to\ngive a sample reproduction. Where I've actually been running into this\nin real life is with oh-my-git, a GitHub-themed Powerline bash prompt:\nhttps://github.com/arialdomartini/oh-my-git/blob/42c11f08540949b75bd513e6880a4ce6824a2bcc/base.sh#L52.\n\nSince this command is invoked every time the prompt is build, I see\nthe error message after every single command I run outside of a Git\nrepository. While this is more indicative of a code smell in\noh-my-git, I figured that, as you said, BUG assertions should never\nget hit in the wild. Thanks for the patch!\n\nCheers,\nJosh\n\nOn Fri, May 12, 2017 at 4:34 PM, Jeff King <peff@peff.net> wrote:\n> On Fri, May 12, 2017 at 10:19:59AM -0400, Josh Hagins wrote:\n>\n>> Since upgrading to Git 2.13.0 I'm seeing this error message whenever\n>> `git config --local <whatever>` is called outside a Git repository.\n>> For example, note the difference in behavior between Git 2.13 and\n>> Apple Git:\n>>\n>>     $ pwd\n>>     /Users/jhagins\n>>     $ /usr/bin/git --version\n>>     git version 2.11.0 (Apple Git-81)\n>>     $ /usr/bin/git config --local --get user.name\n>>     $ /usr/local/bin/git --version\n>>     git version 2.13.0\n>>     $ /usr/local/bin/git config --local --get user.name\n>>     fatal: BUG: setup_git_env called without repository\n>>\n>> Apple Git outputs nothing, as expected. The summarized release notes\n>> published by GitHub specifically mentioned that instances of this\n>> error message should be reported, so here you go!\n>\n> Thanks for reporting. All the developers have been running with this\n> change for months, but I knew as soon as it was released into the wild\n> that somebody would find a new corner case. :)\n>\n> I think dying is the right thing here; you are asking for \"--local\" but\n> there is no local repository. But we should never hit a BUG assertion.\n> Patch is below.\n>\n> I'm not sure exactly what you wanted to accomplish with --local. If you\n> just want to know if user.name is set anywhere (and you may or may not\n> be in a git repo), then just \"git config --get user.name\" would work. If\n> you want to know if you're in a local repo and if so whether the\n> variable is set, you'd need to use two commands, like:\n>\n>   git rev-parse --git-dir >/dev/null 2>&1 &&\n>   git config --local --get user.name\n>\n> -- >8 --\n> Subject: [PATCH] config: complain about --local outside of a git repo\n>\n> The \"--local\" option instructs git-config to read or modify\n> the repository-level config. This doesn't make any sense if\n> you're not actually in a repository.\n>\n> Older versions of Git would blindly try to read or write\n> \".git/config\". For reading, this would result in a quiet\n> failure, since there was no config to read (and thus no\n> matching config value). Writing would generally fail\n> noisily, since \".git\" was unlikely to exist. But since\n> b1ef400ee (setup_git_env: avoid blind fall-back to \".git\",\n> 2016-10-20), we catch this in the call to git_pathdup() and\n> die(\"BUG\").\n>\n> Dying is the right thing to do, but we should catch the\n> problem early and give a more human-friendly error message.\n>\n> Note that even without --local, git-config will sometimes\n> default to using local repository config. These cases are\n> already protected by a similar check.\n>\n> Signed-off-by: Jeff King <peff@peff.net>\n> ---\n>  builtin/config.c | 3 +++\n>  1 file changed, 3 insertions(+)\n>\n> diff --git a/builtin/config.c b/builtin/config.c\n> index 3a554ad50..ad7c6a19c 100644\n> --- a/builtin/config.c\n> +++ b/builtin/config.c\n> @@ -496,6 +496,9 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n>                 usage_with_options(builtin_config_usage, builtin_config_options);\n>         }\n>\n> +       if (use_local_config && nongit)\n> +               die(_(\"--local only be used inside a git repository\"));\n> +\n>         if (given_config_source.file &&\n>                         !strcmp(given_config_source.file, \"-\")) {\n>                 given_config_source.file = NULL;\n> --\n> 2.13.0.452.g0afc8e12b\n>\n\n\n\n-- \nJosh Hagins\n"},{"id":"319742","messageId":"xmqq37c6yht1.fsf@gitster.mtv.corp.google.com","threadId":"45942","inReplyTo":"20170513035503.cubqhzcvhifp54yg@sigill.intra.peff.net","subject":"Re: [PATCH 1/3] usage.c: add BUG() function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-05-15T02:28:42Z","receivedAt":"2017-05-15T02:28:49Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> On Fri, May 12, 2017 at 11:28:50PM -0400, Jeff King wrote:\n>\n>> +static NORETURN void BUG_vfl(const char *file, int line, const char *fmt, va_list params)\n>> +{\n>> +\tchar prefix[256];\n>> +\n>> +\t/* truncation via snprintf is OK here */\n>> +\tif (file)\n>> +\t\tsnprintf(prefix, sizeof(prefix), \"BUG: %s:%d: \", file, line);\n>> +\telse\n>> +\t\tsnprintf(prefix, sizeof(prefix), \"BUG: \");\n>> +\n>> +\tvreportf(prefix, fmt, params);\n>> +\tabort();\n>> +}\n>\n> I used vreportf() here to match die(). But the two things that function\n> does are:\n>\n>   1. Respect error_handle. But after bw/forking-and-threading is merged,\n>      nobody will ever set error_handle (and I just sent a patch to drop\n>      it entirely).\n>\n>   2. Quotes non-printable characters. I don't know how useful this is.\n>      Most of the assertion messages are pretty vanilla (because anything\n>      that relies on user input probably should be a regular die, not an\n>      assertion failure). But a few of them do actually print arbitrary\n>      strings in a reasonable way (e.g., a BUG() which is handling user\n>      string which was supposed to be vetted by an earlier function is\n>      still a reasonable assertion, but it's useful to show the string).\n>\n> So an alternative would be just:\n>\n>   fprintf(stderr, \"BUG: \");\n>   if (file)\n> \tfprintf(stderr, \"%s:%d \", file, line);\n>   vfprintf(stderr, fmt, params);\n>   fputc('\\n', stderr);\n>\n> which is perhaps a bit simpler (not much in lines of code, but there's\n> no extra buffer to reason about). But given the discussion in (2) above,\n> it's probably worth continuing to use vreportf.\n\nYeah, that does sound sensible.  Thanks.\n"},{"id":"319747","messageId":"20170515031831.c4wrhgm7gky3dldw@sigill.intra.peff.net","threadId":"45942","inReplyTo":"CANuW5x2-gzHuPN9ox8hEgNUiTsEKeAqeZQXZZ=SMFbsfabXd1w@mail.gmail.com","subject":"Re: [PATCH] config: complain about --local outside of a git repo","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2017-05-15T03:18:31Z","receivedAt":"2017-05-15T03:18:41Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sun, May 14, 2017 at 08:31:54PM -0400, Josh Hagins wrote:\n\n> For context, the \"user.name\" bit was purely notional; I just wanted to\n> give a sample reproduction. Where I've actually been running into this\n> in real life is with oh-my-git, a GitHub-themed Powerline bash prompt:\n> https://github.com/arialdomartini/oh-my-git/blob/42c11f08540949b75bd513e6880a4ce6824a2bcc/base.sh#L52.\n> \n> Since this command is invoked every time the prompt is build, I see\n> the error message after every single command I run outside of a Git\n> repository. While this is more indicative of a code smell in\n> oh-my-git, I figured that, as you said, BUG assertions should never\n> get hit in the wild. Thanks for the patch!\n\nAh, thanks for the context. That makes a lot more sense. I do think\noh-my-git should just drop the \"--local\", which will cause git-config to\nfollow the usual precedence rules (and it will skip repo-level config\nautomatically when we are not in a repo).\n\nSince the oh-my-git code only looks for \"false\", nobody would ever need\nto default the value to true in their ~/.gitconfig. But respecting the\nusual config rules would mean you could set it to \"false\" in\n~/.gitconfig to turn it off everywhere, but then opt back into it for\nspecific repos by setting it to \"true\" there. Probably not a use case\nanybody cares that much about, but it's how \"git config\" was meant to be\nused. :)\n\nAnyway, thanks again for reporting the BUG assertion. I'm glad to be\nweeding out more cases.\n\n-Peff\n"},{"id":"346438","messageId":"cover.1525253892.git.johannes.schindelin@gmx.de","threadId":"45942","inReplyTo":"20170513032414.mfrwabt4hovujde2@sigill.intra.peff.net","subject":"[PATCH v2 0/4] Finish the conversion from die(\"BUG: ...\") to BUG()","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2018-05-02T09:38:13Z","receivedAt":"2018-05-02T09:38:45Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"The BUG() macro was introduced in this patch series:\nhttps://public-inbox.org/git/20170513032414.mfrwabt4hovujde2@sigill.intra.peff.net\n\nThe second patch in that series converted one caller from die(\"BUG: \")\nto use the BUG() macro.\n\nIt seems that there was no concrete plan to address the same issue in\nthe rest of the code base.\n\nThis patch series tries to do that.\n\nNote: I would be very surprised if the monster commit 3/4 (\"Replace all\ndie(\"BUG: ...\") calls by BUG() ones\") would apply cleanly on `pu` (I\ndevelop this on top of `master`).\n\nFor that reason, the commit message contains the precise Unix shell\ninvocation (GNU sed semantics, not BSD sed ones, because I know that the\nGit maintainer as well as the author of the patch introducing BUG() both\nuse Linux and not macOS or any other platform that would offer a BSD\nsed). It should be straight-forward to handle merge\nconflicts/non-applying patches by simply re-running that command.\n\nChanges since v2:\n\n- Avoided the entire discussion about the previous 2/6 (now dropped)\n  that prepared t1406 to handle SIGABRT by side-stepping the issue: the\n  ref-store test helper will no longer call abort() in BUG() calls but\n  exit with exit code 99 instead.\n\n- As a consequence, I could fold 3/6 into 4/6 (i.e. *not* special-case\n  the refs/*.c code but do one wholesale die(\"BUG: ...\") -> BUG()\n  conversion).\n\n- Further consequence: 1/6, which added handling for ok=sigabrt to\n  test_must_fail, was dropped.\n\n- I also used the opportunity to explain in the commit message of the last\n  commit why the localization was dropped from one die(_(\"BUG: ...\")) call.\n\n\nJohannes Schindelin (4):\n  test-tool: help verifying BUG() code paths\n  run-command: use BUG() to report bugs, not die()\n  Replace all die(\"BUG: ...\") calls by BUG() ones\n  Convert remaining die*(BUG) messages\n\n apply.c                          |  4 ++--\n archive-tar.c                    |  2 +-\n attr.c                           | 10 +++++-----\n blame.c                          |  2 +-\n builtin/am.c                     | 20 +++++++++----------\n builtin/branch.c                 |  2 +-\n builtin/cat-file.c               |  4 ++--\n builtin/clone.c                  |  2 +-\n builtin/commit.c                 |  2 +-\n builtin/config.c                 |  2 +-\n builtin/fast-export.c            |  2 +-\n builtin/fsck.c                   |  2 +-\n builtin/index-pack.c             |  4 ++--\n builtin/init-db.c                |  2 +-\n builtin/ls-files.c               |  2 +-\n builtin/notes.c                  |  8 ++++----\n builtin/pack-objects.c           |  4 ++--\n builtin/pull.c                   |  2 +-\n builtin/receive-pack.c           |  2 +-\n builtin/replace.c                |  2 +-\n builtin/update-index.c           |  2 +-\n bulk-checkin.c                   |  2 +-\n color.c                          |  4 ++--\n column.c                         |  2 +-\n config.c                         | 12 +++++------\n date.c                           |  2 +-\n diff.c                           | 12 +++++------\n dir-iterator.c                   |  2 +-\n git-compat-util.h                |  2 +-\n grep.c                           | 16 +++++++--------\n http.c                           |  8 ++++----\n imap-send.c                      |  2 +-\n lockfile.c                       |  2 +-\n mailinfo.c                       |  2 +-\n merge-recursive.c                | 12 +++++------\n notes-merge.c                    |  4 ++--\n pack-bitmap-write.c              |  2 +-\n pack-bitmap.c                    |  6 +++---\n pack-objects.c                   |  2 +-\n packfile.c                       |  6 +++---\n pathspec.c                       | 12 +++++------\n pkt-line.c                       |  2 +-\n prio-queue.c                     |  2 +-\n ref-filter.c                     |  4 ++--\n refs.c                           | 34 ++++++++++++++++----------------\n refs/files-backend.c             | 20 +++++++++----------\n refs/iterator.c                  |  6 +++---\n refs/packed-backend.c            | 16 +++++++--------\n refs/ref-cache.c                 |  2 +-\n remote.c                         |  2 +-\n revision.c                       |  4 ++--\n run-command.c                    | 33 ++++++++++++++-----------------\n setup.c                          |  4 ++--\n sha1-lookup.c                    |  2 +-\n sha1-name.c                      |  4 ++--\n shallow.c                        |  6 +++---\n sigchain.c                       |  2 +-\n strbuf.c                         |  4 ++--\n submodule.c                      |  8 ++++----\n t/helper/test-example-decorate.c | 16 +++++++--------\n t/helper/test-tool.c             |  2 ++\n tmp-objdir.c                     |  2 +-\n trailer.c                        |  6 +++---\n transport.c                      |  4 ++--\n unpack-trees.c                   |  2 +-\n usage.c                          |  5 +++++\n vcs-svn/fast_export.c            |  6 ++++--\n worktree.c                       |  2 +-\n wrapper.c                        |  4 ++--\n wt-status.c                      | 20 +++++++++----------\n zlib.c                           |  4 ++--\n 71 files changed, 214 insertions(+), 208 deletions(-)\n\n\nbase-commit: 1f1cddd558b54bb0ce19c8ace353fd07b758510d\nPublished-As: https://github.com/dscho/git/releases/tag/use-bug-macro-v2\nFetch-It-Via: git fetch https://github.com/dscho/git use-bug-macro-v2\n\nBranch-diff vs v1:\n 1: 97894dd28d7 < -:  ------- test_must_fail: support ok=sigabrt\n 2: 9bbfd73a8e0 < -:  ------- t1406: prepare for the refs code to fail with BUG()\n 3: b44ce003ae6 < -:  ------- refs/*: report bugs using the BUG() macro\n -:  ------- > 1: 6e2bfd3a6eb test-tool: help verifying BUG() code paths\n 4: 89539a1af3d = 2: 91ddc7ed5ce run-command: use BUG() to report bugs, not die()\n 5: 42584f2f7c9 ! 3: 2133197fdc9 Replace all die(\"BUG: ...\") calls by BUG() ones\n     @@ -1199,6 +1199,214 @@\n       \textra_refname = find_descendant_ref(dirname.buf, extras, skip);\n       \tif (extra_refname)\n      \n     +diff --git a/refs/files-backend.c b/refs/files-backend.c\n     +--- a/refs/files-backend.c\n     ++++ b/refs/files-backend.c\n     +@@\n     + \tif (refs->store_flags & REF_STORE_MAIN)\n     + \t\treturn;\n     + \n     +-\tdie(\"BUG: operation %s only allowed for main ref store\", caller);\n     ++\tBUG(\"operation %s only allowed for main ref store\", caller);\n     + }\n     + \n     + /*\n     +@@\n     + \tstruct files_ref_store *refs;\n     + \n     + \tif (ref_store->be != &refs_be_files)\n     +-\t\tdie(\"BUG: ref_store is type \\\"%s\\\" not \\\"files\\\" in %s\",\n     ++\t\tBUG(\"ref_store is type \\\"%s\\\" not \\\"files\\\" in %s\",\n     + \t\t    ref_store->be->name, caller);\n     + \n     + \trefs = (struct files_ref_store *)ref_store;\n     + \n     + \tif ((refs->store_flags & required_flags) != required_flags)\n     +-\t\tdie(\"BUG: operation %s requires abilities 0x%x, but only have 0x%x\",\n     ++\t\tBUG(\"operation %s requires abilities 0x%x, but only have 0x%x\",\n     + \t\t    caller, required_flags, refs->store_flags);\n     + \n     + \treturn refs;\n     +@@\n     + \t\tstrbuf_addf(sb, \"%s/logs/%s\", refs->gitcommondir, refname);\n     + \t\tbreak;\n     + \tdefault:\n     +-\t\tdie(\"BUG: unknown ref type %d of ref %s\",\n     ++\t\tBUG(\"unknown ref type %d of ref %s\",\n     + \t\t    ref_type(refname), refname);\n     + \t}\n     + }\n     +@@\n     + \t\tstrbuf_addf(sb, \"%s/%s\", refs->gitcommondir, refname);\n     + \t\tbreak;\n     + \tdefault:\n     +-\t\tdie(\"BUG: unknown ref type %d of ref %s\",\n     ++\t\tBUG(\"unknown ref type %d of ref %s\",\n     + \t\t    ref_type(refname), refname);\n     + \t}\n     + }\n     +@@\n     + \n     + \t}\n     + \tif (!ret && sb.len)\n     +-\t\tdie(\"BUG: reverse reflog parser had leftover data\");\n     ++\t\tBUG(\"reverse reflog parser had leftover data\");\n     + \n     + \tfclose(logfp);\n     + \tstrbuf_release(&sb);\n     +@@\n     + static int files_reflog_iterator_peel(struct ref_iterator *ref_iterator,\n     + \t\t\t\t   struct object_id *peeled)\n     + {\n     +-\tdie(\"BUG: ref_iterator_peel() called for reflog_iterator\");\n     ++\tBUG(\"ref_iterator_peel() called for reflog_iterator\");\n     + }\n     + \n     + static int files_reflog_iterator_abort(struct ref_iterator *ref_iterator)\n     +@@\n     + \tassert(err);\n     + \n     + \tif (transaction->state != REF_TRANSACTION_OPEN)\n     +-\t\tdie(\"BUG: commit called for transaction that is not open\");\n     ++\t\tBUG(\"commit called for transaction that is not open\");\n     + \n     + \t/* Fail if a refname appears more than once in the transaction: */\n     + \tfor (i = 0; i < transaction->nr; i++)\n     +@@\n     + \t */\n     + \tif (refs_for_each_rawref(&refs->base, ref_present,\n     + \t\t\t\t &affected_refnames))\n     +-\t\tdie(\"BUG: initial ref transaction called with existing refs\");\n     ++\t\tBUG(\"initial ref transaction called with existing refs\");\n     + \n     + \tpacked_transaction = ref_store_transaction_begin(refs->packed_ref_store, err);\n     + \tif (!packed_transaction) {\n     +@@\n     + \n     + \t\tif ((update->flags & REF_HAVE_OLD) &&\n     + \t\t    !is_null_oid(&update->old_oid))\n     +-\t\t\tdie(\"BUG: initial ref transaction with old_sha1 set\");\n     ++\t\t\tBUG(\"initial ref transaction with old_sha1 set\");\n     + \t\tif (refs_verify_refname_available(&refs->base, update->refname,\n     + \t\t\t\t\t\t  &affected_refnames, NULL,\n     + \t\t\t\t\t\t  err)) {\n     +\n     +diff --git a/refs/iterator.c b/refs/iterator.c\n     +--- a/refs/iterator.c\n     ++++ b/refs/iterator.c\n     +@@\n     + static int empty_ref_iterator_peel(struct ref_iterator *ref_iterator,\n     + \t\t\t\t   struct object_id *peeled)\n     + {\n     +-\tdie(\"BUG: peel called for empty iterator\");\n     ++\tBUG(\"peel called for empty iterator\");\n     + }\n     + \n     + static int empty_ref_iterator_abort(struct ref_iterator *ref_iterator)\n     +@@\n     + \t\t(struct merge_ref_iterator *)ref_iterator;\n     + \n     + \tif (!iter->current) {\n     +-\t\tdie(\"BUG: peel called before advance for merge iterator\");\n     ++\t\tBUG(\"peel called before advance for merge iterator\");\n     + \t}\n     + \treturn ref_iterator_peel(*iter->current, peeled);\n     + }\n     +@@\n     + \t\t\t * trimming, report it as a bug:\n     + \t\t\t */\n     + \t\t\tif (strlen(iter->iter0->refname) <= iter->trim)\n     +-\t\t\t\tdie(\"BUG: attempt to trim too many characters\");\n     ++\t\t\t\tBUG(\"attempt to trim too many characters\");\n     + \t\t\titer->base.refname = iter->iter0->refname + iter->trim;\n     + \t\t} else {\n     + \t\t\titer->base.refname = iter->iter0->refname;\n     +\n     +diff --git a/refs/packed-backend.c b/refs/packed-backend.c\n     +--- a/refs/packed-backend.c\n     ++++ b/refs/packed-backend.c\n     +@@\n     + \tstruct packed_ref_store *refs;\n     + \n     + \tif (ref_store->be != &refs_be_packed)\n     +-\t\tdie(\"BUG: ref_store is type \\\"%s\\\" not \\\"packed\\\" in %s\",\n     ++\t\tBUG(\"ref_store is type \\\"%s\\\" not \\\"packed\\\" in %s\",\n     + \t\t    ref_store->be->name, caller);\n     + \n     + \trefs = (struct packed_ref_store *)ref_store;\n     + \n     + \tif ((refs->store_flags & required_flags) != required_flags)\n     +-\t\tdie(\"BUG: unallowed operation (%s), requires %x, has %x\\n\",\n     ++\t\tBUG(\"unallowed operation (%s), requires %x, has %x\\n\",\n     + \t\t    caller, required_flags, refs->store_flags);\n     + \n     + \treturn refs;\n     +@@\n     + \t\t\t\"packed_refs_unlock\");\n     + \n     + \tif (!is_lock_file_locked(&refs->lock))\n     +-\t\tdie(\"BUG: packed_refs_unlock() called when not locked\");\n     ++\t\tBUG(\"packed_refs_unlock() called when not locked\");\n     + \trollback_lock_file(&refs->lock);\n     + }\n     + \n     +@@\n     + \tchar *packed_refs_path;\n     + \n     + \tif (!is_lock_file_locked(&refs->lock))\n     +-\t\tdie(\"BUG: write_with_updates() called while unlocked\");\n     ++\t\tBUG(\"write_with_updates() called while unlocked\");\n     + \n     + \t/*\n     + \t * If packed-refs is a symlink, we want to overwrite the\n     +@@\n     + \t\t\t       const char *refname, const char *target,\n     + \t\t\t       const char *logmsg)\n     + {\n     +-\tdie(\"BUG: packed reference store does not support symrefs\");\n     ++\tBUG(\"packed reference store does not support symrefs\");\n     + }\n     + \n     + static int packed_rename_ref(struct ref_store *ref_store,\n     + \t\t\t    const char *oldrefname, const char *newrefname,\n     + \t\t\t    const char *logmsg)\n     + {\n     +-\tdie(\"BUG: packed reference store does not support renaming references\");\n     ++\tBUG(\"packed reference store does not support renaming references\");\n     + }\n     + \n     + static int packed_copy_ref(struct ref_store *ref_store,\n     + \t\t\t   const char *oldrefname, const char *newrefname,\n     + \t\t\t   const char *logmsg)\n     + {\n     +-\tdie(\"BUG: packed reference store does not support copying references\");\n     ++\tBUG(\"packed reference store does not support copying references\");\n     + }\n     + \n     + static struct ref_iterator *packed_reflog_iterator_begin(struct ref_store *ref_store)\n     +@@\n     + \t\t\t       const char *refname, int force_create,\n     + \t\t\t       struct strbuf *err)\n     + {\n     +-\tdie(\"BUG: packed reference store does not support reflogs\");\n     ++\tBUG(\"packed reference store does not support reflogs\");\n     + }\n     + \n     + static int packed_delete_reflog(struct ref_store *ref_store,\n     +\n     +diff --git a/refs/ref-cache.c b/refs/ref-cache.c\n     +--- a/refs/ref-cache.c\n     ++++ b/refs/ref-cache.c\n     +@@\n     + \tdir = &entry->u.subdir;\n     + \tif (entry->flag & REF_INCOMPLETE) {\n     + \t\tif (!dir->cache->fill_ref_dir)\n     +-\t\t\tdie(\"BUG: incomplete ref_store without fill_ref_dir function\");\n     ++\t\t\tBUG(\"incomplete ref_store without fill_ref_dir function\");\n     + \n     + \t\tdir->cache->fill_ref_dir(dir->cache->ref_store, dir, entry->name);\n     + \t\tentry->flag &= ~REF_INCOMPLETE;\n     +\n      diff --git a/remote.c b/remote.c\n      --- a/remote.c\n      +++ b/remote.c\n 6: 0e85c7a16e3 ! 4: 57b3a3e9fe3 Convert remaining die*(BUG) messages\n     @@ -4,6 +4,12 @@\n          \n          These were not caught by the previous commit, as they did not match the\n          regular expression.\n     +    \n     +    While at it, remove the localization from one instance: we never want\n     +    BUG() messages to be translated, as they target Git developers, not the\n     +    end user (hence it would be quite unhelpful to not only burden the\n     +    translators, but then even end up with a bug report in a language that\n     +    no core Git contributor understands).\n          \n          Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n      \n-- \n2.17.0.windows.1.36.gdf4ca5fb72a\n\n"},{"id":"346439","messageId":"6e2bfd3a6eb5270c809262f046e6a8b80090b352.1525253892.git.johannes.schindelin@gmx.de","threadId":"45942","inReplyTo":"cover.1525253892.git.johannes.schindelin@gmx.de","subject":"[PATCH v2 1/4] test-tool: help verifying BUG() code paths","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2018-05-02T09:38:28Z","receivedAt":"2018-05-02T09:38:48Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"When we call BUG(), we signal via SIGABRT that something bad happened,\ndumping cores if so configured. In some setups these coredumps are\nredirected to some central place such as /proc/sys/kernel/core_pattern,\nwhich is a good thing.\n\nHowever, when we try to verify in our test suite that bugs are caught in\ncertain code paths, we do *not* want to clutter such a central place\nwith unnecessary coredumps.\n\nSo let's special-case the test helpers (which we use to verify such code\npaths) so that the BUG() calls will *not* call abort() but exit with a\nspecial-purpose exit code instead.\n\nHelped-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n t/helper/test-tool.c | 2 ++\n usage.c              | 5 +++++\n 2 files changed, 7 insertions(+)\n\ndiff --git a/t/helper/test-tool.c b/t/helper/test-tool.c\nindex 87066ced62a..5176f9f20ae 100644\n--- a/t/helper/test-tool.c\n+++ b/t/helper/test-tool.c\n@@ -47,7 +47,9 @@ static struct test_cmd cmds[] = {\n int cmd_main(int argc, const char **argv)\n {\n \tint i;\n+\textern int BUG_exit_code;\n \n+\tBUG_exit_code = 99;\n \tif (argc < 2)\n \t\tdie(\"I need a test name!\");\n \ndiff --git a/usage.c b/usage.c\nindex cdd534c9dfc..9c84dccfa97 100644\n--- a/usage.c\n+++ b/usage.c\n@@ -210,6 +210,9 @@ void warning(const char *warn, ...)\n \tva_end(params);\n }\n \n+/* Only set this, ever, from t/helper/, when verifying that bugs are caught. */\n+int BUG_exit_code;\n+\n static NORETURN void BUG_vfl(const char *file, int line, const char *fmt, va_list params)\n {\n \tchar prefix[256];\n@@ -221,6 +224,8 @@ static NORETURN void BUG_vfl(const char *file, int line, const char *fmt, va_lis\n \t\tsnprintf(prefix, sizeof(prefix), \"BUG: \");\n \n \tvreportf(prefix, fmt, params);\n+\tif (BUG_exit_code)\n+\t\texit(BUG_exit_code);\n \tabort();\n }\n \n-- \n2.17.0.windows.1.36.gdf4ca5fb72a\n\n\n"},{"id":"346440","messageId":"91ddc7ed5ce0279c5d48bbed595d932d985465c4.1525253892.git.johannes.schindelin@gmx.de","threadId":"45942","inReplyTo":"cover.1525253892.git.johannes.schindelin@gmx.de","subject":"[PATCH v2 2/4] run-command: use BUG() to report bugs, not die()","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2018-05-02T09:38:31Z","receivedAt":"2018-05-02T09:38:51Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"The slightly misleading name die_bug() of the function intended to\nreport a bug is actually called always, and only reports a bug if the\npassed-in parameter `err` is non-zero.\n\nIt uses die_errno() to report the bug, to helpfully include the error\nmessage corresponding to `err`.\n\nHowever, as these messages indicate bugs, we really should use BUG().\nAnd as BUG() is a macro to be able to report the exact file and line\nnumber, we need to convert die_bug() to a macro instead of only\nreplacing the die_errno() by a call to BUG().\n\nWhile at it, use a name more indicative of the purpose: CHECK_BUG().\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n run-command.c | 23 ++++++++++-------------\n 1 file changed, 10 insertions(+), 13 deletions(-)\n\ndiff --git a/run-command.c b/run-command.c\nindex 12c94c1dbe5..0ad6f135d5a 100644\n--- a/run-command.c\n+++ b/run-command.c\n@@ -471,15 +471,12 @@ struct atfork_state {\n \tsigset_t old;\n };\n \n-#ifndef NO_PTHREADS\n-static void bug_die(int err, const char *msg)\n-{\n-\tif (err) {\n-\t\terrno = err;\n-\t\tdie_errno(\"BUG: %s\", msg);\n-\t}\n-}\n-#endif\n+#define CHECK_BUG(err, msg) \\\n+\tdo { \\\n+\t\tint e = (err); \\\n+\t\tif (e) \\\n+\t\t\tBUG(\"%s: %s\", msg, strerror(e)); \\\n+\t} while(0)\n \n static void atfork_prepare(struct atfork_state *as)\n {\n@@ -491,9 +488,9 @@ static void atfork_prepare(struct atfork_state *as)\n \tif (sigprocmask(SIG_SETMASK, &all, &as->old))\n \t\tdie_errno(\"sigprocmask\");\n #else\n-\tbug_die(pthread_sigmask(SIG_SETMASK, &all, &as->old),\n+\tCHECK_BUG(pthread_sigmask(SIG_SETMASK, &all, &as->old),\n \t\t\"blocking all signals\");\n-\tbug_die(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &as->cs),\n+\tCHECK_BUG(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &as->cs),\n \t\t\"disabling cancellation\");\n #endif\n }\n@@ -504,9 +501,9 @@ static void atfork_parent(struct atfork_state *as)\n \tif (sigprocmask(SIG_SETMASK, &as->old, NULL))\n \t\tdie_errno(\"sigprocmask\");\n #else\n-\tbug_die(pthread_setcancelstate(as->cs, NULL),\n+\tCHECK_BUG(pthread_setcancelstate(as->cs, NULL),\n \t\t\"re-enabling cancellation\");\n-\tbug_die(pthread_sigmask(SIG_SETMASK, &as->old, NULL),\n+\tCHECK_BUG(pthread_sigmask(SIG_SETMASK, &as->old, NULL),\n \t\t\"restoring signal mask\");\n #endif\n }\n-- \n2.17.0.windows.1.36.gdf4ca5fb72a\n\n\n"},{"id":"346441","messageId":"2133197fdc9347fb8795841beeb98f0950b41aa2.1525253892.git.johannes.schindelin@gmx.de","threadId":"45942","inReplyTo":"cover.1525253892.git.johannes.schindelin@gmx.de","subject":"[PATCH v2 3/4] Replace all die(\"BUG: ...\") calls by BUG() ones","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2018-05-02T09:38:39Z","receivedAt":"2018-05-02T09:38:58Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"In d8193743e08 (usage.c: add BUG() function, 2017-05-12), a new macro\nwas introduced to use for reporting bugs instead of die(). It was then\nsubsequently used to convert one single caller in 588a538ae55\n(setup_git_env: convert die(\"BUG\") to BUG(), 2017-05-12).\n\nThe cover letter of the patch series containing this patch\n(cf 20170513032414.mfrwabt4hovujde2@sigill.intra.peff.net) is not\nterribly clear why only one call site was converted, or what the plan\nis for other, similar calls to die() to report bugs.\n\nLet's just convert all remaining ones in one fell swoop.\n\nThis trick was performed by this invocation:\n\n\tsed -i 's/die(\"BUG: /BUG(\"/g' $(git grep -l 'die(\"BUG' \\*.c)\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n apply.c                          |  4 ++--\n archive-tar.c                    |  2 +-\n attr.c                           | 10 +++++-----\n blame.c                          |  2 +-\n builtin/am.c                     | 20 +++++++++----------\n builtin/branch.c                 |  2 +-\n builtin/cat-file.c               |  4 ++--\n builtin/clone.c                  |  2 +-\n builtin/commit.c                 |  2 +-\n builtin/config.c                 |  2 +-\n builtin/fast-export.c            |  2 +-\n builtin/fsck.c                   |  2 +-\n builtin/index-pack.c             |  4 ++--\n builtin/init-db.c                |  2 +-\n builtin/ls-files.c               |  2 +-\n builtin/notes.c                  |  8 ++++----\n builtin/pack-objects.c           |  4 ++--\n builtin/pull.c                   |  2 +-\n builtin/receive-pack.c           |  2 +-\n builtin/replace.c                |  2 +-\n builtin/update-index.c           |  2 +-\n bulk-checkin.c                   |  2 +-\n color.c                          |  4 ++--\n column.c                         |  2 +-\n config.c                         | 12 +++++------\n date.c                           |  2 +-\n diff.c                           | 12 +++++------\n dir-iterator.c                   |  2 +-\n grep.c                           | 16 +++++++--------\n http.c                           |  8 ++++----\n imap-send.c                      |  2 +-\n lockfile.c                       |  2 +-\n mailinfo.c                       |  2 +-\n merge-recursive.c                | 12 +++++------\n notes-merge.c                    |  4 ++--\n pack-bitmap-write.c              |  2 +-\n pack-bitmap.c                    |  6 +++---\n pack-objects.c                   |  2 +-\n packfile.c                       |  6 +++---\n pathspec.c                       | 10 +++++-----\n pkt-line.c                       |  2 +-\n prio-queue.c                     |  2 +-\n ref-filter.c                     |  4 ++--\n refs.c                           | 34 ++++++++++++++++----------------\n refs/files-backend.c             | 20 +++++++++----------\n refs/iterator.c                  |  6 +++---\n refs/packed-backend.c            | 16 +++++++--------\n refs/ref-cache.c                 |  2 +-\n remote.c                         |  2 +-\n revision.c                       |  4 ++--\n run-command.c                    | 10 +++++-----\n setup.c                          |  4 ++--\n sha1-lookup.c                    |  2 +-\n sha1-name.c                      |  4 ++--\n shallow.c                        |  6 +++---\n sigchain.c                       |  2 +-\n strbuf.c                         |  4 ++--\n submodule.c                      |  6 +++---\n t/helper/test-example-decorate.c | 16 +++++++--------\n tmp-objdir.c                     |  2 +-\n trailer.c                        |  6 +++---\n transport.c                      |  4 ++--\n unpack-trees.c                   |  2 +-\n worktree.c                       |  2 +-\n wrapper.c                        |  4 ++--\n wt-status.c                      | 20 +++++++++----------\n zlib.c                           |  4 ++--\n 67 files changed, 190 insertions(+), 190 deletions(-)\n\ndiff --git a/apply.c b/apply.c\nindex 7e5792c996f..3866adbc97f 100644\n--- a/apply.c\n+++ b/apply.c\n@@ -2375,7 +2375,7 @@ static void update_pre_post_images(struct image *preimage,\n \tif (postlen\n \t    ? postlen < new_buf - postimage->buf\n \t    : postimage->len < new_buf - postimage->buf)\n-\t\tdie(\"BUG: caller miscounted postlen: asked %d, orig = %d, used = %d\",\n+\t\tBUG(\"caller miscounted postlen: asked %d, orig = %d, used = %d\",\n \t\t    (int)postlen, (int) postimage->len, (int)(new_buf - postimage->buf));\n \n \t/* Fix the length of the whole thing */\n@@ -3509,7 +3509,7 @@ static int load_current(struct apply_state *state,\n \tunsigned mode = patch->new_mode;\n \n \tif (!patch->is_new)\n-\t\tdie(\"BUG: patch to %s is not a creation\", patch->old_name);\n+\t\tBUG(\"patch to %s is not a creation\", patch->old_name);\n \n \tpos = cache_name_pos(name, strlen(name));\n \tif (pos < 0)\ndiff --git a/archive-tar.c b/archive-tar.c\nindex 3563bcb9f26..61a1a2547cc 100644\n--- a/archive-tar.c\n+++ b/archive-tar.c\n@@ -441,7 +441,7 @@ static int write_tar_filter_archive(const struct archiver *ar,\n \tint r;\n \n \tif (!ar->data)\n-\t\tdie(\"BUG: tar-filter archiver called with no filter defined\");\n+\t\tBUG(\"tar-filter archiver called with no filter defined\");\n \n \tstrbuf_addstr(&cmd, ar->data);\n \tif (args->compression_level >= 0)\ndiff --git a/attr.c b/attr.c\nindex 03a678fa9be..067fb9e0c08 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -157,7 +157,7 @@ static void all_attrs_init(struct attr_hashmap *map, struct attr_check *check)\n \n \tsize = hashmap_get_size(&map->map);\n \tif (size < check->all_attrs_nr)\n-\t\tdie(\"BUG: interned attributes shouldn't be deleted\");\n+\t\tBUG(\"interned attributes shouldn't be deleted\");\n \n \t/*\n \t * If the number of attributes in the global dictionary has increased\n@@ -541,7 +541,7 @@ static void check_vector_remove(struct attr_check *check)\n \t\t\tbreak;\n \n \tif (i >= check_vector.nr)\n-\t\tdie(\"BUG: no entry found\");\n+\t\tBUG(\"no entry found\");\n \n \t/* shift entries over */\n \tfor (; i < check_vector.nr - 1; i++)\n@@ -599,11 +599,11 @@ struct attr_check *attr_check_initl(const char *one, ...)\n \t\tconst struct git_attr *attr;\n \t\tparam = va_arg(params, const char *);\n \t\tif (!param)\n-\t\t\tdie(\"BUG: counted %d != ended at %d\",\n+\t\t\tBUG(\"counted %d != ended at %d\",\n \t\t\t    check->nr, cnt);\n \t\tattr = git_attr(param);\n \t\tif (!attr)\n-\t\t\tdie(\"BUG: %s: not a valid attribute name\", param);\n+\t\t\tBUG(\"%s: not a valid attribute name\", param);\n \t\tcheck->items[cnt].attr = attr;\n \t}\n \tva_end(params);\n@@ -714,7 +714,7 @@ void git_attr_set_direction(enum git_attr_direction new_direction,\n \t\t\t    struct index_state *istate)\n {\n \tif (is_bare_repository() && new_direction != GIT_ATTR_INDEX)\n-\t\tdie(\"BUG: non-INDEX attr direction in a bare repo\");\n+\t\tBUG(\"non-INDEX attr direction in a bare repo\");\n \n \tif (new_direction != direction)\n \t\tdrop_all_attr_stacks();\ndiff --git a/blame.c b/blame.c\nindex 78c9808bd1a..89a1b11e922 100644\n--- a/blame.c\n+++ b/blame.c\n@@ -1806,7 +1806,7 @@ void setup_scoreboard(struct blame_scoreboard *sb, const char *path, struct blam\n \t\t\tl->item = c;\n \t\t\tif (add_decoration(&sb->revs->children,\n \t\t\t\t\t   &c->parents->item->object, l))\n-\t\t\t\tdie(\"BUG: not unique item in first-parent chain\");\n+\t\t\t\tBUG(\"not unique item in first-parent chain\");\n \t\t\tc = c->parents->item;\n \t\t}\n \ndiff --git a/builtin/am.c b/builtin/am.c\nindex d834f9e62b6..3dc2ef4259a 100644\n--- a/builtin/am.c\n+++ b/builtin/am.c\n@@ -403,11 +403,11 @@ static void am_load(struct am_state *state)\n \tstruct strbuf sb = STRBUF_INIT;\n \n \tif (read_state_file(&sb, state, \"next\", 1) < 0)\n-\t\tdie(\"BUG: state file 'next' does not exist\");\n+\t\tBUG(\"state file 'next' does not exist\");\n \tstate->cur = strtol(sb.buf, NULL, 10);\n \n \tif (read_state_file(&sb, state, \"last\", 1) < 0)\n-\t\tdie(\"BUG: state file 'last' does not exist\");\n+\t\tBUG(\"state file 'last' does not exist\");\n \tstate->last = strtol(sb.buf, NULL, 10);\n \n \tif (read_author_script(state) < 0)\n@@ -986,7 +986,7 @@ static int split_mail(struct am_state *state, enum patch_format patch_format,\n \tcase PATCH_FORMAT_MBOXRD:\n \t\treturn split_mail_mbox(state, paths, keep_cr, 1);\n \tdefault:\n-\t\tdie(\"BUG: invalid patch_format\");\n+\t\tBUG(\"invalid patch_format\");\n \t}\n \treturn -1;\n }\n@@ -1041,7 +1041,7 @@ static void am_setup(struct am_state *state, enum patch_format patch_format,\n \t\tstr = \"b\";\n \t\tbreak;\n \tdefault:\n-\t\tdie(\"BUG: invalid value for state->keep\");\n+\t\tBUG(\"invalid value for state->keep\");\n \t}\n \n \twrite_state_text(state, \"keep\", str);\n@@ -1058,7 +1058,7 @@ static void am_setup(struct am_state *state, enum patch_format patch_format,\n \t\tstr = \"t\";\n \t\tbreak;\n \tdefault:\n-\t\tdie(\"BUG: invalid value for state->scissors\");\n+\t\tBUG(\"invalid value for state->scissors\");\n \t}\n \twrite_state_text(state, \"scissors\", str);\n \n@@ -1216,7 +1216,7 @@ static int parse_mail(struct am_state *state, const char *mail)\n \t\tmi.keep_non_patch_brackets_in_subject = 1;\n \t\tbreak;\n \tdefault:\n-\t\tdie(\"BUG: invalid value for state->keep\");\n+\t\tBUG(\"invalid value for state->keep\");\n \t}\n \n \tif (state->message_id)\n@@ -1232,7 +1232,7 @@ static int parse_mail(struct am_state *state, const char *mail)\n \t\tmi.use_scissors = 1;\n \t\tbreak;\n \tdefault:\n-\t\tdie(\"BUG: invalid value for state->scissors\");\n+\t\tBUG(\"invalid value for state->scissors\");\n \t}\n \n \tmi.input = xfopen(mail, \"r\");\n@@ -1463,7 +1463,7 @@ static int run_apply(const struct am_state *state, const char *index_file)\n \tint options = 0;\n \n \tif (init_apply_state(&apply_state, NULL))\n-\t\tdie(\"BUG: init_apply_state() failed\");\n+\t\tBUG(\"init_apply_state() failed\");\n \n \targv_array_push(&apply_opts, \"apply\");\n \targv_array_pushv(&apply_opts, state->git_apply_opts.argv);\n@@ -1489,7 +1489,7 @@ static int run_apply(const struct am_state *state, const char *index_file)\n \t\tapply_state.apply_verbosity = verbosity_silent;\n \n \tif (check_apply_state(&apply_state, force_apply))\n-\t\tdie(\"BUG: check_apply_state() failed\");\n+\t\tBUG(\"check_apply_state() failed\");\n \n \targv_array_push(&apply_paths, am_path(state, \"patch\"));\n \n@@ -2407,7 +2407,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)\n \t\tret = show_patch(&state);\n \t\tbreak;\n \tdefault:\n-\t\tdie(\"BUG: invalid resume value\");\n+\t\tBUG(\"invalid resume value\");\n \t}\n \n \tam_state_release(&state);\ndiff --git a/builtin/branch.c b/builtin/branch.c\nindex 5bd2a0dd489..1d4b3ce3d79 100644\n--- a/builtin/branch.c\n+++ b/builtin/branch.c\n@@ -497,7 +497,7 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int\n \n \tif (!skip_prefix(oldref.buf, \"refs/heads/\", &interpreted_oldname) ||\n \t    !skip_prefix(newref.buf, \"refs/heads/\", &interpreted_newname)) {\n-\t\tdie(\"BUG: expected prefix missing for refs\");\n+\t\tBUG(\"expected prefix missing for refs\");\n \t}\n \n \tif (copy)\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex 2c46d257cd9..1cc3ccc4515 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -312,7 +312,7 @@ static void print_object_or_die(struct batch_options *opt, struct expand_data *d\n \t\t\t\t\tdie(\"could not convert '%s' %s\",\n \t\t\t\t\t    oid_to_hex(oid), data->rest);\n \t\t\t} else\n-\t\t\t\tdie(\"BUG: invalid cmdmode: %c\", opt->cmdmode);\n+\t\t\t\tBUG(\"invalid cmdmode: %c\", opt->cmdmode);\n \t\t\tbatch_write(opt, contents, size);\n \t\t\tfree(contents);\n \t\t} else if (stream_blob_to_fd(1, oid, NULL, 0) < 0)\n@@ -387,7 +387,7 @@ static void batch_one_object(const char *obj_name, struct batch_options *opt,\n \t\t\t       (uintmax_t)strlen(obj_name), obj_name);\n \t\t\tbreak;\n \t\tdefault:\n-\t\t\tdie(\"BUG: unknown get_sha1_with_context result %d\\n\",\n+\t\t\tBUG(\"unknown get_sha1_with_context result %d\\n\",\n \t\t\t       result);\n \t\t\tbreak;\n \t\t}\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex 7df5932b855..918820c539c 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -823,7 +823,7 @@ static void write_refspec_config(const char *src_ref_prefix,\n \t\t\t} else if (remote_head_points_at) {\n \t\t\t\tconst char *head = remote_head_points_at->name;\n \t\t\t\tif (!skip_prefix(head, \"refs/heads/\", &head))\n-\t\t\t\t\tdie(\"BUG: remote HEAD points at non-head?\");\n+\t\t\t\t\tBUG(\"remote HEAD points at non-head?\");\n \n \t\t\t\tstrbuf_addf(&value, \"+%s:%s%s\", remote_head_points_at->name,\n \t\t\t\t\t\tbranch_top->buf, head);\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex 5571d4a3e2b..7b47d1b7fb3 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -495,7 +495,7 @@ static int is_a_merge(const struct commit *current_head)\n static void assert_split_ident(struct ident_split *id, const struct strbuf *buf)\n {\n \tif (split_ident_line(id, buf->buf, buf->len) || !id->date_begin)\n-\t\tdie(\"BUG: unable to parse our own ident: %s\", buf->buf);\n+\t\tBUG(\"unable to parse our own ident: %s\", buf->buf);\n }\n \n static void export_one(const char *var, const char *s, const char *e, int hack)\ndiff --git a/builtin/config.c b/builtin/config.c\nindex 01169dd628b..c4f20332d74 100644\n--- a/builtin/config.c\n+++ b/builtin/config.c\n@@ -309,7 +309,7 @@ static char *normalize_value(const char *key, const char *value)\n \t\t\treturn xstrdup(v ? \"true\" : \"false\");\n \t}\n \n-\tdie(\"BUG: cannot normalize type %d\", types);\n+\tBUG(\"cannot normalize type %d\", types);\n }\n \n static int get_color_found;\ndiff --git a/builtin/fast-export.c b/builtin/fast-export.c\nindex a15898d6417..116363f685c 100644\n--- a/builtin/fast-export.c\n+++ b/builtin/fast-export.c\n@@ -517,7 +517,7 @@ static void anonymize_ident_line(const char **beg, const char **end)\n \t/* skip \"committer\", \"author\", \"tagger\", etc */\n \tend_of_header = strchr(*beg, ' ');\n \tif (!end_of_header)\n-\t\tdie(\"BUG: malformed line fed to anonymize_ident_line: %.*s\",\n+\t\tBUG(\"malformed line fed to anonymize_ident_line: %.*s\",\n \t\t    (int)(*end - *beg), *beg);\n \tend_of_header++;\n \tstrbuf_add(out, *beg, end_of_header - *beg);\ndiff --git a/builtin/fsck.c b/builtin/fsck.c\nindex 087360a6757..1ea414480a4 100644\n--- a/builtin/fsck.c\n+++ b/builtin/fsck.c\n@@ -519,7 +519,7 @@ static struct object *parse_loose_object(const struct object_id *oid,\n \t\treturn NULL;\n \n \tif (!contents && type != OBJ_BLOB)\n-\t\tdie(\"BUG: read_loose_object streamed a non-blob\");\n+\t\tBUG(\"read_loose_object streamed a non-blob\");\n \n \tobj = parse_object_buffer(oid, type, size, contents, &eaten);\n \ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex 78e66b99866..21f22e34952 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -866,7 +866,7 @@ static void sha1_object(const void *data, struct object_entry *obj_entry,\n \t\t\tif (obj->type == OBJ_COMMIT) {\n \t\t\t\tstruct commit *commit = (struct commit *) obj;\n \t\t\t\tif (detach_commit_buffer(commit, NULL) != data)\n-\t\t\t\t\tdie(\"BUG: parse_object_buffer transmogrified our buffer\");\n+\t\t\t\t\tBUG(\"parse_object_buffer transmogrified our buffer\");\n \t\t\t}\n \t\t\tobj->flags |= FLAG_CHECKED;\n \t\t}\n@@ -1015,7 +1015,7 @@ static struct base_data *find_unresolved_deltas_1(struct base_data *base,\n \n \t\tif (!compare_and_swap_type(&child->real_type, OBJ_REF_DELTA,\n \t\t\t\t\t   base->obj->real_type))\n-\t\t\tdie(\"BUG: child->real_type != OBJ_REF_DELTA\");\n+\t\t\tBUG(\"child->real_type != OBJ_REF_DELTA\");\n \n \t\tresolve_delta(child, base, result);\n \t\tif (base->ref_first == base->ref_last && base->ofs_last == -1)\ndiff --git a/builtin/init-db.c b/builtin/init-db.c\nindex 2542c5244e9..5a5844c1538 100644\n--- a/builtin/init-db.c\n+++ b/builtin/init-db.c\n@@ -391,7 +391,7 @@ int init_db(const char *git_dir, const char *real_git_dir,\n \t\telse if (get_shared_repository() == PERM_EVERYBODY)\n \t\t\txsnprintf(buf, sizeof(buf), \"%d\", OLD_PERM_EVERYBODY);\n \t\telse\n-\t\t\tdie(\"BUG: invalid value for shared_repository\");\n+\t\t\tBUG(\"invalid value for shared_repository\");\n \t\tgit_config_set(\"core.sharedrepository\", buf);\n \t\tgit_config_set(\"receive.denyNonFastforwards\", \"true\");\n \t}\ndiff --git a/builtin/ls-files.c b/builtin/ls-files.c\nindex a71f6bd088a..967b2b3380d 100644\n--- a/builtin/ls-files.c\n+++ b/builtin/ls-files.c\n@@ -166,7 +166,7 @@ static void show_killed_files(const struct index_state *istate,\n \t\t\t\t */\n \t\t\t\tpos = index_name_pos(istate, ent->name, ent->len);\n \t\t\t\tif (0 <= pos)\n-\t\t\t\t\tdie(\"BUG: killed-file %.*s not found\",\n+\t\t\t\t\tBUG(\"killed-file %.*s not found\",\n \t\t\t\t\t\tent->len, ent->name);\n \t\t\t\tpos = -pos - 1;\n \t\t\t\twhile (pos < istate->cache_nr &&\ndiff --git a/builtin/notes.c b/builtin/notes.c\nindex e5bf80eef1d..da279cdd349 100644\n--- a/builtin/notes.c\n+++ b/builtin/notes.c\n@@ -461,7 +461,7 @@ static int add(int argc, const char **argv, const char *prefix)\n \tif (d.buf.len || allow_empty) {\n \t\twrite_note_data(&d, &new_note);\n \t\tif (add_note(t, &object, &new_note, combine_notes_overwrite))\n-\t\t\tdie(\"BUG: combine_notes_overwrite failed\");\n+\t\t\tBUG(\"combine_notes_overwrite failed\");\n \t\tcommit_notes(t, \"Notes added by 'git notes add'\");\n \t} else {\n \t\tfprintf(stderr, _(\"Removing note for object %s\\n\"),\n@@ -544,7 +544,7 @@ static int copy(int argc, const char **argv, const char *prefix)\n \t}\n \n \tif (add_note(t, &object, from_note, combine_notes_overwrite))\n-\t\tdie(\"BUG: combine_notes_overwrite failed\");\n+\t\tBUG(\"combine_notes_overwrite failed\");\n \tcommit_notes(t, \"Notes added by 'git notes copy'\");\n out:\n \tfree_notes(t);\n@@ -621,7 +621,7 @@ static int append_edit(int argc, const char **argv, const char *prefix)\n \tif (d.buf.len || allow_empty) {\n \t\twrite_note_data(&d, &new_note);\n \t\tif (add_note(t, &object, &new_note, combine_notes_overwrite))\n-\t\t\tdie(\"BUG: combine_notes_overwrite failed\");\n+\t\t\tBUG(\"combine_notes_overwrite failed\");\n \t\tlogmsg = xstrfmt(\"Notes added by 'git notes %s'\", argv[0]);\n \t} else {\n \t\tfprintf(stderr, _(\"Removing note for object %s\\n\"),\n@@ -831,7 +831,7 @@ static int merge(int argc, const char **argv, const char *prefix)\n \t\tconst char *short_ref = NULL;\n \n \t\tif (!skip_prefix(o.local_ref, \"refs/notes/\", &short_ref))\n-\t\t\tdie(\"BUG: local ref %s is outside of refs/notes/\",\n+\t\t\tBUG(\"local ref %s is outside of refs/notes/\",\n \t\t\t    o.local_ref);\n \n \t\tstrbuf_addf(&merge_key, \"notes.%s.mergeStrategy\", short_ref);\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex 4bdae5a1d8f..68de9134e1c 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -1620,7 +1620,7 @@ static void break_delta_chains(struct object_entry *entry)\n \t\t * is a bug.\n \t\t */\n \t\tif (cur->dfs_state != DFS_NONE)\n-\t\t\tdie(\"BUG: confusing delta dfs state in first pass: %d\",\n+\t\t\tBUG(\"confusing delta dfs state in first pass: %d\",\n \t\t\t    cur->dfs_state);\n \n \t\t/*\n@@ -1677,7 +1677,7 @@ static void break_delta_chains(struct object_entry *entry)\n \t\tif (cur->dfs_state == DFS_DONE)\n \t\t\tbreak;\n \t\telse if (cur->dfs_state != DFS_ACTIVE)\n-\t\t\tdie(\"BUG: confusing delta dfs state in second pass: %d\",\n+\t\t\tBUG(\"confusing delta dfs state in second pass: %d\",\n \t\t\t    cur->dfs_state);\n \n \t\t/*\ndiff --git a/builtin/pull.c b/builtin/pull.c\nindex 71aac5005e0..a886fa8ad4f 100644\n--- a/builtin/pull.c\n+++ b/builtin/pull.c\n@@ -539,7 +539,7 @@ static int run_fetch(const char *repo, const char **refspecs)\n \t\targv_array_push(&args, repo);\n \t\targv_array_pushv(&args, refspecs);\n \t} else if (*refspecs)\n-\t\tdie(\"BUG: refspecs without repo?\");\n+\t\tBUG(\"refspecs without repo?\");\n \tret = run_command_v_opt(args.argv, RUN_GIT_CMD);\n \targv_array_clear(&args);\n \treturn ret;\ndiff --git a/builtin/receive-pack.c b/builtin/receive-pack.c\nindex 4b68a28e92e..2d719fa5117 100644\n--- a/builtin/receive-pack.c\n+++ b/builtin/receive-pack.c\n@@ -1378,7 +1378,7 @@ static void warn_if_skipped_connectivity_check(struct command *commands,\n \t\t}\n \t}\n \tif (!checked_connectivity)\n-\t\tdie(\"BUG: connectivity check skipped???\");\n+\t\tBUG(\"connectivity check skipped???\");\n }\n \n static void execute_commands_non_atomic(struct command *commands,\ndiff --git a/builtin/replace.c b/builtin/replace.c\nindex 935647be6bd..91a25394c00 100644\n--- a/builtin/replace.c\n+++ b/builtin/replace.c\n@@ -501,6 +501,6 @@ int cmd_replace(int argc, const char **argv, const char *prefix)\n \t\treturn list_replace_refs(argv[0], format);\n \n \tdefault:\n-\t\tdie(\"BUG: invalid cmdmode %d\", (int)cmdmode);\n+\t\tBUG(\"invalid cmdmode %d\", (int)cmdmode);\n \t}\n }\ndiff --git a/builtin/update-index.c b/builtin/update-index.c\nindex 10d070a76fb..ac19bbbb150 100644\n--- a/builtin/update-index.c\n+++ b/builtin/update-index.c\n@@ -1164,7 +1164,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)\n \t\treport(_(\"Untracked cache enabled for '%s'\"), get_git_work_tree());\n \t\tbreak;\n \tdefault:\n-\t\tdie(\"BUG: bad untracked_cache value: %d\", untracked_cache);\n+\t\tBUG(\"bad untracked_cache value: %d\", untracked_cache);\n \t}\n \n \tif (fsmonitor > 0) {\ndiff --git a/bulk-checkin.c b/bulk-checkin.c\nindex de1f4040c78..f8a549dd7a4 100644\n--- a/bulk-checkin.c\n+++ b/bulk-checkin.c\n@@ -230,7 +230,7 @@ static int deflate_to_pack(struct bulk_checkin_state *state,\n \t\t * pack, and write into it.\n \t\t */\n \t\tif (!idx)\n-\t\t\tdie(\"BUG: should not happen\");\n+\t\t\tBUG(\"should not happen\");\n \t\thashfile_truncate(state->f, &checkpoint);\n \t\tstate->offset = checkpoint.offset;\n \t\tfinish_bulk_checkin(state);\ndiff --git a/color.c b/color.c\nindex f277e72e4ce..be1040005b4 100644\n--- a/color.c\n+++ b/color.c\n@@ -174,7 +174,7 @@ static char *color_output(char *out, int len, const struct color *c, char type)\n \t\tbreak;\n \tcase COLOR_ANSI:\n \t\tif (len < 2)\n-\t\t\tdie(\"BUG: color parsing ran out of space\");\n+\t\t\tBUG(\"color parsing ran out of space\");\n \t\t*out++ = type;\n \t\t*out++ = '0' + c->value;\n \t\tbreak;\n@@ -256,7 +256,7 @@ int color_parse_mem(const char *value, int value_len, char *dst)\n #undef OUT\n #define OUT(x) do { \\\n \tif (dst == end) \\\n-\t\tdie(\"BUG: color parsing ran out of space\"); \\\n+\t\tBUG(\"color parsing ran out of space\"); \\\n \t*dst++ = (x); \\\n } while(0)\n \ndiff --git a/column.c b/column.c\nindex 49ab85b7691..2165297608e 100644\n--- a/column.c\n+++ b/column.c\n@@ -214,7 +214,7 @@ void print_columns(const struct string_list *list, unsigned int colopts,\n \t\tdisplay_table(list, colopts, &nopts);\n \t\tbreak;\n \tdefault:\n-\t\tdie(\"BUG: invalid layout mode %d\", COL_LAYOUT(colopts));\n+\t\tBUG(\"invalid layout mode %d\", COL_LAYOUT(colopts));\n \t}\n }\n \ndiff --git a/config.c b/config.c\nindex 62c56099bf8..cface6ab8aa 100644\n--- a/config.c\n+++ b/config.c\n@@ -102,7 +102,7 @@ static int config_buf_ungetc(int c, struct config_source *conf)\n \tif (conf->u.buf.pos > 0) {\n \t\tconf->u.buf.pos--;\n \t\tif (conf->u.buf.buf[conf->u.buf.pos] != c)\n-\t\t\tdie(\"BUG: config_buf can only ungetc the same character\");\n+\t\t\tBUG(\"config_buf can only ungetc the same character\");\n \t\treturn c;\n \t}\n \n@@ -189,7 +189,7 @@ static int prepare_include_condition_pattern(struct strbuf *pat)\n \t\tstrbuf_realpath(&path, cf->path, 1);\n \t\tslash = find_last_dir_sep(path.buf);\n \t\tif (!slash)\n-\t\t\tdie(\"BUG: how is this possible?\");\n+\t\t\tBUG(\"how is this possible?\");\n \t\tstrbuf_splice(pat, 0, 1, path.buf, slash - path.buf);\n \t\tprefix = slash - path.buf + 1 /* slash */;\n \t} else if (!is_absolute_path(pat->buf))\n@@ -1717,7 +1717,7 @@ static int configset_add_value(struct config_set *cs, const char *key, const cha\n \tl_item->value_index = e->value_list.nr - 1;\n \n \tif (!cf)\n-\t\tdie(\"BUG: configset_add_value has no source\");\n+\t\tBUG(\"configset_add_value has no source\");\n \tif (cf->name) {\n \t\tkv_info->filename = strintern(cf->name);\n \t\tkv_info->linenr = cf->linenr;\n@@ -3006,7 +3006,7 @@ const char *current_config_origin_type(void)\n \telse if(cf)\n \t\ttype = cf->origin_type;\n \telse\n-\t\tdie(\"BUG: current_config_origin_type called outside config callback\");\n+\t\tBUG(\"current_config_origin_type called outside config callback\");\n \n \tswitch (type) {\n \tcase CONFIG_ORIGIN_BLOB:\n@@ -3020,7 +3020,7 @@ const char *current_config_origin_type(void)\n \tcase CONFIG_ORIGIN_CMDLINE:\n \t\treturn \"command line\";\n \tdefault:\n-\t\tdie(\"BUG: unknown config origin type\");\n+\t\tBUG(\"unknown config origin type\");\n \t}\n }\n \n@@ -3032,7 +3032,7 @@ const char *current_config_name(void)\n \telse if (cf)\n \t\tname = cf->name;\n \telse\n-\t\tdie(\"BUG: current_config_name called outside config callback\");\n+\t\tBUG(\"current_config_name called outside config callback\");\n \treturn name ? name : \"\";\n }\n \ndiff --git a/date.c b/date.c\nindex c3e673fd042..49f943e25b5 100644\n--- a/date.c\n+++ b/date.c\n@@ -185,7 +185,7 @@ struct date_mode *date_mode_from_type(enum date_mode_type type)\n {\n \tstatic struct date_mode mode;\n \tif (type == DATE_STRFTIME)\n-\t\tdie(\"BUG: cannot create anonymous strftime date_mode struct\");\n+\t\tBUG(\"cannot create anonymous strftime date_mode struct\");\n \tmode.type = type;\n \tmode.local = 0;\n \treturn &mode;\ndiff --git a/diff.c b/diff.c\nindex 1289df4b1f9..9d8c7f60472 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -1184,7 +1184,7 @@ static void emit_diff_symbol_from_struct(struct diff_options *o,\n \t\tfputs(o->stat_sep, o->file);\n \t\tbreak;\n \tdefault:\n-\t\tdie(\"BUG: unknown diff symbol\");\n+\t\tBUG(\"unknown diff symbol\");\n \t}\n \tstrbuf_release(&sb);\n }\n@@ -1343,7 +1343,7 @@ static struct diff_tempfile *claim_diff_tempfile(void) {\n \tfor (i = 0; i < ARRAY_SIZE(diff_temp); i++)\n \t\tif (!diff_temp[i].name)\n \t\t\treturn diff_temp + i;\n-\tdie(\"BUG: diff is failing to clean up its tempfiles\");\n+\tBUG(\"diff is failing to clean up its tempfiles\");\n }\n \n static void remove_tempfile(void)\n@@ -3840,7 +3840,7 @@ static const char *diff_abbrev_oid(const struct object_id *oid, int abbrev)\n \t\tif (abbrev < 0)\n \t\t\tabbrev = FALLBACK_DEFAULT_ABBREV;\n \t\tif (abbrev > GIT_SHA1_HEXSZ)\n-\t\t\tdie(\"BUG: oid abbreviation out of range: %d\", abbrev);\n+\t\t\tBUG(\"oid abbreviation out of range: %d\", abbrev);\n \t\tif (abbrev)\n \t\t\thex[abbrev] = '\\0';\n \t\treturn hex;\n@@ -4334,7 +4334,7 @@ static int stat_opt(struct diff_options *options, const char **av)\n \tint argcount = 1;\n \n \tif (!skip_prefix(arg, \"--stat\", &arg))\n-\t\tdie(\"BUG: stat option does not begin with --stat: %s\", arg);\n+\t\tBUG(\"stat option does not begin with --stat: %s\", arg);\n \tend = (char *)arg;\n \n \tswitch (*arg) {\n@@ -5519,7 +5519,7 @@ static void diff_flush_patch_all_file_pairs(struct diff_options *o)\n \tstruct diff_queue_struct *q = &diff_queued_diff;\n \n \tif (WSEH_NEW & WS_RULE_MASK)\n-\t\tdie(\"BUG: WS rules bit mask overlaps with diff symbol flags\");\n+\t\tBUG(\"WS rules bit mask overlaps with diff symbol flags\");\n \n \tif (o->color_moved)\n \t\to->emitted_symbols = &esm;\n@@ -6053,7 +6053,7 @@ size_t fill_textconv(struct userdiff_driver *driver,\n \t}\n \n \tif (!driver->textconv)\n-\t\tdie(\"BUG: fill_textconv called with non-textconv driver\");\n+\t\tBUG(\"fill_textconv called with non-textconv driver\");\n \n \tif (driver->textconv_cache && df->oid_valid) {\n \t\t*outbuf = notes_cache_get(driver->textconv_cache,\ndiff --git a/dir-iterator.c b/dir-iterator.c\nindex 34182a9a1c1..f2dcd82fde9 100644\n--- a/dir-iterator.c\n+++ b/dir-iterator.c\n@@ -188,7 +188,7 @@ struct dir_iterator *dir_iterator_begin(const char *path)\n \tstruct dir_iterator *dir_iterator = &iter->base;\n \n \tif (!path || !*path)\n-\t\tdie(\"BUG: empty path passed to dir_iterator_begin()\");\n+\t\tBUG(\"empty path passed to dir_iterator_begin()\");\n \n \tstrbuf_init(&iter->base.path, PATH_MAX);\n \tstrbuf_addstr(&iter->base.path, path);\ndiff --git a/grep.c b/grep.c\nindex 65b90c10a38..84f8054a3fd 100644\n--- a/grep.c\n+++ b/grep.c\n@@ -404,7 +404,7 @@ static void compile_pcre1_regexp(struct grep_pat *p, const struct grep_opt *opt)\n \t\t\tdie(\"Couldn't allocate PCRE JIT stack\");\n \t\tpcre_assign_jit_stack(p->pcre1_extra_info, NULL, p->pcre1_jit_stack);\n \t} else if (p->pcre1_jit_on != 0) {\n-\t\tdie(\"BUG: The pcre1_jit_on variable should be 0 or 1, not %d\",\n+\t\tBUG(\"The pcre1_jit_on variable should be 0 or 1, not %d\",\n \t\t    p->pcre1_jit_on);\n \t}\n #endif\n@@ -550,7 +550,7 @@ static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt\n \t\t\tdie(\"Couldn't allocate PCRE2 match context\");\n \t\tpcre2_jit_stack_assign(p->pcre2_match_context, NULL, p->pcre2_jit_stack);\n \t} else if (p->pcre2_jit_on != 0) {\n-\t\tdie(\"BUG: The pcre2_jit_on variable should be 0 or 1, not %d\",\n+\t\tBUG(\"The pcre2_jit_on variable should be 0 or 1, not %d\",\n \t\t    p->pcre1_jit_on);\n \t}\n }\n@@ -917,10 +917,10 @@ static struct grep_expr *prep_header_patterns(struct grep_opt *opt)\n \n \tfor (p = opt->header_list; p; p = p->next) {\n \t\tif (p->token != GREP_PATTERN_HEAD)\n-\t\t\tdie(\"BUG: a non-header pattern in grep header list.\");\n+\t\t\tBUG(\"a non-header pattern in grep header list.\");\n \t\tif (p->field < GREP_HEADER_FIELD_MIN ||\n \t\t    GREP_HEADER_FIELD_MAX <= p->field)\n-\t\t\tdie(\"BUG: unknown header field %d\", p->field);\n+\t\t\tBUG(\"unknown header field %d\", p->field);\n \t\tcompile_regexp(p, opt);\n \t}\n \n@@ -933,7 +933,7 @@ static struct grep_expr *prep_header_patterns(struct grep_opt *opt)\n \n \t\th = compile_pattern_atom(&pp);\n \t\tif (!h || pp != p->next)\n-\t\t\tdie(\"BUG: malformed header expr\");\n+\t\t\tBUG(\"malformed header expr\");\n \t\tif (!header_group[p->field]) {\n \t\t\theader_group[p->field] = h;\n \t\t\tcontinue;\n@@ -1652,7 +1652,7 @@ static int fill_textconv_grep(struct userdiff_driver *driver,\n \t\tfill_filespec(df, &null_oid, 0, 0100644);\n \t\tbreak;\n \tdefault:\n-\t\tdie(\"BUG: attempt to textconv something without a path?\");\n+\t\tBUG(\"attempt to textconv something without a path?\");\n \t}\n \n \t/*\n@@ -1748,7 +1748,7 @@ static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int colle\n \t\tcase GREP_BINARY_TEXT:\n \t\t\tbreak;\n \t\tdefault:\n-\t\t\tdie(\"BUG: unknown binary handling mode\");\n+\t\t\tBUG(\"unknown binary handling mode\");\n \t\t}\n \t}\n \n@@ -2072,7 +2072,7 @@ static int grep_source_load(struct grep_source *gs)\n \tcase GREP_SOURCE_BUF:\n \t\treturn gs->buf ? 0 : -1;\n \t}\n-\tdie(\"BUG: invalid grep_source type to load\");\n+\tBUG(\"invalid grep_source type to load\");\n }\n \n void grep_source_load_driver(struct grep_source *gs)\ndiff --git a/http.c b/http.c\nindex 3034d10b680..ff60936bb0a 100644\n--- a/http.c\n+++ b/http.c\n@@ -1855,7 +1855,7 @@ static int update_url_from_redirect(struct strbuf *base,\n \t\treturn 0;\n \n \tif (!skip_prefix(asked, base->buf, &tail))\n-\t\tdie(\"BUG: update_url_from_redirect: %s is not a superset of %s\",\n+\t\tBUG(\"update_url_from_redirect: %s is not a superset of %s\",\n \t\t    asked, base->buf);\n \n \tnew_len = got->len;\n@@ -1903,7 +1903,7 @@ static int http_request_reauth(const char *url,\n \t\t\tstrbuf_reset(result);\n \t\t\tbreak;\n \t\tdefault:\n-\t\t\tdie(\"BUG: HTTP_KEEP_ERROR is only supported with strbufs\");\n+\t\t\tBUG(\"HTTP_KEEP_ERROR is only supported with strbufs\");\n \t\t}\n \t}\n \n@@ -2114,7 +2114,7 @@ int finish_http_pack_request(struct http_pack_request *preq)\n \t*lst = (*lst)->next;\n \n \tif (!strip_suffix(preq->tmpfile, \".pack.temp\", &len))\n-\t\tdie(\"BUG: pack tmpfile does not end in .pack.temp?\");\n+\t\tBUG(\"pack tmpfile does not end in .pack.temp?\");\n \ttmp_idx = xstrfmt(\"%.*s.idx.temp\", (int)len, preq->tmpfile);\n \n \targv_array_push(&ip.args, \"index-pack\");\n@@ -2210,7 +2210,7 @@ static size_t fwrite_sha1_file(char *ptr, size_t eltsize, size_t nmemb,\n \t\tCURLcode c = curl_easy_getinfo(slot->curl, CURLINFO_HTTP_CODE,\n \t\t\t\t\t\t&slot->http_code);\n \t\tif (c != CURLE_OK)\n-\t\t\tdie(\"BUG: curl_easy_getinfo for HTTP code failed: %s\",\n+\t\t\tBUG(\"curl_easy_getinfo for HTTP code failed: %s\",\n \t\t\t\tcurl_easy_strerror(c));\n \t\tif (slot->http_code >= 300)\n \t\t\treturn size;\ndiff --git a/imap-send.c b/imap-send.c\nindex 3573cbfb0fc..b4eb886e2a6 100644\n--- a/imap-send.c\n+++ b/imap-send.c\n@@ -511,7 +511,7 @@ static int nfsnprintf(char *buf, int blen, const char *fmt, ...)\n \n \tva_start(va, fmt);\n \tif (blen <= 0 || (unsigned)(ret = vsnprintf(buf, blen, fmt, va)) >= (unsigned)blen)\n-\t\tdie(\"BUG: buffer too small. Please report a bug.\");\n+\t\tBUG(\"buffer too small. Please report a bug.\");\n \tva_end(va);\n \treturn ret;\n }\ndiff --git a/lockfile.c b/lockfile.c\nindex efcb7d7dfe3..8e8ab4f29f3 100644\n--- a/lockfile.c\n+++ b/lockfile.c\n@@ -193,7 +193,7 @@ char *get_locked_file_path(struct lock_file *lk)\n \tstrbuf_addstr(&ret, get_tempfile_path(lk->tempfile));\n \tif (ret.len <= LOCK_SUFFIX_LEN ||\n \t    strcmp(ret.buf + ret.len - LOCK_SUFFIX_LEN, LOCK_SUFFIX))\n-\t\tdie(\"BUG: get_locked_file_path() called for malformed lock object\");\n+\t\tBUG(\"get_locked_file_path() called for malformed lock object\");\n \t/* remove \".lock\": */\n \tstrbuf_setlen(&ret, ret.len - LOCK_SUFFIX_LEN);\n \treturn strbuf_detach(&ret, NULL);\ndiff --git a/mailinfo.c b/mailinfo.c\nindex d04142ccc76..3281a37d518 100644\n--- a/mailinfo.c\n+++ b/mailinfo.c\n@@ -716,7 +716,7 @@ static void flush_inbody_header_accum(struct mailinfo *mi)\n \tif (!mi->inbody_header_accum.len)\n \t\treturn;\n \tif (!check_header(mi, &mi->inbody_header_accum, mi->s_hdr_data, 0))\n-\t\tdie(\"BUG: inbody_header_accum, if not empty, must always contain a valid in-body header\");\n+\t\tBUG(\"inbody_header_accum, if not empty, must always contain a valid in-body header\");\n \tstrbuf_reset(&mi->inbody_header_accum);\n }\n \ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex 0c0d48624da..6409d0770f2 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -318,7 +318,7 @@ struct tree *write_tree_from_memory(struct merge_options *o)\n \t\t\t\tfprintf(stderr, \"BUG: %d %.*s\\n\", ce_stage(ce),\n \t\t\t\t\t(int)ce_namelen(ce), ce->name);\n \t\t}\n-\t\tdie(\"BUG: unmerged index entries in merge-recursive.c\");\n+\t\tBUG(\"unmerged index entries in merge-recursive.c\");\n \t}\n \n \tif (!active_cache_tree)\n@@ -1060,7 +1060,7 @@ static int merge_file_1(struct merge_options *o,\n \t\t\t\tbreak;\n \t\t\t}\n \t\t} else\n-\t\t\tdie(\"BUG: unsupported object type in the tree\");\n+\t\t\tBUG(\"unsupported object type in the tree\");\n \t}\n \n \treturn 0;\n@@ -1462,7 +1462,7 @@ static int process_renames(struct merge_options *o,\n \t\t\tconst char *ren2_dst = ren2->pair->two->path;\n \t\t\tenum rename_type rename_type;\n \t\t\tif (strcmp(ren1_src, ren2_src) != 0)\n-\t\t\t\tdie(\"BUG: ren1_src != ren2_src\");\n+\t\t\t\tBUG(\"ren1_src != ren2_src\");\n \t\t\tren2->dst_entry->processed = 1;\n \t\t\tren2->processed = 1;\n \t\t\tif (strcmp(ren1_dst, ren2_dst) != 0) {\n@@ -1496,7 +1496,7 @@ static int process_renames(struct merge_options *o,\n \t\t\tren2 = lookup->util;\n \t\t\tren2_dst = ren2->pair->two->path;\n \t\t\tif (strcmp(ren1_dst, ren2_dst) != 0)\n-\t\t\t\tdie(\"BUG: ren1_dst != ren2_dst\");\n+\t\t\t\tBUG(\"ren1_dst != ren2_dst\");\n \n \t\t\tclean_merge = 0;\n \t\t\tren2->processed = 1;\n@@ -1962,7 +1962,7 @@ static int process_entry(struct merge_options *o,\n \t\t */\n \t\tremove_file(o, 1, path, !a_mode);\n \t} else\n-\t\tdie(\"BUG: fatal merge failure, shouldn't happen.\");\n+\t\tBUG(\"fatal merge failure, shouldn't happen.\");\n \n \treturn clean_merge;\n }\n@@ -2040,7 +2040,7 @@ int merge_trees(struct merge_options *o,\n \t\tfor (i = 0; i < entries->nr; i++) {\n \t\t\tstruct stage_data *e = entries->items[i].util;\n \t\t\tif (!e->processed)\n-\t\t\t\tdie(\"BUG: unprocessed path??? %s\",\n+\t\t\t\tBUG(\"unprocessed path??? %s\",\n \t\t\t\t    entries->items[i].string);\n \t\t}\n \ndiff --git a/notes-merge.c b/notes-merge.c\nindex 8e0726a9418..720e24784c4 100644\n--- a/notes-merge.c\n+++ b/notes-merge.c\n@@ -442,7 +442,7 @@ static int merge_one_change(struct notes_merge_options *o,\n \t\t\tprintf(\"Using remote notes for %s\\n\",\n \t\t\t\t\t\toid_to_hex(&p->obj));\n \t\tif (add_note(t, &p->obj, &p->remote, combine_notes_overwrite))\n-\t\t\tdie(\"BUG: combine_notes_overwrite failed\");\n+\t\t\tBUG(\"combine_notes_overwrite failed\");\n \t\treturn 0;\n \tcase NOTES_MERGE_RESOLVE_UNION:\n \t\tif (o->verbosity >= 2)\n@@ -490,7 +490,7 @@ static int merge_changes(struct notes_merge_options *o,\n \t\t\ttrace_printf(\"\\t\\t\\tno local change, adopted remote\\n\");\n \t\t\tif (add_note(t, &p->obj, &p->remote,\n \t\t\t\t     combine_notes_overwrite))\n-\t\t\t\tdie(\"BUG: combine_notes_overwrite failed\");\n+\t\t\t\tBUG(\"combine_notes_overwrite failed\");\n \t\t} else {\n \t\t\t/* need file-level merge between local and remote */\n \t\t\ttrace_printf(\"\\t\\t\\tneed content-level merge\\n\");\ndiff --git a/pack-bitmap-write.c b/pack-bitmap-write.c\nindex 41ae27fb19a..3c7b5edda8a 100644\n--- a/pack-bitmap-write.c\n+++ b/pack-bitmap-write.c\n@@ -474,7 +474,7 @@ static void write_selected_commits_v1(struct hashfile *f,\n \t\t\tsha1_pos(stored->commit->object.oid.hash, index, index_nr, sha1_access);\n \n \t\tif (commit_pos < 0)\n-\t\t\tdie(\"BUG: trying to write commit not in index\");\n+\t\t\tBUG(\"trying to write commit not in index\");\n \n \t\thashwrite_be32(f, commit_pos);\n \t\thashwrite_u8(f, stored->xor_offset);\ndiff --git a/pack-bitmap.c b/pack-bitmap.c\nindex 3f2dab340f6..a4837af0f4b 100644\n--- a/pack-bitmap.c\n+++ b/pack-bitmap.c\n@@ -255,7 +255,7 @@ static char *pack_bitmap_filename(struct packed_git *p)\n \tsize_t len;\n \n \tif (!strip_suffix(p->pack_name, \".pack\", &len))\n-\t\tdie(\"BUG: pack_name does not end in .pack\");\n+\t\tBUG(\"pack_name does not end in .pack\");\n \treturn xstrfmt(\"%.*s.bitmap\", (int)len, p->pack_name);\n }\n \n@@ -723,13 +723,13 @@ int prepare_bitmap_walk(struct rev_info *revs)\n \t\trevs->ignore_missing_links = 0;\n \n \t\tif (haves_bitmap == NULL)\n-\t\t\tdie(\"BUG: failed to perform bitmap walk\");\n+\t\t\tBUG(\"failed to perform bitmap walk\");\n \t}\n \n \twants_bitmap = find_objects(revs, wants, haves_bitmap);\n \n \tif (!wants_bitmap)\n-\t\tdie(\"BUG: failed to perform bitmap walk\");\n+\t\tBUG(\"failed to perform bitmap walk\");\n \n \tif (haves_bitmap)\n \t\tbitmap_and_not(wants_bitmap, haves_bitmap);\ndiff --git a/pack-objects.c b/pack-objects.c\nindex 9558d13834e..0acab27133c 100644\n--- a/pack-objects.c\n+++ b/pack-objects.c\n@@ -58,7 +58,7 @@ static void rehash_objects(struct packing_data *pdata)\n \t\t\t\t\t\t       &found);\n \n \t\tif (found)\n-\t\t\tdie(\"BUG: Duplicate object in hash\");\n+\t\t\tBUG(\"Duplicate object in hash\");\n \n \t\tpdata->index[ix] = i + 1;\n \t\tentry++;\ndiff --git a/packfile.c b/packfile.c\nindex 0bc67d0e009..9df0dab44da 100644\n--- a/packfile.c\n+++ b/packfile.c\n@@ -188,7 +188,7 @@ int open_pack_index(struct packed_git *p)\n \t\treturn 0;\n \n \tif (!strip_suffix(p->pack_name, \".pack\", &len))\n-\t\tdie(\"BUG: pack_name does not end in .pack\");\n+\t\tBUG(\"pack_name does not end in .pack\");\n \tidx_name = xstrfmt(\"%.*s.idx\", (int)len, p->pack_name);\n \tret = check_packed_git_idx(idx_name, p);\n \tfree(idx_name);\n@@ -317,7 +317,7 @@ void close_all_packs(struct raw_object_store *o)\n \n \tfor (p = o->packed_git; p; p = p->next)\n \t\tif (p->do_not_close)\n-\t\t\tdie(\"BUG: want to close pack marked 'do-not-close'\");\n+\t\t\tBUG(\"want to close pack marked 'do-not-close'\");\n \t\telse\n \t\t\tclose_pack(p);\n }\n@@ -1561,7 +1561,7 @@ void *unpack_entry(struct packed_git *p, off_t obj_offset,\n \tcase OBJ_OFS_DELTA:\n \tcase OBJ_REF_DELTA:\n \t\tif (data)\n-\t\t\tdie(\"BUG: unpack_entry: left loop at a valid delta\");\n+\t\t\tBUG(\"unpack_entry: left loop at a valid delta\");\n \t\tbreak;\n \tcase OBJ_COMMIT:\n \tcase OBJ_TREE:\ndiff --git a/pathspec.c b/pathspec.c\nindex 82eb39cd679..a637a6d15c0 100644\n--- a/pathspec.c\n+++ b/pathspec.c\n@@ -198,7 +198,7 @@ static void parse_pathspec_attr_match(struct pathspec_item *item, const char *va\n \t}\n \n \tif (item->attr_check->nr != item->attr_match_nr)\n-\t\tdie(\"BUG: should have same number of entries\");\n+\t\tBUG(\"should have same number of entries\");\n \n \tstring_list_clear(&list, 0);\n }\n@@ -422,7 +422,7 @@ static void init_pathspec_item(struct pathspec_item *item, unsigned flags,\n \n \tif (pathspec_prefix >= 0 &&\n \t    (prefixlen || (prefix && *prefix)))\n-\t\tdie(\"BUG: 'prefix' magic is supposed to be used at worktree's root\");\n+\t\tBUG(\"'prefix' magic is supposed to be used at worktree's root\");\n \n \tif ((magic & PATHSPEC_LITERAL) && (magic & PATHSPEC_GLOB))\n \t\tdie(_(\"%s: 'literal' and 'glob' are incompatible\"), elt);\n@@ -545,7 +545,7 @@ void parse_pathspec(struct pathspec *pathspec,\n \n \tif ((flags & PATHSPEC_PREFER_CWD) &&\n \t    (flags & PATHSPEC_PREFER_FULL))\n-\t\tdie(\"BUG: PATHSPEC_PREFER_CWD and PATHSPEC_PREFER_FULL are incompatible\");\n+\t\tBUG(\"PATHSPEC_PREFER_CWD and PATHSPEC_PREFER_FULL are incompatible\");\n \n \t/* No arguments with prefix -> prefix pathspec */\n \tif (!entry) {\n@@ -553,7 +553,7 @@ void parse_pathspec(struct pathspec *pathspec,\n \t\t\treturn;\n \n \t\tif (!(flags & PATHSPEC_PREFER_CWD))\n-\t\t\tdie(\"BUG: PATHSPEC_PREFER_CWD requires arguments\");\n+\t\t\tBUG(\"PATHSPEC_PREFER_CWD requires arguments\");\n \n \t\tpathspec->items = item = xcalloc(1, sizeof(*item));\n \t\titem->match = xstrdup(prefix);\n@@ -609,7 +609,7 @@ void parse_pathspec(struct pathspec *pathspec,\n \n \tif (pathspec->magic & PATHSPEC_MAXDEPTH) {\n \t\tif (flags & PATHSPEC_KEEP_ORDER)\n-\t\t\tdie(\"BUG: PATHSPEC_MAXDEPTH_VALID and PATHSPEC_KEEP_ORDER are incompatible\");\n+\t\t\tBUG(\"PATHSPEC_MAXDEPTH_VALID and PATHSPEC_KEEP_ORDER are incompatible\");\n \t\tQSORT(pathspec->items, pathspec->nr, pathspec_item_cmp);\n \t}\n }\ndiff --git a/pkt-line.c b/pkt-line.c\nindex 2827ca772a3..cd3dab4025a 100644\n--- a/pkt-line.c\n+++ b/pkt-line.c\n@@ -249,7 +249,7 @@ static int get_packet_data(int fd, char **src_buf, size_t *src_size,\n \tssize_t ret;\n \n \tif (fd >= 0 && src_buf && *src_buf)\n-\t\tdie(\"BUG: multiple sources given to packet_read\");\n+\t\tBUG(\"multiple sources given to packet_read\");\n \n \t/* Read up to \"size\" bytes from our source, whatever it is. */\n \tif (src_buf && *src_buf) {\ndiff --git a/prio-queue.c b/prio-queue.c\nindex 126d0967273..a0784518723 100644\n--- a/prio-queue.c\n+++ b/prio-queue.c\n@@ -20,7 +20,7 @@ void prio_queue_reverse(struct prio_queue *queue)\n \tint i, j;\n \n \tif (queue->compare != NULL)\n-\t\tdie(\"BUG: prio_queue_reverse() on non-LIFO queue\");\n+\t\tBUG(\"prio_queue_reverse() on non-LIFO queue\");\n \tfor (i = 0; i < (j = (queue->nr - 1) - i); i++)\n \t\tswap(queue, i, j);\n }\ndiff --git a/ref-filter.c b/ref-filter.c\nindex ac82f9f21e1..0291feaf0db 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -751,7 +751,7 @@ static int grab_objectname(const char *name, const struct object_id *oid,\n \t\t\tv->s = xstrdup(find_unique_abbrev(oid, atom->u.objectname.length));\n \t\t\treturn 1;\n \t\t} else\n-\t\t\tdie(\"BUG: unknown %%(objectname) option\");\n+\t\t\tBUG(\"unknown %%(objectname) option\");\n \t}\n \treturn 0;\n }\n@@ -1299,7 +1299,7 @@ static void fill_remote_ref_details(struct used_atom *atom, const char *refname,\n \t\telse\n \t\t\t*s = \"\";\n \t} else\n-\t\tdie(\"BUG: unhandled RR_* enum\");\n+\t\tBUG(\"unhandled RR_* enum\");\n }\n \n char *get_head_description(void)\ndiff --git a/refs.c b/refs.c\nindex 8b7a77fe5ee..f7a577c0d60 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -944,10 +944,10 @@ void ref_transaction_free(struct ref_transaction *transaction)\n \t\t/* OK */\n \t\tbreak;\n \tcase REF_TRANSACTION_PREPARED:\n-\t\tdie(\"BUG: free called on a prepared reference transaction\");\n+\t\tBUG(\"free called on a prepared reference transaction\");\n \t\tbreak;\n \tdefault:\n-\t\tdie(\"BUG: unexpected reference transaction state\");\n+\t\tBUG(\"unexpected reference transaction state\");\n \t\tbreak;\n \t}\n \n@@ -969,7 +969,7 @@ struct ref_update *ref_transaction_add_update(\n \tstruct ref_update *update;\n \n \tif (transaction->state != REF_TRANSACTION_OPEN)\n-\t\tdie(\"BUG: update called for transaction that is not open\");\n+\t\tBUG(\"update called for transaction that is not open\");\n \n \tFLEX_ALLOC_STR(update, refname, refname);\n \tALLOC_GROW(transaction->updates, transaction->nr + 1, transaction->alloc);\n@@ -1019,7 +1019,7 @@ int ref_transaction_create(struct ref_transaction *transaction,\n \t\t\t   struct strbuf *err)\n {\n \tif (!new_oid || is_null_oid(new_oid))\n-\t\tdie(\"BUG: create called without valid new_oid\");\n+\t\tBUG(\"create called without valid new_oid\");\n \treturn ref_transaction_update(transaction, refname, new_oid,\n \t\t\t\t      &null_oid, flags, msg, err);\n }\n@@ -1031,7 +1031,7 @@ int ref_transaction_delete(struct ref_transaction *transaction,\n \t\t\t   struct strbuf *err)\n {\n \tif (old_oid && is_null_oid(old_oid))\n-\t\tdie(\"BUG: delete called with old_oid set to zeros\");\n+\t\tBUG(\"delete called with old_oid set to zeros\");\n \treturn ref_transaction_update(transaction, refname,\n \t\t\t\t      &null_oid, old_oid,\n \t\t\t\t      flags, msg, err);\n@@ -1044,7 +1044,7 @@ int ref_transaction_verify(struct ref_transaction *transaction,\n \t\t\t   struct strbuf *err)\n {\n \tif (!old_oid)\n-\t\tdie(\"BUG: verify called with old_oid set to NULL\");\n+\t\tBUG(\"verify called with old_oid set to NULL\");\n \treturn ref_transaction_update(transaction, refname,\n \t\t\t\t      NULL, old_oid,\n \t\t\t\t      flags, NULL, err);\n@@ -1645,7 +1645,7 @@ static struct ref_store *ref_store_init(const char *gitdir,\n \tstruct ref_store *refs;\n \n \tif (!be)\n-\t\tdie(\"BUG: reference backend %s is unknown\", be_name);\n+\t\tBUG(\"reference backend %s is unknown\", be_name);\n \n \trefs = be->init(gitdir, flags);\n \treturn refs;\n@@ -1673,7 +1673,7 @@ static void register_ref_store_map(struct hashmap *map,\n \t\thashmap_init(map, ref_store_hash_cmp, NULL, 0);\n \n \tif (hashmap_put(map, alloc_ref_store_hash_entry(name, refs)))\n-\t\tdie(\"BUG: %s ref_store '%s' initialized twice\", type, name);\n+\t\tBUG(\"%s ref_store '%s' initialized twice\", type, name);\n }\n \n struct ref_store *get_submodule_ref_store(const char *submodule)\n@@ -1819,7 +1819,7 @@ int ref_update_reject_duplicates(struct string_list *refnames,\n \t\t\t\t    refnames->items[i].string);\n \t\t\treturn 1;\n \t\t} else if (cmp > 0) {\n-\t\t\tdie(\"BUG: ref_update_reject_duplicates() received unsorted list\");\n+\t\t\tBUG(\"ref_update_reject_duplicates() received unsorted list\");\n \t\t}\n \t}\n \treturn 0;\n@@ -1835,13 +1835,13 @@ int ref_transaction_prepare(struct ref_transaction *transaction,\n \t\t/* Good. */\n \t\tbreak;\n \tcase REF_TRANSACTION_PREPARED:\n-\t\tdie(\"BUG: prepare called twice on reference transaction\");\n+\t\tBUG(\"prepare called twice on reference transaction\");\n \t\tbreak;\n \tcase REF_TRANSACTION_CLOSED:\n-\t\tdie(\"BUG: prepare called on a closed reference transaction\");\n+\t\tBUG(\"prepare called on a closed reference transaction\");\n \t\tbreak;\n \tdefault:\n-\t\tdie(\"BUG: unexpected reference transaction state\");\n+\t\tBUG(\"unexpected reference transaction state\");\n \t\tbreak;\n \t}\n \n@@ -1868,10 +1868,10 @@ int ref_transaction_abort(struct ref_transaction *transaction,\n \t\tret = refs->be->transaction_abort(refs, transaction, err);\n \t\tbreak;\n \tcase REF_TRANSACTION_CLOSED:\n-\t\tdie(\"BUG: abort called on a closed reference transaction\");\n+\t\tBUG(\"abort called on a closed reference transaction\");\n \t\tbreak;\n \tdefault:\n-\t\tdie(\"BUG: unexpected reference transaction state\");\n+\t\tBUG(\"unexpected reference transaction state\");\n \t\tbreak;\n \t}\n \n@@ -1896,10 +1896,10 @@ int ref_transaction_commit(struct ref_transaction *transaction,\n \t\t/* Fall through to finish. */\n \t\tbreak;\n \tcase REF_TRANSACTION_CLOSED:\n-\t\tdie(\"BUG: commit called on a closed reference transaction\");\n+\t\tBUG(\"commit called on a closed reference transaction\");\n \t\tbreak;\n \tdefault:\n-\t\tdie(\"BUG: unexpected reference transaction state\");\n+\t\tBUG(\"unexpected reference transaction state\");\n \t\tbreak;\n \t}\n \n@@ -1980,7 +1980,7 @@ int refs_verify_refname_available(struct ref_store *refs,\n \t}\n \n \tif (ok != ITER_DONE)\n-\t\tdie(\"BUG: error while iterating over references\");\n+\t\tBUG(\"error while iterating over references\");\n \n \textra_refname = find_descendant_ref(dirname.buf, extras, skip);\n \tif (extra_refname)\ndiff --git a/refs/files-backend.c b/refs/files-backend.c\nindex a92a2aa8213..332da47edd9 100644\n--- a/refs/files-backend.c\n+++ b/refs/files-backend.c\n@@ -125,7 +125,7 @@ static void files_assert_main_repository(struct files_ref_store *refs,\n \tif (refs->store_flags & REF_STORE_MAIN)\n \t\treturn;\n \n-\tdie(\"BUG: operation %s only allowed for main ref store\", caller);\n+\tBUG(\"operation %s only allowed for main ref store\", caller);\n }\n \n /*\n@@ -141,13 +141,13 @@ static struct files_ref_store *files_downcast(struct ref_store *ref_store,\n \tstruct files_ref_store *refs;\n \n \tif (ref_store->be != &refs_be_files)\n-\t\tdie(\"BUG: ref_store is type \\\"%s\\\" not \\\"files\\\" in %s\",\n+\t\tBUG(\"ref_store is type \\\"%s\\\" not \\\"files\\\" in %s\",\n \t\t    ref_store->be->name, caller);\n \n \trefs = (struct files_ref_store *)ref_store;\n \n \tif ((refs->store_flags & required_flags) != required_flags)\n-\t\tdie(\"BUG: operation %s requires abilities 0x%x, but only have 0x%x\",\n+\t\tBUG(\"operation %s requires abilities 0x%x, but only have 0x%x\",\n \t\t    caller, required_flags, refs->store_flags);\n \n \treturn refs;\n@@ -166,7 +166,7 @@ static void files_reflog_path(struct files_ref_store *refs,\n \t\tstrbuf_addf(sb, \"%s/logs/%s\", refs->gitcommondir, refname);\n \t\tbreak;\n \tdefault:\n-\t\tdie(\"BUG: unknown ref type %d of ref %s\",\n+\t\tBUG(\"unknown ref type %d of ref %s\",\n \t\t    ref_type(refname), refname);\n \t}\n }\n@@ -184,7 +184,7 @@ static void files_ref_path(struct files_ref_store *refs,\n \t\tstrbuf_addf(sb, \"%s/%s\", refs->gitcommondir, refname);\n \t\tbreak;\n \tdefault:\n-\t\tdie(\"BUG: unknown ref type %d of ref %s\",\n+\t\tBUG(\"unknown ref type %d of ref %s\",\n \t\t    ref_type(refname), refname);\n \t}\n }\n@@ -2010,7 +2010,7 @@ static int files_for_each_reflog_ent_reverse(struct ref_store *ref_store,\n \n \t}\n \tif (!ret && sb.len)\n-\t\tdie(\"BUG: reverse reflog parser had leftover data\");\n+\t\tBUG(\"reverse reflog parser had leftover data\");\n \n \tfclose(logfp);\n \tstrbuf_release(&sb);\n@@ -2088,7 +2088,7 @@ static int files_reflog_iterator_advance(struct ref_iterator *ref_iterator)\n static int files_reflog_iterator_peel(struct ref_iterator *ref_iterator,\n \t\t\t\t   struct object_id *peeled)\n {\n-\tdie(\"BUG: ref_iterator_peel() called for reflog_iterator\");\n+\tBUG(\"ref_iterator_peel() called for reflog_iterator\");\n }\n \n static int files_reflog_iterator_abort(struct ref_iterator *ref_iterator)\n@@ -2873,7 +2873,7 @@ static int files_initial_transaction_commit(struct ref_store *ref_store,\n \tassert(err);\n \n \tif (transaction->state != REF_TRANSACTION_OPEN)\n-\t\tdie(\"BUG: commit called for transaction that is not open\");\n+\t\tBUG(\"commit called for transaction that is not open\");\n \n \t/* Fail if a refname appears more than once in the transaction: */\n \tfor (i = 0; i < transaction->nr; i++)\n@@ -2899,7 +2899,7 @@ static int files_initial_transaction_commit(struct ref_store *ref_store,\n \t */\n \tif (refs_for_each_rawref(&refs->base, ref_present,\n \t\t\t\t &affected_refnames))\n-\t\tdie(\"BUG: initial ref transaction called with existing refs\");\n+\t\tBUG(\"initial ref transaction called with existing refs\");\n \n \tpacked_transaction = ref_store_transaction_begin(refs->packed_ref_store, err);\n \tif (!packed_transaction) {\n@@ -2912,7 +2912,7 @@ static int files_initial_transaction_commit(struct ref_store *ref_store,\n \n \t\tif ((update->flags & REF_HAVE_OLD) &&\n \t\t    !is_null_oid(&update->old_oid))\n-\t\t\tdie(\"BUG: initial ref transaction with old_sha1 set\");\n+\t\t\tBUG(\"initial ref transaction with old_sha1 set\");\n \t\tif (refs_verify_refname_available(&refs->base, update->refname,\n \t\t\t\t\t\t  &affected_refnames, NULL,\n \t\t\t\t\t\t  err)) {\ndiff --git a/refs/iterator.c b/refs/iterator.c\nindex bd35da4e622..2ac91ac3401 100644\n--- a/refs/iterator.c\n+++ b/refs/iterator.c\n@@ -54,7 +54,7 @@ static int empty_ref_iterator_advance(struct ref_iterator *ref_iterator)\n static int empty_ref_iterator_peel(struct ref_iterator *ref_iterator,\n \t\t\t\t   struct object_id *peeled)\n {\n-\tdie(\"BUG: peel called for empty iterator\");\n+\tBUG(\"peel called for empty iterator\");\n }\n \n static int empty_ref_iterator_abort(struct ref_iterator *ref_iterator)\n@@ -177,7 +177,7 @@ static int merge_ref_iterator_peel(struct ref_iterator *ref_iterator,\n \t\t(struct merge_ref_iterator *)ref_iterator;\n \n \tif (!iter->current) {\n-\t\tdie(\"BUG: peel called before advance for merge iterator\");\n+\t\tBUG(\"peel called before advance for merge iterator\");\n \t}\n \treturn ref_iterator_peel(*iter->current, peeled);\n }\n@@ -338,7 +338,7 @@ static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator)\n \t\t\t * trimming, report it as a bug:\n \t\t\t */\n \t\t\tif (strlen(iter->iter0->refname) <= iter->trim)\n-\t\t\t\tdie(\"BUG: attempt to trim too many characters\");\n+\t\t\t\tBUG(\"attempt to trim too many characters\");\n \t\t\titer->base.refname = iter->iter0->refname + iter->trim;\n \t\t} else {\n \t\t\titer->base.refname = iter->iter0->refname;\ndiff --git a/refs/packed-backend.c b/refs/packed-backend.c\nindex 369c34f886f..cec3fb9e00f 100644\n--- a/refs/packed-backend.c\n+++ b/refs/packed-backend.c\n@@ -221,13 +221,13 @@ static struct packed_ref_store *packed_downcast(struct ref_store *ref_store,\n \tstruct packed_ref_store *refs;\n \n \tif (ref_store->be != &refs_be_packed)\n-\t\tdie(\"BUG: ref_store is type \\\"%s\\\" not \\\"packed\\\" in %s\",\n+\t\tBUG(\"ref_store is type \\\"%s\\\" not \\\"packed\\\" in %s\",\n \t\t    ref_store->be->name, caller);\n \n \trefs = (struct packed_ref_store *)ref_store;\n \n \tif ((refs->store_flags & required_flags) != required_flags)\n-\t\tdie(\"BUG: unallowed operation (%s), requires %x, has %x\\n\",\n+\t\tBUG(\"unallowed operation (%s), requires %x, has %x\\n\",\n \t\t    caller, required_flags, refs->store_flags);\n \n \treturn refs;\n@@ -1036,7 +1036,7 @@ void packed_refs_unlock(struct ref_store *ref_store)\n \t\t\t\"packed_refs_unlock\");\n \n \tif (!is_lock_file_locked(&refs->lock))\n-\t\tdie(\"BUG: packed_refs_unlock() called when not locked\");\n+\t\tBUG(\"packed_refs_unlock() called when not locked\");\n \trollback_lock_file(&refs->lock);\n }\n \n@@ -1089,7 +1089,7 @@ static int write_with_updates(struct packed_ref_store *refs,\n \tchar *packed_refs_path;\n \n \tif (!is_lock_file_locked(&refs->lock))\n-\t\tdie(\"BUG: write_with_updates() called while unlocked\");\n+\t\tBUG(\"write_with_updates() called while unlocked\");\n \n \t/*\n \t * If packed-refs is a symlink, we want to overwrite the\n@@ -1563,21 +1563,21 @@ static int packed_create_symref(struct ref_store *ref_store,\n \t\t\t       const char *refname, const char *target,\n \t\t\t       const char *logmsg)\n {\n-\tdie(\"BUG: packed reference store does not support symrefs\");\n+\tBUG(\"packed reference store does not support symrefs\");\n }\n \n static int packed_rename_ref(struct ref_store *ref_store,\n \t\t\t    const char *oldrefname, const char *newrefname,\n \t\t\t    const char *logmsg)\n {\n-\tdie(\"BUG: packed reference store does not support renaming references\");\n+\tBUG(\"packed reference store does not support renaming references\");\n }\n \n static int packed_copy_ref(struct ref_store *ref_store,\n \t\t\t   const char *oldrefname, const char *newrefname,\n \t\t\t   const char *logmsg)\n {\n-\tdie(\"BUG: packed reference store does not support copying references\");\n+\tBUG(\"packed reference store does not support copying references\");\n }\n \n static struct ref_iterator *packed_reflog_iterator_begin(struct ref_store *ref_store)\n@@ -1610,7 +1610,7 @@ static int packed_create_reflog(struct ref_store *ref_store,\n \t\t\t       const char *refname, int force_create,\n \t\t\t       struct strbuf *err)\n {\n-\tdie(\"BUG: packed reference store does not support reflogs\");\n+\tBUG(\"packed reference store does not support reflogs\");\n }\n \n static int packed_delete_reflog(struct ref_store *ref_store,\ndiff --git a/refs/ref-cache.c b/refs/ref-cache.c\nindex e90bd3e727f..9b110c8494f 100644\n--- a/refs/ref-cache.c\n+++ b/refs/ref-cache.c\n@@ -23,7 +23,7 @@ struct ref_dir *get_ref_dir(struct ref_entry *entry)\n \tdir = &entry->u.subdir;\n \tif (entry->flag & REF_INCOMPLETE) {\n \t\tif (!dir->cache->fill_ref_dir)\n-\t\t\tdie(\"BUG: incomplete ref_store without fill_ref_dir function\");\n+\t\t\tBUG(\"incomplete ref_store without fill_ref_dir function\");\n \n \t\tdir->cache->fill_ref_dir(dir->cache->ref_store, dir, entry->name);\n \t\tentry->flag &= ~REF_INCOMPLETE;\ndiff --git a/remote.c b/remote.c\nindex 91eb010ca98..63c41787882 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -1819,7 +1819,7 @@ static const char *branch_get_push_1(struct branch *branch, struct strbuf *err)\n \t\t}\n \t}\n \n-\tdie(\"BUG: unhandled push situation\");\n+\tBUG(\"unhandled push situation\");\n }\n \n const char *branch_get_push(struct branch *branch, struct strbuf *err)\ndiff --git a/revision.c b/revision.c\nindex b42c836d7a6..67f8e74cbb3 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -2107,7 +2107,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t\trevs->ignore_missing = 1;\n \t} else if (!strcmp(arg, \"--exclude-promisor-objects\")) {\n \t\tif (fetch_if_missing)\n-\t\t\tdie(\"BUG: exclude_promisor_objects can only be used when fetch_if_missing is 0\");\n+\t\t\tBUG(\"exclude_promisor_objects can only be used when fetch_if_missing is 0\");\n \t\trevs->exclude_promisor_objects = 1;\n \t} else {\n \t\tint opts = diff_opt_parse(&revs->diffopt, argv, argc, revs->prefix);\n@@ -2173,7 +2173,7 @@ static int handle_revision_pseudo_opt(const char *submodule,\n \t\t * supported right now, so stick to single worktree.\n \t\t */\n \t\tif (!revs->single_worktree)\n-\t\t\tdie(\"BUG: --single-worktree cannot be used together with submodule\");\n+\t\t\tBUG(\"--single-worktree cannot be used together with submodule\");\n \t\trefs = get_submodule_ref_store(submodule);\n \t} else\n \t\trefs = get_main_ref_store();\ndiff --git a/run-command.c b/run-command.c\nindex 0ad6f135d5a..84b883c2132 100644\n--- a/run-command.c\n+++ b/run-command.c\n@@ -245,7 +245,7 @@ int sane_execvp(const char *file, char * const argv[])\n static const char **prepare_shell_cmd(struct argv_array *out, const char **argv)\n {\n \tif (!argv[0])\n-\t\tdie(\"BUG: shell command is empty\");\n+\t\tBUG(\"shell command is empty\");\n \n \tif (strcspn(argv[0], \"|&;<>()$`\\\\\\\"' \\t\\n*?[#~=%\") != strlen(argv[0])) {\n #ifndef GIT_WINDOWS_NATIVE\n@@ -383,7 +383,7 @@ static void child_err_spew(struct child_process *cmd, struct child_err *cerr)\n static void prepare_cmd(struct argv_array *out, const struct child_process *cmd)\n {\n \tif (!cmd->argv[0])\n-\t\tdie(\"BUG: command is empty\");\n+\t\tBUG(\"command is empty\");\n \n \t/*\n \t * Add SHELL_PATH so in the event exec fails with ENOEXEC we can\n@@ -964,7 +964,7 @@ int run_command(struct child_process *cmd)\n \tint code;\n \n \tif (cmd->out < 0 || cmd->err < 0)\n-\t\tdie(\"BUG: run_command with a pipe can cause deadlock\");\n+\t\tBUG(\"run_command with a pipe can cause deadlock\");\n \n \tcode = start_command(cmd);\n \tif (code)\n@@ -1554,7 +1554,7 @@ static void pp_init(struct parallel_processes *pp,\n \n \tpp->data = data;\n \tif (!get_next_task)\n-\t\tdie(\"BUG: you need to specify a get_next_task function\");\n+\t\tBUG(\"you need to specify a get_next_task function\");\n \tpp->get_next_task = get_next_task;\n \n \tpp->start_failure = start_failure ? start_failure : default_start_failure;\n@@ -1616,7 +1616,7 @@ static int pp_start_one(struct parallel_processes *pp)\n \t\tif (pp->children[i].state == GIT_CP_FREE)\n \t\t\tbreak;\n \tif (i == pp->max_processes)\n-\t\tdie(\"BUG: bookkeeping is hard\");\n+\t\tBUG(\"bookkeeping is hard\");\n \n \tcode = pp->get_next_task(&pp->children[i].process,\n \t\t\t\t &pp->children[i].err,\ndiff --git a/setup.c b/setup.c\nindex 3e03d442b6f..b24c811c1c3 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -539,7 +539,7 @@ void read_gitfile_error_die(int error_code, const char *path, const char *dir)\n \tcase READ_GITFILE_ERR_NOT_A_REPO:\n \t\tdie(_(\"not a git repository: %s\"), dir);\n \tdefault:\n-\t\tdie(\"BUG: unknown error code\");\n+\t\tBUG(\"unknown error code\");\n \t}\n }\n \n@@ -1086,7 +1086,7 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \t\t      \"Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).\"),\n \t\t    dir.buf);\n \tdefault:\n-\t\tdie(\"BUG: unhandled setup_git_directory_1() result\");\n+\t\tBUG(\"unhandled setup_git_directory_1() result\");\n \t}\n \n \tif (prefix)\ndiff --git a/sha1-lookup.c b/sha1-lookup.c\nindex 8d0b1db3e27..796ab68da83 100644\n--- a/sha1-lookup.c\n+++ b/sha1-lookup.c\n@@ -81,7 +81,7 @@ int sha1_pos(const unsigned char *sha1, void *table, size_t nr,\n \t\t\t\tmi = (nr - 1) * (miv - lov) / (hiv - lov);\n \t\t\t\tif (lo <= mi && mi < hi)\n \t\t\t\t\tbreak;\n-\t\t\t\tdie(\"BUG: assertion failed in binary search\");\n+\t\t\t\tBUG(\"assertion failed in binary search\");\n \t\t\t}\n \t\t}\n \t}\ndiff --git a/sha1-name.c b/sha1-name.c\nindex 5b93bf8da36..60d04bf74e1 100644\n--- a/sha1-name.c\n+++ b/sha1-name.c\n@@ -384,7 +384,7 @@ static int get_short_oid(const char *name, int len, struct object_id *oid,\n \t\treturn -1;\n \n \tif (HAS_MULTI_BITS(flags & GET_OID_DISAMBIGUATORS))\n-\t\tdie(\"BUG: multiple get_short_oid disambiguator flags\");\n+\t\tBUG(\"multiple get_short_oid disambiguator flags\");\n \n \tif (flags & GET_OID_COMMIT)\n \t\tds.fn = disambiguate_commit_only;\n@@ -1729,6 +1729,6 @@ void maybe_die_on_misspelt_object_name(const char *name, const char *prefix)\n int get_oid_with_context(const char *str, unsigned flags, struct object_id *oid, struct object_context *oc)\n {\n \tif (flags & GET_OID_FOLLOW_SYMLINKS && flags & GET_OID_ONLY_TO_DIE)\n-\t\tdie(\"BUG: incompatible flags for get_sha1_with_context\");\n+\t\tBUG(\"incompatible flags for get_sha1_with_context\");\n \treturn get_oid_with_context_1(str, flags, NULL, oid, oc);\n }\ndiff --git a/shallow.c b/shallow.c\nindex df4d44ea7a3..c7b6b3d9d8a 100644\n--- a/shallow.c\n+++ b/shallow.c\n@@ -20,7 +20,7 @@ static char *alternate_shallow_file;\n void set_alternate_shallow_file(const char *path, int override)\n {\n \tif (is_shallow != -1)\n-\t\tdie(\"BUG: is_repository_shallow must not be called before set_alternate_shallow_file\");\n+\t\tBUG(\"is_repository_shallow must not be called before set_alternate_shallow_file\");\n \tif (alternate_shallow_file && !override)\n \t\treturn;\n \tfree(alternate_shallow_file);\n@@ -218,7 +218,7 @@ struct commit_list *get_shallow_commits_by_rev_list(int ac, const char **av,\n static void check_shallow_file_for_update(void)\n {\n \tif (is_shallow == -1)\n-\t\tdie(\"BUG: shallow must be initialized by now\");\n+\t\tBUG(\"shallow must be initialized by now\");\n \n \tif (!stat_validity_check(&shallow_stat, git_path_shallow()))\n \t\tdie(\"shallow file has changed since we read it\");\n@@ -446,7 +446,7 @@ static uint32_t *paint_alloc(struct paint_info *info)\n \tvoid *p;\n \tif (!info->pool_count || size > info->end - info->free) {\n \t\tif (size > POOL_SIZE)\n-\t\t\tdie(\"BUG: pool size too small for %d in paint_alloc()\",\n+\t\t\tBUG(\"pool size too small for %d in paint_alloc()\",\n \t\t\t    size);\n \t\tinfo->pool_count++;\n \t\tREALLOC_ARRAY(info->pools, info->pool_count);\ndiff --git a/sigchain.c b/sigchain.c\nindex 2ac43bbd282..022677b6aba 100644\n--- a/sigchain.c\n+++ b/sigchain.c\n@@ -13,7 +13,7 @@ static struct sigchain_signal signals[SIGCHAIN_MAX_SIGNALS];\n static void check_signum(int sig)\n {\n \tif (sig < 1 || sig >= SIGCHAIN_MAX_SIGNALS)\n-\t\tdie(\"BUG: signal out of range: %d\", sig);\n+\t\tBUG(\"signal out of range: %d\", sig);\n }\n \n int sigchain_push(int sig, sigchain_fun f)\ndiff --git a/strbuf.c b/strbuf.c\nindex 43a840c67b3..2954622c103 100644\n--- a/strbuf.c\n+++ b/strbuf.c\n@@ -309,12 +309,12 @@ void strbuf_vaddf(struct strbuf *sb, const char *fmt, va_list ap)\n \tlen = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, cp);\n \tva_end(cp);\n \tif (len < 0)\n-\t\tdie(\"BUG: your vsnprintf is broken (returned %d)\", len);\n+\t\tBUG(\"your vsnprintf is broken (returned %d)\", len);\n \tif (len > strbuf_avail(sb)) {\n \t\tstrbuf_grow(sb, len);\n \t\tlen = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);\n \t\tif (len > strbuf_avail(sb))\n-\t\t\tdie(\"BUG: your vsnprintf is broken (insatiable)\");\n+\t\t\tBUG(\"your vsnprintf is broken (insatiable)\");\n \t}\n \tstrbuf_setlen(sb, sb->len + len);\n }\ndiff --git a/submodule.c b/submodule.c\nindex 9a50168b237..733db441714 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -1398,7 +1398,7 @@ unsigned is_submodule_modified(const char *path, int ignore_untracked)\n \t\t    buf.buf[0] == '2') {\n \t\t\t/* T = line type, XY = status, SSSS = submodule state */\n \t\t\tif (buf.len < strlen(\"T XY SSSS\"))\n-\t\t\t\tdie(\"BUG: invalid status --porcelain=2 line %s\",\n+\t\t\t\tBUG(\"invalid status --porcelain=2 line %s\",\n \t\t\t\t    buf.buf);\n \n \t\t\tif (buf.buf[5] == 'S' && buf.buf[8] == 'U')\n@@ -1607,7 +1607,7 @@ int submodule_move_head(const char *path,\n \tsub = submodule_from_path(&null_oid, path);\n \n \tif (!sub)\n-\t\tdie(\"BUG: could not get submodule information for '%s'\", path);\n+\t\tBUG(\"could not get submodule information for '%s'\", path);\n \n \tif (old_head && !(flags & SUBMODULE_MOVE_HEAD_FORCE)) {\n \t\t/* Check if the submodule has a dirty index. */\n@@ -1965,7 +1965,7 @@ void absorb_git_dir_into_superproject(const char *prefix,\n \t\tstruct strbuf sb = STRBUF_INIT;\n \n \t\tif (flags & ~ABSORB_GITDIR_RECURSE_SUBMODULES)\n-\t\t\tdie(\"BUG: we don't know how to pass the flags down?\");\n+\t\t\tBUG(\"we don't know how to pass the flags down?\");\n \n \t\tstrbuf_addstr(&sb, get_super_prefix_or_empty());\n \t\tstrbuf_addstr(&sb, path);\ndiff --git a/t/helper/test-example-decorate.c b/t/helper/test-example-decorate.c\nindex 081115bf8eb..a20a6161e4f 100644\n--- a/t/helper/test-example-decorate.c\n+++ b/t/helper/test-example-decorate.c\n@@ -30,10 +30,10 @@ int cmd__example_decorate(int argc, const char **argv)\n \ttwo = lookup_unknown_object(two_oid.hash);\n \tret = add_decoration(&n, one, &decoration_a);\n \tif (ret)\n-\t\tdie(\"BUG: when adding a brand-new object, NULL should be returned\");\n+\t\tBUG(\"when adding a brand-new object, NULL should be returned\");\n \tret = add_decoration(&n, two, NULL);\n \tif (ret)\n-\t\tdie(\"BUG: when adding a brand-new object, NULL should be returned\");\n+\t\tBUG(\"when adding a brand-new object, NULL should be returned\");\n \n \t/*\n \t * When re-adding an already existing object, the old decoration is\n@@ -41,10 +41,10 @@ int cmd__example_decorate(int argc, const char **argv)\n \t */\n \tret = add_decoration(&n, one, NULL);\n \tif (ret != &decoration_a)\n-\t\tdie(\"BUG: when readding an already existing object, existing decoration should be returned\");\n+\t\tBUG(\"when readding an already existing object, existing decoration should be returned\");\n \tret = add_decoration(&n, two, &decoration_b);\n \tif (ret)\n-\t\tdie(\"BUG: when readding an already existing object, existing decoration should be returned\");\n+\t\tBUG(\"when readding an already existing object, existing decoration should be returned\");\n \n \t/*\n \t * Lookup returns the added declarations, or NULL if the object was\n@@ -52,14 +52,14 @@ int cmd__example_decorate(int argc, const char **argv)\n \t */\n \tret = lookup_decoration(&n, one);\n \tif (ret)\n-\t\tdie(\"BUG: lookup should return added declaration\");\n+\t\tBUG(\"lookup should return added declaration\");\n \tret = lookup_decoration(&n, two);\n \tif (ret != &decoration_b)\n-\t\tdie(\"BUG: lookup should return added declaration\");\n+\t\tBUG(\"lookup should return added declaration\");\n \tthree = lookup_unknown_object(three_oid.hash);\n \tret = lookup_decoration(&n, three);\n \tif (ret)\n-\t\tdie(\"BUG: lookup for unknown object should return NULL\");\n+\t\tBUG(\"lookup for unknown object should return NULL\");\n \n \t/*\n \t * The user can also loop through all entries.\n@@ -69,7 +69,7 @@ int cmd__example_decorate(int argc, const char **argv)\n \t\t\tobjects_noticed++;\n \t}\n \tif (objects_noticed != 2)\n-\t\tdie(\"BUG: should have 2 objects\");\n+\t\tBUG(\"should have 2 objects\");\n \n \treturn 0;\n }\ndiff --git a/tmp-objdir.c b/tmp-objdir.c\nindex fea3f55545c..91c00567f4d 100644\n--- a/tmp-objdir.c\n+++ b/tmp-objdir.c\n@@ -127,7 +127,7 @@ struct tmp_objdir *tmp_objdir_create(void)\n \tstruct tmp_objdir *t;\n \n \tif (the_tmp_objdir)\n-\t\tdie(\"BUG: only one tmp_objdir can be used at a time\");\n+\t\tBUG(\"only one tmp_objdir can be used at a time\");\n \n \tt = xmalloc(sizeof(*t));\n \tstrbuf_init(&t->path, 0);\ndiff --git a/trailer.c b/trailer.c\nindex c508c9b7521..4e309460d13 100644\n--- a/trailer.c\n+++ b/trailer.c\n@@ -298,7 +298,7 @@ static void apply_arg_if_exists(struct trailer_item *in_tok,\n \t\t\tfree_arg_item(arg_tok);\n \t\tbreak;\n \tdefault:\n-\t\tdie(\"BUG: trailer.c: unhandled value %d\",\n+\t\tBUG(\"trailer.c: unhandled value %d\",\n \t\t    arg_tok->conf.if_exists);\n \t}\n }\n@@ -323,7 +323,7 @@ static void apply_arg_if_missing(struct list_head *head,\n \t\t\tlist_add(&to_add->list, head);\n \t\tbreak;\n \tdefault:\n-\t\tdie(\"BUG: trailer.c: unhandled value %d\",\n+\t\tBUG(\"trailer.c: unhandled value %d\",\n \t\t    arg_tok->conf.if_missing);\n \t}\n }\n@@ -557,7 +557,7 @@ static int git_trailer_config(const char *conf_key, const char *value, void *cb)\n \t\t\twarning(_(\"unknown value '%s' for key '%s'\"), value, conf_key);\n \t\tbreak;\n \tdefault:\n-\t\tdie(\"BUG: trailer.c: unhandled type %d\", type);\n+\t\tBUG(\"trailer.c: unhandled type %d\", type);\n \t}\n \treturn 0;\n }\ndiff --git a/transport.c b/transport.c\nindex 94eccf29aa3..969645ccb13 100644\n--- a/transport.c\n+++ b/transport.c\n@@ -636,7 +636,7 @@ void transport_take_over(struct transport *transport,\n \tstruct git_transport_data *data;\n \n \tif (!transport->smart_options)\n-\t\tdie(\"BUG: taking over transport requires non-NULL \"\n+\t\tBUG(\"taking over transport requires non-NULL \"\n \t\t    \"smart_options field.\");\n \n \tdata = xcalloc(1, sizeof(*data));\n@@ -761,7 +761,7 @@ int is_transport_allowed(const char *type, int from_user)\n \t\treturn from_user;\n \t}\n \n-\tdie(\"BUG: invalid protocol_allow_config type\");\n+\tBUG(\"invalid protocol_allow_config type\");\n }\n \n void transport_check_allowed(const char *type)\ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex e73745051e5..4239dfd285e 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -398,7 +398,7 @@ static int check_updates(struct unpack_trees_options *o)\n \n \t\tif (ce->ce_flags & CE_UPDATE) {\n \t\t\tif (ce->ce_flags & CE_WT_REMOVE)\n-\t\t\t\tdie(\"BUG: both update and delete flags are set on %s\",\n+\t\t\t\tBUG(\"both update and delete flags are set on %s\",\n \t\t\t\t    ce->name);\n \t\t\tdisplay_progress(progress, ++cnt);\n \t\t\tce->ce_flags &= ~CE_UPDATE;\ndiff --git a/worktree.c b/worktree.c\nindex 28989cf06ef..97cda5f97bb 100644\n--- a/worktree.c\n+++ b/worktree.c\n@@ -338,7 +338,7 @@ void update_worktree_location(struct worktree *wt, const char *path_)\n \tstruct strbuf path = STRBUF_INIT;\n \n \tif (is_main_worktree(wt))\n-\t\tdie(\"BUG: can't relocate main worktree\");\n+\t\tBUG(\"can't relocate main worktree\");\n \n \tstrbuf_realpath(&path, path_, 1);\n \tif (fspathcmp(wt->path, path.buf)) {\ndiff --git a/wrapper.c b/wrapper.c\nindex 1fd5e33ea8f..e4fa9d84cd0 100644\n--- a/wrapper.c\n+++ b/wrapper.c\n@@ -643,9 +643,9 @@ int xsnprintf(char *dst, size_t max, const char *fmt, ...)\n \tva_end(ap);\n \n \tif (len < 0)\n-\t\tdie(\"BUG: your snprintf is broken\");\n+\t\tBUG(\"your snprintf is broken\");\n \tif (len >= max)\n-\t\tdie(\"BUG: attempt to snprintf into too-small buffer\");\n+\t\tBUG(\"attempt to snprintf into too-small buffer\");\n \treturn len;\n }\n \ndiff --git a/wt-status.c b/wt-status.c\nindex 50815e5faff..26d037610ee 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -264,7 +264,7 @@ static const char *wt_status_unmerged_status_string(int stagemask)\n \tcase 7:\n \t\treturn _(\"both modified:\");\n \tdefault:\n-\t\tdie(\"BUG: unhandled unmerged status %x\", stagemask);\n+\t\tBUG(\"unhandled unmerged status %x\", stagemask);\n \t}\n }\n \n@@ -377,7 +377,7 @@ static void wt_longstatus_print_change_data(struct wt_status *s,\n \t\tstatus = d->worktree_status;\n \t\tbreak;\n \tdefault:\n-\t\tdie(\"BUG: unhandled change_type %d in wt_longstatus_print_change_data\",\n+\t\tBUG(\"unhandled change_type %d in wt_longstatus_print_change_data\",\n \t\t    change_type);\n \t}\n \n@@ -395,7 +395,7 @@ static void wt_longstatus_print_change_data(struct wt_status *s,\n \tstatus_printf(s, color(WT_STATUS_HEADER, s), \"\\t\");\n \twhat = wt_status_diff_status_string(status);\n \tif (!what)\n-\t\tdie(\"BUG: unhandled diff status %c\", status);\n+\t\tBUG(\"unhandled diff status %c\", status);\n \tlen = label_width - utf8_strwidth(what);\n \tassert(len >= 0);\n \tif (one_name != two_name)\n@@ -470,7 +470,7 @@ static void wt_status_collect_changed_cb(struct diff_queue_struct *q,\n \t\tcase DIFF_STATUS_COPIED:\n \t\tcase DIFF_STATUS_RENAMED:\n \t\t\tif (d->rename_status)\n-\t\t\t\tdie(\"BUG: multiple renames on the same target? how?\");\n+\t\t\t\tBUG(\"multiple renames on the same target? how?\");\n \t\t\td->rename_source = xstrdup(p->one->path);\n \t\t\td->rename_score = p->score * 100 / MAX_SCORE;\n \t\t\td->rename_status = p->status;\n@@ -484,7 +484,7 @@ static void wt_status_collect_changed_cb(struct diff_queue_struct *q,\n \t\t\tbreak;\n \n \t\tdefault:\n-\t\t\tdie(\"BUG: unhandled diff-files status '%c'\", p->status);\n+\t\t\tBUG(\"unhandled diff-files status '%c'\", p->status);\n \t\t\tbreak;\n \t\t}\n \n@@ -547,7 +547,7 @@ static void wt_status_collect_updated_cb(struct diff_queue_struct *q,\n \t\tcase DIFF_STATUS_COPIED:\n \t\tcase DIFF_STATUS_RENAMED:\n \t\t\tif (d->rename_status)\n-\t\t\t\tdie(\"BUG: multiple renames on the same target? how?\");\n+\t\t\t\tBUG(\"multiple renames on the same target? how?\");\n \t\t\td->rename_source = xstrdup(p->one->path);\n \t\t\td->rename_score = p->score * 100 / MAX_SCORE;\n \t\t\td->rename_status = p->status;\n@@ -569,7 +569,7 @@ static void wt_status_collect_updated_cb(struct diff_queue_struct *q,\n \t\t\tbreak;\n \n \t\tdefault:\n-\t\t\tdie(\"BUG: unhandled diff-index status '%c'\", p->status);\n+\t\t\tBUG(\"unhandled diff-index status '%c'\", p->status);\n \t\t\tbreak;\n \t\t}\n \t}\n@@ -2158,7 +2158,7 @@ static void wt_porcelain_v2_print_unmerged_entry(\n \tcase 6: key = \"AA\"; break; /* both added */\n \tcase 7: key = \"UU\"; break; /* both modified */\n \tdefault:\n-\t\tdie(\"BUG: unhandled unmerged status %x\", d->stagemask);\n+\t\tBUG(\"unhandled unmerged status %x\", d->stagemask);\n \t}\n \n \t/*\n@@ -2185,7 +2185,7 @@ static void wt_porcelain_v2_print_unmerged_entry(\n \t\tsum |= (1 << (stage - 1));\n \t}\n \tif (sum != d->stagemask)\n-\t\tdie(\"BUG: observed stagemask 0x%x != expected stagemask 0x%x\", sum, d->stagemask);\n+\t\tBUG(\"observed stagemask 0x%x != expected stagemask 0x%x\", sum, d->stagemask);\n \n \tif (s->null_termination)\n \t\tpath_index = it->string;\n@@ -2289,7 +2289,7 @@ void wt_status_print(struct wt_status *s)\n \t\twt_porcelain_v2_print(s);\n \t\tbreak;\n \tcase STATUS_FORMAT_UNSPECIFIED:\n-\t\tdie(\"BUG: finalize_deferred_config() should have been called\");\n+\t\tBUG(\"finalize_deferred_config() should have been called\");\n \t\tbreak;\n \tcase STATUS_FORMAT_NONE:\n \tcase STATUS_FORMAT_LONG:\ndiff --git a/zlib.c b/zlib.c\nindex 4223f1a8c57..d594cba3fc9 100644\n--- a/zlib.c\n+++ b/zlib.c\n@@ -52,9 +52,9 @@ static void zlib_post_call(git_zstream *s)\n \tbytes_consumed = s->z.next_in - s->next_in;\n \tbytes_produced = s->z.next_out - s->next_out;\n \tif (s->z.total_out != s->total_out + bytes_produced)\n-\t\tdie(\"BUG: total_out mismatch\");\n+\t\tBUG(\"total_out mismatch\");\n \tif (s->z.total_in != s->total_in + bytes_consumed)\n-\t\tdie(\"BUG: total_in mismatch\");\n+\t\tBUG(\"total_in mismatch\");\n \n \ts->total_out = s->z.total_out;\n \ts->total_in = s->z.total_in;\n-- \n2.17.0.windows.1.36.gdf4ca5fb72a\n\n\n"},{"id":"346442","messageId":"57b3a3e9fe3a04e1f9fbcad9164bc71929d4bb29.1525253893.git.johannes.schindelin@gmx.de","threadId":"45942","inReplyTo":"cover.1525253892.git.johannes.schindelin@gmx.de","subject":"[PATCH v2 4/4] Convert remaining die*(BUG) messages","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2018-05-02T09:38:41Z","receivedAt":"2018-05-02T09:38:59Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"These were not caught by the previous commit, as they did not match the\nregular expression.\n\nWhile at it, remove the localization from one instance: we never want\nBUG() messages to be translated, as they target Git developers, not the\nend user (hence it would be quite unhelpful to not only burden the\ntranslators, but then even end up with a bug report in a language that\nno core Git contributor understands).\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n git-compat-util.h     | 2 +-\n pathspec.c            | 2 +-\n submodule.c           | 2 +-\n vcs-svn/fast_export.c | 6 ++++--\n 4 files changed, 7 insertions(+), 5 deletions(-)\n\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 07e383257b4..3a7216f5313 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -1052,7 +1052,7 @@ int git_qsort_s(void *base, size_t nmemb, size_t size,\n \n #define QSORT_S(base, n, compar, ctx) do {\t\t\t\\\n \tif (qsort_s((base), (n), sizeof(*(base)), compar, ctx))\t\\\n-\t\tdie(\"BUG: qsort_s() failed\");\t\t\t\\\n+\t\tBUG(\"qsort_s() failed\");\t\t\t\\\n } while (0)\n \n #ifndef REG_STARTEND\ndiff --git a/pathspec.c b/pathspec.c\nindex a637a6d15c0..27cd6067860 100644\n--- a/pathspec.c\n+++ b/pathspec.c\n@@ -486,7 +486,7 @@ static void init_pathspec_item(struct pathspec_item *item, unsigned flags,\n \t/* sanity checks, pathspec matchers assume these are sane */\n \tif (item->nowildcard_len > item->len ||\n \t    item->prefix         > item->len) {\n-\t\tdie (\"BUG: error initializing pathspec_item\");\n+\t\tBUG(\"error initializing pathspec_item\");\n \t}\n }\n \ndiff --git a/submodule.c b/submodule.c\nindex 733db441714..c282fa8fe51 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -2043,7 +2043,7 @@ const char *get_superproject_working_tree(void)\n \n \t\tif (super_sub_len > cwd_len ||\n \t\t    strcmp(&cwd[cwd_len - super_sub_len], super_sub))\n-\t\t\tdie (_(\"BUG: returned path string doesn't match cwd?\"));\n+\t\t\tBUG(\"returned path string doesn't match cwd?\");\n \n \t\tsuper_wt = xstrdup(cwd);\n \t\tsuper_wt[cwd_len - super_sub_len] = '\\0';\ndiff --git a/vcs-svn/fast_export.c b/vcs-svn/fast_export.c\nindex 3fd047a8b82..b5b8913cb0f 100644\n--- a/vcs-svn/fast_export.c\n+++ b/vcs-svn/fast_export.c\n@@ -320,7 +320,8 @@ const char *fast_export_read_path(const char *path, uint32_t *mode_out)\n \terr = fast_export_ls(path, mode_out, &buf);\n \tif (err) {\n \t\tif (errno != ENOENT)\n-\t\t\tdie_errno(\"BUG: unexpected fast_export_ls error\");\n+\t\t\tBUG(\"unexpected fast_export_ls error: %s\",\n+\t\t\t    strerror(errno));\n \t\t/* Treat missing paths as directories. */\n \t\t*mode_out = S_IFDIR;\n \t\treturn NULL;\n@@ -338,7 +339,8 @@ void fast_export_copy(uint32_t revision, const char *src, const char *dst)\n \terr = fast_export_ls_rev(revision, src, &mode, &data);\n \tif (err) {\n \t\tif (errno != ENOENT)\n-\t\t\tdie_errno(\"BUG: unexpected fast_export_ls_rev error\");\n+\t\t\tBUG(\"unexpected fast_export_ls_rev error: %s\",\n+\t\t\t    strerror(errno));\n \t\tfast_export_delete(dst);\n \t\treturn;\n \t}\n-- \n2.17.0.windows.1.36.gdf4ca5fb72a\n"},{"id":"346456","messageId":"CACsJy8D+h+7BXSs1cggRP_UQc5qvtu6ZtrtLiBcu-qLeTpz3Yg@mail.gmail.com","threadId":"45942","inReplyTo":"6e2bfd3a6eb5270c809262f046e6a8b80090b352.1525253892.git.johannes.schindelin@gmx.de","subject":"Re: [PATCH v2 1/4] test-tool: help verifying BUG() code paths","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-05-02T15:18:42Z","receivedAt":"2018-05-02T15:19:16Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Wed, May 2, 2018 at 11:38 AM, Johannes Schindelin\n<johannes.schindelin@gmx.de> wrote:\n> When we call BUG(), we signal via SIGABRT that something bad happened,\n> dumping cores if so configured. In some setups these coredumps are\n> redirected to some central place such as /proc/sys/kernel/core_pattern,\n> which is a good thing.\n>\n> However, when we try to verify in our test suite that bugs are caught in\n> certain code paths, we do *not* want to clutter such a central place\n> with unnecessary coredumps.\n>\n> So let's special-case the test helpers (which we use to verify such code\n> paths) so that the BUG() calls will *not* call abort() but exit with a\n> special-purpose exit code instead.\n>\n> Helped-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n> ---\n>  t/helper/test-tool.c | 2 ++\n>  usage.c              | 5 +++++\n>  2 files changed, 7 insertions(+)\n>\n> diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c\n> index 87066ced62a..5176f9f20ae 100644\n> --- a/t/helper/test-tool.c\n> +++ b/t/helper/test-tool.c\n> @@ -47,7 +47,9 @@ static struct test_cmd cmds[] = {\n>  int cmd_main(int argc, const char **argv)\n>  {\n>         int i;\n> +       extern int BUG_exit_code;\n>\n> +       BUG_exit_code = 99;\n\nIt may be even better to let individual tests in t1406 control this,\npretty much like your original patch, except that we tell usage.c to\nnot send SIGABRT and just return a special fault code. That way we\ndon't accidentally suppress BUG()'s sigabrt behavior  in tests that do\nnot anticipate it (even in t1406).\n\nBut this patch is ok for me too if you don't want another reroll.\n\n>         if (argc < 2)\n>                 die(\"I need a test name!\");\n>\n> diff --git a/usage.c b/usage.c\n> index cdd534c9dfc..9c84dccfa97 100644\n> --- a/usage.c\n> +++ b/usage.c\n> @@ -210,6 +210,9 @@ void warning(const char *warn, ...)\n>         va_end(params);\n>  }\n>\n> +/* Only set this, ever, from t/helper/, when verifying that bugs are caught. */\n> +int BUG_exit_code;\n> +\n>  static NORETURN void BUG_vfl(const char *file, int line, const char *fmt, va_list params)\n>  {\n>         char prefix[256];\n> @@ -221,6 +224,8 @@ static NORETURN void BUG_vfl(const char *file, int line, const char *fmt, va_lis\n>                 snprintf(prefix, sizeof(prefix), \"BUG: \");\n>\n>         vreportf(prefix, fmt, params);\n> +       if (BUG_exit_code)\n> +               exit(BUG_exit_code);\n>         abort();\n>  }\n>\n> --\n> 2.17.0.windows.1.36.gdf4ca5fb72a\n>\n>\n\n\n\n-- \nDuy\n"},{"id":"346729","messageId":"nycvar.QRO.7.76.6.1805052126410.77@tvgsbejvaqbjf.bet","threadId":"45942","inReplyTo":"CACsJy8D+h+7BXSs1cggRP_UQc5qvtu6ZtrtLiBcu-qLeTpz3Yg@mail.gmail.com","subject":"Re: [PATCH v2 1/4] test-tool: help verifying BUG() code paths","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2018-05-05T19:30:04Z","receivedAt":"2018-05-05T19:30:24Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Duy,\n\nOn Wed, 2 May 2018, Duy Nguyen wrote:\n\n> On Wed, May 2, 2018 at 11:38 AM, Johannes Schindelin\n> <johannes.schindelin@gmx.de> wrote:\n> > When we call BUG(), we signal via SIGABRT that something bad happened,\n> > dumping cores if so configured. In some setups these coredumps are\n> > redirected to some central place such as /proc/sys/kernel/core_pattern,\n> > which is a good thing.\n> >\n> > However, when we try to verify in our test suite that bugs are caught in\n> > certain code paths, we do *not* want to clutter such a central place\n> > with unnecessary coredumps.\n> >\n> > So let's special-case the test helpers (which we use to verify such code\n> > paths) so that the BUG() calls will *not* call abort() but exit with a\n> > special-purpose exit code instead.\n> >\n> > Helped-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n> > Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n> > ---\n> >  t/helper/test-tool.c | 2 ++\n> >  usage.c              | 5 +++++\n> >  2 files changed, 7 insertions(+)\n> >\n> > diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c\n> > index 87066ced62a..5176f9f20ae 100644\n> > --- a/t/helper/test-tool.c\n> > +++ b/t/helper/test-tool.c\n> > @@ -47,7 +47,9 @@ static struct test_cmd cmds[] = {\n> >  int cmd_main(int argc, const char **argv)\n> >  {\n> >         int i;\n> > +       extern int BUG_exit_code;\n> >\n> > +       BUG_exit_code = 99;\n> \n> It may be even better to let individual tests in t1406 control this,\n> pretty much like your original patch, except that we tell usage.c to\n> not send SIGABRT and just return a special fault code. That way we\n> don't accidentally suppress BUG()'s sigabrt behavior  in tests that do\n> not anticipate it (even in t1406).\n\nI thought long and hard about this, even slept over it. And I came to the\nconclusion that I do not really know whether we want such a special\ntreatment (you may even want to go crazier and limit *which* BUG() call\nyou intend to catch, so that others are still reported).\n\nAnd I came to an important realization: whether or not to handle the bugs\nin the way you described is actually *outside* the purpose of this patch\nseries. This patch series is really only about converting die(BUG:...)\ncalls to BUG() calls. And it simply leaves the concern you raised for\nanother patch series.\n\n> But this patch is ok for me too if you don't want another reroll.\n\nI don't ;-) (for the reasons mentioned above: I don't disagree with you, I\njust think it should be addressed in another patch series than this here\npatch series).\n\nCiao,\nDscho"},{"id":"346853","messageId":"20180507090109.GA367@sigill.intra.peff.net","threadId":"45942","inReplyTo":"cover.1525253892.git.johannes.schindelin@gmx.de","subject":"Re: [PATCH v2 0/4] Finish the conversion from die(\"BUG: ...\") to BUG()","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2018-05-07T09:01:10Z","receivedAt":"2018-05-07T09:01:15Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, May 02, 2018 at 11:38:13AM +0200, Johannes Schindelin wrote:\n\n> The BUG() macro was introduced in this patch series:\n> https://public-inbox.org/git/20170513032414.mfrwabt4hovujde2@sigill.intra.peff.net\n> \n> The second patch in that series converted one caller from die(\"BUG: \")\n> to use the BUG() macro.\n> \n> It seems that there was no concrete plan to address the same issue in\n> the rest of the code base.\n\nI had a plan; it was that people would convert these as they touched the\nrelevant areas. :)\n\nI'm happy to see a mass-conversion, though.\n\n> For that reason, the commit message contains the precise Unix shell\n> invocation (GNU sed semantics, not BSD sed ones, because I know that the\n> Git maintainer as well as the author of the patch introducing BUG() both\n> use Linux and not macOS or any other platform that would offer a BSD\n> sed). It should be straight-forward to handle merge\n> conflicts/non-applying patches by simply re-running that command.\n\nI suspect this could have been done with coccinelle, but it's definitely\nnot worth going back to re-do it now.\n\n> Changes since v2:\n> \n> - Avoided the entire discussion about the previous 2/6 (now dropped)\n>   that prepared t1406 to handle SIGABRT by side-stepping the issue: the\n>   ref-store test helper will no longer call abort() in BUG() calls but\n>   exit with exit code 99 instead.\n\nI actually think this should be a runtime flag in the environment, like\nGIT_BUG_EXIT_CODE (and if not set, continue to abort). That can help if\nyou come across a BUG() in real Git code, but for some reason your\nenvironment makes aborting a pain. For example, maybe you're debugging a\nracy BUG() and don't want to generate a bunch of coredumps.\n\nOr here's an interesting related case I came across a few months ago.\nt6210 has a test that's known to segfault due to stack exhaustion. It's\nmarked test_expect_failure, so all is good, right?  Normally, yes, but\nwhen I run the test suite inside our local Jenkins setup, it detects a\nsegfault in _any_ child process of the test runner and aborts the whole\nthing. This is great as a belt-and-suspenders if we miss an unexpected\nsegfault, but is obviously annoying in this case.\n\nTriggering BUG()s in the test suite, even inside an expect_failure,\nwould introduce the same headache. It would be nice if I could just do:\n\n  GIT_BUG_EXIT_CODE=134 make test\n\nto avoid it.  Possibly expect_failure should even set that\nautomatically.\n\nI also suspect that nobody really needs to set a specific exit code.\nUsing 134 is enough to avoid all of the unpleasantness of SIGABRT, but\nstill enough to trigger test_must_fail to distinguish it from a non-BUG\ndeath. The callers that intentionally trigger bugs probably ought to be\nusing test_expect_code to make sure they are hitting a BUG() and not\nsome other death, anyway.\n\nSo we could probably simplify it to something like this:\n\ndiff --git a/usage.c b/usage.c\nindex cdd534c9df..50651bed40 100644\n--- a/usage.c\n+++ b/usage.c\n@@ -221,7 +221,11 @@ static NORETURN void BUG_vfl(const char *file, int line, const char *fmt, va_lis\n \t\tsnprintf(prefix, sizeof(prefix), \"BUG: \");\n \n \tvreportf(prefix, fmt, params);\n-\tabort();\n+\n+\tif (git_env_bool(\"GIT_BUG_ABORT\"), 1)\n+\t\tabort();\n+\telse\n+\t\texit(134);\n }\n \n #ifdef HAVE_VARIADIC_MACROS\n\n-Peff\n"},{"id":"346854","messageId":"20180507090806.GB367@sigill.intra.peff.net","threadId":"45942","inReplyTo":"91ddc7ed5ce0279c5d48bbed595d932d985465c4.1525253892.git.johannes.schindelin@gmx.de","subject":"Re: [PATCH v2 2/4] run-command: use BUG() to report bugs, not die()","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2018-05-07T09:08:06Z","receivedAt":"2018-05-07T09:08:11Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, May 02, 2018 at 11:38:31AM +0200, Johannes Schindelin wrote:\n\n> The slightly misleading name die_bug() of the function intended to\n> report a bug is actually called always, and only reports a bug if the\n> passed-in parameter `err` is non-zero.\n> \n> It uses die_errno() to report the bug, to helpfully include the error\n> message corresponding to `err`.\n> \n> However, as these messages indicate bugs, we really should use BUG().\n> And as BUG() is a macro to be able to report the exact file and line\n> number, we need to convert die_bug() to a macro instead of only\n> replacing the die_errno() by a call to BUG().\n> \n> While at it, use a name more indicative of the purpose: CHECK_BUG().\n\nHrm, at first glance these _don't_ seem like BUGs, because we're\nchecking the value of errno. I guess the argument is that for these\n_particular_ syscalls, we know that they can only complain with EINVAL,\nand only when we feed them junk. And therefore any such error return is\na bug.\n\nI guess I buy that line of reasoning for pthread_setcancelstate(). But I\nthink pthread_sigmask() could return an error based on in-kernel\nlimitations of sigsetsize. I suppose that's pretty unlikely.\n\nBut what I'm suggesting is that these probably should not have been\ndie(\"BUG\") in the first place. And that the rule of thumb should\nprobably be that anything relying on system calls or errno should not\nBUG(), but be a regular die().\n\n-Peff\n"}]}