New upstream version 2017.15

This commit is contained in:
Simon McVittie committed 2018-01-02 11:53:43 +00:00
commit ef9ffc09f4
66 files changed
+2620 -638

No files matched your search

+63 -13
View File
@@ -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 (&current_text, g_free);
if (console->is_tty)
fputc ('\n', stdout);
+5 -1
View File
@@ -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);
+75
View File
@@ -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
View File
@@ -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
View File
@@ -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* */