mirror of
https://github.com/systemd/systemd.git
synced 2024-12-22 17:35:35 +03:00
Merge pull request #34198 from AdrianVovk/updatectl-bugfixes
updatectl: Bugfixes
This commit is contained in:
commit
6434d0bbf7
@ -45,7 +45,7 @@ static const char* arg_format = NULL;
|
||||
static sd_json_format_flags_t arg_json_format_flags = SD_JSON_FORMAT_OFF;
|
||||
static ImageClass arg_image_class = _IMAGE_CLASS_INVALID;
|
||||
|
||||
#define PROGRESS_PREFIX "Total: "
|
||||
#define PROGRESS_PREFIX "Total:"
|
||||
|
||||
static int settle_image_class(void) {
|
||||
|
||||
|
@ -153,5 +153,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_REBALANCE_NOT_NEEDED, EALREADY),
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_HOME_NOT_REFERENCED, EBADR),
|
||||
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_NO_UPDATE_CANDIDATE, EALREADY),
|
||||
|
||||
SD_BUS_ERROR_MAP_END
|
||||
};
|
||||
|
@ -158,4 +158,6 @@
|
||||
#define BUS_ERROR_REBALANCE_NOT_NEEDED "org.freedesktop.home1.RebalanceNotNeeded"
|
||||
#define BUS_ERROR_HOME_NOT_REFERENCED "org.freedesktop.home1.HomeNotReferenced"
|
||||
|
||||
#define BUS_ERROR_NO_UPDATE_CANDIDATE "org.freedesktop.sysupdate1.NoCandidate"
|
||||
|
||||
BUS_ERROR_MAP_ELF_USE(bus_common_errors);
|
||||
|
@ -4553,7 +4553,7 @@ static int progress_bytes(uint64_t n_bytes, void *userdata) {
|
||||
|
||||
p->copy_blocks_done += n_bytes;
|
||||
|
||||
if (asprintf(&s, "%s %s %s %s/%s ",
|
||||
if (asprintf(&s, "%s %s %s %s/%s",
|
||||
strna(p->copy_blocks_path),
|
||||
special_glyph(SPECIAL_GLYPH_ARROW_RIGHT),
|
||||
strna(p->definition_path),
|
||||
|
@ -460,21 +460,16 @@ bool shall_tint_background(void) {
|
||||
return cache != 0;
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
void draw_progress_bar_unbuffered(const char *prefix, double percentage) {
|
||||
fputc('\r', stderr);
|
||||
if (prefix)
|
||||
if (prefix) {
|
||||
fputs(prefix, stderr);
|
||||
fputc(' ', stderr);
|
||||
}
|
||||
|
||||
if (!terminal_is_dumb()) {
|
||||
size_t cols = columns();
|
||||
size_t prefix_width = utf8_console_width(prefix);
|
||||
size_t prefix_width = utf8_console_width(prefix) + 1 /* space */;
|
||||
size_t length = cols > prefix_width + 6 ? cols - prefix_width - 6 : 0;
|
||||
|
||||
if (length > 5 && percentage >= 0.0 && percentage <= 100.0) {
|
||||
@ -518,6 +513,33 @@ void draw_progress_bar(const char *prefix, double percentage) {
|
||||
fputs(ANSI_ERASE_TO_END_OF_LINE, stderr);
|
||||
|
||||
fputc('\r', stderr);
|
||||
|
||||
}
|
||||
|
||||
void clear_progress_bar_unbuffered(const char *prefix) {
|
||||
fputc('\r', stderr);
|
||||
|
||||
if (terminal_is_dumb())
|
||||
fputs(strrepa(" ",
|
||||
prefix ? utf8_console_width(prefix) + 5 : /* %3.0f%% (4 chars) + space */
|
||||
LESS_BY(columns(), 1U)),
|
||||
stderr);
|
||||
else
|
||||
fputs(ANSI_ERASE_TO_END_OF_LINE, stderr);
|
||||
|
||||
fputc('\r', stderr);
|
||||
}
|
||||
|
||||
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 */
|
||||
@ -525,23 +547,12 @@ void draw_progress_bar(const char *prefix, double percentage) {
|
||||
}
|
||||
|
||||
void clear_progress_bar(const char *prefix) {
|
||||
|
||||
char buffer[LONG_LINE_MAX];
|
||||
setvbuf(stderr, buffer, _IOFBF, sizeof(buffer));
|
||||
|
||||
fputc('\r', stderr);
|
||||
clear_progress_bar_unbuffered(prefix);
|
||||
|
||||
if (terminal_is_dumb())
|
||||
fputs(strrepa(" ",
|
||||
prefix ? utf8_console_width(prefix) + 4 :
|
||||
LESS_BY(columns(), 1U)), /* 4: %3.0f%% */
|
||||
stderr);
|
||||
else
|
||||
fputs(ANSI_ERASE_TO_END_OF_LINE, stderr);
|
||||
|
||||
fputc('\r', stderr);
|
||||
fflush(stderr);
|
||||
|
||||
/* Disable buffering again */
|
||||
setvbuf(stderr, NULL, _IONBF, 0);
|
||||
}
|
||||
|
@ -55,3 +55,5 @@ 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);
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "sd-json.h"
|
||||
|
||||
#include "build-path.h"
|
||||
#include "bus-common-errors.h"
|
||||
#include "bus-error.h"
|
||||
#include "bus-get-properties.h"
|
||||
#include "bus-label.h"
|
||||
@ -1044,8 +1045,8 @@ static int target_method_update_finished_early(
|
||||
/* Called when job finishes w/ a successful exit code, but before any work begins.
|
||||
* This happens when there is no candidate (i.e. we're already up-to-date), or
|
||||
* specified update is already installed. */
|
||||
return sd_bus_error_setf(error, "org.freedesktop.sysupdate1.NoCandidate",
|
||||
"Job exited successfully with no work to do, assume already updated");
|
||||
return sd_bus_error_setf(error, BUS_ERROR_NO_UPDATE_CANDIDATE,
|
||||
"Job exited successfully with no work to do, assume already updated");
|
||||
}
|
||||
|
||||
static int target_method_update_detach(sd_bus_message *msg, const Job *j) {
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "bus-map-properties.h"
|
||||
#include "bus-util.h"
|
||||
#include "errno-list.h"
|
||||
#include "fileio.h"
|
||||
#include "format-table.h"
|
||||
#include "json-util.h"
|
||||
#include "main-func.h"
|
||||
@ -775,6 +776,7 @@ static int verb_check(int argc, char **argv, void *userdata) {
|
||||
}
|
||||
|
||||
#define UPDATE_PROGRESS_FAILED INT_MIN
|
||||
#define UPDATE_PROGRESS_DONE INT_MAX
|
||||
/* Make sure it doesn't overlap w/ errno values */
|
||||
assert_cc(UPDATE_PROGRESS_FAILED < -ERRNO_MAX);
|
||||
|
||||
@ -794,6 +796,11 @@ static int update_render_progress(sd_event_source *source, void *userdata) {
|
||||
if (n == 0)
|
||||
return 0;
|
||||
|
||||
/* 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));
|
||||
|
||||
if (!terminal_is_dumb()) {
|
||||
for (size_t i = 0; i <= n; i++)
|
||||
fputs("\n", stderr); /* Possibly scroll the terminal to make room (including total)*/
|
||||
@ -808,24 +815,36 @@ static int update_render_progress(sd_event_source *source, void *userdata) {
|
||||
int progress = PTR_TO_INT(p);
|
||||
|
||||
if (progress == UPDATE_PROGRESS_FAILED) {
|
||||
fprintf(stderr, "%s %s\n", RED_CROSS_MARK(), target);
|
||||
clear_progress_bar_unbuffered(target);
|
||||
fprintf(stderr, "%s: %s Unknown failure\n", target, RED_CROSS_MARK());
|
||||
total += 100;
|
||||
} else if (progress == -EALREADY) {
|
||||
fprintf(stderr, "%s %s (Already up-to-date)\n", GREEN_CHECK_MARK(), target);
|
||||
clear_progress_bar_unbuffered(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) {
|
||||
fprintf(stderr, "%s %s (%s)\n", RED_CROSS_MARK(), target, STRERROR(progress));
|
||||
clear_progress_bar_unbuffered(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);
|
||||
fprintf(stderr, "%s: %s Done\n", target, GREEN_CHECK_MARK());
|
||||
total += 100;
|
||||
} else {
|
||||
draw_progress_bar(target, progress);
|
||||
draw_progress_bar_unbuffered(target, progress);
|
||||
fputs("\n", stderr);
|
||||
total += progress;
|
||||
}
|
||||
}
|
||||
|
||||
if (n > 1) {
|
||||
draw_progress_bar("TOTAL", (double) total / n);
|
||||
fputs("\n", stderr);
|
||||
if (exiting)
|
||||
clear_progress_bar_unbuffered(target);
|
||||
else {
|
||||
draw_progress_bar_unbuffered("Total", (double) total / n);
|
||||
if (terminal_is_dumb())
|
||||
fputs("\n", stderr);
|
||||
}
|
||||
}
|
||||
|
||||
if (!terminal_is_dumb()) {
|
||||
@ -837,6 +856,7 @@ static int update_render_progress(sd_event_source *source, void *userdata) {
|
||||
fputs("------\n", stderr);
|
||||
|
||||
fflush(stderr);
|
||||
setvbuf(stderr, NULL, _IONBF, 0); /* Disable buffering again */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -895,7 +915,7 @@ static int update_finished(sd_bus_message *m, void *userdata, sd_bus_error *erro
|
||||
}
|
||||
|
||||
if (status == 0) /* success */
|
||||
status = 100;
|
||||
status = UPDATE_PROGRESS_DONE;
|
||||
else if (status > 0) /* exit status without errno */
|
||||
status = UPDATE_PROGRESS_FAILED; /* i.e. EXIT_FAILURE */
|
||||
/* else errno */
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "random-util.h"
|
||||
#include "tests.h"
|
||||
|
||||
#define PROGRESS_PREFIX "test: "
|
||||
#define PROGRESS_PREFIX "test:"
|
||||
|
||||
TEST(progress_bar) {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user