All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Ævar Arnfjörð Bjarmason" <avarab@gmail.com>
To: git@vger.kernel.org
Cc: "Junio C Hamano" <gitster@pobox.com>, "Jeff King" <peff@peff.net>,
	"Jeff Hostetler" <jeffhost@microsoft.com>,
	"Elijah Newren" <newren@gmail.com>,
	"Jonathan Tan" <jonathantanmy@google.com>,
	"Johannes Schindelin" <Johannes.Schindelin@gmx.de>,
	"Ævar Arnfjörð Bjarmason" <avarab@gmail.com>
Subject: [RFC PATCH 14/21] usage API: create a new usage.h, move API docs there
Date: Mon, 15 Nov 2021 23:18:24 +0100	[thread overview]
Message-ID: <RFC-patch-14.21-f553b790601-20211115T220831Z-avarab@gmail.com> (raw)
In-Reply-To: <RFC-cover-00.21-00000000000-20211115T220831Z-avarab@gmail.com>

Follow-up 26c816a67de (Merge branch 'hw/doc-in-header', 2019-12-16)
and move the API docs for the usage.c API to a new usage.h, which is
included from "git-compat-util.h".

All of the code and documentation is unchanged here, with the
following exceptions:

 * Added a short paragraph to the start of the comment in usage.h
   describing the API in general terms.

 * Prefixed comments with " * ", reformatted "+"-flowing lines away
   from that ASCIIDOC syntax.

 * Re-arranged the function definitions that were previously in
   "git-compat-util.h" to be grouped by task, and added short comments
   above each one. None of the code was changed.

 * There was an unrelated forward-declaration of "struct strbuf" that
   happened to be just above these usage functions. Move it down to just
   above "unlink_or_msg()" where it's needed.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 .../technical/api-error-handling.txt          |  92 ----------
 git-compat-util.h                             |  59 +------
 usage.h                                       | 161 ++++++++++++++++++
 3 files changed, 163 insertions(+), 149 deletions(-)
 delete mode 100644 Documentation/technical/api-error-handling.txt
 create mode 100644 usage.h

diff --git a/Documentation/technical/api-error-handling.txt b/Documentation/technical/api-error-handling.txt
deleted file mode 100644
index 818489bc3d4..00000000000
--- a/Documentation/technical/api-error-handling.txt
+++ /dev/null
@@ -1,92 +0,0 @@
-Error reporting in git
-======================
-
-`BUG`, `bug`, `die`, `usage`, `error`, and `warning` report errors of
-various kinds.
-
-- `BUG` is for failed internal assertions that should never happen,
-  i.e. a bug in git itself.
-
-- `die` is for fatal application errors.  It prints a message to
-  the user and exits with status 128.
-
-- `usage` is for errors in command line usage.  After printing its
-  message, it exits with status 129.  (See also `usage_with_options`
-  in the link:api-parse-options.html[parse-options API].)
-
-- `error` is for non-fatal library errors.  It prints a message
-  to the user and returns -1 for convenience in signaling the error
-  to the caller.
-
-- `bug` (lower-case, not `BUG`) is supposed to be used like `BUG` but
-  returns -1 like error. The user should then call `BUG_if_bug()` to die.
-+
-This is for the convenience of APIs who'd like to potentially report
-more than one bug before calling `BUG_if_bug()`, which will invoke
-`BUG()` if there were any preceding calls to `bug()`.
-+
-We call `BUG_if_bug()` ourselves in on `exit()` (via a wrapper, not
-`atexit()`), which guarantees that we'll catch cases where we forgot
-to invoke `BUG_if_bug()` following a call or calls to `bug()`.
-
-- `warning` is for reporting situations that probably should not
-  occur but which the user (and Git) can continue to work around
-  without running into too many problems.  Like `error`, it
-  returns -1 after reporting the situation to the caller.
-
-These reports will be logged via the trace2 facility. See the "error"
-event in link:api-trace2.txt[trace2 API].
-
-Customizable error handlers
----------------------------
-
-The default behavior of `die` and `error` is to write a message to
-stderr and then exit or return as appropriate.  This behavior can be
-overridden using `set_die_routine` and `set_error_routine`.  For
-example, "git daemon" uses set_die_routine to write the reason `die`
-was called to syslog before exiting.
-
-Library errors
---------------
-
-Functions return a negative integer on error.  Details beyond that
-vary from function to function:
-
-- Some functions return -1 for all errors.  Others return a more
-  specific value depending on how the caller might want to react
-  to the error.
-
-- Some functions report the error to stderr with `error`,
-  while others leave that for the caller to do.
-
-- errno is not meaningful on return from most functions (except
-  for thin wrappers for system calls).
-
-Check the function's API documentation to be sure.
-
-Caller-handled errors
----------------------
-
-An increasing number of functions take a parameter 'struct strbuf *err'.
-On error, such functions append a message about what went wrong to the
-'err' strbuf.  The message is meant to be complete enough to be passed
-to `die` or `error` as-is.  For example:
-
-	if (ref_transaction_commit(transaction, &err))
-		die("%s", err.buf);
-
-The 'err' parameter will be untouched if no error occurred, so multiple
-function calls can be chained:
-
-	t = ref_transaction_begin(&err);
-	if (!t ||
-	    ref_transaction_update(t, "HEAD", ..., &err) ||
-	    ret_transaction_commit(t, &err))
-		die("%s", err.buf);
-
-The 'err' parameter must be a pointer to a valid strbuf.  To silence
-a message, pass a strbuf that is explicitly ignored:
-
-	if (thing_that_can_fail_in_an_ignorable_way(..., &err))
-		/* This failure is okay. */
-		strbuf_reset(&err);
diff --git a/git-compat-util.h b/git-compat-util.h
index 9b02a3e05ba..7a0b88a54c6 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -462,20 +462,7 @@ static inline int git_has_dir_sep(const char *path)
 #include "compat/bswap.h"
 
 #include "wildmatch.h"
