Skip to content

Commit 170dadd

Browse files
committed
feat: ✨ add cli
1 parent 35073af commit 170dadd

File tree

4 files changed

+76
-40
lines changed

4 files changed

+76
-40
lines changed

Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
authors = ["koro33 <[email protected]>"]
33
edition = "2021"
44
name = "s-backup"
5-
version = "0.1.0"
5+
version = "0.1.2"
66

77
license = "MIT"
88
publish = false
@@ -13,6 +13,7 @@ repository = "https://github.com/Koro33/s-backup"
1313
anyhow = "1.0.79"
1414
blake3 = { version = "1.5.0", features = ["mmap", "rayon"] }
1515
chrono = { version = "0.4.34" }
16+
clap = { version = "4.5.0", features = ["derive"] }
1617
humansize = { version = "2.1.3", features = ["impl_style"] }
1718
opendal = { version = "0.45.0", features = ["layers-tracing"] }
1819
serde = { version = "1.0.196", features = ["derive"] }
@@ -23,7 +24,6 @@ tokio = { version = "1.36.0", features = [
2324
"rt-multi-thread",
2425
"signal",
2526
] }
26-
tokio-cron-scheduler = "0.10.0"
2727
toml = "0.8.10"
2828
tracing = "0.1.40"
2929
tracing-subscriber = { version = "0.3.18", features = ["env-filter", "fmt"] }

src/lib.rs

+26
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,39 @@ use anyhow::anyhow;
66
use blake3::Hash;
77
use chrono::prelude::*;
88

9+
use clap::{Parser, Subcommand};
910
use std::{
1011
fs::File,
1112
io::{BufReader, Error},
1213
path::Path,
1314
};
1415
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
1516

