ruby-build
ruby-build copied to clipboard
show downloading progress when --verbose is on
this PR enable the downloading progress for curl and wget, so we can get clear about the progress while downloading the ruby source like this:
Downloading ruby-2.1.0.tar.gz...
/tmp/ruby-build.20140327132203.5768 ~
-> http://cache.ruby-lang.org/pub/ruby/2.1/ruby-2.1.0.tar.gz
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 14.3M 0 99345 0 0 703 0 5:57:25 0:02:21 5:55:04 174
(oh shit, 174 bytes per second)
I don't know if the quiet policy is by design or not, unluckily the network in china is really sucks on downloading ruby :( , maybe a progress could make us life better on sucks network?
Not a bad idea, but this enables progress bars unconditionally regardless of the --verbose
flag. That means progress bars will end up in install logs, which is unwanted.
I would like to see a solution that only displays progress bars on stderr if --verbose
was used, but this information never enters the log file.
This is feature I've often wanted considering the flurry of flaky networks around the world, it would help users decide whether to give up the download or not. At least reporting the total package size would be useful information to decide whether to pursue or abort on bad networks.
@mislav Why the concern with polluting install logs? Would a simple progress bar be acceptable?
-#, --progress-bar
Make curl display progress as a simple progress bar instead of the standard, more informational, meter.
Progress bars are implemented by repeated redrawing of the same line in an interactive shell. That does not look good in logs. You might end up with 100s of lines of just progress bar.
Is there a --quiet
/--silent
flag?
Maybe ruby-build
could be verbose by default and have a --quiet
/--silent
flag that suppresses all output unless an error occurs?
@cmckni3 ruby-build is silent by default and only shows part of the build log when an error occurs.
I'll think about whether it's feasible to show progress bars by default.
Coming here from Nodenv #292 (where I requested this very feature) — although I haven't used rbenv in years, I hope my input is still welcome:
:+1: for implementing under --verbose
-only, initially; but :-1: for leaving it that way indefinitely. Showing a progress bar by default (without having to intuit that it might be an option, and then having to read a manpage to figure out how) is definitely a more user-friendly behaviour — so I suggest you leave toggling it on-by-default until the next semver-major release?
(Large systems implementing automated nodenv/rbenv stuff seem the most likely to check the changelog for version-major changes before implementing updates — assuming the Ruby community in 2017 is anything like the modern JavaScript one!)
One common way to cope with this is to check whether stdout is a TTY. It's no guarantee that the output is being read by a human, but it's a reasonable default for using ANSI colors and control codes.
@flaneur2020 Are you interested in using @jeremy's suggestion? If not I can recreate this PR with some TTY check.
Leaving this here for future reference: https://stackoverflow.com/a/911213/385622
if [ -t 1 ] ; then echo terminal; else echo "not a terminal"; fi
Thanks for the tip, @olivierlacan!
Note that ruby-build redirects the output of curl
and wget
to a log file opened at fd 4: https://github.com/rbenv/ruby-build/blob/cbdbc6e44be4756df3fc526ee97c1a5ce0632b74/bin/ruby-build#L1451
As per my previous comments, we absolutely do not want progress bars written into the log file because that both writes garbage to the log and is not displayed to the user (unless they have enabled verbose mode). Furthermore, since programs like curl
and wget
will detect that their output is not connected to a terminal, they will automatically change their rendering of a progress meter unless one is enforced by explicit flags.
ruby-build preserves the original stderr (the one that is usually connected to a terminal) at fd 3. This is where we want progress bars to be rendered to so that they are seen by the user. So, whenever we start a program that downloads something, we should:
- Check whether fd 3 is a terminal;
- redirect the stderr of a program that's doing the downloading to fd 3:
2>&3
; - pass explicit flags that control the display and behavior of the progress meter;
- Ensure that any non-progress meter error messages rendered from
curl
orwget
are also written to fd 4 so that they will be recorded in the log file. This is the hard part! I do not know how to best separate the progress meter rendering from legitimate error messages, since they will all be written to the same stream, and these programs don't seem to support a configuration option for writing the progress meter to a different output stream.