parallel: bare bones i guess

master
Avril 4 years ago
parent 7d384f96c9
commit 30a380e7ec
Signed by: flanchan
GPG Key ID: 284488987C31F630

367
Cargo.lock generated

@ -1,11 +1,66 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "addr2line"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b6a2d3371669ab3ca9797670853d61402b03d0b4b9ebf33d677dfa720203072"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
[[package]]
name = "aho-corasick"
version = "0.7.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86"
dependencies = [
"memchr",
]
[[package]]
name = "arc-swap"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d25d88fd6b8041580a654f9d0c581a047baee2b3efee13275f2fc392fc75034"
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi 0.3.9",
]
[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "backtrace"
version = "0.3.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec1931848a574faa8f7c71a12ea00453ff5effbb5f51afe7f77d7a48cace6ac1"
dependencies = [
"addr2line",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]]
name = "bitflags"
version = "1.2.1"
@ -24,6 +79,42 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "color-eyre"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2a5123db5af8349c41c43ed0e5dca1cd56c911ea0c4ce6e6ff30f159fa5d27e"
dependencies = [
"backtrace",
"eyre",
"indenter",
"once_cell",
"owo-colors",
]
[[package]]
name = "env_logger"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
dependencies = [
"atty",
"humantime",
"log",
"regex",
"termcolor",
]
[[package]]
name = "eyre"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4c5cb4dc433c59f09df4b4450f649cbfed61e8a3505abe32e4154066439157e"
dependencies = [
"indenter",
"once_cell",
]
[[package]]
name = "fnv"
version = "1.0.7"
@ -46,11 +137,106 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
[[package]]
name = "futures"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d8e3078b7b2a8a671cb7a3d17b4760e4181ea243227776ba83fd043b4ca034e"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a4d35f7401e948629c9c3d6638fb9bf94e0b2121e96c3b428cc4e631f3eb74"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
name = "futures-core"
version = "0.3.5"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59f5fff90fd5d971f936ad674802482ba441b6f09ba5e15fd8b39145582ca399"
checksum = "d674eaa0056896d5ada519900dbf97ead2e46a7b6621e8160d79e2f2e1e2784b"
[[package]]
name = "futures-executor"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc709ca1da6f66143b8c9bec8e6260181869893714e9b5a490b169b0414144ab"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fc94b64bb39543b4e432f1790b6bf18e3ee3b74653c5449f63310e9a74b123c"
[[package]]
name = "futures-macro"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f57ed14da4603b2554682e9f2ff3c65d7567b53188db96cb71538217fc64581b"
dependencies = [
"proc-macro-hack",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "futures-sink"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d8764258ed64ebc5d9ed185cf86a95db5cac810269c5d20ececb32e0088abbd"
[[package]]
name = "futures-task"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dd26820a9f3637f1302da8bceba3ff33adbe53464b54ca24d4e2d4f1db30f94"
dependencies = [
"once_cell",
]
[[package]]
name = "futures-util"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a894a0acddba51a2d49a6f4263b1e64b8c579ece8af50fa86503d52cd1eea34"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project",
"pin-utils",
"proc-macro-hack",
"proc-macro-nested",
"slab",
]
[[package]]
name = "gimli"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724"
[[package]]
name = "hermit-abi"
@ -61,6 +247,21 @@ dependencies = [
"libc",
]
[[package]]
name = "humantime"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
dependencies = [
"quick-error",
]
[[package]]
name = "indenter"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0bd112d44d9d870a6819eb505d04dd92b5e4d94bb8c304924a0872ae7016fb5"
[[package]]
name = "iovec"
version = "0.1.4"
@ -107,6 +308,16 @@ version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
[[package]]
name = "miniz_oxide"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c60c0dfe32c10b43a144bad8fc83538c52f58302c92300ea7ec7bf7b38d5a7b9"
dependencies = [
"adler",
"autocfg",
]
[[package]]
name = "mio"
version = "0.6.22"
@ -192,12 +403,78 @@ dependencies = [
"libc",
]
[[package]]
name = "object"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5"
[[package]]
name = "once_cell"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad"
[[package]]
name = "owo-colors"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a1250cdd103eef6bd542b5ae82989f931fc00a41a27f60377338241594410f3"
[[package]]
name = "pin-project"
version = "0.4.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13fbdfd6bdee3dc9be46452f86af4a4072975899cf8592466668620bebfbcc17"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "0.4.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c82fb1329f632c3552cf352d14427d57a511b1cf41db93b3a7d77906a82dcc8e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "pin-project-lite"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e555d9e657502182ac97b539fb3dae8b79cda19e3e4f8ffb5e8de4f18df93c95"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pretty_env_logger"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d"
dependencies = [
"env_logger",
"log",
]
[[package]]
name = "proc-macro-hack"
version = "0.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99c605b9a0adc77b7211c6b1f722dcb613d68d66859a44f3d485a6da332b0598"
[[package]]
name = "proc-macro-nested"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a"
[[package]]
name = "proc-macro2"
version = "1.0.24"
@ -207,6 +484,12 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "quick-error"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
[[package]]
name = "quote"
version = "1.0.7"
@ -222,11 +505,64 @@ version = "0.1.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
[[package]]
name = "regex"
version = "1.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
"thread_local",
]
[[package]]
name = "regex-syntax"
version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8"
[[package]]
name = "rustc-demangle"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
[[package]]
name = "rustc_version"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
dependencies = [
"semver",
]
[[package]]
name = "semver"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
dependencies = [
"semver-parser",
]
[[package]]
name = "semver-parser"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "sever"
version = "0.1.0"
dependencies = [
"cfg-if",
"color-eyre",
"futures",
"log",
"pretty_env_logger",
"rustc_version",
"tokio",
]
@ -269,6 +605,24 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "termcolor"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
dependencies = [
"winapi-util",
]
[[package]]
name = "thread_local"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
dependencies = [
"lazy_static",
]
[[package]]
name = "tokio"
version = "0.2.22"
@ -338,6 +692,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"

