bender icon indicating copy to clipboard operation
bender copied to clipboard

Add CLI progress bars

Open fischeti opened this issue 1 month ago • 0 comments

CLI Progress bars

Adds progress bars to bender actions that require longer network access. A taste is shown below*

bender

*some style changes have been done since this recording.

Implementation

The progress bars are rendered with the crate indicatif, that allows rendering of multiple progress bars at once. The state of the progress bars is extracted from the stderr output of the spawned git commands i.e. a separate task is spawned alongside git tasks to parse git output lines and update the progress bar state. I initially thought about adopting the git2 crate, which would have built in progress callbacks. However, this would have been a larger change and also poses some challenges since those git tasks are not asynchronous and also credential handling would be more complicated, which is why I opted for stderr parsing in the end.

Related Changes

Apart from the implementation of the progress bars, some additional changes were necessary:

error macros

Previously, all messages were simply printed to stdout/stderr with println!/eprintln! without any specific order. Rendering the progress bars together with warning/error messaged caused unwanted artifacts. The reason is that the progress bar requires exclusive access over stdout/stderr, since it needs to clear lines again. If warning/error messages are sent in between, it might clear the warning/error message instead of the actual progress bar which is left behind as an artifact. For that matter, the MultiProgress instance can be suspended, which essentially means clearing all progress bars, writing the desired custom message to stdout/stderr and then redraw all the progress bars. This means the previous warnln!, errorln! etc., macros are now passed through the MultiProgress.suspend() function.

Styling changes

  • To easily style the messages (color, bold, dim etc.,) I pulled in the console crate, and also adapted the existing message formatting to use it.
  • I renamed the note message to info. It was not previously used at all, but I use it now to show the elapsed time of the checkout command.
  • I aligned the formatting of error and warning messages with the messages of the progress bars i.e. they now have the same indentation and are capitalized (this is subjective, and can be discussed).

git spawns

  • Where appropriate the git spawn functions now accept a Option<ProgressHandler> argument. If None is passed, the behaviour is as before, whereas Some(pb) will add a new progress bar.
  • Similarily, git throttling is now more selectively and only applies to commands that perform network operations. Previously every command was automatically throttled because every Git instance clonsed the git_throttle. Now, git_throttle is exposed as an argument to spawn tasks, and can be set to None the same way as for the progress handler.
  • The git submodule update commands are only performed if a dependency contains a .gitmodules. Otherwise, too many no-op progress messages are spawned.

TODOs

  • [x] Check output in log files (e.g. CI). In theory, this should work outside of the box.
  • [x] Check more bender commands. I focused mostly on checkout, but others use the same underlying functions so there should not be an issue in theory.

fischeti avatar Jan 01 '26 20:01 fischeti