BNPSVXIC72C3WT33YKCH766OBLLNCS7POX6U6JXZSQQPJF2M22MQC
3WO4H2MMMQTYKCPBWYE67IRAEX7DFA2XAOMIKICA6BYDN23K6DQQC
HDGRZISM2SS4TK5BMNGDIYG22SOXAZRTTC6YFIOPY4LSO53QDWZQC
L4JXJHWXYNCL4QGJXNKKTOKKTAXKKXBJUUY7HFZGEUZ5A2V5H34QC
Q45QHPO4HDTEZF2W4UDZSYYQ46BPEIWSW4GJILZR5HTJNLKXJABQC
SXEYMYF7P4RZMZ46WPL4IZUTSQ2ATBWYZX7QNVMS3SGOYXYOHAGQC
KTTKF3RWYAK2YSH2DYYW5QVG4KSNGWUBJBFHKE24OJ7LFCBF5FEAC
367UBQ6KNAKUEWG32R4QRJ6H7IE7NAZFOPTC3ZOE4Z6E44RV3ISQC
FE5ES6Q46FMWYPNNNJLORY377QGDE57LBBDIVWDTC6Z7U4U73NEQC
UDHP4ZVBQZT2VBURB2MDCU2IZDNMCAFSIUKWRBDQ5BWMFKSN2LYQC
PCEJFKFXAFGYGHMM4BOBGFV3WRFXEBF2UQYQHLJ7MURRYBKRM3EAC
5QTMRUXNE2XNJCMLN6MQN24UEZ55EFC3LIR4PO6OPNTT5KEL7WXQC
TKEVOH7HXON7SOBGXTUDHAHO2U2GPTQRNESP6ERKUQAS526OZIRAC
WLUID7NANDWTN5GOECNEKFTLZF3MUVS7K26YWLYLSGJ56G63NV4QC
K6GWUOD55G377RVEEMMRPZ4EUAHCM2BGXNRJTE5UZJFFMJGFCEZQC
MU5GSJAW65PEG3BRYUKZ7O37BPHW3MOX3S5E2RFOXKGUOJEEDQ5AC
76PCXGML77EZWTRI5E6KHLVRAFTJ2AB5YRN5EKOYNAPKTWY2KCGAC
X6YFD4WVMUYJCR5IYPJH6UKYVWSA7DKBRVJ6XQFXHOE2TRYUTAHAC
YN63NUZO4LVJ7XPMURDULTXBVJKW5MVCTZ24R7Z52QMHO3HPDUVQC
HXEIH4UQ6EX3MAY33JK4WQUE5GUSZ673OX57JKNFXC2N2QLTXKXAC
TPEH2XNBS5RO4IEVKENVF6P65AH7IX64KK2JAYMSJT3J5GXO67EAC
CCLLB7OIFNFYJZTG3UCI7536TOCWSCSXR67VELSB466R24WLJSDAC
FBXYP7QM7SG6P2JDJVQPPCRKJE3GVYXNQ5GVV4GRDUNG6Q4ZRDJQC
I52XSRUH5RVHQBFWVMAQPTUSPAJ4KNVID2RMI3UGCVKFLYUO6WZAC
IQ4FCHPZYGTZHCQHUIRCMUI5LCHIDSJCM2AZXGRJARWLCPPLXZOQC
VBMXB443FGZL6DLT6KAP2ICFCCQNXCUMDEUL67HB4CNKFMBBNSSAC
WTZXEWY7IAXJAFNV7STCNQY2SNRDPHX3MKOEZ77NEJUN4MS2VYSQC
44BN7FWSIXKG75IJUTCXLJE7VANNQFPRHQXTPLQHFU7AKGLSPQRAC
MDADYULS5AWVMTJDGYCGNQTN6T7XJDRUBDTFILDY5MLF6I2PE5NAC
JL4WKA5PBKXRNAMETYO4I52QKASQ3COYHH2JKGA7W5YLIRZZH53AC
ZRUPLBBTT4S6S7A3LOAHG4ONYEGPA5CFO4L2XBCNFKK45MWX3BDAC
G734WNM64AR5BLAZMN5MDPKSFTYXTUQR6MAGB32NRBC5FXFRWSJAC
SAGSYAPXQ2T6GC3B3TNRPNFTZMS7UMME6YQGSF5MOIM66S5NKB2QC
Q7CAYX5N2GFOGMZL3VXVWORMAPWEOECXE22BLXK7Q4WEPS4CE2SAC
3VJB4ULDDBRUZQ3TSOEJQ3TFVYYHE347ONKMFWGTSCLUYUV536XQC
ENKQ3QZGH2QW246C7GSZRKYLODJOQHKZZSYV7QHB7VPOFP5PASVQC
JRENVH5DF2F4SOV7UNJENFA7VDI3H63XK76R3LFZK6QCW7JIBLSQC
3WIQYEISUMGOL5FY4LCWOJS55CTTQA7WMJZXAE3Q4GQUTBFLAE7QC
VYHHOEYHO67JNJEODX5L3CQFIV3DAXZBBIQUOMCWJDYF3VWICDNQC
let progress = ProgressBar::new(changes.len() as u64);
progress.set_style(
indicatif::ProgressStyle::default_bar()
.template(" Uploading changes {wide_bar} {pos:>5}/{len}"),
);
let progress = super::PROGRESS.add(progress);
*PROGRESS.lock().await = Some(progress);
}
if let Some(ref mut progress) = *PROGRESS.lock().await {
progress.set_style(
indicatif::ProgressStyle::default_bar()
.template("✓ Uploading changes {pos:>5}/{len}"),
);
progress.finish();
c: &mut tokio::sync::mpsc::Receiver<libpijul::pristine::Hash>,
mut sender: Option<&mut tokio::sync::mpsc::Sender<libpijul::pristine::Hash>>,
progress: Arc<std::sync::Mutex<crate::progress::InnerCursors>>,
c: &mut tokio::sync::mpsc::UnboundedReceiver<libpijul::pristine::Hash>,
sender: Option<&mut tokio::sync::mpsc::Sender<libpijul::pristine::Hash>>,
let mut len = 0;
let progress = ProgressBar::new(len as u64);
progress.set_style(
indicatif::ProgressStyle::default_bar()
.template(" Downloading changes {wide_bar} {pos:>5}/{len}"),
);
*PROGRESS.lock().await = Some(progress);
let mut dropped = false;
loop {
tokio::select! {
x = recv.recv() => {
let hash = if let Some(hash) = x {
debug!("received hash {:?}", hash);
hash
} else {
debug!("finished");
break
};
if let Some(ref mut progress) = *PROGRESS.lock().await {
progress.inc(1);
}
if let Some(ref mut sender) = sender {
if sender.send(hash).await.is_err() {
if let Some(ref mut progress) = *PROGRESS.lock().await {
progress.abandon();
}
break;
}
}
}
x = c.recv(), if !dropped => {
let c = if let Some(c) = x {
c
} else {
debug!("other end dropped");
dropped = true;
if len == 0 {
break
} else {
continue
}
};
if let State::Changes { ref mut hashes, .. } = *self.state.lock().await {
hashes.push(c);
}
debug!("download_change {:?} {:?}", c, full);
if full {
self.c
.data(format!("change {}\n", c.to_base32()).as_bytes())
.await?;
} else {
self.c
.data(format!("partial {}\n", c.to_base32()).as_bytes())
.await?;
}
if let Some(ref mut p) = *PROGRESS.lock().await {
p.inc_length(1)
}
len += 1;
let mut sender = sender.map(|x| x.clone());
let t = tokio::spawn(async move {
while let Some(hash) = recv.recv().await {
debug!("received hash {:?}", hash);
progress.lock().unwrap().cursors[0].incr();
debug!("received");
if let Some(ref mut sender) = sender {
sender.send(hash).await.unwrap_or(());
}
if let Some(ref mut progress) = *PROGRESS.lock().await {
if !progress.is_finished() {
progress.set_style(
indicatif::ProgressStyle::default_bar()
.template("✓ Downloading changes {pos:>5}/{len}"),
);
progress.finish();
debug!("download_change {:?} {:?}", h, full);
if full {
self.c
.data(format!("change {}\n", h.to_base32()).as_bytes())
.await?;
} else {
self.c
.data(format!("partial {}\n", h.to_base32()).as_bytes())
.await?;
let progress = indicatif::ProgressBar::new_spinner();
progress.set_style(
indicatif::ProgressStyle::default_spinner()
.template("{spinner} Updating remote changelist"),
);
progress.enable_steady_tick(100);
*SPINNER.lock().await = Some(progress);
RemoteRepo::Local(ref mut l) => l.download_changes(hashes, send, path).await?,
RemoteRepo::Ssh(ref mut s) => s.download_changes(hashes, send, path, full).await?,
RemoteRepo::Http(ref mut h) => h.download_changes(hashes, send, path, full).await?,
RemoteRepo::Local(ref mut l) => {
l.download_changes(progress, hashes, send, path).await?
}
RemoteRepo::Ssh(ref mut s) => {
s.download_changes(progress, hashes, send, path, full)
.await?
}
RemoteRepo::Http(ref mut h) => {
h.download_changes(progress, hashes, send, path, full)
.await?
}
let progress = crate::progress::Cursors::new();
{
let mut pro = progress.borrow_mut().unwrap();
pro.cursors.push(crate::progress::Cursor::Bar {
i: 0,
n: to_apply.len(),
pre: "Downloading changes".into(),
});
if do_apply {
pro.cursors.push(crate::progress::Cursor::Bar {
i: 0,
n: to_apply.len(),
pre: "Applying".into(),
});
}
}
let mut change_path = repo.changes_dir.clone();
let progress = if do_apply {
let p = indicatif::ProgressBar::new(len);
p.set_style(
indicatif::ProgressStyle::default_bar()
.template(" Applying changes {wide_bar} {pos:>5}/{len}"),
);
Some(PROGRESS.add(p))
} else {
None
};
let t_progress = std::thread::spawn(|| {
PROGRESS.join().unwrap_or(());
});
libpijul::changestore::filesystem::push_filename(&mut change_path, &h);
debug!("change_path = {:?}", change_path);
while std::fs::metadata(&change_path).is_err() {
debug!("waiting");
let r = recv.recv().await;
debug!("r = {:?}", r);
if r.is_none() {
if let Some(ref progress) = progress {
progress.abandon();
}
debug!("to_apply: {:?}", h);
while to_download.contains(&h) {
debug!("waiting for {:?}", h);
if let Some(h) = recv.recv().await {
debug!("recv {:?}", h);
to_download.remove(&h);
} else {
}
}
if let Some(progress) = progress {
if !progress.is_finished() {
progress.set_style(
indicatif::ProgressStyle::default_bar()
.template("✓ Applying changes {pos:>5}/{len}"),
);
progress.finish()
let progress = ProgressBar::new(0 as u64);
progress.set_style(
indicatif::ProgressStyle::default_bar()
.template(" Downloading changes {wide_bar} {pos:>5}/{len}"),
);
let progress = super::PROGRESS.add(progress);
}
if !progress.is_finished() {
progress.set_style(
indicatif::ProgressStyle::default_bar()
.template("✓ Downloading changes {pos:>5}/{len}"),
);
progress.finish();
let progress = ProgressBar::new(changes.len() as u64);
progress.set_style(
indicatif::ProgressStyle::default_bar()
.template(" Uploading changes {wide_bar} {pos:>5}/{len}"),
);
progress.set_style(
indicatif::ProgressStyle::default_bar().template("✓ Uploading changes {pos:>5}/{len}"),
);
progress.finish();
use std::borrow::Cow;
use std::io::Write;
use std::sync::{Arc, Mutex};
pub struct Cursors {
pub inner: Arc<Mutex<InnerCursors>>,
t: std::thread::JoinHandle<()>,
}
pub struct InnerCursors {
drawn: usize,
pub cursors: Vec<Cursor>,
n_post: usize,
n_pre: usize,
w: usize,
stop: bool,
}
impl Cursors {
pub fn new() -> Self {
let inner = Arc::new(Mutex::new(InnerCursors {
drawn: 0,
cursors: Vec::new(),
n_post: 0,
n_pre: 0,
stop: false,
w: 0,
}));
let inner_ = inner.clone();
let t = std::thread::spawn(move || loop {
{
let mut inner = if let Ok(inner) = inner_.lock() {
inner
} else {
break;
};
if inner.stop {
inner.render().unwrap();
break;
} else {
inner.render().unwrap();
}
}
std::thread::sleep(std::time::Duration::from_millis(100));
});
Cursors { inner, t }
}
pub fn stop(&self) {
if let Ok(mut n) = self.inner.lock() {
n.stop = true
}
}
pub fn join(self) {
self.stop();
self.t.join().unwrap();
}
pub fn borrow_mut(
&self,
) -> Result<
std::sync::MutexGuard<InnerCursors>,
std::sync::PoisonError<std::sync::MutexGuard<'_, InnerCursors>>,
> {
let mut m = self.inner.lock()?;
m.n_pre = 0;
Ok(m)
}
}
#[allow(dead_code)]
pub enum Cursor {
Static {
pre: Cow<'static, str>,
},
Bar {
pre: Cow<'static, str>,
n: usize,
i: usize,
},
Spin {
pre: Cow<'static, str>,
i: usize,
},
}
impl Cursor {
fn pre(&self) -> &str {
match self {
Cursor::Static { pre } => pre,
Cursor::Bar { pre, .. } => pre,
Cursor::Spin { pre, .. } => pre,
}
}
fn n(&self) -> usize {
match self {
Cursor::Bar { n, .. } => {
let mut n = *n;
let mut r = 6;
while n > 0 {
n /= 10;
r += 2
}
r
}
_ => 0,
}
}
pub fn incr(&mut self) {
match self {
Cursor::Bar { i, .. } => *i += 1,
_ => {}
}
}
fn render<W: std::io::Write>(
&mut self,
stdout: &mut W,
npre: usize,
npost: usize,
w: usize,
) -> Result<(), std::io::Error> {
match self {
Cursor::Static { pre } => {
for _ in 0..npre - pre.chars().count() {
stdout.write_all(b" ")?;
}
stdout.write_all(pre.as_bytes())?;
// Fil the rest of the line with spaces.
for _ in 0..w - npre {
stdout.write_all(b" ")?;
}
Ok(())
}
Cursor::Bar { pre, i, n } => {
for _ in 0..npre - pre.chars().count() {
stdout.write_all(b" ")?;
}
// Comupte the appropriate width for the bar.
let w = w - npre - npost;
// Output the bar.
write!(stdout, "{} [", pre)?;
let k = (w as usize * *i) / (*n - 1);
for j in 0..w as usize {
if j < k {
write!(stdout, "=")?;
} else if j == k {
write!(stdout, ">")?;
} else {
write!(stdout, " ")?
}
}
write!(stdout, "] {}/{}", *i, *n)?;
let mut nw = npost - 6;
{
let mut n = *n;
while n > 0 {
n /= 10;
nw -= 1
}
let mut n = *i;
while n > 0 {
n /= 10;
nw -= 1
}
}
for _ in 0..nw {
stdout.write_all(b" ")?;
}
Ok(())
}
Cursor::Spin { pre, i } => {
for _ in 0..npre - pre.chars().count() {
stdout.write_all(b" ")?;
}
stdout.write_all(pre.as_bytes())?;
stdout.write_all(b" ")?;
const SYM: [&str; 8] = ["←", "↖", "↑", "↗", "→", "↘", "↓", "↙"];
stdout.write_all(SYM[*i].as_bytes())?;
*i = (*i + 1) % SYM.len();
// Fill the rest of the line with spaces.
for _ in 0..w - npre - 2 {
stdout.write_all(b" ")?;
}
Ok(())
}
}
}
}
impl InnerCursors {
fn render(&mut self) -> Result<(), std::io::Error> {
use terminal_size::*;
let mut stdout = std::io::stdout();
if let Some((Width(w), _)) = terminal_size() {
if self.n_pre == 0 {
self.n_post = 0;
for c in self.cursors.iter() {
let n_pre = c.pre().chars().count();
self.n_pre = self.n_pre.max(n_pre);
self.n_post = self.n_post.max(c.n());
}
}
let n = (self.w + w as usize - 1) / w as usize;
for _ in 0..self.drawn * n {
stdout.write_all(b"\x1B[F")?;
}
self.w = w as usize;
for c in self.cursors.iter_mut() {
c.render(&mut stdout, self.n_pre, self.n_post, w as usize)?;
// Clear the end of the line and move to the next one.
stdout.write_all(b"\x1B[K\n")?;
}
self.drawn = self.cursors.len();
// Erase the terminal after the cursor.
stdout.write_all(b"\x1B[J")?;
stdout.flush()?;
}
Ok(())
}
}
let progress = indicatif::ProgressBar::new(to_download.len() as u64);
progress.set_style(
indicatif::ProgressStyle::default_spinner()
.template(" Applying changes {wide_bar} {pos}/{len}"),
);
"console" = rec {
crateName = "console";
version = "0.14.0";
edition = "2018";
sha256 = "1ajnr0rga4vya0fza12ighf3ffkm86w1rv8p5wf443s8nd30kj3w";
authors = [
"Armin Ronacher <armin.ronacher@active-4.com>"
];
dependencies = [
{
name = "encode_unicode";
packageId = "encode_unicode";
target = { target, features }: (target."windows" or false);
}
{
name = "lazy_static";
packageId = "lazy_static";
}
{
name = "libc";
packageId = "libc";
}
{
name = "regex";
packageId = "regex";
optional = true;
usesDefaultFeatures = false;
features = [ "std" ];
}
{
name = "terminal_size";
packageId = "terminal_size";
}
{
name = "unicode-width";
packageId = "unicode-width";
optional = true;
}
{
name = "winapi";
packageId = "winapi";
target = { target, features }: (target."windows" or false);
features = [ "winbase" "winuser" "consoleapi" "processenv" "wincon" ];
}
];
features = {
"ansi-parsing" = [ "regex" ];
"default" = [ "unicode-width" "ansi-parsing" ];
"windows-console-colors" = [ "ansi-parsing" "winapi-util" ];
};
resolvedDefaultFeatures = [ "ansi-parsing" "default" "regex" "unicode-width" ];
};
"encode_unicode" = rec {
crateName = "encode_unicode";
version = "0.3.6";
edition = "2015";
sha256 = "07w3vzrhxh9lpjgsg2y5bwzfar2aq35mdznvcp3zjl0ssj7d4mx3";
authors = [
"Torbjørn Birch Moltu <t.b.moltu@lyse.net>"
];
features = {
"default" = [ "std" ];
};
resolvedDefaultFeatures = [ "default" "std" ];
};
"indicatif" = rec {
crateName = "indicatif";
version = "0.15.0";
edition = "2018";
sha256 = "1r4n50mclyi4c7b9c9mlma1rhchjamw71r3z8vgqcmp24mhvbakv";
authors = [
"Armin Ronacher <armin.ronacher@active-4.com>"
];
dependencies = [
{
name = "console";
packageId = "console";
}
{
name = "lazy_static";
packageId = "lazy_static";
}
{
name = "number_prefix";
packageId = "number_prefix";
}
{
name = "regex";
packageId = "regex";
usesDefaultFeatures = false;
features = [ "std" ];
}
];
features = {
"improved_unicode" = [ "unicode-segmentation" "unicode-width" "console/unicode-width" ];
"with_rayon" = [ "rayon" ];
};
resolvedDefaultFeatures = [ "default" ];
};
};
"number_prefix" = rec {
crateName = "number_prefix";
version = "0.3.0";
edition = "2015";
sha256 = "0slm4mqmpgs6hvz22ycny9lvyvl9ivs80a1lncslp7lszz02zc0p";
authors = [
"Benjamin Sago <ogham@bsago.me>"
];
features = {
"default" = [ "std" ];
};
resolvedDefaultFeatures = [ "default" "std" ];
"progress" = rec {
crateName = "progress";
version = "0.1.0";
edition = "2018";
crateBin = [
{ name = "progress"; path = "src/main.rs"; }
];
src = lib.cleanSourceWith { filter = sourceFilter; src = ./progress; };
authors = [
"Pierre-Étienne Meunier <pmeunier@mailbox.org>"
];
dependencies = [
{
name = "terminal_size";
packageId = "terminal_size";
}
];
};
resolvedDefaultFeatures = [ "basetsd" "cfg" "consoleapi" "errhandlingapi" "evntrace" "fileapi" "handleapi" "impl-debug" "impl-default" "in6addr" "inaddr" "ioapiset" "knownfolders" "lmcons" "memoryapi" "minschannel" "minwinbase" "minwindef" "mswsock" "namedpipeapi" "ntdef" "ntsecapi" "ntstatus" "objbase" "processenv" "processthreadsapi" "profileapi" "schannel" "securitybaseapi" "shlobj" "sspi" "std" "synchapi" "sysinfoapi" "threadpoollegacyapiset" "timezoneapi" "winbase" "wincon" "wincrypt" "windef" "winerror" "winioctl" "winnt" "winreg" "winsock2" "winuser" "ws2def" "ws2ipdef" "ws2tcpip" ];
resolvedDefaultFeatures = [ "basetsd" "cfg" "consoleapi" "errhandlingapi" "evntrace" "fileapi" "handleapi" "impl-debug" "impl-default" "in6addr" "inaddr" "ioapiset" "knownfolders" "lmcons" "memoryapi" "minschannel" "minwinbase" "minwindef" "mswsock" "namedpipeapi" "ntdef" "ntsecapi" "ntstatus" "objbase" "processenv" "processthreadsapi" "profileapi" "schannel" "securitybaseapi" "shlobj" "sspi" "std" "synchapi" "sysinfoapi" "threadpoollegacyapiset" "timezoneapi" "winbase" "wincon" "wincrypt" "windef" "winerror" "winioctl" "winnt" "winreg" "winsock2" "ws2def" "ws2ipdef" "ws2tcpip" ];
name = "console"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cc80946b3480f421c2f17ed1cb841753a371c7c5104f51d507e13f532c856aa"
dependencies = [
"encode_unicode",
"lazy_static",
"libc",
"regex",
"terminal_size",
"unicode-width",
"winapi",
]
[[package]]
]
[[package]]
name = "indicatif"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7baab56125e25686df467fe470785512329883aab42696d661247aca2a2896e4"
dependencies = [
"console",
"lazy_static",
"number_prefix",
"regex",