-
-struct strbuf;
-
-/* General helper functions */
-NORETURN void usage(const char *err);
-NORETURN void usagef(const char *err, ...) __attribute__((format (printf, 1, 2)));
-NORETURN void die(const char *err, ...) __attribute__((format (printf, 1, 2)));
-NORETURN void die_errno(const char *err, ...) __attribute__((format (printf, 1, 2)));
-int die_message(const char *err, ...) __attribute__((format (printf, 1, 2)));
-int die_message_errno(const char *err, ...) __attribute__((format (printf, 1, 2)));
-int error(const char *err, ...) __attribute__((format (printf, 1, 2)));
-int error_errno(const char *err, ...) __attribute__((format (printf, 1, 2)));
-void warning(const char *err, ...) __attribute__((format (printf, 1, 2)));
-void warning_errno(const char *err, ...) __attribute__((format (printf, 1, 2)));
+#include "usage.h"
 
 #ifndef NO_OPENSSL
 #ifdef APPLE_COMMON_CRYPTO
@@ -487,30 +474,6 @@ void warning_errno(const char *err, ...) __attribute__((format (printf, 1, 2)));
 #include <openssl/x509v3.h>
 #endif /* NO_OPENSSL */
 
-/*
- * Let callers be aware of the constant return value; this can help
- * gcc with -Wuninitialized analysis. We restrict this trick to gcc, though,
- * because other compilers may be confused by this.
- */
-#if defined(__GNUC__)
-static inline int const_error(void)
-{
-	return -1;
-}
-#define error(...) (error(__VA_ARGS__), const_error())
-#define error_errno(...) (error_errno(__VA_ARGS__), const_error())
-#endif
-
-typedef void (*report_fn)(const char *, va_list params);
-
-void set_die_routine(NORETURN_PTR report_fn routine);
-report_fn get_die_message_routine(void);
-void set_error_routine(report_fn routine);
-report_fn get_error_routine(void);
-void set_warn_routine(report_fn routine);
-report_fn get_warn_routine(void);
-void set_die_is_recursing_routine(int (*routine)(void));
-
 int starts_with(const char *str, const char *prefix);
 int istarts_with(const char *str, const char *prefix);
 
