|
|
|
@ -36,24 +36,37 @@ where T: Future
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async fn do_work(process: impl AsRef<Path>, file: impl AsRef<OsStr>, mut prog: progress::ProgressSender) -> Result<fixed_stack::IntoIter<String>, process::Error>
|
|
|
|
|
#[cfg(feature="progress")]
|
|
|
|
|
type ProgressSender = progress::ProgressSender;
|
|
|
|
|
#[cfg(not(feature="progress"))]
|
|
|
|
|
type ProgressSender = ();
|
|
|
|
|
|
|
|
|
|
#[allow(unused_mut)]
|
|
|
|
|
#[allow(unused_variables)]
|
|
|
|
|
async fn do_work(process: impl AsRef<Path>, file: impl AsRef<OsStr>, mut prog: ProgressSender) -> Result<fixed_stack::IntoIter<String>, process::Error>
|
|
|
|
|
{
|
|
|
|
|
let process = process.as_ref();
|
|
|
|
|
let file = file.as_ref();
|
|
|
|
|
|
|
|
|
|
let (tx, mut rx) = mpsc::channel::<(bool, String)>(16);
|
|
|
|
|
|
|
|
|
|
let _opt_await: OptionFuture<_> = prog.println(format!("[p]: Processing {:?}", file)).await.ok().into();
|
|
|
|
|
#[cfg(feature="progress")] let _opt_await: OptionFuture<_> = prog.println(format!("[p]: Processing {:?}", file)).await.ok().into();
|
|
|
|
|
#[cfg(not(feature="progress"))] let _opt_await = println!("[p]: Processing {:?}", file);
|
|
|
|
|
let collector = {
|
|
|
|
|
let mut prog = prog.clone();
|
|
|
|
|
let file = file.to_owned();
|
|
|
|
|
tokio::spawn(async move {
|
|
|
|
|
let mut stack = fixed_stack::FixedStack::new(100);
|
|
|
|
|
while let Some((err, value)) = rx.recv().await {
|
|
|
|
|
if err {
|
|
|
|
|
let value = format!("[!] {:?}: {}", file, value);
|
|
|
|
|
if let Err(_) = prog.eprintln(&value[..]).await {
|
|
|
|
|
eprintln!("\n{}", value);
|
|
|
|
|
cfg_if!{
|
|
|
|
|
if #[cfg(feature="progress")] {
|
|
|
|
|
let value = format!("[!] {:?}: {}", file, value);
|
|
|
|
|
if let Err(_) = prog.eprintln(&value[..]).await {
|
|
|
|
|
eprintln!("\n{}", value);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
eprintln!("[!] {:?}: {}", file, value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
stack.push(value);
|
|
|
|
@ -70,7 +83,7 @@ async fn do_work(process: impl AsRef<Path>, file: impl AsRef<OsStr>, mut prog: p
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub async fn work<I,T,U>(process: U, files: I, children: Option<NonZeroUsize>) -> Result<(), Box<dyn std::error::Error>>
|
|
|
|
|
pub async fn work<I,T,U>(flags: &arg::Flags, process: U, files: I, children: Option<NonZeroUsize>) -> Result<(), Box<dyn std::error::Error>>
|
|
|
|
|
where I: IntoIterator<Item=T>,
|
|
|
|
|
<I as IntoIterator>::IntoIter: ExactSizeIterator,
|
|
|
|
|
T: AsRef<OsStr> + Send + Sync + 'static + Clone,
|
|
|
|
@ -82,21 +95,35 @@ where I: IntoIterator<Item=T>,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let files = files.into_iter();
|
|
|
|
|
#[cfg(feature="progress")] let (mut progress, prog_handle) = progress::create_progress::<termprogress::progress::Bar,_>(files.len(), iter::empty());
|
|
|
|
|
|
|
|
|
|
#[cfg(feature="progress")] let (mut progress, prog_handle) = {
|
|
|
|
|
if flags.progress {
|
|
|
|
|
progress::create_progress::<termprogress::progress::Bar,_>(files.len(), iter::empty())
|
|
|
|
|
} else {
|
|
|
|
|
progress::create_progress::<termprogress::silent::Silent,_>(files.len(), iter::empty())
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let display = {
|
|
|
|
|
let mut progress = progress.clone();
|
|
|
|
|
#[cfg(feature="progress")] let mut progress = progress.clone();
|
|
|
|
|
tokio::spawn(async move {
|
|
|
|
|
//let mut last: OptionFuture<_> = None.into();
|
|
|
|
|
while let Some((file, values, i)) = rx.recv().await {
|
|
|
|
|
let mut builder =progress.builder();
|
|
|
|
|
for line in values.into_iter()
|
|
|
|
|
{
|
|
|
|
|
let line = format!(" -> ({}) {:?}: {}", i, file.as_ref(), line);
|
|
|
|
|
builder.println(line);
|
|
|
|
|
cfg_if!{
|
|
|
|
|
if #[cfg(feature="progress")] {
|
|
|
|
|
let mut builder =progress.builder();
|
|
|
|
|
for line in values.into_iter()
|
|
|
|
|
{
|
|
|
|
|
let line = format!(" -> ({}) {:?}: {}", i, file.as_ref(), line);
|
|
|
|
|
builder.println(line);
|
|
|
|
|
}
|
|
|
|
|
let _ = builder.send().await;
|
|
|
|
|
} else {
|
|
|
|
|
for line in values.into_iter()
|
|
|
|
|
{
|
|
|
|
|
println!(" -> ({}) {:?}: {}", i, file.as_ref(), line);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
let _ = builder.send().await;
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
};
|
|
|
|
@ -106,24 +133,45 @@ where I: IntoIterator<Item=T>,
|
|
|
|
|
let semaphore = semaphore.clone();
|
|
|
|
|
let process = Arc::clone(&process);
|
|
|
|
|
let mut tx = tx.clone();
|
|
|
|
|
let mut progress = progress.clone();
|
|
|
|
|
|
|
|
|
|
#[cfg(feature="progress")] let mut progress = progress.clone();
|
|
|
|
|
|
|
|
|
|
(tokio::spawn(async move {
|
|
|
|
|
let task_id: OptionFuture<_> = {
|
|
|
|
|
#[cfg(feature="progress")] type Opt<T> = OptionFuture<T>;
|
|
|
|
|
#[cfg(not(feature="progress"))] type Opt<T> = std::marker::PhantomData<T>;
|
|
|
|
|
let _task_id: Opt<_> = {
|
|
|
|
|
let _lock = maybe_await(semaphore.map(|x| x.acquire_owned())).await;
|
|
|
|
|
let worker = do_work(process.as_ref(), &filename, progress.clone());
|
|
|
|
|
let task = progress.add_task(format!("{:?}", filename.as_ref()));
|
|
|
|
|
let worker = future::join(task, worker).await;
|
|
|
|
|
|
|
|
|
|
// (task_id, worker_result)
|
|
|
|
|
let worker = {
|
|
|
|
|
cfg_if!{
|
|
|
|
|
if #[cfg(feature="progress")] {
|
|
|
|
|
let worker = do_work(process.as_ref(), &filename, progress.clone());
|
|
|
|
|
let task = progress.add_task(format!("{:?}", filename.as_ref()));
|
|
|
|
|
future::join(task, worker).await
|
|
|
|
|
} else {
|
|
|
|
|
(Option::<!>::None, do_work(process.as_ref(), &filename, ()).await)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
match worker.1 {
|
|
|
|
|
Ok(strings) => tx.send((filename, strings, i)).await.map_err(|_| "Child panic").unwrap(),
|
|
|
|
|
Err(error) => {
|
|
|
|
|
//eprintln!("[!] {:?}: {}", filename.as_ref(), error)
|
|
|
|
|
let _ = progress.eprintln(format!("[!] ({}) {:?}: {}", i, filename.as_ref(), error)).await.or_else(|e| {eprintln!("\n{}",e); Err(e)});
|
|
|
|
|
#[cfg(not(feature="progress"))] eprintln!("[!] {:?}: {}", filename.as_ref(), error);
|
|
|
|
|
#[cfg(feature="progress")] let _ = progress.eprintln(format!("[!] ({}) {:?}: {}", i, filename.as_ref(), error)).await.or_else(|e| {eprintln!("\n{}",e); Err(e)});
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
worker.0.ok().into()
|
|
|
|
|
cfg_if!{
|
|
|
|
|
if #[cfg(feature="progress")] {
|
|
|
|
|
worker.0.ok().into()
|
|
|
|
|
} else {
|
|
|
|
|
std::marker::PhantomData::<!>
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
if let Some(Ok(id)) = task_id.await {
|
|
|
|
|
#[cfg(feature="progress")]
|
|
|
|
|
if let Some(Ok(id)) = _task_id.await {
|
|
|
|
|
let mut builder = progress.builder();
|
|
|
|
|
builder.bump_min(1);
|
|
|
|
|
builder.remove_task(id);
|
|
|
|
@ -135,15 +183,16 @@ where I: IntoIterator<Item=T>,
|
|
|
|
|
})).await
|
|
|
|
|
.into_iter()
|
|
|
|
|
.filter_map(|x| x.err());
|
|
|
|
|
|
|
|
|
|
progress.shutdown().await?;
|
|
|
|
|
|
|
|
|
|
#[cfg(feature="progress")] progress.shutdown().await?;
|
|
|
|
|
for failed in results
|
|
|
|
|
{
|
|
|
|
|
progress.eprintln(format!("[e] Child panic {:?}", failed)).await?.await?;
|
|
|
|
|
#[cfg(feature="progress")] progress.eprintln(format!("[e] Child panic {:?}", failed)).await?.await?;
|
|
|
|
|
#[cfg(not(feature="progress"))] eprintln!("[e] Child panic {:?}", failed);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
drop(tx);
|
|
|
|
|
display.await?;
|
|
|
|
|
prog_handle.await.expect("Child panic")?;
|
|
|
|
|
#[cfg(feature="progress")] prog_handle.await.expect("Child panic")?;
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|