add cg ls, prepare for rc subcommands
This commit is contained in:
@@ -1,9 +1,38 @@
|
||||
use eyre::Result;
|
||||
use std::fs::Metadata;
|
||||
use std::path::PathBuf;
|
||||
use tokio::fs::read_dir;
|
||||
use std::path::{Path, PathBuf};
|
||||
use tokio::fs;
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
#[error("{0}: read_dir: {1}")]
|
||||
ReadDir(PathBuf, std::io::Error),
|
||||
#[error("{0}: read: {1}")]
|
||||
Read(PathBuf, std::io::Error),
|
||||
#[error("{0}: stat: {1}")]
|
||||
Stat(PathBuf, std::io::Error),
|
||||
#[error("{0}: write: {1}")]
|
||||
Write(PathBuf, std::io::Error),
|
||||
#[error("{0}: {1}")]
|
||||
Other(PathBuf, String),
|
||||
}
|
||||
|
||||
macro_rules! wrap_path {
|
||||
($fn:ident $( ( $( $pname:ident : $ptype:ty ),* ) )? -> $result:ty, $err:ident) => {
|
||||
pub async fn $fn(path: impl AsRef<Path>$($(, $pname: $ptype)*)?) -> Result<$result> {
|
||||
let path = path.as_ref();
|
||||
fs::$fn(path $($(, $pname)*)?).await.map_err(|e| Error::$err(path.into(), e))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
wrap_path!(read_dir -> fs::ReadDir, ReadDir);
|
||||
wrap_path!(read -> Vec<u8>, Read);
|
||||
wrap_path!(read_to_string -> String, Read);
|
||||
wrap_path!(write(content: &[u8]) -> (), Write);
|
||||
|
||||
pub fn spawn_walk_dir(
|
||||
dir: impl Into<PathBuf> + Send + 'static,
|
||||
) -> mpsc::Receiver<Result<(PathBuf, Metadata)>> {
|
||||
@@ -24,7 +53,7 @@ pub async fn walk_dir(dir: impl Into<PathBuf>, tx: mpsc::Sender<Result<(PathBuf,
|
||||
let entry = match rd.next_entry().await {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
if tx.send(Err(e.into())).await.is_err() {
|
||||
if tx.send(Err(Error::ReadDir(dir.clone(), e))).await.is_err() {
|
||||
return;
|
||||
}
|
||||
todo.pop_front(); // skip dir on error
|
||||
|
||||
Reference in New Issue
Block a user