use std::path::PathBuf;
use clap::{Args, Parser, Subcommand};
use shellock_homes::{Backend, ConfigWithBackend};
use shellock_homes::{Config, FileSystemBackend};
use log::debug;
use log::error;
use log::info;
#[derive(Debug, Parser)]
#[clap(name = "shellock-homes")]
#[clap(version)]
#[clap(about = "Manage dotfiles like a pro")]
struct Cli {
#[clap(subcommand)]
command: Commands,
}
#[derive(Debug, Subcommand)]
enum Commands {
Monitor,
Init(Init),
List,
#[clap(arg_required_else_help = true)]
Sync(Sync),
#[clap(arg_required_else_help = true)]
Add {
#[clap(required = true)]
path: Vec<PathBuf>,
},
#[clap(arg_required_else_help = true)]
Remove {
#[clap(required = true)]
path: Vec<PathBuf>,
},
}
#[derive(Args, Debug)]
struct Init {
#[clap(long, possible_values = ["git", "file-system"])]
backend: String,
#[clap(long)]
remote: Option<String>,
#[clap(long)]
branch: Option<String>,
#[clap(long)]
dir_name: Option<String>,
#[clap(long)]
auto_commit: bool,
#[clap(long)]
auto_push: bool,
}
#[derive(Args, Debug)]
struct Sync {
#[clap(long, conflicts_with = "to-home")]
from_home: bool,
#[clap(long)]
to_home: bool,
}
fn main() {
env_logger::init();
let args = Cli::parse();
match args.command {
Commands::Monitor => {
info!("Starting monitor.")
}
Commands::Init(init) => {
let config: Box<dyn ConfigWithBackend> = match init.backend.as_str() {
"git" => {
error!("Git backend is not yet implemented");
return;
}
"file-system" => Box::new(Config::<FileSystemBackend>::default()),
_ => {
error!("Unknown backend: {}", init.backend);
return;
}
};
match config.init() {
Err(e) => {
error!("Could not init: {}", e);
return;
}
_ => {
debug!("config initialized");
}
};
}
Commands::Sync(direction) => {
let config = get_config();
info!("direction: {:?}", direction);
let d = if direction.from_home {
shellock_homes::Direction::FromHome
} else {
shellock_homes::Direction::FromRepo
};
match config
.backend
.sync(d, config.sync.files, config.sync.ignore)
{
Err(e) => error!("failed to sync: {e}"),
_ => {}
}
}
Commands::Add { path } => match get_config().add_path(path) {
Err(e) => error!("failed to add path: {e}"),
_ => {}
},
Commands::Remove { path } => match get_config().remove_path(path) {
Err(e) => error!("failed to remove path: {e}"),
_ => {}
},
Commands::List => {
for entry in get_config().backend.list() {
println!("{}", entry.into_os_string().into_string().unwrap());
}
}
}
}
fn get_config() -> Config<FileSystemBackend> {
let mut config = Config::<FileSystemBackend>::default();
match config.load() {
Err(e) => {
panic!("could not load config file: {}", e);
}
_ => {}
}
config
}