@ -8,7 +8,9 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
parallel = ["tokio"]
default = ["parallel"]
parallel = ["tokio", "futures"]
threads = ["parallel", "tokio/rt-threaded"]
# use PRETTY_ENV_LOGGER I guess
@ -18,3 +20,10 @@ threads = ["parallel", "tokio/rt-threaded"]
[dependencies]
cfg-if = "0.1.10"
tokio = {version = "0.2", features = ["full"], optional = true}
log = "0.4.11"
pretty_env_logger = "0.4.0"
color-eyre = {version = "0.5.6", default-features=false}
futures = {version = "0.3.5", optional = true}
[build-dependencies]
rustc_version = "0.2"

@ -0,0 +1,24 @@
extern crate rustc_version;
use rustc_version::{version, version_meta, Channel};
fn main() {
// Assert we haven't travelled back in time
assert!(version().unwrap().major >= 1);
// Set cfg flags depending on release channel
match version_meta().unwrap().channel {
Channel::Stable => {
println!("cargo:rustc-cfg=stable");
}
Channel::Beta => {
println!("cargo:rustc-cfg=beta");
}
Channel::Nightly => {
println!("cargo:rustc-cfg=nightly");
}
Channel::Dev => {
println!("cargo:rustc-cfg=dev");
}
}
}

