From 43850a126b94690302bc2564905141b077b490e7 Mon Sep 17 00:00:00 2001 From: Timo Teräs Date: Thu, 20 Sep 2012 15:12:15 +0300 Subject: apk: implement --progress-fd to write progress to a specified fd --- src/apk.c | 5 +++++ src/apk_database.h | 4 ++-- src/database.c | 1 + src/solver.c | 44 +++++++++++++++++++++++++++----------------- 4 files changed, 35 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/apk.c b/src/apk.c index 3bf1154..0404831 100644 --- a/src/apk.c +++ b/src/apk.c @@ -48,6 +48,7 @@ static struct apk_option generic_options[] = { { 'f', "force", "Do what was asked even if it looks dangerous" }, { 'U', "update-cache", "Update the repository cache" }, { 0x101, "progress", "Show a progress bar" }, + { 0x10f, "progress-fd", "Write progress to fd", required_argument, "FD" }, { 0x110, "no-progress", "Disable progress bar even for TTYs" }, { 0x102, "clean-protected", "Do not create .apk-new files to " "configuration dirs" }, @@ -265,6 +266,7 @@ static void setup_terminal(void) { setvbuf(stderr, NULL, _IOLBF, BUFSIZ); signal(SIGWINCH, on_sigwinch); + signal(SIGPIPE, SIG_IGN); } static void setup_automatic_flags(void) @@ -383,6 +385,9 @@ int main(int argc, char **argv) case 0x110: apk_flags &= ~APK_PROGRESS; break; + case 0x10f: + dbopts.progress_fd = atoi(optarg); + break; case 0x102: apk_flags |= APK_CLEAN_PROTECTED; break; diff --git a/src/apk_database.h b/src/apk_database.h index 235030c..4628c23 100644 --- a/src/apk_database.h +++ b/src/apk_database.h @@ -108,7 +108,7 @@ struct apk_repository_list { }; struct apk_db_options { - int lock_wait; + int lock_wait, progress_fd; unsigned long open_flags; char *root; char *arch; @@ -127,7 +127,7 @@ struct apk_repository_tag { struct apk_database { char *root; - int root_fd, lock_fd, cache_fd, cachetmp_fd, keys_fd; + int root_fd, lock_fd, cache_fd, cachetmp_fd, keys_fd, progress_fd; unsigned num_repos, num_repo_tags; const char *cache_dir; char *cache_remount_dir; diff --git a/src/database.c b/src/database.c index d1a8f1a..e130f0b 100644 --- a/src/database.c +++ b/src/database.c @@ -1359,6 +1359,7 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) int r, fd, write_arch = FALSE; memset(db, 0, sizeof(*db)); + db->progress_fd = dbopts->progress_fd; if (apk_flags & APK_SIMULATE) { dbopts->open_flags &= ~(APK_OPENF_CREATE | APK_OPENF_WRITE); dbopts->open_flags |= APK_OPENF_READ; diff --git a/src/solver.c b/src/solver.c index 457d5ff..ec44958 100644 --- a/src/solver.c +++ b/src/solver.c @@ -10,6 +10,7 @@ */ #include +#include #include "apk_defines.h" #include "apk_database.h" #include "apk_package.h" @@ -1650,23 +1651,34 @@ struct progress { struct apk_stats done; struct apk_stats total; struct apk_package *pkg; - size_t count; + size_t percent; + int progress_fd; }; -static void progress_cb(void *ctx, size_t progress) +static void update_progress(struct progress *prog, size_t percent) +{ + if (prog->percent == percent) + return; + prog->percent = percent; + if (apk_flags & APK_PROGRESS) + draw_progress(percent); + if (prog->progress_fd != 0) { + char buf[8]; + size_t n = snprintf(buf, sizeof(buf), "%d\n", percent); + write(prog->progress_fd, buf, n); + } +} + +static void progress_cb(void *ctx, size_t pkg_percent) { struct progress *prog = (struct progress *) ctx; - size_t partial = 0, count; + size_t partial = 0, percent; if (prog->pkg != NULL) - partial = muldiv(progress, prog->pkg->installed_size, APK_PROGRESS_SCALE); - - count = muldiv(100, prog->done.bytes + prog->done.packages + partial, - prog->total.bytes + prog->total.packages); - - if (prog->count != count) - draw_progress(count); - prog->count = count; + partial = muldiv(pkg_percent, prog->pkg->installed_size, APK_PROGRESS_SCALE); + percent = muldiv(100, prog->done.bytes + prog->done.packages + partial, + prog->total.bytes + prog->total.packages); + update_progress(prog, percent); } static int dump_packages(struct apk_changeset *changeset, @@ -1784,6 +1796,7 @@ int apk_solver_commit_changeset(struct apk_database *db, /* Count what needs to be done */ memset(&prog, 0, sizeof(prog)); + prog.progress_fd = db->progress_fd; for (i = 0; i < changeset->changes->num; i++) { change = &changeset->changes->item[i]; count_change(change, &prog.total); @@ -1831,17 +1844,15 @@ int apk_solver_commit_changeset(struct apk_database *db, change = &changeset->changes->item[i]; print_change(db, change, i, changeset->changes->num); - if (apk_flags & APK_PROGRESS) - draw_progress(prog.count); prog.pkg = change->newpkg; + progress_cb(&prog, 0); if (!(apk_flags & APK_SIMULATE)) { if (change->oldpkg != change->newpkg || (change->reinstall && pkg_available(db, change->newpkg))) r = apk_db_install_pkg(db, change->oldpkg, change->newpkg, - (apk_flags & APK_PROGRESS) ? progress_cb : NULL, - &prog); + progress_cb, &prog); if (r != 0) break; if (change->newpkg) @@ -1850,8 +1861,7 @@ int apk_solver_commit_changeset(struct apk_database *db, count_change(change, &prog.done); } - if (apk_flags & APK_PROGRESS) - draw_progress(100); + update_progress(&prog, 100); run_triggers(db); -- cgit v1.2.3-70-g09d2