🎉 init

This commit is contained in:
JMARyA 2025-01-28 16:42:02 +01:00
commit bc6e30fe0c
Signed by: jmarya
GPG key ID: 901B2ADDF27C2263
6 changed files with 609 additions and 0 deletions

40
src/args.rs Normal file
View file

@ -0,0 +1,40 @@
use clap::{arg, command};
pub fn get_args() -> clap::ArgMatches {
command!()
.about("snapshot utility")
.subcommand(
command!("ls")
.about("List all snapshots")
.arg(
arg!(-d --depth <DEPTH> "How deep to search for cephfs snapshots")
.default_value("5"),
)
.arg(
arg!(<START_DIR> "Starting directory to search")
.default_value(".")
.required(false),
),
)
.subcommand(
command!("create")
.about("Create a snapshot")
.arg(arg!(-n --name <NAME> "The name of the snapshot"))
.arg(
arg!(<DIR> "The directory to snapshot")
.default_value(".")
.required(false),
),
)
.subcommand(
command!("remove")
.about("Remove a snapshot")
.arg(arg!(<NAME> "The name of the snapshot").required(true))
.arg(
arg!(<DIR> "The directory containing the snapshot")
.default_value(".")
.required(false),
),
)
.get_matches()
}

124
src/main.rs Normal file
View file

@ -0,0 +1,124 @@
use args::get_args;
mod args;
pub fn cephfs_snapshot(dir: &str, name: &str) {
std::fs::create_dir(std::path::Path::new(dir).join(".snap").join(name)).unwrap();
}
pub fn cephfs_snapshot_remove(dir: &str, name: &str) {
std::fs::remove_dir(std::path::Path::new(dir).join(".snap").join(name)).unwrap();
}
pub fn cephfs_find_snap(dir: &str, depth: u16) -> Vec<String> {
let mut result = Vec::new();
let start_path = std::path::Path::new(dir);
// Call the recursive helper function
find_snap_recursive(start_path, depth, 0, &mut result);
result
}
fn find_snap_recursive(
dir: &std::path::Path,
max_depth: u16,
current_depth: u16,
result: &mut Vec<String>,
) {
// Stop recursion if we've reached the maximum depth
if current_depth >= max_depth {
return;
}
let snap_dir = dir.join(".snap");
if std::fs::read_dir(&snap_dir)
.unwrap()
.filter(|x| {
!x.as_ref()
.unwrap()
.file_name()
.to_str()
.unwrap()
.starts_with("_")
})
.count()
!= 0
{
result.push(dir.display().to_string());
}
// Read the directory content
if let Ok(entries) = std::fs::read_dir(dir) {
for entry in entries.filter_map(Result::ok) {
let path = entry.path();
// If the entry is a directory, check if it contains a ".snap" directory
if path.is_dir() {
// Recurse into the directory
find_snap_recursive(&path, max_depth, current_depth + 1, result);
}
}
}
}
pub fn cephfs_snap_show(dir: &str) -> std::io::Result<()> {
// Create the path to the ".snap" directory
let snap_dir = format!("{}/.snap", dir);
let snap_path = std::path::Path::new(&snap_dir);
// Check if the .snap directory exists
if !snap_path.exists() {
return Ok(());
}
println!("Snapshots for {dir}:");
// List the contents of the .snap directory
match std::fs::read_dir(snap_path) {
Ok(entries) => {
for entry in entries {
match entry {
Ok(entry) => {
let entry_name = entry.file_name();
println!("- {}", entry_name.to_string_lossy());
}
Err(_) => eprintln!("Error reading entry in .snap directory."),
}
}
}
Err(e) => eprintln!("Error reading .snap directory: {}", e),
}
Ok(())
}
fn main() {
let args = get_args();
match args.subcommand() {
Some(("ls", ls_args)) => {
let depth: &String = ls_args.get_one("depth").unwrap();
let start_dir: &String = ls_args.get_one("START_DIR").unwrap();
let snap_dirs = cephfs_find_snap(&start_dir, depth.parse().unwrap());
snap_dirs.into_iter().for_each(|x| {
cephfs_snap_show(&x).unwrap();
});
}
Some(("create", c_args)) => {
let name: Option<String> = c_args.get_one("NAME").cloned();
let dir: &String = c_args.get_one("DIR").unwrap();
let name = name.unwrap_or_else(|| {
let now = chrono::Utc::now();
now.format("SNAP_%Y_%m_%d-%H_%M").to_string()
});
cephfs_snapshot(&dir, &name);
}
Some(("remove", rm_args)) => {
let name: &String = rm_args.get_one("NAME").unwrap();
let dir: &String = rm_args.get_one("DIR").unwrap();
cephfs_snapshot_remove(&dir, &name);
}
_ => {}
}
}