17+
// Simple program to greet a person
18+
#[derive(Parser, Debug)]
19+
#[command(version, about, long_about = None)]
20+
pub struct Args {
21+
#[command(subcommand)]
22+
pub command: Commands,
23+
}
24+
25+
#[derive(Subcommand, Debug)]
26+
pub enum Commands {
27+
/// Run Backup
28+
Run {
29+
/// config file path
30+
#[arg(short, long, default_value = "./config.toml")]
31+
config: String,
32+
},
33+
34+
/// Test Config
35+
Test {
36+
/// config file path
37+
#[arg(short, long, default_value = "./config.toml")]
38+
config: String,
39+
},
40+
}
41+
1642
#[derive(Debug, Clone)]
1743
pub struct CpsdFileName {
1844
pub prefix: String,

src/main.rs

+41-28
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1-
use anyhow::{anyhow, Result};
2-
use humansize::{FormatSize, DECIMAL};
3-
use opendal::Operator;
41
use s_backup::{
52
calc_hash_mmap_rayon,
63
config::{read_config, Backup},
74
init_tracing,
85
s3::init_s3,
9-
CpsdFileName,
6+
Args, Commands, CpsdFileName,
107
};
118

9+
use anyhow::{anyhow, Result};
10+
use clap::Parser;
11+
use humansize::{FormatSize, DECIMAL};
12+
use opendal::Operator;
1213
use std::{os::linux::fs::MetadataExt, path::Path, process::Stdio};
1314
use tempfile::TempDir;
1415
use tokio::{
@@ -22,28 +23,11 @@ use tokio::{
2223
async fn main() -> Result<()> {
2324
init_tracing();
2425

25-
let default_config_path = if cfg!(debug_assertions) {
26-
"./tests/config.toml"
27-
} else {
28-
"./config.toml"
29-
};
26+
let args = Args::parse();
3027

31-
let config =
32-
read_config(std::env::var("SB_CONFIG_PATH").unwrap_or(default_config_path.to_string()))
33-
.await
34-
.map_err(|e| {
35-
tracing::error!("read config failed: {}", e);
36-
e
37-
})?;
38-
39-
let s3_op = init_s3(&config.s3).await?;
40-
41-
for b in &config.backup {
42-
let b_clone = b.clone();
43-
let s3_op_clone = s3_op.clone();
44-
let _handle = tokio::spawn(async move {
45-
period_backup(&b_clone, &s3_op_clone).await.unwrap();
46-
});
28+
match &args.command {
29+
Commands::Run { config } => run(config).await?,
30+
Commands::Test { config } => test(config).await?,
4731
}
4832

4933
#[cfg(unix)]
@@ -73,13 +57,43 @@ async fn main() -> Result<()> {
7357
Ok(())
7458
}
7559

60+
async fn run(config_path: &str) -> Result<()> {
61+
let config = read_config(config_path).await.map_err(|e| {
62+
tracing::error!("read config failed at `{}`: {}", config_path, e);
63+
e
64+
})?;
65+
66+
let s3_op = init_s3(&config.s3).await?;
67+
68+
for b in &config.backup {
69+
let b_clone = b.clone();
70+
let s3_op_clone = s3_op.clone();
71+
let _handle = tokio::spawn(async move {
72+
period_backup(&b_clone, &s3_op_clone).await.unwrap();
73+
});
74+
}
75+
76+
Ok(())
77+
}
78+
79+
async fn test(config_path: &str) -> Result<()> {
80+
tracing::warn!("test unimplemented");
81+
Ok(())
82+
}
83+
7684
async fn period_backup(b: &Backup, s3_oprator: &Operator) -> Result<()> {
7785
loop {
7886
let _ = backup(b, s3_oprator).await.map_err(|e| {
7987
tracing::error!("backup failed: {}", e);
8088
e
8189
});
8290

91+
let next_run_date = chrono::Utc::now() + chrono::Duration::seconds(b.interval as i64);
92+
tracing::info!(
93+
"The next backup will be run at {}",
94+
next_run_date.to_rfc2822()
95+
);
96+
8397
tokio::time::sleep(std::time::Duration::from_secs(b.interval as u64)).await
8498
}
8599
}
@@ -115,8 +129,7 @@ async fn backup(b: &Backup, s3_oprator: &Operator) -> Result<()> {
115129
.to_string(),
116130
);
117131

118-
cmd.args(args)
119-
.kill_on_drop(true);
132+
cmd.args(args).kill_on_drop(true);
120133

121134
cmd.stdin(Stdio::piped());
122135
cmd.stdout(Stdio::null());
@@ -129,7 +142,6 @@ async fn backup(b: &Backup, s3_oprator: &Operator) -> Result<()> {
129142
tracing::warn!("{}", line);
130143
}
131144
if !child.wait().await?.success() {
132-
tracing::error!("failed to compress");
133145
return Err(anyhow!("failed to compress"));
134146
};
135147

@@ -173,6 +185,7 @@ async fn backup(b: &Backup, s3_oprator: &Operator) -> Result<()> {
173185
.unwrap();
174186

175187
// start upload
188+
tracing::info!("start uploading...",);
176189
match tokio::io::copy(&mut reader, &mut writer).await {
177190
Ok(_) => writer.close().await?,
178191
Err(_e) => {

src/s3.rs

+7-10
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,16 @@ mod tests {
2424

2525
#[tokio::test]
2626
async fn test_init_s3() {
27-
let config = read_config(
28-
std::env::var("SB_CONFIG_PATH").unwrap_or("./tests/config.toml".to_string()),
29-
)
30-
.await
31-
.map_err(|e| {
32-
tracing::error!("read config failed: {}", e);
33-
e
34-
})
35-
.unwrap();
27+
let config = read_config("./tests/config.toml")
28+
.await
29+
.map_err(|e| {
30+
tracing::error!("read config failed: {}", e);
31+
e
32+
})
33+
.unwrap();
3634
let s3_op = init_s3(&config.s3).await.unwrap();
3735

3836
let entries = s3_op.list("/backup/").await.unwrap();
3937
println!("{:#?}", entries);
40-
4138
}
4239
}

0 commit comments

Comments
 (0)