summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/libalpm/alpm.h6
-rw-r--r--lib/libalpm/handle.c18
-rw-r--r--lib/libalpm/handle.h1
-rw-r--r--lib/libalpm/sync.c20
-rw-r--r--src/pacman/callback.c76
-rw-r--r--src/pacman/callback.h2
-rw-r--r--src/pacman/pacman.c5
7 files changed, 107 insertions, 21 deletions
diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
index fd3be0d3..9ed2c676 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -82,19 +82,21 @@ int alpm_logaction(char *fmt, ...);
typedef void (*alpm_cb_download)(const char *filename,
off_t xfered, off_t total);
+typedef void (*alpm_cb_totaldl)(off_t total);
/*
* Options
*/
-#define PM_DLFNM_LEN 22
-
alpm_cb_log alpm_option_get_logcb();
void alpm_option_set_logcb(alpm_cb_log cb);
alpm_cb_download alpm_option_get_dlcb();
void alpm_option_set_dlcb(alpm_cb_download cb);
+alpm_cb_totaldl alpm_option_get_totaldlcb();
+void alpm_option_set_totaldlcb(alpm_cb_totaldl cb);
+
const char *alpm_option_get_root();
int alpm_option_set_root(const char *root);
diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c
index c01dd551..af1cc78b 100644
--- a/lib/libalpm/handle.c
+++ b/lib/libalpm/handle.c
@@ -115,6 +115,15 @@ alpm_cb_download SYMEXPORT alpm_option_get_dlcb()
return handle->dlcb;
}
+alpm_cb_totaldl SYMEXPORT alpm_option_get_totaldlcb()
+{
+ if (handle == NULL) {
+ pm_errno = PM_ERR_HANDLE_NULL;
+ return NULL;
+ }
+ return handle->totaldlcb;
+}
+
const char SYMEXPORT *alpm_option_get_root()
{
if (handle == NULL) {
@@ -268,6 +277,15 @@ void SYMEXPORT alpm_option_set_dlcb(alpm_cb_download cb)
handle->dlcb = cb;
}
+void SYMEXPORT alpm_option_set_totaldlcb(alpm_cb_totaldl cb)
+{
+ if (handle == NULL) {
+ pm_errno = PM_ERR_HANDLE_NULL;
+ return;
+ }
+ handle->totaldlcb = cb;
+}
+
int SYMEXPORT alpm_option_set_root(const char *root)
{
struct stat st;
diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h
index 9c537b14..bec0a6f1 100644
--- a/lib/libalpm/handle.h
+++ b/lib/libalpm/handle.h
@@ -39,6 +39,7 @@ typedef struct _pmhandle_t {
/* callback functions */
alpm_cb_log logcb; /* Log callback function */
alpm_cb_download dlcb; /* Download callback function */
+ alpm_cb_totaldl totaldlcb; /* Total download callback function */
/* filesystem paths */
char *root; /* Root path, default '/' */
diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c
index 2dad8bf7..3dc54d0a 100644
--- a/lib/libalpm/sync.c
+++ b/lib/libalpm/sync.c
@@ -811,12 +811,25 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
ALPM_LOG_FUNC;
- ASSERT(db_local != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
cachedir = _alpm_filecache_setup();
trans->state = STATE_DOWNLOADING;
+ /* Total progress - figure out the total download size if required to
+ * pass to the callback. This function is called once, and it is up to the
+ * frontend to compute incremental progress. */
+ if(handle->totaldlcb) {
+ off_t total_size = (off_t)0;
+ /* sum up the download size for each package and store total */
+ for(i = trans->packages; i; i = i->next) {
+ pmsyncpkg_t *sync = i->data;
+ pmpkg_t *spkg = sync->pkg;
+ total_size += spkg->download_size;
+ }
+ handle->totaldlcb(total_size);
+ }
+
/* group sync records by repository and download */
for(i = handle->dbs_sync; i; i = i->next) {
pmdb_t *current = i->data;
@@ -877,6 +890,11 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
return(0);
}
+ /* clear out value to let callback know we are done */
+ if(handle->totaldlcb) {
+ handle->totaldlcb(0);
+ }
+
if(handle->usedelta) {
int ret = 0;
diff --git a/src/pacman/callback.c b/src/pacman/callback.c
index 1942aefd..ff125c36 100644
--- a/src/pacman/callback.c
+++ b/src/pacman/callback.c
@@ -38,6 +38,8 @@
/* download progress bar */
static float rate_last;
static off_t xfered_last;
+static off_t list_xfered = 0.0;
+static off_t list_total = 0.0;
static struct timeval initial_time;
/* transaction progress bar */
@@ -84,14 +86,15 @@ static float get_update_timediff(int first_call)
}
/* refactored from cb_trans_progress */
-static void fill_progress(const int percent, const int proglen)
+static void fill_progress(const int bar_percent, const int disp_percent,
+ const int proglen)
{
const unsigned int hashlen = proglen - 8;
- const unsigned int hash = percent * hashlen / 100;
+ const unsigned int hash = bar_percent * hashlen / 100;
static unsigned int lasthash = 0, mouth = 0;
unsigned int i;
- if(percent == 0) {
+ if(bar_percent == 0) {
lasthash = 0;
mouth = 0;
}
@@ -136,10 +139,12 @@ static void fill_progress(const int percent, const int proglen)
}
/* print percent after progress bar */
if(proglen > 5) {
- printf(" %3d%%", percent);
+ /* use disp_percent if it is not 0, else show bar_percent */
+ int p = disp_percent ? disp_percent : bar_percent;
+ printf(" %3d%%", p);
}
- if(percent == 100) {
+ if(bar_percent == 100) {
printf("\n");
} else {
printf("\r");
@@ -395,7 +400,7 @@ void cb_trans_progress(pmtransprog_t event, const char *pkgname, int percent,
free(wcstr);
/* call refactored fill progress function */
- fill_progress(percent, getcols() - infolen);
+ fill_progress(percent, percent, getcols() - infolen);
if(percent == 100) {
alpm_list_t *i = NULL;
@@ -410,8 +415,19 @@ void cb_trans_progress(pmtransprog_t event, const char *pkgname, int percent,
}
}
+/* callback to handle receipt of total download value */
+void cb_dl_total(off_t total)
+{
+ list_total = total;
+ /* if we get a 0 value, it means this list has finished downloading,
+ * so clear out our list_xfered as well */
+ if(total == 0) {
+ list_xfered = 0;
+ }
+}
+
/* callback to handle display of download progress */
-void cb_dl_progress(const char *filename, off_t xfered, off_t total)
+void cb_dl_progress(const char *filename, off_t file_xfered, off_t file_total)
{
const int infolen = 50;
const int filenamelen = infolen - 27;
@@ -420,24 +436,38 @@ void cb_dl_progress(const char *filename, off_t xfered, off_t total)
int len, wclen, wcwid, padwid;
wchar_t *wcfname;
+ off_t xfered, total;
float rate = 0.0, timediff = 0.0, f_xfered = 0.0;
unsigned int eta_h = 0, eta_m = 0, eta_s = 0;
- int percent;
+ int file_percent = 0, total_percent = 0;
char rate_size = 'K', xfered_size = 'K';
if(config->noprogressbar) {
return;
}
+ /* only use TotalDownload if enabled and we have a callback value */
+ if(config->totaldownload && list_total) {
+ xfered = list_xfered + file_xfered;
+ total = list_total;
+ } else {
+ xfered = file_xfered;
+ total = file_total;
+ }
+
/* this is basically a switch on xfered: 0, total, and
* anything else */
- if(xfered == 0) {
- /* set default starting values */
- gettimeofday(&initial_time, NULL);
- xfered_last = (off_t)0;
- rate_last = 0.0;
- timediff = get_update_timediff(1);
- } else if(xfered == total) {
+ if(file_xfered == 0) {
+ /* set default starting values, ensure we only call this once
+ * if TotalDownload is enabled */
+ if(!(config->totaldownload)
+ || (config->totaldownload && list_xfered == 0)) {
+ gettimeofday(&initial_time, NULL);
+ xfered_last = (off_t)0;
+ rate_last = 0.0;
+ timediff = get_update_timediff(1);
+ }
+ } else if(file_xfered == file_total) {
/* compute final values */
struct timeval current_time;
float diff_sec, diff_usec;
@@ -446,7 +476,7 @@ void cb_dl_progress(const char *filename, off_t xfered, off_t total)
diff_sec = current_time.tv_sec - initial_time.tv_sec;
diff_usec = current_time.tv_usec - initial_time.tv_usec;
timediff = diff_sec + (diff_usec / 1000000.0);
- rate = total / (timediff * 1024.0);
+ rate = xfered / (timediff * 1024.0);
/* round elapsed time to the nearest second */
eta_s = (int)(timediff + 0.5);
@@ -466,7 +496,17 @@ void cb_dl_progress(const char *filename, off_t xfered, off_t total)
xfered_last = xfered;
}
- percent = (int)((float)xfered) / ((float)total) * 100;
+ file_percent = (int)((float)file_xfered) / ((float)file_total) * 100;
+
+ if(config->totaldownload && list_total) {
+ total_percent = (int)((float)list_xfered + file_xfered) /
+ ((float)list_total) * 100;
+
+ /* if we are at the end, add the completed file to list_xfered */
+ if(file_xfered == file_total) {
+ list_xfered += file_total;
+ }
+ }
/* fix up time for display */
eta_h = eta_s / 3600;
@@ -539,7 +579,7 @@ void cb_dl_progress(const char *filename, off_t xfered, off_t total)
free(fname);
free(wcfname);
- fill_progress(percent, getcols() - infolen);
+ fill_progress(file_percent, total_percent, getcols() - infolen);
return;
}
diff --git a/src/pacman/callback.h b/src/pacman/callback.h
index 28d396e8..2961be84 100644
--- a/src/pacman/callback.h
+++ b/src/pacman/callback.h
@@ -34,6 +34,8 @@ void cb_trans_conv(pmtransconv_t event, void *data1, void *data2,
void cb_trans_progress(pmtransprog_t event, const char *pkgname, int percent,
int howmany, int remain);
+/* callback to handle receipt of total download value */
+void cb_dl_total(off_t total);
/* callback to handle display of download progress */
void cb_dl_progress(const char *filename, off_t file_xfered, off_t file_total);
diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c
index 0ce9c1e8..7aa1bf69 100644
--- a/src/pacman/pacman.c
+++ b/src/pacman/pacman.c
@@ -850,6 +850,11 @@ int main(int argc, char *argv[])
cleanup(ret);
}
+ /* set TotalDownload callback if option enabled */
+ if(config->totaldownload) {
+ alpm_option_set_totaldlcb(cb_dl_total);
+ }
+
#if defined(HAVE_GETEUID) && !defined(CYGWIN)
/* check if we have sufficient permission for the requested operation */
if(myuid > 0 && needs_transaction()) {