New upstream version 2017.15
This commit is contained in:
commit
ef9ffc09f4
66 files changed
+2620
-638
No files matched your search
+63
-13
@@ -29,9 +29,22 @@
|
||||
#include <errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
static char *current_text = NULL;
|
||||
static gint current_percent = -1;
|
||||
/* For people with widescreen monitors and maximized terminals, it looks pretty
|
||||
* bad to have an enormous progress bar. For much the same reason as web pages
|
||||
* tend to have a maximum width;
|
||||
* https://ux.stackexchange.com/questions/48982/suggest-good-max-width-for-fluid-width-design
|
||||
*/
|
||||
#define MAX_PROGRESSBAR_COLUMNS 20
|
||||
|
||||
/* Max updates output per second. On a tty there's no point to rendering
|
||||
* extremely fast; and for a non-tty we're probably in a Jenkins job
|
||||
* or whatever and having percentages spam multiple lines there is annoying.
|
||||
*/
|
||||
#define MAX_TTY_UPDATE_HZ (5)
|
||||
#define MAX_NONTTY_UPDATE_HZ (1)
|
||||
|
||||
static gboolean locked;
|
||||
static guint64 last_update_ms; /* monotonic time in millis we last updated */
|
||||
|
||||
static gboolean
|
||||
stdout_is_tty (void)
|
||||
@@ -147,8 +160,6 @@ glnx_console_lock (GLnxConsoleRef *console)
|
||||
|
||||
locked = console->locked = TRUE;
|
||||
|
||||
current_percent = 0;
|
||||
|
||||
if (console->is_tty)
|
||||
{
|
||||
if (g_once_init_enter (&sigwinch_initialized))
|
||||
@@ -181,6 +192,26 @@ static void
|
||||
text_percent_internal (const char *text,
|
||||
int percentage)
|
||||
{
|
||||
/* Check whether we're trying to render too fast; unless percentage is 100, in
|
||||
* which case we assume this is the last call, so we always render it.
|
||||
*/
|
||||
const guint64 current_ms = g_get_monotonic_time () / 1000;
|
||||
if (percentage != 100)
|
||||
{
|
||||
const guint64 diff_ms = current_ms - last_update_ms;
|
||||
if (stdout_is_tty ())
|
||||
{
|
||||
if (diff_ms < (1000/MAX_TTY_UPDATE_HZ))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (diff_ms < (1000/MAX_NONTTY_UPDATE_HZ))
|
||||
return;
|
||||
}
|
||||
}
|
||||
last_update_ms = current_ms;
|
||||
|
||||
static const char equals[] = "====================";
|
||||
const guint n_equals = sizeof (equals) - 1;
|
||||
static const char spaces[] = " ";
|
||||
@@ -193,10 +224,6 @@ text_percent_internal (const char *text,
|
||||
|
||||
const guint input_textlen = text ? strlen (text) : 0;
|
||||
|
||||
if (percentage == current_percent
|
||||
&& g_strcmp0 (text, current_text) == 0)
|
||||
return;
|
||||
|
||||
if (!stdout_is_tty ())
|
||||
{
|
||||
if (text)
|
||||
@@ -232,7 +259,7 @@ text_percent_internal (const char *text,
|
||||
else
|
||||
{
|
||||
const guint textlen = MIN (input_textlen, ncolumns - bar_min);
|
||||
const guint barlen = ncolumns - (textlen + 1);;
|
||||
const guint barlen = MIN (MAX_PROGRESSBAR_COLUMNS, ncolumns - (textlen + 1));
|
||||
|
||||
if (textlen > 0)
|
||||
{
|
||||
@@ -245,7 +272,7 @@ text_percent_internal (const char *text,
|
||||
const guint textpercent_len = 5;
|
||||
const guint bar_internal_len = barlen - nbraces - textpercent_len;
|
||||
const guint eqlen = bar_internal_len * (percentage / 100.0);
|
||||
const guint spacelen = bar_internal_len - eqlen;
|
||||
const guint spacelen = bar_internal_len - eqlen;
|
||||
|
||||
fputc ('[', stdout);
|
||||
printpad (equals, n_equals, eqlen);
|
||||
@@ -280,6 +307,32 @@ glnx_console_progress_text_percent (const char *text,
|
||||
text_percent_internal (text, percentage);
|
||||
}
|
||||
|
||||
/**
|
||||
* glnx_console_progress_n_items:
|
||||
* @text: Show this text before the progress bar
|
||||
* @current: An integer for how many items have been processed
|
||||
* @total: An integer for how many items there are total
|
||||
*
|
||||
* On a tty, print to the console @text followed by [@current/@total],
|
||||
* then an ASCII art progress bar, like glnx_console_progress_text_percent().
|
||||
*
|
||||
* You must have called glnx_console_lock() before invoking this
|
||||
* function.
|
||||
*/
|
||||
void
|
||||
glnx_console_progress_n_items (const char *text,
|
||||
guint current,
|
||||
guint total)
|
||||
{
|
||||
g_return_if_fail (current <= total);
|
||||
g_return_if_fail (total > 0);
|
||||
|
||||
g_autofree char *newtext = g_strdup_printf ("%s (%u/%u)", text, current, total);
|
||||
/* Special case current == total to ensure we end at 100% */
|
||||
int percentage = (current == total) ? 100 : (((double)current) / total * 100);
|
||||
glnx_console_progress_text_percent (newtext, percentage);
|
||||
}
|
||||
|
||||
void
|
||||
glnx_console_text (const char *text)
|
||||
{
|
||||
@@ -299,9 +352,6 @@ glnx_console_unlock (GLnxConsoleRef *console)
|
||||
g_return_if_fail (locked);
|
||||
g_return_if_fail (console->locked);
|
||||
|
||||
current_percent = -1;
|
||||
g_clear_pointer (¤t_text, g_free);
|
||||
|
||||
if (console->is_tty)
|
||||
fputc ('\n', stdout);
|
||||
|
||||
|
||||
@@ -36,7 +36,11 @@ void glnx_console_lock (GLnxConsoleRef *ref);
|
||||
void glnx_console_text (const char *text);
|
||||
|
||||
void glnx_console_progress_text_percent (const char *text,
|
||||
guint percentage);
|
||||
guint percentage);
|
||||
|
||||
void glnx_console_progress_n_items (const char *text,
|
||||
guint current,
|
||||
guint total);
|
||||
|
||||
void glnx_console_unlock (GLnxConsoleRef *ref);
|
||||
|
||||
|
||||
@@ -23,6 +23,32 @@
|
||||
#include <glnx-backport-autocleanups.h>
|
||||
#include <glnx-errors.h>
|
||||
|
||||
/* Set @error with G_IO_ERROR/G_IO_ERROR_FAILED.
|
||||
*
|
||||
* This function returns %FALSE so it can be used conveniently in a single
|
||||
* statement:
|
||||
*
|
||||
* ```
|
||||
* if (strcmp (foo, "somevalue") != 0)
|
||||
* return glnx_throw (error, "key must be somevalue, not '%s'", foo);
|
||||
* ```
|
||||
*/
|
||||
gboolean
|
||||
glnx_throw (GError **error,
|
||||
const char *fmt,
|
||||
...)
|
||||
{
|
||||
if (error == NULL)
|
||||
return FALSE;
|
||||
|
||||
va_list args;
|
||||
va_start (args, fmt);
|
||||
GError *new = g_error_new_valist (G_IO_ERROR, G_IO_ERROR_FAILED, fmt, args);
|
||||
va_end (args);
|
||||
g_propagate_error (error, g_steal_pointer (&new));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
glnx_real_set_prefix_error_va (GError *error,
|
||||
const char *format,
|
||||
@@ -39,6 +65,30 @@ glnx_real_set_prefix_error_va (GError *error,
|
||||
error->message = g_string_free (g_steal_pointer (&buf), FALSE);
|
||||
}
|
||||
|
||||
/* Prepend to @error's message by `$prefix: ` where `$prefix` is computed via
|
||||
* printf @fmt. Returns %FALSE so it can be used conveniently in a single
|
||||
* statement:
|
||||
*
|
||||
* ```
|
||||
* if (!function_that_fails (s, error))
|
||||
* return glnx_throw_prefix (error, "while handling '%s'", s);
|
||||
* ```
|
||||
* */
|
||||
gboolean
|
||||
glnx_prefix_error (GError **error,
|
||||
const char *fmt,
|
||||
...)
|
||||
{
|
||||
if (error == NULL)
|
||||
return FALSE;
|
||||
|
||||
va_list args;
|
||||
va_start (args, fmt);
|
||||
glnx_real_set_prefix_error_va (*error, fmt, args);
|
||||
va_end (args);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
glnx_real_set_prefix_error_from_errno_va (GError **error,
|
||||
gint errsv,
|
||||
@@ -54,3 +104,28 @@ glnx_real_set_prefix_error_from_errno_va (GError **error,
|
||||
g_strerror (errsv));
|
||||
glnx_real_set_prefix_error_va (*error, format, args);
|
||||
}
|
||||
|
||||
/* Set @error using the value of `$prefix: g_strerror (errno)` where `$prefix`
|
||||
* is computed via printf @fmt.
|
||||
*
|
||||
* This function returns %FALSE so it can be used conveniently in a single
|
||||
* statement:
|
||||
*
|
||||
* ```
|
||||
* return glnx_throw_errno_prefix (error, "unlinking %s", pathname);
|
||||
* ```
|
||||
*/
|
||||
gboolean
|
||||
glnx_throw_errno_prefix (GError **error,
|
||||
const char *fmt,
|
||||
...)
|
||||
{
|
||||
int errsv = errno;
|
||||
va_list args;
|
||||
va_start (args, fmt);
|
||||
glnx_real_set_prefix_error_from_errno_va (error, errsv, fmt, args);
|
||||
va_end (args);
|
||||
/* See comment in glnx_throw_errno() about preserving errno */
|
||||
errno = errsv;
|
||||
return FALSE;
|
||||
}
|
||||
+3
-66
@@ -25,29 +25,7 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* Set @error with G_IO_ERROR/G_IO_ERROR_FAILED.
|
||||
*
|
||||
* This function returns %FALSE so it can be used conveniently in a single
|
||||
* statement:
|
||||
*
|
||||
* ```
|
||||
* if (strcmp (foo, "somevalue") != 0)
|
||||
* return glnx_throw (error, "key must be somevalue, not '%s'", foo);
|
||||
* ```
|
||||
*/
|
||||
static inline gboolean G_GNUC_PRINTF (2,3)
|
||||
glnx_throw (GError **error, const char *fmt, ...)
|
||||
{
|
||||
if (error == NULL)
|
||||
return FALSE;
|
||||
|
||||
va_list args;
|
||||
va_start (args, fmt);
|
||||
GError *new = g_error_new_valist (G_IO_ERROR, G_IO_ERROR_FAILED, fmt, args);
|
||||
va_end (args);
|
||||
g_propagate_error (error, g_steal_pointer (&new));
|
||||
return FALSE;
|
||||
}
|
||||
gboolean glnx_throw (GError **error, const char *fmt, ...) G_GNUC_PRINTF (2,3);
|
||||
|
||||
/* Like `glnx_throw ()`, but returns %NULL. */
|
||||
#define glnx_null_throw(error, args...) \
|
||||
@@ -58,27 +36,7 @@ void glnx_real_set_prefix_error_va (GError *error,
|
||||
const char *format,
|
||||
va_list args) G_GNUC_PRINTF (2,0);
|
||||
|
||||
/* Prepend to @error's message by `$prefix: ` where `$prefix` is computed via
|
||||
* printf @fmt. Returns %FALSE so it can be used conveniently in a single
|
||||
* statement:
|
||||
*
|
||||
* ```
|
||||
* if (!function_that_fails (s, error))
|
||||
* return glnx_throw_prefix (error, "while handling '%s'", s);
|
||||
* ```
|
||||
* */
|
||||
static inline gboolean G_GNUC_PRINTF (2,3)
|
||||
glnx_prefix_error (GError **error, const char *fmt, ...)
|
||||
{
|
||||
if (error == NULL)
|
||||
return FALSE;
|
||||
|
||||
va_list args;
|
||||
va_start (args, fmt);
|
||||
glnx_real_set_prefix_error_va (*error, fmt, args);
|
||||
va_end (args);
|
||||
return FALSE;
|
||||
}
|
||||
gboolean glnx_prefix_error (GError **error, const char *fmt, ...) G_GNUC_PRINTF (2,3);
|
||||
|
||||
/* Like `glnx_prefix_error ()`, but returns %NULL. */
|
||||
#define glnx_prefix_error_null(error, args...) \
|
||||
@@ -155,28 +113,7 @@ void glnx_real_set_prefix_error_from_errno_va (GError **error,
|
||||
const char *format,
|
||||
va_list args) G_GNUC_PRINTF (3,0);
|
||||
|
||||
/* Set @error using the value of `$prefix: g_strerror (errno)` where `$prefix`
|
||||
* is computed via printf @fmt.
|
||||
*
|
||||
* This function returns %FALSE so it can be used conveniently in a single
|
||||
* statement:
|
||||
*
|
||||
* ```
|
||||
* return glnx_throw_errno_prefix (error, "unlinking %s", pathname);
|
||||
* ```
|
||||
*/
|
||||
static inline gboolean G_GNUC_PRINTF (2,3)
|
||||
glnx_throw_errno_prefix (GError **error, const char *fmt, ...)
|
||||
{
|
||||
int errsv = errno;
|
||||
va_list args;
|
||||
va_start (args, fmt);
|
||||
glnx_real_set_prefix_error_from_errno_va (error, errsv, fmt, args);
|
||||
va_end (args);
|
||||
/* See comment above about preserving errno */
|
||||
errno = errsv;
|
||||
return FALSE;
|
||||
}
|
||||
gboolean glnx_throw_errno_prefix (GError **error, const char *fmt, ...) G_GNUC_PRINTF (2,3);
|
||||
|
||||
/* Like glnx_throw_errno_prefix(), but yields a NULL pointer. */
|
||||
#define glnx_null_throw_errno_prefix(error, args...) \
|
||||
|
||||
+7
-6
@@ -29,12 +29,8 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/xattr.h>
|
||||
/* From systemd/src/shared/util.h */
|
||||
/* When we include libgen.h because we need dirname() we immediately
|
||||
* undefine basename() since libgen.h defines it as a macro to the XDG
|
||||
* version which is really broken. */
|
||||
// For dirname(), and previously basename()
|
||||
#include <libgen.h>
|
||||
#undef basename
|
||||
|
||||
#include <glnx-macros.h>
|
||||
#include <glnx-errors.h>
|
||||
@@ -47,7 +43,12 @@ G_BEGIN_DECLS
|
||||
static inline
|
||||
const char *glnx_basename (const char *path)
|
||||
{
|
||||
return (basename) (path);
|
||||
gchar *base = strrchr (path, G_DIR_SEPARATOR);
|
||||
|
||||
if (base)
|
||||
return base + 1;
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
/* Utilities for standard FILE* */
|
||||
|
||||
Reference in new issue
Block a user