@@ -1195,25 +1158,6 @@ static inline int regexec_buf(const regex_t *preg, const char *buf, size_t size,
 #endif
 #endif
 
-/* usage.c: only to be used for testing BUG() implementation (see test-tool) */
-extern int BUG_exit_code;
-
-/* usage.c: if bug() is called we must have a BUG() invocation afterwards */
-extern int bug_called_must_BUG;
-
-__attribute__((format (printf, 3, 4))) NORETURN
-void BUG_fl(const char *file, int line, const char *fmt, ...);
-#define BUG(...) BUG_fl(__FILE__, __LINE__, __VA_ARGS__)
-__attribute__((format (printf, 3, 4)))
-int bug_fl(const char *file, int line, const char *fmt, ...);
-#define bug(...) bug_fl(__FILE__, __LINE__, __VA_ARGS__)
-#define BUG_if_bug() do { \
-	if (bug_called_must_BUG) { \
-		bug_called_must_BUG = 0; \
-		BUG_fl(__FILE__, __LINE__, "see bug() output above"); \
-	} \
-} while (0)
-
 /*
  * Preserves errno, prints a message, but gives no warning for ENOENT.
  * Returns 0 on success, which includes trying to unlink an object that does
@@ -1226,6 +1170,7 @@ int unlink_or_warn(const char *path);
   * appends a message to err suitable for
   * 'error("%s", err->buf)' on error.
   */
