Show More
@@ -231,6 +231,19 dependencies = [ | |||||
231 | ] |
|
231 | ] | |
232 |
|
232 | |||
233 | [[package]] |
|
233 | [[package]] | |
|
234 | name = "console" | |||
|
235 | version = "0.15.8" | |||
|
236 | source = "registry+https://github.com/rust-lang/crates.io-index" | |||
|
237 | checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" | |||
|
238 | dependencies = [ | |||
|
239 | "encode_unicode", | |||
|
240 | "lazy_static", | |||
|
241 | "libc", | |||
|
242 | "unicode-width", | |||
|
243 | "windows-sys 0.52.0", | |||
|
244 | ] | |||
|
245 | ||||
|
246 | [[package]] | |||
234 | name = "convert_case" |
|
247 | name = "convert_case" | |
235 | version = "0.4.0" |
|
248 | version = "0.4.0" | |
236 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
249 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
@@ -451,6 +464,12 source = "registry+https://github.com/ru | |||||
451 | checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" |
|
464 | checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" | |
452 |
|
465 | |||
453 | [[package]] |
|
466 | [[package]] | |
|
467 | name = "encode_unicode" | |||
|
468 | version = "0.3.6" | |||
|
469 | source = "registry+https://github.com/rust-lang/crates.io-index" | |||
|
470 | checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" | |||
|
471 | ||||
|
472 | [[package]] | |||
454 | name = "env_logger" |
|
473 | name = "env_logger" | |
455 | version = "0.9.3" |
|
474 | version = "0.9.3" | |
456 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
475 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
@@ -609,6 +628,7 dependencies = [ | |||||
609 | "hashbrown 0.13.1", |
|
628 | "hashbrown 0.13.1", | |
610 | "home", |
|
629 | "home", | |
611 | "im-rc", |
|
630 | "im-rc", | |
|
631 | "indicatif", | |||
612 | "itertools", |
|
632 | "itertools", | |
613 | "lazy_static", |
|
633 | "lazy_static", | |
614 | "libc", |
|
634 | "libc", | |
@@ -711,6 +731,19 dependencies = [ | |||||
711 | ] |
|
731 | ] | |
712 |
|
732 | |||
713 | [[package]] |
|
733 | [[package]] | |
|
734 | name = "indicatif" | |||
|
735 | version = "0.17.8" | |||
|
736 | source = "registry+https://github.com/rust-lang/crates.io-index" | |||
|
737 | checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3" | |||
|
738 | dependencies = [ | |||
|
739 | "console", | |||
|
740 | "instant", | |||
|
741 | "number_prefix", | |||
|
742 | "portable-atomic", | |||
|
743 | "unicode-width", | |||
|
744 | ] | |||
|
745 | ||||
|
746 | [[package]] | |||
714 | name = "instant" |
|
747 | name = "instant" | |
715 | version = "0.1.12" |
|
748 | version = "0.1.12" | |
716 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
749 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
@@ -890,6 +923,12 dependencies = [ | |||||
890 | ] |
|
923 | ] | |
891 |
|
924 | |||
892 | [[package]] |
|
925 | [[package]] | |
|
926 | name = "number_prefix" | |||
|
927 | version = "0.4.0" | |||
|
928 | source = "registry+https://github.com/rust-lang/crates.io-index" | |||
|
929 | checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" | |||
|
930 | ||||
|
931 | [[package]] | |||
893 | name = "once_cell" |
|
932 | name = "once_cell" | |
894 | version = "1.16.0" |
|
933 | version = "1.16.0" | |
895 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
934 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
@@ -938,6 +977,12 source = "registry+https://github.com/ru | |||||
938 | checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" |
|
977 | checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" | |
939 |
|
978 | |||
940 | [[package]] |
|
979 | [[package]] | |
|
980 | name = "portable-atomic" | |||
|
981 | version = "1.9.0" | |||
|
982 | source = "registry+https://github.com/rust-lang/crates.io-index" | |||
|
983 | checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" | |||
|
984 | ||||
|
985 | [[package]] | |||
941 | name = "ppv-lite86" |
|
986 | name = "ppv-lite86" | |
942 | version = "0.2.17" |
|
987 | version = "0.2.17" | |
943 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
988 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
@@ -1646,6 +1691,15 dependencies = [ | |||||
1646 |
|
1691 | |||
1647 | [[package]] |
|
1692 | [[package]] | |
1648 | name = "windows-sys" |
|
1693 | name = "windows-sys" | |
|
1694 | version = "0.52.0" | |||
|
1695 | source = "registry+https://github.com/rust-lang/crates.io-index" | |||
|
1696 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" | |||
|
1697 | dependencies = [ | |||
|
1698 | "windows-targets 0.52.6", | |||
|
1699 | ] | |||
|
1700 | ||||
|
1701 | [[package]] | |||
|
1702 | name = "windows-sys" | |||
1649 | version = "0.59.0" |
|
1703 | version = "0.59.0" | |
1650 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1704 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1651 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" |
|
1705 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" |
@@ -16,6 +16,7 derive_more = "0.99.17" | |||||
16 | hashbrown = { version = "0.13.1", features = ["rayon"] } |
|
16 | hashbrown = { version = "0.13.1", features = ["rayon"] } | |
17 | home = "0.5.4" |
|
17 | home = "0.5.4" | |
18 | im-rc = "15.1.0" |
|
18 | im-rc = "15.1.0" | |
|
19 | indicatif = "0.17.8" | |||
19 | itertools = "0.10.5" |
|
20 | itertools = "0.10.5" | |
20 | lazy_static = "1.4.0" |
|
21 | lazy_static = "1.4.0" | |
21 | libc = "0.2.137" |
|
22 | libc = "0.2.137" |
@@ -1,5 +1,12 | |||||
1 | //! Progress-bar related things |
|
1 | //! Progress-bar related things | |
2 |
|
2 | |||
|
3 | use std::{ | |||
|
4 | sync::atomic::{AtomicBool, Ordering}, | |||
|
5 | time::Duration, | |||
|
6 | }; | |||
|
7 | ||||
|
8 | use indicatif::{ProgressBar, ProgressDrawTarget, ProgressStyle}; | |||
|
9 | ||||
3 | /// A generic determinate progress bar trait |
|
10 | /// A generic determinate progress bar trait | |
4 | pub trait Progress: Send + Sync + 'static { |
|
11 | pub trait Progress: Send + Sync + 'static { | |
5 | /// Set the current position and optionally the total |
|
12 | /// Set the current position and optionally the total | |
@@ -9,3 +16,77 pub trait Progress: Send + Sync + 'stati | |||||
9 | /// Declare that progress is over and the progress bar should be deleted |
|
16 | /// Declare that progress is over and the progress bar should be deleted | |
10 | fn complete(self); |
|
17 | fn complete(self); | |
11 | } |
|
18 | } | |
|
19 | ||||
|
20 | const PROGRESS_DELAY: Duration = Duration::from_secs(1); | |||
|
21 | ||||
|
22 | /// A generic (determinate) progress bar. Stays hidden until [`PROGRESS_DELAY`] | |||
|
23 | /// to prevent flickering a progress bar for super fast operations. | |||
|
24 | pub struct HgProgressBar { | |||
|
25 | progress: ProgressBar, | |||
|
26 | has_been_shown: AtomicBool, | |||
|
27 | } | |||
|
28 | ||||
|
29 | impl HgProgressBar { | |||
|
30 | // TODO pass config to check progress.disable/assume-tty/delay/etc. | |||
|
31 | /// Return a new progress bar with `topic` as the prefix. | |||
|
32 | /// The progress and total are both set to 0, and it is hidden until the | |||
|
33 | /// next call to `update` given that more than a second has elapsed. | |||
|
34 | pub fn new(topic: &str) -> Self { | |||
|
35 | let template = | |||
|
36 | format!("{} {{wide_bar}} {{pos}}/{{len}} {{eta}} ", topic); | |||
|
37 | let style = ProgressStyle::with_template(&template).unwrap(); | |||
|
38 | let progress_bar = ProgressBar::new(0).with_style(style); | |||
|
39 | // Hide the progress bar and only show it if we've elapsed more | |||
|
40 | // than a second | |||
|
41 | progress_bar.set_draw_target(ProgressDrawTarget::hidden()); | |||
|
42 | Self { | |||
|
43 | progress: progress_bar, | |||
|
44 | has_been_shown: false.into(), | |||
|
45 | } | |||
|
46 | } | |||
|
47 | ||||
|
48 | /// Called whenever the progress changes to determine whether to start | |||
|
49 | /// showing the progress bar | |||
|
50 | fn maybe_show(&self) { | |||
|
51 | if self.progress.is_hidden() | |||
|
52 | && self.progress.elapsed() > PROGRESS_DELAY | |||
|
53 | { | |||
|
54 | // Catch a race condition whereby we check if it's hidden, then | |||
|
55 | // set the draw target from another thread, then do it again from | |||
|
56 | // this thread, which results in multiple progress bar lines being | |||
|
57 | // left drawn. | |||
|
58 | let has_been_shown = | |||
|
59 | self.has_been_shown.fetch_or(true, Ordering::Relaxed); | |||
|
60 | if !has_been_shown { | |||
|
61 | // Here we are certain that we're the only thread that has | |||
|
62 | // set `has_been_shown` and we can change the draw target | |||
|
63 | self.progress.set_draw_target(ProgressDrawTarget::stderr()); | |||
|
64 | self.progress.tick(); | |||
|
65 | } | |||
|
66 | } | |||
|
67 | } | |||
|
68 | } | |||
|
69 | ||||
|
70 | impl Progress for HgProgressBar { | |||
|
71 | fn update(&self, pos: u64, total: Option<u64>) { | |||
|
72 | self.progress.update(|state| { | |||
|
73 | state.set_pos(pos); | |||
|
74 | if let Some(t) = total { | |||
|
75 | state.set_len(t) | |||
|
76 | } | |||
|
77 | }); | |||
|
78 | self.maybe_show(); | |||
|
79 | } | |||
|
80 | ||||
|
81 | fn increment(&self, step: u64, total: Option<u64>) { | |||
|
82 | self.progress.inc(step); | |||
|
83 | if let Some(t) = total { | |||
|
84 | self.progress.set_length(t) | |||
|
85 | } | |||
|
86 | self.maybe_show(); | |||
|
87 | } | |||
|
88 | ||||
|
89 | fn complete(self) { | |||
|
90 | self.progress.finish_and_clear(); | |||
|
91 | } | |||
|
92 | } |
General Comments 0
You need to be logged in to leave comments.
Login now