@ -0,0 +1,94 @@
use super::*;
use std::{
error, fmt,
io,
path::{PathBuf, Path,}
};
#[derive(Debug)]
#[non_exhaustive]
pub enum ErrorKind
{
Stat(io::Error),
Open(io::Error),
Copy(io::Error),
}
impl ErrorKind
{
pub fn is_skippable(&self) -> bool
{
match self {
Self::Stat(_) => true,
_ => false,
}
}
pub fn suggestion(&self) -> &'static str
{
//TODO: Maybe?
match self {
_ => "Are you sure file exists, and you have write privilages here?"
}
}
}
#[derive(Debug)]
pub struct Error {
kind: ErrorKind,
path: PathBuf,
}
impl<P: AsRef<Path>> From<(ErrorKind, P)> for Error
{
fn from((kind, p): (ErrorKind, P)) -> Self
{
Self::new(kind, p.as_ref())
}
}
impl Error
{
pub fn new(kind: ErrorKind, path: impl Into<PathBuf>) -> Self
{
Self {
kind,
path: path.into()
}
}
pub fn path(&self) -> &Path
{
self.path.as_ref()
}
pub fn kind(&self) -> &ErrorKind
{
&self.kind
}
}
impl std::error::Error for Error
{
fn source(&self) -> Option<&(dyn error::Error + 'static)>
{
Some(match &self.kind {
ErrorKind::Stat(io) => io,
ErrorKind::Open(io) => io,
ErrorKind::Copy(io) => io,
// _ => return None,
})
}
}
impl std::fmt::Display for Error
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
match &self.kind {
ErrorKind::Stat(_) => write!(f, "Failed to stat file {:?}", self.path),
ErrorKind::Open(_) => write!(f, "Failed to open file {:?}", self.path),
ErrorKind::Copy(_) => write!(f, "Failed to create copy of file {:?}", self.path),
}
}
}

@ -0,0 +1,60 @@
#![allow(unused_macros)]
/// Run something as async or or depending on feature flag `parallel`
macro_rules! sync
{
(if {$($if:tt)*} else {$($else:tt)*}) => {
cfg_if::cfg_if! {
if #[cfg(feature="parallel")] {
$($if)*
} else {
$($else)*
}
}
};
(if {$($if:tt)*}) => {
cfg_if::cfg_if! {
if #[cfg(feature="parallel")] {
$($if)*
}
}
};
(else {$($if:tt)*}) => {
cfg_if::cfg_if! {
if #[cfg(not(eature="parallel"))] {
$($if)*
}
}
};
}
#[macro_export] macro_rules! reyre {
(m {$($body:tt)*} $lit:literal $($tt:tt)*) => {
{
let cls = move || {
$($body)*
};
$crate::reyre!{
cls(), $lit $($tt)*
}
}
};
({$($body:tt)*} $lit:literal $($tt:tt)*) => {
{
let cls = || {
$($body)*
};
$crate::reyre!{
cls(), $lit $($tt)*
}
}
};
($expr:expr, $lit:literal $($tt:tt)*) => {
{
use ::color_eyre::eyre::WrapErr;
$expr.wrap_err_with(|| ::color_eyre::eyre::eyre!($lit $($tt)*))
}
}
}

