From d351992ad529dccb95fc1c8997cd328e9c694a92 Mon Sep 17 00:00:00 2001 From: Timo Teräs Date: Mon, 27 Dec 2021 14:34:01 +0200 Subject: print: improve indented printing api - make sure all commit errors go to stderr - make it a bit more api like (cherry picked and rebased from commit a662047e2c43604bc087ec4dda9a7358368d850b) fixes #10879 --- src/apk_print.h | 9 ++- src/app_del.c | 15 ++--- src/commit.c | 29 ++++----- src/print.c | 188 ++++++++++++++++++++++++++++++++++---------------------- 4 files changed, 137 insertions(+), 104 deletions(-) diff --git a/src/apk_print.h b/src/apk_print.h index 1d5dfd6..f8a2003 100644 --- a/src/apk_print.h +++ b/src/apk_print.h @@ -41,11 +41,16 @@ int apk_get_screen_width(void); const char *apk_get_human_size(off_t size, off_t *dest); struct apk_indent { - int x; - int indent; + FILE *f; + unsigned int x, indent, width; }; void apk_print_progress(size_t done, size_t total); + +void apk_print_indented_init(struct apk_indent *i, int err); +void apk_print_indented_line(struct apk_indent *i, const char *fmt, ...); +void apk_print_indented_group(struct apk_indent *i, int indent, const char *fmt, ...); +void apk_print_indented_end(struct apk_indent *i); int apk_print_indented(struct apk_indent *i, apk_blob_t blob); void apk_print_indented_words(struct apk_indent *i, const char *text); void apk_print_indented_fmt(struct apk_indent *i, const char *fmt, ...) diff --git a/src/app_del.c b/src/app_del.c index c8a9e36..7d3cf36 100644 --- a/src/app_del.c +++ b/src/app_del.c @@ -66,14 +66,10 @@ static void print_not_deleted_pkg(struct apk_package *pkg0, struct apk_dependenc apk_message("World updated, but the following packages are not removed due to:"); ctx->header = 1; } - if (!ctx->indent.indent) { - ctx->indent.x = printf(" %s:", ctx->name->name); - ctx->indent.indent = ctx->indent.x + 1; - } - - if (name_in_world(pkg0->name)) { + if (!ctx->indent.indent) + apk_print_indented_group(&ctx->indent, 0, " %s:", ctx->name->name); + if (name_in_world(pkg0->name)) apk_print_indented(&ctx->indent, APK_BLOB_STR(pkg0->name->name)); - } foreach_array_item(d, pkg0->provides) { if (!name_in_world(d->name)) continue; apk_print_indented(&ctx->indent, APK_BLOB_STR(d->name->name)); @@ -95,14 +91,13 @@ static void print_not_deleted_name(struct apk_database *db, const char *match, struct not_deleted_ctx *ctx = (struct not_deleted_ctx *) pctx; struct apk_provider *p; - ctx->indent.indent = 0; ctx->name = name; ctx->matches = apk_foreach_genid() | APK_FOREACH_MARKED | APK_DEP_SATISFIES; + apk_print_indented_init(&ctx->indent, 0); foreach_array_item(p, name->providers) if (p->pkg->marked) print_not_deleted_pkg(p->pkg, NULL, NULL, ctx); - if (ctx->indent.indent) - printf("\n"); + apk_print_indented_end(&ctx->indent); } static void delete_pkg(struct apk_package *pkg0, struct apk_dependency *dep0, diff --git a/src/commit.c b/src/commit.c index f9f14ba..f582ec2 100644 --- a/src/commit.c +++ b/src/commit.c @@ -130,12 +130,13 @@ static int dump_packages(struct apk_change_array *changes, { struct apk_change *change; struct apk_name *name; - struct apk_indent indent = { .indent = 2 }; + struct apk_indent indent; int match = 0; + apk_print_indented_init(&indent, 0); foreach_array_item(change, changes) { if (!cmp(change)) continue; - if (!match) printf("%s:\n", msg); + if (!match) apk_print_indented_group(&indent, 2, "%s:\n", msg); if (change->new_pkg != NULL) name = change->new_pkg->name; else @@ -144,7 +145,7 @@ static int dump_packages(struct apk_change_array *changes, apk_print_indented(&indent, APK_BLOB_STR(name->name)); match++; } - if (match) printf("\n"); + apk_print_indented_end(&indent); return match; } @@ -316,11 +317,11 @@ int apk_solver_commit_changeset(struct apk_database *db, "The following packages will be reinstalled"); if (download_size) { size_unit = apk_get_human_size(download_size, &humanized); - printf("Need to download %lld %s of packages.\n", + apk_message("Need to download %lld %s of packages.", (long long)humanized, size_unit); } size_unit = apk_get_human_size(llabs(size_diff), &humanized); - printf("After this operation, %lld %s of %s.\n", + apk_message("After this operation, %lld %s of %s.", (long long)humanized, size_unit, (size_diff < 0) ? @@ -417,22 +418,15 @@ struct print_state { static void label_start(struct print_state *ps, const char *text) { if (ps->label) { - printf(" %s:\n", ps->label); + apk_print_indented_line(&ps->i, " %s:\n", ps->label); ps->label = NULL; - ps->i.x = ps->i.indent = 0; ps->num_labels++; } - if (ps->i.x == 0) { - ps->i.x = printf(" %s", text); - ps->i.indent = ps->i.x + 1; - } + if (!ps->i.x) apk_print_indented_group(&ps->i, 0, " %s", text); } static void label_end(struct print_state *ps) { - if (ps->i.x != 0) { - printf("\n"); - ps->i.x = ps->i.indent = 0; - } + apk_print_indented_end(&ps->i); } static void print_pinning_errors(struct print_state *ps, struct apk_package *pkg, unsigned int tag) @@ -760,6 +754,7 @@ void apk_solver_print_errors(struct apk_database *db, .db = db, .world = world, }; + apk_print_indented_init(&ps.i, 1); analyze_deps(&ps, world); foreach_array_item(change, changeset->changes) { struct apk_package *pkg = change->new_pkg; @@ -768,8 +763,8 @@ void apk_solver_print_errors(struct apk_database *db, analyze_deps(&ps, pkg->depends); } - if (ps.num_labels == 0) - printf(" Huh? Error reporter did not find the broken constraints.\n"); + if (!ps.num_labels) + apk_print_indented_line(&ps.i, "Huh? Error reporter did not find the broken constraints.\n"); } int apk_solver_commit(struct apk_database *db, diff --git a/src/print.c b/src/print.c index 23f4614..c15ab1b 100644 --- a/src/print.c +++ b/src/print.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -68,81 +69,6 @@ const char *apk_get_human_size(off_t size, off_t *dest) return apk_size_units[min(i, ARRAY_SIZE(apk_size_units) - 1)]; } -void apk_print_progress(size_t done, size_t total) -{ - static size_t last_done = 0; - static int last_bar = 0, last_percent = 0; - int bar_width; - int bar = 0; - char buf[64]; /* enough for petabytes... */ - int i, percent = 0; - - if (last_done == done && !apk_progress_force) - return; - - if (apk_progress_fd != 0) { - i = snprintf(buf, sizeof(buf), "%zu/%zu\n", done, total); - write(apk_progress_fd, buf, i); - } - last_done = done; - - if (!(apk_flags & APK_PROGRESS)) - return; - - bar_width = apk_get_screen_width() - 6; - if (total > 0) { - bar = muldiv(bar_width, done, total); - percent = muldiv(100, done, total); - } - - if (bar == last_bar && percent == last_percent && !apk_progress_force) - return; - - last_bar = bar; - last_percent = percent; - apk_progress_force = 0; - - fprintf(stdout, "\e7%3i%% ", percent); - - for (i = 0; i < bar; i++) - fputs(apk_progress_char, stdout); - for (; i < bar_width; i++) - fputc(' ', stdout); - - fflush(stdout); - fputs("\e8\e[0K", stdout); -} - -int apk_print_indented(struct apk_indent *i, apk_blob_t blob) -{ - if (i->x <= i->indent) - i->x += printf("%*s" BLOB_FMT, i->indent - i->x, "", BLOB_PRINTF(blob)); - else if (i->x + blob.len + 1 >= apk_get_screen_width()) - i->x = printf("\n%*s" BLOB_FMT, i->indent, "", BLOB_PRINTF(blob)) - 1; - else - i->x += printf(" " BLOB_FMT, BLOB_PRINTF(blob)); - apk_progress_force = 1; - return 0; -} - -void apk_print_indented_words(struct apk_indent *i, const char *text) -{ - apk_blob_for_each_segment(APK_BLOB_STR(text), " ", - (apk_blob_cb) apk_print_indented, i); -} - -void apk_print_indented_fmt(struct apk_indent *i, const char *fmt, ...) -{ - char tmp[256]; - size_t n; - va_list va; - - va_start(va, fmt); - n = vsnprintf(tmp, sizeof(tmp), fmt, va); - apk_print_indented(i, APK_BLOB_PTR_LEN(tmp, n)); - va_end(va); -} - const char *apk_error_str(int error) { if (error < 0) @@ -242,3 +168,115 @@ void apk_url_parse(struct apk_url_print *urlp, const char *url) .len_before_pw = pw - url + 1, }; } + +void apk_print_progress(size_t done, size_t total) +{ + static size_t last_done = 0; + static int last_bar = 0, last_percent = 0; + int bar_width; + int bar = 0; + char buf[64]; /* enough for petabytes... */ + int i, percent = 0; + + if (last_done == done && !apk_progress_force) + return; + + if (apk_progress_fd != 0) { + i = snprintf(buf, sizeof(buf), "%zu/%zu\n", done, total); + write(apk_progress_fd, buf, i); + } + last_done = done; + + if (!(apk_flags & APK_PROGRESS)) + return; + + bar_width = apk_get_screen_width() - 6; + if (total > 0) { + bar = muldiv(bar_width, done, total); + percent = muldiv(100, done, total); + } + + if (bar == last_bar && percent == last_percent && !apk_progress_force) + return; + + last_bar = bar; + last_percent = percent; + apk_progress_force = 0; + + fprintf(stdout, "\e7%3i%% ", percent); + + for (i = 0; i < bar; i++) + fputs(apk_progress_char, stdout); + for (; i < bar_width; i++) + fputc(' ', stdout); + + fflush(stdout); + fputs("\e8\e[0K", stdout); +} + +void apk_print_indented_init(struct apk_indent *i, int err) +{ + *i = (struct apk_indent) { + .f = err ? stderr : stdout, + .width = apk_get_screen_width(), + }; + apk_progress_force = 1; +} + +void apk_print_indented_line(struct apk_indent *i, const char *fmt, ...) +{ + va_list va; + + va_start(va, fmt); + vfprintf(i->f, fmt, va); + va_end(va); + i->x = i->indent = 0; +} + +void apk_print_indented_group(struct apk_indent *i, int indent, const char *fmt, ...) +{ + va_list va; + + va_start(va, fmt); + i->x = vfprintf(i->f, fmt, va); + i->indent = indent ?: (i->x + 1); + if (fmt[strlen(fmt)-1] == '\n') i->x = 0; + va_end(va); +} + +void apk_print_indented_end(struct apk_indent *i) +{ + if (i->x) { + fprintf(i->f, "\n"); + i->x = i->indent = 0; + } +} + +int apk_print_indented(struct apk_indent *i, apk_blob_t blob) +{ + if (i->x <= i->indent) + i->x += fprintf(i->f, "%*s" BLOB_FMT, i->indent - i->x, "", BLOB_PRINTF(blob)); + else if (i->x + blob.len + 1 >= i->width) + i->x = fprintf(i->f, "\n%*s" BLOB_FMT, i->indent, "", BLOB_PRINTF(blob)) - 1; + else + i->x += fprintf(i->f, " " BLOB_FMT, BLOB_PRINTF(blob)); + return 0; +} + +void apk_print_indented_words(struct apk_indent *i, const char *text) +{ + apk_blob_for_each_segment(APK_BLOB_STR(text), " ", + (apk_blob_cb) apk_print_indented, i); +} + +void apk_print_indented_fmt(struct apk_indent *i, const char *fmt, ...) +{ + char tmp[256]; + size_t n; + va_list va; + + va_start(va, fmt); + n = vsnprintf(tmp, sizeof(tmp), fmt, va); + apk_print_indented(i, APK_BLOB_PTR_LEN(tmp, n)); + va_end(va); +} -- cgit v1.2.3-60-g2f50