diff --git a/src/apk.c b/src/apk.c
index c834b76..f5f6f13 100644
--- a/src/apk.c
+++ b/src/apk.c
@@ -386,7 +386,7 @@ int main(int argc, char **argv)
 			apk_flags &= ~APK_PROGRESS;
 			break;
 		case 0x10f:
-			dbopts.progress_fd = atoi(optarg);
+			apk_progress_fd = atoi(optarg);
 			break;
 		case 0x102:
 			apk_flags |= APK_CLEAN_PROTECTED;
diff --git a/src/apk_database.h b/src/apk_database.h
index 0017ade..02ba196 100644
--- a/src/apk_database.h
+++ b/src/apk_database.h
@@ -107,7 +107,7 @@ struct apk_repository_list {
 };
 
 struct apk_db_options {
-	int lock_wait, progress_fd;
+	int lock_wait;
 	unsigned long open_flags;
 	char *root;
 	char *arch;
@@ -129,7 +129,7 @@ struct apk_repository_tag {
 
 struct apk_database {
 	char *root;
-	int root_fd, lock_fd, cache_fd, keys_fd, progress_fd;
+	int root_fd, lock_fd, cache_fd, keys_fd;
 	unsigned num_repos, num_repo_tags;
 	const char *cache_dir;
 	char *cache_remount_dir;
diff --git a/src/apk_print.h b/src/apk_print.h
index 4c004be..61e27d4 100644
--- a/src/apk_print.h
+++ b/src/apk_print.h
@@ -18,6 +18,8 @@
 #define apk_warning(args...)	do { if (apk_verbosity > 0) { apk_log("WARNING: ", args); } } while (0)
 #define apk_message(args...)	do { if (apk_verbosity > 0) { apk_log(NULL, args); } } while (0)
 
+extern int apk_progress_fd;
+
 void apk_log(const char *prefix, const char *format, ...);
 const char *apk_error_str(int error);
 
@@ -29,7 +31,11 @@ struct apk_indent {
 	int indent;
 };
 
-int apk_print_indented(struct apk_indent *i, apk_blob_t blob);
+#define APK_PRINT_PROGRESS_MASK		0xff
+#define APK_PRINT_PROGRESS_FORCE	0x100
+
+void apk_print_progress(int percent);
+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/commit.c b/src/commit.c
index c0996f2..8030692 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -118,43 +118,12 @@ static void count_change(struct apk_change *change, struct apk_stats *stats)
 	}
 }
 
-static void draw_progress(int percent)
-{
-	const int bar_width = apk_get_screen_width() - 7;
-	int i;
-
-	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);
-}
-
 struct progress {
 	struct apk_stats done;
 	struct apk_stats total;
 	struct apk_package *pkg;
-	size_t percent;
-	int progress_fd;
 };
 
-static void update_progress(struct progress *prog, size_t percent, int force)
-{
-	if (prog->percent == percent && !force)
-		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), "%zu\n", percent);
-		write(prog->progress_fd, buf, n);
-	}
-}
-
 static void progress_cb(void *ctx, size_t pkg_percent)
 {
 	struct progress *prog = (struct progress *) ctx;
@@ -168,7 +137,9 @@ static void progress_cb(void *ctx, size_t pkg_percent)
 				 prog->total.bytes + prog->total.packages);
 	else
 		percent = 0;
-	update_progress(prog, percent, pkg_percent == 0);
+	if (pkg_percent == 0)
+		percent |= APK_PRINT_PROGRESS_FORCE;
+	apk_print_progress(percent);
 }
 
 static int dump_packages(struct apk_changeset *changeset,
@@ -279,7 +250,6 @@ 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);
@@ -345,7 +315,7 @@ int apk_solver_commit_changeset(struct apk_database *db,
 
 		count_change(change, &prog.done);
 	}
-	update_progress(&prog, 100, 1);
+	apk_print_progress(100 | APK_PRINT_PROGRESS_FORCE);
 
 	run_triggers(db, changeset);
 
diff --git a/src/database.c b/src/database.c
index ab129b4..db8bb5e 100644
--- a/src/database.c
+++ b/src/database.c
@@ -1453,7 +1453,6 @@ 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/print.c b/src/print.c
index aceef38..df53be8 100644
--- a/src/print.c
+++ b/src/print.c
@@ -19,6 +19,7 @@
 #include "apk_defines.h"
 #include "apk_print.h"
 
+int apk_progress_fd;
 static int apk_screen_width = 0;
 
 void apk_reset_screen_width(void)
@@ -40,6 +41,37 @@ int apk_get_screen_width(void)
 	return apk_screen_width;
 }
 
+void apk_print_progress(int percent_flags)
+{
+	static int last_written = 0;
+	const int bar_width = apk_get_screen_width() - 7;
+	char buf[8];
+	int i, percent;
+
+	percent = percent_flags & APK_PRINT_PROGRESS_MASK;
+
+	if (last_written == percent && !(percent_flags & APK_PRINT_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), "%zu\n", percent);
+		write(apk_progress_fd, buf, i);
+	}
+}
+
 int apk_print_indented(struct apk_indent *i, apk_blob_t blob)
 {
 	if (i->x + blob.len + 1 >= apk_get_screen_width())