diff --git a/NEWS b/NEWS index 51531231..d911febe 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,10 @@ Please send GNU Wget bug reports to <bug-wget@gnu.org>. * Changes in Wget X.Y.Z +** Default progress bar output changed + +** Introduce --show-progress to force display the progress bar + ** Introduce --no-config. ** Introduce --start-pos to allow starting downloads from a specified position. diff --git a/doc/ChangeLog b/doc/ChangeLog index 68629c69..91269b04 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,7 @@ +2014-05-01 Darshit Shah <darnir@gmail.com> + + * wget.texi: Add documentation for --show-progress + 2014-02-10 Yousong Zhou <yszhou4tech@gmail.com> * wget.texi: Add documentation for --start-pos. diff --git a/doc/wget.texi b/doc/wget.texi index 11f2c404..e1f29dc7 100644 --- a/doc/wget.texi +++ b/doc/wget.texi @@ -751,6 +751,16 @@ command line. The exception is that, when the output is not a TTY, the ``dot'' progress will be favored over ``bar''. To force the bar output, use @samp{--progress=bar:force}. +@item --show-progress +Force wget to display the progress bar in any verbosity. + +By default, wget only displays the progress bar in verbose mode. One may +however want wget to display the progress bar on screen in conjunction with +any other verbosity modes like @samp{--no-verbose} or @samp{--quiet}. This +is often a desired a property when invoking wget to download several small/large +files. In such a case, wget could simply be invoked with this parameter to get +a much cleaner output on the screen. + @item -N @itemx --timestamping Turn on time-stamping. @xref{Time-Stamping}, for details. diff --git a/src/ChangeLog b/src/ChangeLog index 63589384..96723dd5 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,39 @@ +2014-04-19 Darshit Shah <darnir@gmail.com> + + * log.h (log_options): Add new logging options, LOG_PROGRESS. All progress + bar related output should use LOG_PROGRESS. + * log.c (CHECK_VERBOSE): Implement LOG_PROGRESS output + * progress.c (dot_create, print_row_stats, dot_update, dot_finish, + bar_finish, display_image): Output progress information through LOG_PROGRESS + (progress_implementation, dot_create, bar_create, progress_create): The + progress bar create functions accept an extra paramter for the filename of the + local file + (bar_progress): Add new variable to store filename of currently downloading + file + (bar_finish): Aesthetic change. Print two newlines if in verbose mode, else + only one. + (MACRO): Define new macro, MIN + (create_image): Implement displaying filename in progress bar output + Filename tick implementation copied from Giuseppe's patch on parallel-wget + * progress.h (progress_create): Accept another parameter for filename + * http.c (gethttp): Remove unnecessary conditional + (read_response_body): Send local filename to fd_read_body so that it can be + printed on the progress bar + * main.c (option_data): Add new switch, --show-progress + (main): If in verbose output, show progress bar by default + (main): Set progress implemetation when displaying progress bar + (no_prefix): Increase buffer size to 2048 to prevent overflows + * init.c (commands): Add new command, showprogress + (defaults): By default initialize show_progress to false + * options.h (options): Add new option, show_progress + * retr.c (fd_read_body): Accept new parameter for filename of currently + downlaoding file + (fd_read_body): Create and update progress bar when opt.show_progress is set + (fd_read_body): Display progress information in Windows console titlebars + * retr.h (fd_read_body): Update declaration + * ftp.c (getftp): Send filename of the local file so that it can be printed + with the progress bar. + 2013-11-02 Giuseppe Scrivano <gscrivan@redhat.com> * progress.c (struct progress_implementation): New method draw. @@ -9,7 +45,7 @@ 2014-04-22 Tim Ruehsen <tim.ruehsen@gmx.de> - * http.c (gethttp): Fix 204 response handling + * http.c (gethttp): Fix 204 response handling 2014-03-26 Darshit Shah <darnir@gmail.com> diff --git a/src/ftp.c b/src/ftp.c index 00d753a8..2db98bb9 100644 --- a/src/ftp.c +++ b/src/ftp.c @@ -1310,7 +1310,7 @@ Error in server response, closing control connection.\n")); if (restval && rest_failed) flags |= rb_skip_startpos; rd_size = 0; - res = fd_read_body (dtsock, fp, + res = fd_read_body (con->target, dtsock, fp, expected_bytes ? expected_bytes - restval : 0, restval, &rd_size, qtyread, &con->dltime, flags, warc_tmp); diff --git a/src/http.c b/src/http.c index 00a35b32..9551fb12 100644 --- a/src/http.c +++ b/src/http.c @@ -1586,7 +1586,7 @@ read_response_body (struct http_stat *hs, int sock, FILE *fp, wgint contlen, /* Download the response body and write it to fp. If we are working on a WARC file, we simultaneously write the response body to warc_tmp. */ - hs->res = fd_read_body (sock, fp, contlen != -1 ? contlen : 0, + hs->res = fd_read_body (hs->local_file, sock, fp, contlen != -1 ? contlen : 0, hs->restval, &hs->rd_size, &hs->len, &hs->dltime, flags, warc_tmp); if (hs->res >= 0) @@ -2961,11 +2961,8 @@ read_header: fp = output_stream; /* Print fetch message, if opt.verbose. */ - if (opt.verbose) - { - logprintf (LOG_NOTQUIET, _("Saving to: %s\n"), + logprintf (LOG_VERBOSE, _("Saving to: %s\n"), HYPHENP (hs->local_file) ? quote ("STDOUT") : quote (hs->local_file)); - } err = read_response_body (hs, sock, fp, contlen, contrange, diff --git a/src/init.c b/src/init.c index 9ed72b2a..7d024f88 100644 --- a/src/init.c +++ b/src/init.c @@ -268,6 +268,7 @@ static const struct { #endif { "serverresponse", &opt.server_response, cmd_boolean }, { "showalldnsentries", &opt.show_all_dns_entries, cmd_boolean }, + { "showprogress", &opt.show_progress, cmd_boolean }, { "spanhosts", &opt.spanhost, cmd_boolean }, { "spider", &opt.spider, cmd_boolean }, { "startpos", &opt.start_pos, cmd_bytes }, @@ -410,6 +411,7 @@ defaults (void) /* Use a negative value to mark the absence of --start-pos option */ opt.start_pos = -1; + opt.show_progress = false; } /* Return the user's home directory (strdup-ed), or NULL if none is diff --git a/src/log.c b/src/log.c index 4f93a21c..3bd58330 100644 --- a/src/log.c +++ b/src/log.c @@ -278,6 +278,10 @@ saved_append (const char *s) #define CHECK_VERBOSE(x) \ switch (x) \ { \ + case LOG_PROGRESS: \ + if (!opt.show_progress) \ + return; \ + break; \ case LOG_ALWAYS: \ break; \ case LOG_NOTQUIET: \ diff --git a/src/log.h b/src/log.h index d74ca53d..144be242 100644 --- a/src/log.h +++ b/src/log.h @@ -36,7 +36,7 @@ as that of the covered work. */ #include <stdio.h> -enum log_options { LOG_VERBOSE, LOG_NOTQUIET, LOG_NONVERBOSE, LOG_ALWAYS }; +enum log_options { LOG_VERBOSE, LOG_NOTQUIET, LOG_NONVERBOSE, LOG_ALWAYS, LOG_PROGRESS }; void log_set_warc_log_fp (FILE *); diff --git a/src/main.c b/src/main.c index 39fcff44..3d99a1ef 100644 --- a/src/main.c +++ b/src/main.c @@ -247,6 +247,7 @@ static struct cmdline_option option_data[] = { IF_SSL ("private-key"), 0, OPT_VALUE, "privatekey", -1 }, { IF_SSL ("private-key-type"), 0, OPT_VALUE, "privatekeytype", -1 }, { "progress", 0, OPT_VALUE, "progress", -1 }, + { "show-progress", 0, OPT_BOOLEAN, "showprogress", -1 }, { "protocol-directories", 0, OPT_BOOLEAN, "protocoldirectories", -1 }, { "proxy", 0, OPT_BOOLEAN, "useproxy", -1 }, { "proxy__compat", 'Y', OPT_VALUE, "useproxy", -1 }, /* back-compatible */ @@ -316,7 +317,7 @@ static struct cmdline_option option_data[] = static char * no_prefix (const char *s) { - static char buffer[1024]; + static char buffer[2048]; static char *p = buffer; char *cp = p; @@ -490,6 +491,8 @@ Download:\n"), --start-pos=OFFSET start downloading from zero-based position OFFSET.\n"), N_("\ --progress=TYPE select progress gauge type.\n"), + N_("\ + --show-progress display the progress bar in any verbosity mode.\n"), N_("\ -N, --timestamping don't re-retrieve files unless newer than\n\ local.\n"), @@ -1218,6 +1221,7 @@ main (int argc, char **argv) /* All user options have now been processed, so it's now safe to do interoption dependency checks. */ + if (opt.noclobber && opt.convert_links) { fprintf (stderr, @@ -1245,6 +1249,8 @@ main (int argc, char **argv) if (opt.verbose == -1) opt.verbose = !opt.quiet; + if (opt.verbose == 1) + opt.show_progress = true; /* Sanity checks. */ if (opt.verbose && opt.quiet) @@ -1502,7 +1508,7 @@ for details.\n\n")); /* Initialize progress. Have to do this after the options are processed so we know where the log file is. */ - if (opt.verbose) + if (opt.show_progress) set_progress_implementation (opt.progress_type); /* Fill in the arguments. */ diff --git a/src/options.h b/src/options.h index b527829e..563207f5 100644 --- a/src/options.h +++ b/src/options.h @@ -134,6 +134,7 @@ struct options char **no_proxy; char *base_href; char *progress_type; /* progress indicator type. */ + bool show_progress; /* Show only the progress bar */ char *proxy_user; /*oli*/ char *proxy_passwd; diff --git a/src/progress.c b/src/progress.c index 47d13e6a..b1d50950 100644 --- a/src/progress.c +++ b/src/progress.c @@ -47,7 +47,7 @@ as that of the covered work. */ struct progress_implementation { const char *name; bool interactive; - void *(*create) (wgint, wgint); + void *(*create) (const char *, wgint, wgint); void (*update) (void *, wgint, double); void (*draw) (void *); void (*finish) (void *, double); @@ -56,13 +56,13 @@ struct progress_implementation { /* Necessary forward declarations. */ -static void *dot_create (wgint, wgint); +static void *dot_create (const char *, wgint, wgint); static void dot_update (void *, wgint, double); static void dot_finish (void *, double); static void dot_draw (void *); static void dot_set_params (const char *); -static void *bar_create (wgint, wgint); +static void *bar_create (const char *, wgint, wgint); static void bar_update (void *, wgint, double); static void bar_draw (void *); static void bar_finish (void *, double); @@ -154,7 +154,7 @@ progress_schedule_redirect (void) advance. */ void * -progress_create (wgint initial, wgint total) +progress_create (const char *f_download, wgint initial, wgint total) { /* Check if the log status has changed under our feet. */ if (output_redirected) @@ -164,7 +164,7 @@ progress_create (wgint initial, wgint total) output_redirected = 0; } - return current_impl->create (initial, total); + return current_impl->create (f_download, initial, total); } /* Return true if the progress gauge is "interactive", i.e. if it can @@ -218,7 +218,7 @@ struct dot_progress { /* Dot-progress backend for progress_create. */ static void * -dot_create (wgint initial, wgint total) +dot_create (const char *f_download _GL_UNUSED, wgint initial, wgint total) { struct dot_progress *dp = xnew0 (struct dot_progress); dp->initial_length = initial; @@ -242,18 +242,18 @@ dot_create (wgint initial, wgint total) /* Align the [ skipping ... ] line with the dots. To do that, insert the number of spaces equal to the number of digits in the skipped amount in K. */ - logprintf (LOG_VERBOSE, _("\n%*s[ skipping %sK ]"), + logprintf (LOG_PROGRESS, _("\n%*s[ skipping %sK ]"), 2 + skipped_k_len, "", number_to_static_string (skipped_k)); } - logprintf (LOG_VERBOSE, "\n%6sK", + logprintf (LOG_PROGRESS, "\n%6sK", number_to_static_string (skipped / 1024)); for (; remainder >= dot_bytes; remainder -= dot_bytes) { if (dp->dots % opt.dot_spacing == 0) - logputs (LOG_VERBOSE, " "); - logputs (LOG_VERBOSE, ","); + logputs (LOG_PROGRESS, " "); + logputs (LOG_PROGRESS, ","); ++dp->dots; } assert (dp->dots < opt.dots_in_line); @@ -294,7 +294,7 @@ print_row_stats (struct dot_progress *dp, double dltime, bool last) been retrieved. 12.8% will round to 12% because the 13% mark has not yet been reached. 100% is only shown when done. */ int percentage = 100.0 * bytes_displayed / dp->total_length; - logprintf (LOG_VERBOSE, "%3d%%", percentage); + logprintf (LOG_PROGRESS, "%3d%%", percentage); } { @@ -311,7 +311,7 @@ print_row_stats (struct dot_progress *dp, double dltime, bool last) if (dp->rows == dp->initial_length / ROW_BYTES) bytes_this_row -= dp->initial_length % ROW_BYTES; rate = calc_rate (bytes_this_row, dltime - dp->last_timer_value, &units); - logprintf (LOG_VERBOSE, " %4.*f%c", + logprintf (LOG_PROGRESS, " %4.*f%c", rate >= 99.95 ? 0 : rate >= 9.995 ? 1 : 2, rate, names[units]); dp->last_timer_value = dltime; @@ -328,7 +328,7 @@ print_row_stats (struct dot_progress *dp, double dltime, bool last) wgint bytes_sofar = bytes_displayed - dp->initial_length; double eta = dltime * bytes_remaining / bytes_sofar; if (eta < INT_MAX - 1) - logprintf (LOG_VERBOSE, " %s", + logprintf (LOG_PROGRESS, " %s", eta_to_human_short ((int) (eta + 0.5), true)); } } @@ -336,10 +336,10 @@ print_row_stats (struct dot_progress *dp, double dltime, bool last) { /* When done, print the total download time */ if (dltime >= 10) - logprintf (LOG_VERBOSE, "=%s", + logprintf (LOG_PROGRESS, "=%s", eta_to_human_short ((int) (dltime + 0.5), true)); else - logprintf (LOG_VERBOSE, "=%ss", print_decimal (dltime)); + logprintf (LOG_PROGRESS, "=%ss", print_decimal (dltime)); } } @@ -365,12 +365,12 @@ dot_draw (void *progress) for (; dp->accumulated >= dot_bytes; dp->accumulated -= dot_bytes) { if (dp->dots == 0) - logprintf (LOG_VERBOSE, "\n%6sK", + logprintf (LOG_PROGRESS, "\n%6sK", number_to_static_string (dp->rows * ROW_BYTES / 1024)); if (dp->dots % opt.dot_spacing == 0) - logputs (LOG_VERBOSE, " "); - logputs (LOG_VERBOSE, "."); + logputs (LOG_PROGRESS, " "); + logputs (LOG_PROGRESS, "."); ++dp->dots; if (dp->dots >= opt.dots_in_line) @@ -397,17 +397,17 @@ dot_finish (void *progress, double dltime) log_set_flush (false); if (dp->dots == 0) - logprintf (LOG_VERBOSE, "\n%6sK", + logprintf (LOG_PROGRESS, "\n%6sK", number_to_static_string (dp->rows * ROW_BYTES / 1024)); for (i = dp->dots; i < opt.dots_in_line; i++) { if (i % opt.dot_spacing == 0) - logputs (LOG_VERBOSE, " "); - logputs (LOG_VERBOSE, " "); + logputs (LOG_PROGRESS, " "); + logputs (LOG_PROGRESS, " "); } print_row_stats (dp, dltime, true); - logputs (LOG_VERBOSE, "\n\n"); + logputs (LOG_PROGRESS, "\n\n"); log_set_flush (false); xfree (dp); @@ -507,6 +507,7 @@ static volatile sig_atomic_t received_sigwinch; #define ETA_REFRESH_INTERVAL 0.99 struct bar_progress { + const char *f_download; /* Filename of the downloaded file */ wgint initial_length; /* how many bytes have been downloaded previously. */ wgint total_length; /* expected total byte count when the @@ -564,7 +565,7 @@ static void create_image (struct bar_progress *, double, bool); static void display_image (char *); static void * -bar_create (wgint initial, wgint total) +bar_create (const char *f_download, wgint initial, wgint total) { struct bar_progress *bp = xnew0 (struct bar_progress); @@ -575,6 +576,7 @@ bar_create (wgint initial, wgint total) bp->initial_length = initial; bp->total_length = total; + bp->f_download = f_download; /* Initialize screen_width if this hasn't been done or if it might have changed, as indicated by receiving SIGWINCH. */ @@ -670,7 +672,8 @@ bar_finish (void *progress, double dltime) create_image (bp, dltime, true); display_image (bp->buffer); - logputs (LOG_VERBOSE, "\n\n"); + logputs (LOG_VERBOSE, "\n"); + logputs (LOG_PROGRESS, "\n"); xfree (bp->buffer); xfree (bp); @@ -865,10 +868,14 @@ get_eta (int *bcd) #ifndef MAX # define MAX(a, b) ((a) >= (b) ? (a) : (b)) #endif +#ifndef MIN +# define MIN(a, b) ((a) <= (b) ? (a) : (b)) +#endif static void create_image (struct bar_progress *bp, double dl_total_time, bool done) { + const int MAX_FILENAME_LEN = bp->width / 3; char *p = bp->buffer; wgint size = bp->initial_length + bp->count; @@ -879,9 +886,11 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done) int size_grouped_pad; /* Used to pad the field width for size_grouped. */ struct bar_progress_hist *hist = &bp->hist; + int orig_filename_len = strlen (bp->f_download); + int filename_len = MIN (orig_filename_len, MAX_FILENAME_LEN); /* The progress bar should look like this: - xx% [=======> ] nn,nnn 12.34KB/s eta 36m 51s + file xx% [=======> ] nn,nnn 12.34KB/s eta 36m 51s Calculate the geometry. The idea is to assign as much room as possible to the progress bar. The other idea is to never let @@ -890,16 +899,17 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done) It would be especially bad for the progress bar to be resized randomly. + "file " - Downloaded filename - MAX MAX_FILENAME_LEN chars + 1 "xx% " or "100%" - percentage - 4 chars "[]" - progress bar decorations - 2 chars " nnn,nnn,nnn" - downloaded bytes - 12 chars or very rarely more - " 12.5KB/s" - download rate - 9 chars + " 12.5KB/s" - download rate - 9 chars " eta 36m 51s" - ETA - 14 chars "=====>..." - progress bar - the rest */ int dlbytes_size = 1 + MAX (size_grouped_len, 11); - int progress_size = bp->width - (4 + 2 + dlbytes_size + 8 + 14); + int progress_size = bp->width - (filename_len + 1 + 4 + 2 + dlbytes_size + 8 + 14); /* The difference between the number of bytes used, and the number of columns used. */ @@ -908,6 +918,25 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done) if (progress_size < 5) progress_size = 0; + if (orig_filename_len <= MAX_FILENAME_LEN) + { + sprintf (p, "%s ", bp->f_download); + p += filename_len + 1; + } + else + { + int offset; + + if (orig_filename_len > MAX_FILENAME_LEN) + offset = ((int) bp->tick) % (orig_filename_len - MAX_FILENAME_LEN); + else + offset = 0; + *p++ = ' '; + memcpy (p, bp->f_download + offset, MAX_FILENAME_LEN); + p += MAX_FILENAME_LEN; + *p++ = ' '; + } + /* "xx% " */ if (bp->total_length > 0) { @@ -981,8 +1010,8 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done) } *p++ = ']'; - ++bp->tick; } + ++bp->tick; /* " 234,567,890" */ sprintf (p, " %s", size_grouped); @@ -1090,8 +1119,8 @@ static void display_image (char *buf) { bool old = log_set_save_context (false); - logputs (LOG_VERBOSE, "\r"); - logputs (LOG_VERBOSE, buf); + logputs (LOG_PROGRESS, "\r"); + logputs (LOG_PROGRESS, buf); log_set_save_context (old); } diff --git a/src/progress.h b/src/progress.h index 8a8a20d4..778dfa51 100644 --- a/src/progress.h +++ b/src/progress.h @@ -35,7 +35,7 @@ bool valid_progress_implementation_p (const char *); void set_progress_implementation (const char *); void progress_schedule_redirect (void); -void *progress_create (wgint, wgint); +void *progress_create (const char *, wgint, wgint); bool progress_interactive_p (void *); void progress_update (void *, wgint, double); void progress_finish (void *, double); diff --git a/src/retr.c b/src/retr.c index 683c8117..135f599e 100644 --- a/src/retr.c +++ b/src/retr.c @@ -226,7 +226,8 @@ write_data (FILE *out, FILE *out2, const char *buf, int bufsize, data to OUT2, -3 is returned. */ int -fd_read_body (int fd, FILE *out, wgint toread, wgint startpos, +fd_read_body (const char *downloaded_filename, int fd, FILE *out, wgint toread, wgint startpos, + wgint *qtyread, wgint *qtywritten, double *elapsed, int flags, FILE *out2) { @@ -262,13 +263,13 @@ fd_read_body (int fd, FILE *out, wgint toread, wgint startpos, if (flags & rb_skip_startpos) skip = startpos; - if (opt.verbose) + if (opt.show_progress) { /* If we're skipping STARTPOS bytes, pass 0 as the INITIAL argument to progress_create because the indicator doesn't (yet) know about "skipping" data. */ wgint start = skip ? 0 : startpos; - progress = progress_create (start, start + toread); + progress = progress_create (downloaded_filename, start, start + toread); progress_interactive = progress_interactive_p (progress); } @@ -411,7 +412,7 @@ fd_read_body (int fd, FILE *out, wgint toread, wgint startpos, if (progress) progress_update (progress, ret, ptimer_read (timer)); #ifdef WINDOWS - if (toread > 0 && !opt.quiet) + if (toread > 0 && opt.show_progress) ws_percenttitle (100.0 * (startpos + sum_read) / (startpos + toread)); #endif diff --git a/src/retr.h b/src/retr.h index 22ab9ecd..d766ec52 100644 --- a/src/retr.h +++ b/src/retr.h @@ -50,7 +50,7 @@ enum { rb_chunked_transfer_encoding = 4 }; -int fd_read_body (int, FILE *, wgint, wgint, wgint *, wgint *, double *, int, FILE *); +int fd_read_body (const char *, int, FILE *, wgint, wgint, wgint *, wgint *, double *, int, FILE *); typedef const char *(*hunk_terminator_t) (const char *, const char *, int);