+struct strbuf;
 int unlink_or_msg(const char *file, struct strbuf *err);
 /*
  * Preserves errno, prints a message, but gives no warning for ENOENT.
diff --git a/usage.h b/usage.h
new file mode 100644
index 00000000000..a2567a609fc
--- /dev/null
+++ b/usage.h
@@ -0,0 +1,161 @@
+#ifndef USAGE_H
+#define USAGE_H
+
+/**
+ * The usage.h is an API for error reporting in git, errors are
+ * reported both to the user, to Trace2 (see "trace2.h"), and possibly
+ * to custom callbacks via "report_fn" callbacks.
+ *
+ * `BUG`, `bug`, `die`, `usage`, `error`, and `warning` report errors of
+ * various kinds.
+ *
+ * - `BUG` is for failed internal assertions that should never happen,
+ *   i.e. a bug in git itself.
+ *
+ * - `die` is for fatal application errors.  It prints a message to
+ *   the user and exits with status 128.
+ *
+ * - `usage` is for errors in command line usage.  After printing its
+ *   message, it exits with status 129.  (See also `usage_with_options`
+ *   in the link:api-parse-options.html[parse-options API].)
+ *
+ * - `error` is for non-fatal library errors.  It prints a message
+ *   to the user and returns -1 for convenience in signaling the error
+ *   to the caller.
+ *
+ * - `bug` (lower-case, not `BUG`) is supposed to be used like `BUG` but
+ *   returns -1 like error. The user should then call `BUG_if_bug()` to die.
+ *
+ *   This is for the convenience of APIs who'd like to potentially report
+ *   more than one bug before calling `BUG_if_bug()`, which will invoke
+ *   `BUG()` if there were any preceding calls to `bug()`.
+ *
+ *   We call `BUG_if_bug()` ourselves in on `exit()` (via a wrapper, not
+ *   `atexit()`), which guarantees that we'll catch cases where we forgot
+ *   to invoke `BUG_if_bug()` following a call or calls to `bug()`.
+ *
+ * - `warning` is for reporting situations that probably should not
+ *   occur but which the user (and Git) can continue to work around
+ *   without running into too many problems.  Like `error`, it
+ *   returns -1 after reporting the situation to the caller.
+ *
+ * These reports will be logged via the trace2 facility. See the "error"
+ * event in link:api-trace2.txt[trace2 API].
+ *
+ * Customizable error handlers
+ * ---------------------------
+ *
+ * The default behavior of `die` and `error` is to write a message to
+ * stderr and then exit or return as appropriate.  This behavior can be
+ * overridden using `set_die_routine` and `set_error_routine`.  For
+ * example, "git daemon" uses set_die_routine to write the reason `die`
+ * was called to syslog before exiting.
+ *
+ * Library errors
+ * --------------
+ *
+ * Functions return a negative integer on error.  Details beyond that
+ * vary from function to function:
+ *
+ * - Some functions return -1 for all errors.  Others return a more
+ *   specific value depending on how the caller might want to react
+ *   to the error.
+ *
+ * - Some functions report the error to stderr with `error`,
+ *   while others leave that for the caller to do.
+ *
+ * - errno is not meaningful on return from most functions (except
+ *   for thin wrappers for system calls).
+ *
+ * Check the function's API documentation to be sure.
+ *
+ * Caller-handled errors
+ * ---------------------
+ *
+ * An increasing number of functions take a parameter 'struct strbuf *err'.
+ * On error, such functions append a message about what went wrong to the
+ * 'err' strbuf.  The message is meant to be complete enough to be passed
+ * to `die` or `error` as-is.  For example:
+ *
+ * 	if (ref_transaction_commit(transaction, &err))
+ * 		die("%s", err.buf);
+ *
+ * The 'err' parameter will be untouched if no error occurred, so multiple
+ * function calls can be chained:
+ *
+ * 	t = ref_transaction_begin(&err);
+ * 	if (!t ||
+ * 	    ref_transaction_update(t, "HEAD", ..., &err) ||
+ * 	    ret_transaction_commit(t, &err))
+ * 		die("%s", err.buf);
+ *
+ * The 'err' parameter must be a pointer to a valid strbuf.  To silence
+ * a message, pass a strbuf that is explicitly ignored:
+ *
+ * 	if (thing_that_can_fail_in_an_ignorable_way(..., &err))
+ * 		// This failure is okay.
+ * 		strbuf_reset(&err);
+ */
+
+/**
+ * External but private variables, don't use these except for
+ * implementation details of this API itself.
+ */
+/* Only to be used for testing BUG() implementation (see test-tool) */
+extern int BUG_exit_code;
+/* If bug() is called we must have a BUG() invocation afterwards */
+extern int bug_called_must_BUG;
+
+/* General helper functions */
+NORETURN void usage(const char *err);
+NORETURN void usagef(const char *err, ...) __attribute__((format (printf, 1, 2)));
+NORETURN void die(const char *err, ...) __attribute__((format (printf, 1, 2)));
+NORETURN void die_errno(const char *err, ...) __attribute__((format (printf, 1, 2)));
+int die_message(const char *err, ...) __attribute__((format (printf, 1, 2)));
+int die_message_errno(const char *err, ...) __attribute__((format (printf, 1, 2)));
+int error(const char *err, ...) __attribute__((format (printf, 1, 2)));
+int error_errno(const char *err, ...) __attribute__((format (printf, 1, 2)));
+void warning(const char *err, ...) __attribute__((format (printf, 1, 2)));
+void warning_errno(const char *err, ...) __attribute__((format (printf, 1, 2)));
+
+/* General helper functions invoked via macro wrappers */
+__attribute__((format (printf, 3, 4))) NORETURN
+void BUG_fl(const char *file, int line, const char *fmt, ...);
+__attribute__((format (printf, 3, 4)))
+int bug_fl(const char *file, int line, const char *fmt, ...);
+
+/* General helper macros */
+#define BUG(...) BUG_fl(__FILE__, __LINE__, __VA_ARGS__)
+#define bug(...) bug_fl(__FILE__, __LINE__, __VA_ARGS__)
+#define BUG_if_bug() do { \
+	if (bug_called_must_BUG) { \
+		bug_called_must_BUG = 0; \
+		BUG_fl(__FILE__, __LINE__, "see bug() output above"); \
+	} \
+} while (0)
+
+/* Setting custom handling routines */
+typedef void (*report_fn)(const char *, va_list params);
+void set_die_routine(NORETURN_PTR report_fn routine);
+report_fn get_die_message_routine(void);
+void set_error_routine(report_fn routine);
+report_fn get_error_routine(void);
+void set_warn_routine(report_fn routine);
+report_fn get_warn_routine(void);
+void set_die_is_recursing_routine(int (*routine)(void));
+
+/*
+ * Let callers be aware of the constant return value; this can help
+ * gcc with -Wuninitialized analysis. We restrict this trick to gcc, though,
+ * because other compilers may be confused by this.
+ */
+#if defined(__GNUC__)
+static inline int const_error(void)
+{
+	return -1;
+}
+#define error(...) (error(__VA_ARGS__), const_error())
+#define error_errno(...) (error_errno(__VA_ARGS__), const_error())
+#endif
+
+#endif
-- 
2.34.0.rc2.809.g11e21d44b24


  parent reply	other threads:[~2021-11-15 23:28 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-11-15 22:18 [RFC PATCH 00/21] C99: show meaningful <file>:<line> in trace2 via macros Ævar Arnfjörð Bjarmason
2021-11-15 22:18 ` [RFC PATCH 01/21] git-compat-util.h: clarify GCC v.s. C99-specific in comment Ævar Arnfjörð Bjarmason
2021-11-15 22:18 ` [RFC PATCH 02/21] C99 support: hard-depend on C99 variadic macros Ævar Arnfjörð Bjarmason
2021-11-15 22:18 ` [RFC PATCH 03/21] usage.c: add a die_message() routine Ævar Arnfjörð Bjarmason
2021-11-15 22:18 ` [RFC PATCH 04/21] usage.c API users: use die_message() where appropriate Ævar Arnfjörð Bjarmason
2021-11-15 22:18 ` [RFC PATCH 05/21] usage.c + gc: add and use a die_message_errno() Ævar Arnfjörð Bjarmason
2021-11-15 22:18 ` [RFC PATCH 06/21] config API: don't use vreportf(), make it static in usage.c Ævar Arnfjörð Bjarmason
2021-11-15 22:18 ` [RFC PATCH 07/21] common-main.c: call exit(), don't return Ævar Arnfjörð Bjarmason
2021-11-15 22:18 ` [RFC PATCH 08/21] usage.c: add a non-fatal bug() function to go with BUG() Ævar Arnfjörð Bjarmason
2021-11-15 22:18 ` [RFC PATCH 09/21] parse-options.[ch] API: use bug() to improve error output Ævar Arnfjörð Bjarmason
2021-11-15 22:18 ` [RFC PATCH 10/21] receive-pack: use bug() and BUG_if_bug() Ævar Arnfjörð Bjarmason
2021-11-15 22:18 ` [RFC PATCH 11/21] cache-tree.c: " Ævar Arnfjörð Bjarmason
2021-11-15 22:18 ` [RFC PATCH 12/21] pack-objects: use BUG(...) not die("BUG: ...") Ævar Arnfjörð Bjarmason
2021-11-15 22:18 ` [RFC PATCH 13/21] strbuf.h: " Ævar Arnfjörð Bjarmason
2021-11-15 22:18 ` Ævar Arnfjörð Bjarmason [this message]
2021-11-15 22:18 ` [RFC PATCH 15/21] usage.[ch] API users: use report_fn, not hardcoded prototype Ævar Arnfjörð Bjarmason
2021-11-15 22:18 ` [RFC PATCH 16/21] usage.[ch] API: rename "warn" vars functions to "warning" Ævar Arnfjörð Bjarmason
2021-11-15 22:18 ` [RFC PATCH 17/21] usage.c: move usage routines around Ævar Arnfjörð Bjarmason
2021-11-15 22:18 ` [RFC PATCH 18/21] usage.c: move rename variables in " Ævar Arnfjörð Bjarmason
2021-11-15 22:18 ` [RFC PATCH 19/21] usage API: use C99 macros for {usage,usagef,die,error,warning,die}*() Ævar Arnfjörð Bjarmason
2021-12-27 19:32   ` Jeff Hostetler
2021-12-27 23:01     ` Ævar Arnfjörð Bjarmason
2021-12-28 16:32       ` Jeff Hostetler
2021-12-28 18:51         ` Elijah Newren
2021-12-28 23:48           ` Ævar Arnfjörð Bjarmason
2021-12-29  2:15             ` Elijah Newren
2021-12-28 23:42         ` Ævar Arnfjörð Bjarmason
2021-12-29 16:13         ` Jeff Hostetler
2021-11-15 22:18 ` [RFC PATCH 20/21] usage API: make the "{usage,fatal,error,warning,BUG}: " translatable Ævar Arnfjörð Bjarmason
2021-11-15 22:18 ` [RFC PATCH 21/21] usage API: add "core.usageAddSource" config to add <file>:<line> Ævar Arnfjörð Bjarmason
2021-11-16 18:43 ` [RFC PATCH 00/21] C99: show meaningful <file>:<line> in trace2 via macros Taylor Blau
2021-11-16 18:58   ` Ævar Arnfjörð Bjarmason
2021-11-16 19:36     ` Taylor Blau
2021-11-16 20:16       ` Ævar Arnfjörð Bjarmason

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=RFC-patch-14.21-f553b790601-20211115T220831Z-avarab@gmail.com \
    --to=avarab@gmail.com \
    --cc=Johannes.Schindelin@gmx.de \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=jeffhost@microsoft.com \
    --cc=jonathantanmy@google.com \
    --cc=newren@gmail.com \
    --cc=peff@peff.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.