summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Griffin <aaron@archlinux.org>2007-02-04 01:36:45 +0000
committerAaron Griffin <aaron@archlinux.org>2007-02-04 01:36:45 +0000
commite3c7e92f1090204ba945c063b7aba3b3b1d8095b (patch)
tree08d49f36264059a878c7c40c80d99ec5bbcdcdc0
parentd18259b532a09de8025881532bc9ef6152a31891 (diff)
downloadpacman-e3c7e92f1090204ba945c063b7aba3b3b1d8095b.tar.xz
* unified the progress bars (fill_progress function)
* fixed progress output (needs an fflush to move cursor properly) * broke display_targets function out, to display a list of syncpkgs in preparation for a -Qu option * added get_update_time function to deal with progress functions that shouldn't update too fast due to output redraw speeds
-rw-r--r--src/pacman/downloadprog.c89
-rw-r--r--src/pacman/pacman.c6
-rw-r--r--src/pacman/sync.c54
-rw-r--r--src/pacman/trans.c82
-rw-r--r--src/pacman/util.c162
-rw-r--r--src/pacman/util.h6
6 files changed, 218 insertions, 181 deletions
diff --git a/src/pacman/downloadprog.c b/src/pacman/downloadprog.c
index 4ea40535..35bbab72 100644
--- a/src/pacman/downloadprog.c
+++ b/src/pacman/downloadprog.c
@@ -40,58 +40,57 @@
/* progress bar */
static float rate_last;
static int xfered_last;
-static struct timeval last_time;
static struct timeval initial_time;
/* pacman options */
extern config_t *config;
-#define FILENAME_TRIM_LEN 21
-#define UPDATE_SPEED_SEC 0.1
+#define FILENAME_TRIM_LEN 23
void log_progress(const char *filename, int xfered, int total)
{
- static unsigned int lasthash = 0, mouth = 0;
- unsigned int i, hash;
- /* a little hard to conceal easter eggs in open-source software,
- * but they're still fun. ;) */
- const unsigned short chomp = alpm_option_get_chomp();
+ const int infolen = 50;
char *fname, *p;
- unsigned int maxcols = getcols();
- unsigned int progresslen = maxcols - 57;
- int percent = (int)((float)xfered) / ((float)total) * 100;
+
struct timeval current_time;
float rate = 0.0;
unsigned int eta_h = 0, eta_m = 0, eta_s = 0;
float total_timediff, timediff;
+ if(config->noprogressbar) {
+ return;
+ }
+
+ int percent = (int)((float)xfered) / ((float)total) * 100;
+
if(xfered == 0) {
set_output_padding(1); /* we need padding from pm_fprintf output */
gettimeofday(&initial_time, NULL);
- gettimeofday(&last_time, NULL);
xfered_last = 0;
rate_last = 0.0;
+ timediff = get_update_timediff(1);
+ } else {
+ timediff = get_update_timediff(0);
}
- if(config->noprogressbar) {
+ if(percent > 0 && percent < 100 && !timediff) {
+ /* only update the progress bar when
+ * a) we first start
+ * b) we end the progress
+ * c) it has been long enough since the last call
+ */
return;
}
gettimeofday(&current_time, NULL);
total_timediff = current_time.tv_sec-initial_time.tv_sec
+ (float)(current_time.tv_usec-initial_time.tv_usec) / 1000000;
- timediff = current_time.tv_sec-last_time.tv_sec
- + (float)(current_time.tv_usec-last_time.tv_usec) / 1000000;
if(xfered == total) {
/* compute final values */
rate = (float)total / (total_timediff * 1024);
eta_s = (unsigned int)total_timediff;
set_output_padding(0); /* shut off padding */
- } else if(timediff < UPDATE_SPEED_SEC) {
- /* we avoid computing the ETA on too small periods of time, so that
- results are more significant */
- return;
} else {
rate = (float)(xfered - xfered_last) / (timediff * 1024);
rate = (float)(rate + 2*rate_last) / 3;
@@ -99,7 +98,6 @@ void log_progress(const char *filename, int xfered, int total)
}
rate_last = rate;
- last_time = current_time;
xfered_last = xfered;
/* fix up time for display */
@@ -116,61 +114,18 @@ void log_progress(const char *filename, int xfered, int total)
fname[FILENAME_TRIM_LEN] = '\0';
}
- /* hide the cursor i - prevent flicker
- printf("\033[?25l\033[?1c");
- */
-
- /*
- * DL rate cap, for printf formatting - this should be sane for a while
- * if anything we can change to MB/s if we need a higher rate
- */
+ /* DL rate cap, for printf formatting - this should be sane for a while
+ * if anything we can change to MB/s if we need a higher rate */
if(rate > 9999.9) {
rate = 9999.9;
}
- printf(" %-*s %6dK %#6.1fK/s %02u:%02u:%02u [", FILENAME_TRIM_LEN, fname,
+ printf(" %-*s %6dK %#6.1fK/s %02u:%02u:%02u", FILENAME_TRIM_LEN, fname,
xfered/1024, rate, eta_h, eta_m, eta_s);
free(fname);
- hash = (unsigned int)percent*progresslen/100;
- for(i = progresslen; i > 0; --i) {
- if(chomp) {
- if(i > progresslen - hash) {
- printf("-");
- } else if(i == progresslen - hash) {
- if(lasthash == hash) {
- if(mouth) {
- printf("\033[1;33mC\033[m");
- } else {
- printf("\033[1;33mc\033[m");
- }
- } else {
- lasthash = hash;
- mouth = mouth == 1 ? 0 : 1;
- if(mouth) {
- printf("\033[1;33mC\033[m");
- } else {
- printf("\033[1;33mc\033[m");
- }
- }
- } else if(i%3 == 0) {
- printf("\033[0;37mo\033[m");
- } else {
- printf("\033[0;37m \033[m");
- }
- } else if(i > progresslen - hash) {
- printf("#");
- } else {
- printf("-");
- }
- }
- printf("] %3d%%\r", percent);
-
- if(percent == 100) {
- printf("\n");
- }
- fflush(stdout);
+ fill_progress(percent, getcols() - infolen);
return;
}
diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c
index 7f6f4192..c473227c 100644
--- a/src/pacman/pacman.c
+++ b/src/pacman/pacman.c
@@ -130,6 +130,7 @@ static void usage(int op, char *myname)
printf(_(" -o, --owns <file> query the package that owns <file>\n"));
printf(_(" -p, --file query the package file [package] instead of the database\n"));
printf(_(" -s, --search search locally-installed packages for matching strings\n"));
+ printf(_(" -u, --upgrades list all packages that can be upgraded\n"));
} else if(op == PM_OP_SYNC) {
printf(_("usage: %s {-S --sync} [options] [package]\n"), myname);
printf(_("options:\n"));
@@ -369,7 +370,10 @@ static int parseargs(int argc, char *argv[])
config->op_q_search = 1;
config->flags |= PM_TRANS_FLAG_RECURSE;
break;
- case 'u': config->op_s_upgrade = 1; break;
+ case 'u':
+ config->op_s_upgrade = 1;
+ /* TODO config->op_q_upgrade = 1; */
+ break;
case 'v': (config->verbose)++; break;
case 'w':
config->op_s_downloadonly = 1;
diff --git a/src/pacman/sync.c b/src/pacman/sync.c
index 09f4587d..0a5ef72b 100644
--- a/src/pacman/sync.c
+++ b/src/pacman/sync.c
@@ -626,60 +626,8 @@ int pacman_sync(alpm_list_t *targets)
goto cleanup;
}
- /* list targets and get confirmation */
if(!(alpm_trans_get_flags() & PM_TRANS_FLAG_PRINTURIS)) {
- alpm_list_t *list_install = NULL, *list_remove = NULL;
-
- char *str;
- unsigned long totalsize = 0;
- unsigned long totalisize = 0;
- double mb, umb;
-
- for(i = packages; i; i = alpm_list_next(i)) {
- pmsyncpkg_t *sync = alpm_list_getdata(i);
- pmpkg_t *pkg = alpm_sync_get_package(sync);
- const char *pkgname, *pkgver;
-
- if(alpm_sync_get_type(sync) == PM_SYNC_TYPE_REPLACE) {
- alpm_list_t *data = alpm_sync_get_data(sync);
- for(j = data; j; j = alpm_list_next(j)) {
- pmpkg_t *p = alpm_list_getdata(j);
- const char *pkgname = alpm_pkg_get_name(p);
- if(!alpm_list_find_str(list_remove, pkgname)) {
- list_remove = alpm_list_add(list_remove, strdup(pkgname));
- }
- }
- }
-
- pkgname = alpm_pkg_get_name(pkg);
- pkgver = alpm_pkg_get_version(pkg);
- totalsize += alpm_pkg_get_size(pkg);
- totalisize += alpm_pkg_get_isize(pkg);
-
- asprintf(&str, "%s-%s", pkgname, pkgver);
- list_install = alpm_list_add(list_install, str);
- }
- if(list_remove) {
- MSG(NL, "\n"); /* TODO ugly hack. printing a single NL should be easy */
- list_display(_("Remove:"), list_remove);
- FREELIST(list_remove);
- }
- mb = (double)(totalsize / 1048576.0);
- umb = (double)(totalisize / 1048576.0);
- /* round up to 0.1 */
- if(mb < 0.1) {
- mb = 0.1;
- }
- if(umb > 0 && umb < 0.1) {
- umb = 0.1;
- }
- MSG(NL, "\n");
- list_display(_("Targets:"), list_install);
- MSG(NL, _("\nTotal Package Size: %.1f MB\n"), mb);
- if(umb > 0) {
- MSG(NL, _("Total Installed Size: %.1f MB\n"), umb);
- }
- FREELIST(list_install);
+ display_targets(packages);
if(config->op_s_downloadonly) {
if(config->noconfirm) {
diff --git a/src/pacman/trans.c b/src/pacman/trans.c
index f2f7113c..e2dcf645 100644
--- a/src/pacman/trans.c
+++ b/src/pacman/trans.c
@@ -57,58 +57,6 @@ static void retrieve_local(void *data1, void *data2)
fputs(_("] 100% LOCAL "), stdout);
}
-/* refactored from cb_trans_progress */
-/* TODO with a little more work, we may be able to incorporate this
- * into the download progress bar as well. */
-static void fill_progress(const int percent, const int proglen)
-{
- const unsigned short chomp = alpm_option_get_chomp();
- const unsigned int hashlen = proglen - 8;
- const unsigned int hash = percent * hashlen / 100;
- unsigned int lasthash = 0, mouth = 0;
- unsigned int i;
-
- printf(" [");
- for(i = hashlen; i > 1; --i) {
- /* if special progress bar enabled */
- if(chomp) {
- if(i > hashlen - hash) {
- printf("-");
- } else if(i == hashlen - hash) {
- if(lasthash == hash) {
- if(mouth) {
- printf("\033[1;33mC\033[m");
- } else {
- printf("\033[1;33mc\033[m");
- }
- } else {
- lasthash = hash;
- mouth = mouth == 1 ? 0 : 1;
- if(mouth) {
- printf("\033[1;33mC\033[m");
- } else {
- printf("\033[1;33mc\033[m");
- }
- }
- } else if(i%3 == 0) {
- printf("\033[0;37mo\033[m");
- } else {
- printf("\033[0;37m \033[m");
- }
- } /* else regular progress bar */
- else if(i > hashlen - hash) {
- printf("#");
- } else {
- printf("-");
- }
- }
- printf("] %3d%%\r", percent);
-
- if(percent == 100) {
- printf("\n");
- }
-}
-
/* Callback to handle transaction events
*/
void cb_trans_evt(pmtransevt_t event, void *data1, void *data2)
@@ -347,9 +295,11 @@ void cb_trans_conv(pmtransconv_t event, void *data1, void *data2,
void cb_trans_progress(pmtransprog_t event, char *pkgname, const int percent,
const int howmany, const int remain)
{
+ float timediff;
+
/* size of line to allocate for text printing (e.g. not progressbar) */
const int infolen = 50;
- int i, digits, textlen, pkglen, proglen;
+ int i, digits, textlen, pkglen;
char *ptr = NULL;
if(config->noprogressbar) {
@@ -358,12 +308,22 @@ void cb_trans_progress(pmtransprog_t event, char *pkgname, const int percent,
if(percent == 0) {
set_output_padding(1); /* turn on output padding with ' ' */
- } else if(percent == 100) {
- set_output_padding(0); /* shut it off again */
+ timediff = get_update_timediff(1);
+ } else {
+ timediff = get_update_timediff(0);
+ }
+
+ if(percent > 0 && percent < 100 && !timediff) {
+ /* only update the progress bar when
+ * a) we first start
+ * b) we end the progress
+ * c) it has been long enough since the last call
+ */
+ return;
}
/* if no pkgname, percent is too high or unchanged, then return */
- if (!pkgname || percent > 100 || percent == prevpercent) {
+ if(!pkgname || percent == prevpercent) {
return;
}
@@ -403,17 +363,19 @@ void cb_trans_progress(pmtransprog_t event, char *pkgname, const int percent,
printf("(%*d/%*d) %s %-*.*s", digits, remain, digits, howmany,
ptr, pkglen, pkglen, pkgname);
break;
-
case PM_TRANS_PROGRESS_CONFLICTS_START:
printf("(%*d/%*d) %-*s", digits, remain, digits, howmany,
textlen, ptr);
break;
-
}
/* call refactored fill progress function */
- proglen = getcols() - infolen;
- fill_progress(percent, proglen);
+ fill_progress(percent, getcols() - infolen);
+
+ if(percent >= 100) {
+ set_output_padding(0); /* restore padding */
+ }
+
}
/* vim: set ts=2 sw=2 noet: */
diff --git a/src/pacman/util.c b/src/pacman/util.c
index 7cff41b7..a30ae617 100644
--- a/src/pacman/util.c
+++ b/src/pacman/util.c
@@ -26,6 +26,7 @@
#include <sys/types.h>
#include <sys/ioctl.h>
+#include <sys/time.h>
#include "config.h"
#include <stdio.h>
@@ -258,4 +259,165 @@ void list_display(const char *title, alpm_list_t *list)
}
}
+/* Display a list of transaction targets.
+ * `pkgs` should be a list of pmsyncpkg_t's,
+ * retrieved from a transaction object
+ */
+void display_targets(alpm_list_t *pkgs)
+{
+ char *str;
+ alpm_list_t *i, *j;
+ alpm_list_t *targets = NULL, *to_remove = NULL;
+ unsigned long totalsize = 0, totalisize = 0, totalrsize = 0;
+
+ for(i = pkgs; i; i = alpm_list_next(i)) {
+ pmsyncpkg_t *sync = alpm_list_getdata(i);
+ pmpkg_t *pkg = alpm_sync_get_package(sync);
+
+ /* If this sync record is a replacement, the data member contains
+ * a list of packages to be removed due to the package that is being
+ * installed. */
+ if(alpm_sync_get_type(sync) == PM_SYNC_TYPE_REPLACE) {
+ alpm_list_t *to_replace = alpm_sync_get_data(sync);
+
+ for(j = to_replace; j; j = alpm_list_next(j)) {
+ pmpkg_t *rp = alpm_list_getdata(j);
+ const char *name = alpm_pkg_get_name(rp);
+
+ if(!alpm_list_find_str(to_remove, name)) {
+ totalrsize += alpm_pkg_get_isize(rp);
+ to_remove = alpm_list_add(to_remove, strdup(name));
+ }
+ }
+ }
+
+ totalsize += alpm_pkg_get_size(pkg);
+ totalisize += alpm_pkg_get_isize(pkg);
+
+ asprintf(&str, "%s-%s", alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg));
+ targets = alpm_list_add(targets, str);
+ }
+
+ if(to_remove) {
+ MSG(NL, "\n"); /* TODO ugly hack. printing a single NL should be easy */
+ list_display(_("Remove:"), to_remove);
+ FREELIST(to_remove);
+
+ double rmb = (double)(totalrsize) / (1024.0 * 1024.0);
+ if(rmb > 0) {
+ if(rmb < 0.1) {
+ rmb = 0.1;
+ }
+ MSG(NL, _("\nTotal Removed Size: %.2f MB\n"), rmb);
+ }
+ }
+
+ MSG(NL, "\n"); /* TODO ugly hack. printing a single NL should be easy */
+ list_display(_("Targets:"), targets);
+
+ double mb = (double)(totalsize) / (1024.0 * 1024.0);
+ if(mb < 0.1) {
+ mb = 0.1;
+ }
+ MSG(NL, _("\nTotal Package Size: %.2f MB\n"), mb);
+
+ double umb = (double)(totalisize) / (1024.0 * 1024.0);
+ if(umb > 0) {
+ if(umb < 0.1) {
+ umb = 0.1;
+ }
+ MSG(NL, _("Total Installed Size: %.2f MB\n"), umb);
+ }
+
+ FREELIST(targets);
+}
+
+/* Silly little helper function, determines if the caller needs a visual update
+ * since the last time this function was called.
+ * This is made for the two progress bar functions, to prevent flicker
+ *
+ * first_call indicates if this is the first time it is called, for
+ * initialization purposes */
+float get_update_timediff(int first_call)
+{
+ float retval = 0.0;
+ static struct timeval last_time = {0};
+ struct timeval this_time;
+
+ if(first_call) {
+ /* always update on the first call */
+ retval = 1.0;
+ } else {
+ gettimeofday(&this_time, NULL);
+
+ float diff_sec = this_time.tv_sec - last_time.tv_sec;
+ float diff_usec = this_time.tv_usec - last_time.tv_usec;
+
+ retval = diff_sec + (diff_usec / 1000000.0f);
+ /*printf("update time: %fs %fus = %f\n", diff_sec, diff_usec, retval);*/
+
+ if(retval < UPDATE_SPEED_SEC) {
+ /* maintain the last_time value for the next call */
+ return(0.0);
+ }
+ }
+
+ /* set the time for the next call */
+ gettimeofday(&last_time, NULL);
+
+ return(retval);
+}
+
+/* refactored from cb_trans_progress */
+void fill_progress(const int percent, const int proglen)
+{
+ const unsigned short chomp = alpm_option_get_chomp();
+ const unsigned int hashlen = proglen - 8;
+ const unsigned int hash = percent * hashlen / 100;
+ unsigned int lasthash = 0, mouth = 0;
+ unsigned int i;
+
+ printf(" [");
+ for(i = hashlen; i > 1; --i) {
+ /* if special progress bar enabled */
+ if(chomp) {
+ if(i > hashlen - hash) {
+ printf("-");
+ } else if(i == hashlen - hash) {
+ if(lasthash == hash) {
+ if(mouth) {
+ printf("\033[1;33mC\033[m");
+ } else {
+ printf("\033[1;33mc\033[m");
+ }
+ } else {
+ lasthash = hash;
+ mouth = mouth == 1 ? 0 : 1;
+ if(mouth) {
+ printf("\033[1;33mC\033[m");
+ } else {
+ printf("\033[1;33mc\033[m");
+ }
+ }
+ } else if(i%3 == 0) {
+ printf("\033[0;37mo\033[m");
+ } else {
+ printf("\033[0;37m \033[m");
+ }
+ } /* else regular progress bar */
+ else if(i > hashlen - hash) {
+ printf("#");
+ } else {
+ printf("-");
+ }
+ }
+ printf("] %3d%%\r", percent);
+
+ if(percent == 100) {
+ printf("\n");
+ }
+ fflush(stdout);
+}
+
+
/* vim: set ts=2 sw=2 noet: */
diff --git a/src/pacman/util.h b/src/pacman/util.h
index 37509788..61bf09ee 100644
--- a/src/pacman/util.h
+++ b/src/pacman/util.h
@@ -47,6 +47,9 @@
s1[(len)-1] = 0; \
} while(0)
+/* update speed for the fill_progress based functions */
+#define UPDATE_SPEED_SEC 0.2f
+
#define _(str) gettext(str)
unsigned int getcols();
int makepath(char *path);
@@ -56,6 +59,9 @@ char *strtoupper(char *str);
char *strtrim(char *str);
int reg_match(char *string, char *pattern);
void list_display(const char *title, alpm_list_t *list);
+void display_targets(alpm_list_t *pkgs);
+float get_update_timediff(int first_call);
+void fill_progress(const int percent, const int proglen);
#endif /* _PM_UTIL_H */