@ -1,42 +1,39 @@
#![allow(dead_code)]
/// Run something as async or or depending on feature flag `parallel`
macro_rules! sync
{
(if {$($if:tt)*} else {$($else:tt)*}) => {
cfg_if::cfg_if! {
if #[cfg(feature="parallel")] {
$($if)*
} else {
$($else)*
}
}
};
#[macro_use] extern crate log;
#[macro_use] mod macros;
(if {$($if:tt)*}) => {
cfg_if::cfg_if! {
if #[cfg(feature="parallel")] {
$($if)*
}
}
use color_eyre::{
eyre::{self, eyre, WrapErr},
Help, SectionExt,
};
(else {$($if:tt)*}) => {
cfg_if::cfg_if! {
if #[cfg(not(eature="parallel"))] {
$($if)*
}
}
};
fn init() -> eyre::Result<()>
{
color_eyre::install()?;
pretty_env_logger::init(); //TODO: Change to builder
trace!("Initialised");
Ok(())
}
mod error;
#[cfg(feature="parallel")]
mod parallel;
#[cfg(feature="parallel")]
#[cfg_attr(feature="parallel", tokio::main)]
async fn main() {
println!("Hello world!")
async fn main() -> eyre::Result<()> {
reyre!(init(), "Failed to initialise")?;
reyre!(parallel::main(std::env::args().skip(1)).await, "Jobs failed")
}
#[cfg(not(feature="parallel"))]
mod serial;
#[cfg(not(feature="parallel"))]
fn main() {
println!("Hello world! sync")
fn main() -> eyre::Result<()> {
reyre!(init(), "Failed to initialise")?;
todo!("Sync unimplemented")
}

@ -0,0 +1,132 @@
//! Async operations
use super::*;
use std::{
num::NonZeroUsize,
convert::{TryFrom, TryInto,},
path::Path,
sync::Arc,
};
use futures::{
future::{
OptionFuture,
FutureExt,
join_all,
},
};
use tokio::{
sync::{
Semaphore,
},
fs::{
OpenOptions,
File,
self,
},
};
use error::{Error, ErrorKind};
const MAX_WORKERS: Option<NonZeroUsize> = Some(unsafe {NonZeroUsize::new_unchecked(4096)});
fn gensem() -> Option<Arc<Semaphore>>
{
trace!("Limiting concurrency to {:?}", MAX_WORKERS);
match MAX_WORKERS {
Some(nz) => Some(Arc::new(Semaphore::new(nz.into()))),
None => None,
}
}
fn tpath() -> String
{
todo!();
".test.tmp".to_owned()
}
async fn unlink(path: &Path) -> Result<(), Error>
{
let tmp = path.parent().unwrap().join(tpath());
fs::copy(path, tmp).await.map_err(|e| Error::new(ErrorKind::Copy(e), path.to_owned()))?;
todo!();
Ok(())
}
async fn work<P: AsRef<Path>>(apath: P, sem: Option<Arc<Semaphore>>) -> Result<(P, bool), Error>
{
let path = apath.as_ref();
let _lock = OptionFuture::from(sem.map(Semaphore::acquire_owned)).await;
let file = OpenOptions::new()
.read(true)
.open(path).await
.map_err(|e| (ErrorKind::Open(e), path))?;
let meta = match file.metadata().await {
Ok(meta) => meta,
Err(err) => {
debug!("Failed to stat file: {}", err);
warn!("Failed to stat {:?}, skipping", path);
return Err((ErrorKind::Stat(err), path).into());
},
};
use std::os::unix::fs::MetadataExt;
let nlink = meta.nlink();
trace!("<{:?}> Links: {}", path, nlink);
if nlink > 1 {
//todo work i guess fuck it
unlink(path).await?;
Ok((apath, true))
} else {
Ok((apath, false))
}
}
pub async fn main<I: IntoIterator<Item=String>>(list: I) -> eyre::Result<()>
{
let sem = gensem();
let mut failures = 0usize;
for (i, res) in (0usize..).zip(join_all(list.into_iter().map(|file| tokio::spawn(work(file, sem.clone()))))
.map(|x| {trace!("--- {} Finished ---", x.len()); x}).await)
{
//trace!("Done on {:?}", res);
match res {
Ok(Ok((path, true))) => info!("<{:?}> OK (processed)", path),
Ok(Ok((path, false))) => info!("<{:?}> OK (skipped)", path),
Err(e) => {
trace!("child {} cancelled by {}", i, if e.is_panic(){"panic"} else {"cancel"});
if e.is_panic() {
return Err(eyre!("Child {} panic", i))
.with_error(move || e)
.with_warning(|| "This suggests a bug in the program");
} else {
warn!("Child {} cancelled", i);
failures += 1;
}
},
Ok(Err(kind)) if !kind.kind().is_skippable() => { //
let fuck = format!("{:?}", kind.path());
let sug = kind.kind().suggestion();
let err = Err::<std::convert::Infallible, _>(kind)
.wrap_err_with(|| eyre!("<{}> Failed", fuck))
.with_section(move || fuck.header("Path was"))
.with_suggestion(|| sug)
.unwrap_err();
error!("{}", err);
debug!("Error: {:?}", err);
failures += 1;
},
Ok(Err(k)) => {
trace!("<{:?}> Failed (skipped)", k.path());
failures+=1;
},
}
}
if failures > 0 {
return Err(eyre!("Some tasks failed to complete successfullly"))
.with_section(|| failures.to_string().header("Number of failed tasks"))
.with_suggestion(|| "Run with `RUST_LOG=debug` or `RUST_LOG=trace` for verbose error reporting");
}
Ok(())
}

@ -0,0 +1,3 @@
//! Sync operations
use super::*;
Loading…
Cancel
Save