use crate::config::Config;
use crate::make_tokio_runtime;
use crate::params::config::ConfigParams;
use anyhow::Result;
use futures::AsyncWriteExt;
use tokio::io::AsyncReadExt as TokioAsyncReadExt;
use tokio::io::AsyncWriteExt as TokioAsyncWriteExt;
#[derive(Debug, clap::Parser)]
#[command(
name = "tee",
about = "Read from standard input and write to destination and stdout",
disable_version_flag = true
)]
pub struct TeeCmd {
#[command(flatten)]
pub config_params: ConfigParams,
#[arg()]
pub destination: String,
#[arg(short, long, help = "Append to the given FILEs, do not overwrite")]
pub append: bool,
}
impl TeeCmd {
pub fn run(self) -> Result<()> {
make_tokio_runtime(1).block_on(self.do_run())
}
async fn do_run(self) -> Result<()> {
let cfg = Config::load(&self.config_params.config)?;
let (dst_op, dst_path) = cfg.parse_location(&self.destination)?;
let mut writer = if self.append {
dst_op
.writer_with(&dst_path)
.append(true)
.await?
.into_futures_async_write()
} else {
dst_op.writer(&dst_path).await?.into_futures_async_write()
};
let mut stdout = tokio::io::stdout();
let mut buf = vec![0; 8 * 1024 * 1024];
let mut stdin = tokio::io::stdin();
loop {
let n = stdin.read(&mut buf).await?;
if n == 0 {
break;
}
writer.write_all(&buf[..n]).await?;
stdout.write_all(&buf[..n]).await?;
}
writer.close().await?;
stdout.flush().await?;
Ok(())
}
}