print: move progress bar update logic to apk_print_progress

- let the apk_print functions deal with the forced print itself. We
  avoid that the callbacks need to deal with the force flag. We can
  also get rid of the APK_PRINT_PROGRESS_* defines.

- let the reader of --progress-fd decide how often things are updated
  rather than having a fixed granularity off 1/100 (percent)

- avoid detect screen size and percent/bar calculations in case the
  --no-progress was given

- track satistics for both the ascii bar and percent info and update bar
  only if either percent or bar changes. This makes the bar go smoother
  when width is wider than 100 chars and it makes the percent counter
  go smooth when screen width is less thann 100 chars. It also
  simplifies the callbacks as they no longer need to deal with update
  granularity.
cute-signatures
Natanael Copa 2013-06-19 08:47:09 +00:00
parent 0c1a26f25c
commit adc5b0b161
5 changed files with 48 additions and 49 deletions

View File

@ -31,10 +31,7 @@ struct apk_indent {
int indent;
};
#define APK_PRINT_PROGRESS_MASK 0xff
#define APK_PRINT_PROGRESS_FORCE 0x100
void apk_print_progress(int percent);
void apk_print_progress(size_t done, size_t total);
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, ...);

View File

@ -28,14 +28,12 @@
struct progress {
size_t done, total;
int flags;
};
static void progress_cb(void *ctx, size_t bytes_done)
{
struct progress *prog = (struct progress *) ctx;
apk_print_progress(muldiv(100, prog->done + bytes_done, prog->total) | prog->flags);
prog->flags = 0;
apk_print_progress(prog->done + bytes_done, prog->total);
}
static int cache_download(struct apk_database *db)
@ -68,7 +66,6 @@ static int cache_download(struct apk_database *db)
if (repo == NULL)
continue;
prog.flags = APK_PRINT_PROGRESS_FORCE;
r = apk_cache_download(db, repo, pkg, APK_SIGN_VERIFY_IDENTITY,
progress_cb, &prog);
if (r) {

View File

@ -91,7 +91,7 @@ static int print_change(struct apk_database *db, struct apk_change *change,
struct apk_stats {
unsigned int changes;
unsigned int bytes;
size_t bytes;
unsigned int packages;
};
@ -115,22 +115,13 @@ struct progress {
struct apk_stats done;
struct apk_stats total;
struct apk_package *pkg;
int flags;
};
static void progress_cb(void *ctx, size_t installed_bytes)
{
struct progress *prog = (struct progress *) ctx;
size_t percent, total;
total = prog->total.bytes + prog->total.packages;
if (total > 0)
percent = muldiv(100, prog->done.bytes + prog->done.packages + installed_bytes,
prog->total.bytes + prog->total.packages);
else
percent = 0;
apk_print_progress(percent | prog->flags);
prog->flags = 0;
apk_print_progress(prog->done.bytes + prog->done.packages + installed_bytes,
prog->total.bytes + prog->total.packages);
}
static int dump_packages(struct apk_changeset *changeset,
@ -283,7 +274,6 @@ int apk_solver_commit_changeset(struct apk_database *db,
foreach_array_item(change, changeset->changes) {
if (print_change(db, change, prog.done.changes, prog.total.changes)) {
prog.pkg = change->new_pkg;
prog.flags = APK_PRINT_PROGRESS_FORCE;
progress_cb(&prog, 0);
if (!(apk_flags & APK_SIMULATE)) {
@ -301,7 +291,8 @@ int apk_solver_commit_changeset(struct apk_database *db,
count_change(change, &prog.done);
}
apk_print_progress(100 | APK_PRINT_PROGRESS_FORCE);
apk_print_progress(prog.total.bytes + prog.total.packages,
prog.total.bytes + prog.total.packages);
run_triggers(db, changeset);

View File

@ -28,7 +28,7 @@
struct fetch_ctx {
unsigned int flags;
int outdir_fd, errors, prog_flags;
int outdir_fd, errors;
struct apk_database *db;
size_t done, total;
};
@ -94,8 +94,7 @@ static int fetch_parse(void *ctx, struct apk_db_options *dbopts,
static void progress_cb(void *pctx, size_t bytes_done)
{
struct fetch_ctx *ctx = (struct fetch_ctx *) pctx;
apk_print_progress(muldiv(100, ctx->done + bytes_done, ctx->total) | ctx->prog_flags);
ctx->prog_flags = 0;
apk_print_progress(ctx->done + bytes_done, ctx->total);
}
static int fetch_package(apk_hash_item item, void *pctx)
@ -133,8 +132,6 @@ static int fetch_package(apk_hash_item item, void *pctx)
if (apk_flags & APK_SIMULATE)
return 0;
ctx->prog_flags = APK_PRINT_PROGRESS_FORCE;
r = apk_repo_format_item(db, repo, pkg, &urlfd, url, sizeof(url));
if (r < 0)
goto err;

View File

@ -21,10 +21,12 @@
int apk_progress_fd;
static int apk_screen_width = 0;
static int apk_progress_force = 1;
void apk_reset_screen_width(void)
{
apk_screen_width = 0;
apk_progress_force = 1;
}
int apk_get_screen_width(void)
@ -41,35 +43,48 @@ int apk_get_screen_width(void)
return apk_screen_width;
}
void apk_print_progress(int percent_flags)
void apk_print_progress(size_t done, size_t total)
{
static int last_written = 0;
const int bar_width = apk_get_screen_width() - 7;
char buf[8];
int i, percent;
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;
percent = percent_flags & APK_PRINT_PROGRESS_MASK;
if (last_written == percent && !(percent_flags & APK_PRINT_PROGRESS_FORCE))
if (last_done == done && !apk_progress_force)
return;
last_written = percent;
if (apk_flags & APK_PROGRESS) {
fprintf(stderr, "\e7%3i%% [", percent);
for (i = 0; i < bar_width * percent / 100; i++)
fputc('#', stderr);
for (; i < bar_width; i++)
fputc(' ', stderr);
fputc(']', stderr);
fflush(stderr);
fputs("\e8\e[0K", stderr);
}
if (apk_progress_fd != 0) {
i = snprintf(buf, sizeof(buf), "%i\n", percent);
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() - 7;
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(stderr, "\e7%3i%% [", percent);
for (i = 0; i < bar; i++)
fputc('#', stderr);
for (; i < bar_width; i++)
fputc(' ', stderr);
fputc(']', stderr);
fflush(stderr);
fputs("\e8\e[0K", stderr);
}
int apk_print_indented(struct apk_indent *i, apk_blob_t blob)
@ -80,6 +95,7 @@ int apk_print_indented(struct apk_indent *i, apk_blob_t blob)
i->x += printf("%*s" BLOB_FMT, i->indent - i->x, "", BLOB_PRINTF(blob));
else
i->x += printf(" " BLOB_FMT, BLOB_PRINTF(blob));
apk_progress_force = 1;
return 0;
}
@ -133,5 +149,6 @@ void apk_log(const char *prefix, const char *format, ...)
vfprintf(stderr, format, va);
va_end(va);
fprintf(stderr, "\n");
apk_progress_force = 1;
}