mirror of
https://github.com/systemd/systemd.git
synced 2024-12-22 17:35:35 +03:00
Merge pull request #34205 from yuwata/pretty-print-buffering
pretty-print: introduce WITH_BUFFERED_STDERR macro to enable buffering
This commit is contained in:
commit
5d6d2d6ced
@ -460,7 +460,7 @@ bool shall_tint_background(void) {
|
||||
return cache != 0;
|
||||
}
|
||||
|
||||
void draw_progress_bar_unbuffered(const char *prefix, double percentage) {
|
||||
void draw_progress_bar_impl(const char *prefix, double percentage) {
|
||||
fputc('\r', stderr);
|
||||
if (prefix) {
|
||||
fputs(prefix, stderr);
|
||||
@ -516,7 +516,7 @@ void draw_progress_bar_unbuffered(const char *prefix, double percentage) {
|
||||
|
||||
}
|
||||
|
||||
void clear_progress_bar_unbuffered(const char *prefix) {
|
||||
void clear_progress_bar_impl(const char *prefix) {
|
||||
fputc('\r', stderr);
|
||||
|
||||
if (terminal_is_dumb())
|
||||
@ -531,28 +531,14 @@ void clear_progress_bar_unbuffered(const char *prefix) {
|
||||
}
|
||||
|
||||
void draw_progress_bar(const char *prefix, double percentage) {
|
||||
|
||||
/* We are going output a bunch of small strings that shall appear as a single line to STDERR which is
|
||||
* unbuffered by default. Let's temporarily turn on full buffering, so that this is passed to the tty
|
||||
* as a single buffer, to make things more efficient. */
|
||||
char buffer[LONG_LINE_MAX];
|
||||
setvbuf(stderr, buffer, _IOFBF, sizeof(buffer));
|
||||
|
||||
draw_progress_bar_unbuffered(prefix, percentage);
|
||||
|
||||
fflush(stderr);
|
||||
|
||||
/* Disable buffering again */
|
||||
setvbuf(stderr, NULL, _IONBF, 0);
|
||||
WITH_BUFFERED_STDERR;
|
||||
draw_progress_bar_impl(prefix, percentage);
|
||||
}
|
||||
|
||||
void clear_progress_bar(const char *prefix) {
|
||||
char buffer[LONG_LINE_MAX];
|
||||
setvbuf(stderr, buffer, _IOFBF, sizeof(buffer));
|
||||
|
||||
clear_progress_bar_unbuffered(prefix);
|
||||
|
||||
fflush(stderr);
|
||||
|
||||
setvbuf(stderr, NULL, _IONBF, 0);
|
||||
WITH_BUFFERED_STDERR;
|
||||
clear_progress_bar_impl(prefix);
|
||||
}
|
||||
|
@ -55,5 +55,34 @@ bool shall_tint_background(void);
|
||||
|
||||
void draw_progress_bar(const char *prefix, double percentage);
|
||||
void clear_progress_bar(const char *prefix);
|
||||
void draw_progress_bar_unbuffered(const char *prefix, double percentage);
|
||||
void clear_progress_bar_unbuffered(const char *prefix);
|
||||
void draw_progress_bar_impl(const char *prefix, double percentage);
|
||||
void clear_progress_bar_impl(const char *prefix);
|
||||
|
||||
static inline FILE* enable_buffering(FILE *f, char *buffer, size_t size) {
|
||||
assert(f);
|
||||
assert(buffer);
|
||||
assert(size > 0);
|
||||
|
||||
if (setvbuf(f, buffer, _IOFBF, size) != 0)
|
||||
return NULL;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
static inline void fflush_and_disable_bufferingp(FILE **p) {
|
||||
assert(p);
|
||||
|
||||
if (*p) {
|
||||
fflush(*p);
|
||||
setvbuf(*p, NULL, _IONBF, 0); /* Disable buffering again. */
|
||||
}
|
||||
}
|
||||
|
||||
/* Even though the macro below is slightly generic, but it may not work most streams except for stderr,
|
||||
* as stdout is buffered and fopen() enables buffering by default. */
|
||||
#define _WITH_BUFFERED_STREAM(f, size, p) \
|
||||
_unused_ _cleanup_(fflush_and_disable_bufferingp) FILE *p = \
|
||||
enable_buffering(f, (char[size]) {}, size)
|
||||
|
||||
#define WITH_BUFFERED_STDERR \
|
||||
_WITH_BUFFERED_STREAM(stderr, LONG_LINE_MAX, UNIQ_T(p, UNIQ))
|
||||
|
@ -798,8 +798,7 @@ static int update_render_progress(sd_event_source *source, void *userdata) {
|
||||
|
||||
/* We're outputting lots of small strings to STDERR, which is unbuffered by default. So let's turn
|
||||
* on full buffering, so we pass this all to the TTY in one go, to make things more efficient */
|
||||
char buffer[LONG_LINE_MAX];
|
||||
setvbuf(stderr, buffer, _IOFBF, sizeof(buffer));
|
||||
WITH_BUFFERED_STDERR;
|
||||
|
||||
if (!terminal_is_dumb()) {
|
||||
for (size_t i = 0; i <= n; i++)
|
||||
@ -815,23 +814,23 @@ static int update_render_progress(sd_event_source *source, void *userdata) {
|
||||
int progress = PTR_TO_INT(p);
|
||||
|
||||
if (progress == UPDATE_PROGRESS_FAILED) {
|
||||
clear_progress_bar_unbuffered(target);
|
||||
clear_progress_bar_impl(target);
|
||||
fprintf(stderr, "%s: %s Unknown failure\n", target, RED_CROSS_MARK());
|
||||
total += 100;
|
||||
} else if (progress == -EALREADY) {
|
||||
clear_progress_bar_unbuffered(target);
|
||||
clear_progress_bar_impl(target);
|
||||
fprintf(stderr, "%s: %s Already up-to-date\n", target, GREEN_CHECK_MARK());
|
||||
n--; /* Don't consider this target in the total */
|
||||
} else if (progress < 0) {
|
||||
clear_progress_bar_unbuffered(target);
|
||||
clear_progress_bar_impl(target);
|
||||
fprintf(stderr, "%s: %s %s\n", target, RED_CROSS_MARK(), STRERROR(progress));
|
||||
total += 100;
|
||||
} else if (progress == UPDATE_PROGRESS_DONE) {
|
||||
clear_progress_bar_unbuffered(target);
|
||||
clear_progress_bar_impl(target);
|
||||
fprintf(stderr, "%s: %s Done\n", target, GREEN_CHECK_MARK());
|
||||
total += 100;
|
||||
} else {
|
||||
draw_progress_bar_unbuffered(target, progress);
|
||||
draw_progress_bar_impl(target, progress);
|
||||
fputs("\n", stderr);
|
||||
total += progress;
|
||||
}
|
||||
@ -839,9 +838,9 @@ static int update_render_progress(sd_event_source *source, void *userdata) {
|
||||
|
||||
if (n > 1) {
|
||||
if (exiting)
|
||||
clear_progress_bar_unbuffered(target);
|
||||
clear_progress_bar_impl(target);
|
||||
else {
|
||||
draw_progress_bar_unbuffered("Total", (double) total / n);
|
||||
draw_progress_bar_impl("Total", (double) total / n);
|
||||
if (terminal_is_dumb())
|
||||
fputs("\n", stderr);
|
||||
}
|
||||
@ -855,8 +854,6 @@ static int update_render_progress(sd_event_source *source, void *userdata) {
|
||||
} else if (!exiting)
|
||||
fputs("------\n", stderr);
|
||||
|
||||
fflush(stderr);
|
||||
setvbuf(stderr, NULL, _IONBF, 0); /* Disable buffering again */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user