use { clap::ArgMatches, hpk_cli::cli, hpk::{Creator, Dependency, Message, Specs, Version}, ron::ser::{to_writer_pretty, PrettyConfig}, std::{ env, error::Error, ffi::OsStr, fs::File, io::{self, BufWriter}, path::PathBuf, sync::mpsc, }, }; fn main() -> Result<(), Box> { let matches = cli().get_matches(); match matches.subcommand() { Some(("create", matches)) => create(matches)?, Some(("init", matches)) => { let specsfile = init(matches)?; println!("Created specsfile {}", specsfile.display()); } Some(("search", matches)) => search(matches)?, Some(("install", matches)) => install(matches)?, Some(("remove", matches)) => remove(matches)?, Some(("upgrade", _)) => upgrade()?, _ => {} } Ok(()) } fn create(matches: &ArgMatches) -> Result<(), Box> { let dir = PathBuf::from(matches.get_one::("directory").unwrap().to_string()); let outdir = if let Some(d) = matches.get_one::("output") { PathBuf::from(&d.to_string()) } else { env::current_dir()? }; let mut specs = if let Some(s) = matches.get_one::("specs") { let path = PathBuf::from(s.to_string()); let fd = File::open(path)?; ron::de::from_reader(fd)? } else { Specs::default() }; if let Some(n) = matches.get_one::("name") { specs.name = n.to_string(); } if let Some(v) = matches.get_one::("package-version") { specs.version = v.to_string().parse::()?; } if let Some(r) = matches.get_one::("release") { specs.release = *r; } if let Some(deps) = matches.get_many::("dependencies") { for d in deps { let d = Dependency { name: d.to_string(), version: (None, None), }; specs.dependencies.push(d); } } let creator = Creator::new(&dir, specs)?; let (sender, receiver) = mpsc::channel(); creator.create(&outdir, sender)?; for msg in receiver.iter() { match msg { Message::MemberAdded(_s) => {} Message::Success(s) => println!("{s}"), Message::Failure(s) => { eprint!("{s}"); return Err(io::Error::new(io::ErrorKind::Other, s).into()); } } } Ok(()) } fn init(matches: &ArgMatches) -> Result> { let specsfile = PathBuf::from("package.specs"); let cfg = PrettyConfig::new().struct_names(true); let buf = File::create(&specsfile)?; let writer = BufWriter::new(buf); let specs = create_specs(matches)?; to_writer_pretty(writer, &specs, cfg)?; Ok(specsfile) } fn search(_matches: &ArgMatches) -> Result<(), Box> { unimplemented!(); } fn install(_matches: &ArgMatches) -> Result<(), Box> { unimplemented!(); } fn remove(_matches: &ArgMatches) -> Result<(), Box> { unimplemented!(); } fn upgrade() -> Result<(), Box> { unimplemented!(); } #[allow(clippy::cast_possible_truncation)] pub fn create_specs(matches: &ArgMatches) -> Result> { let mut specs = Specs::default(); let mut name: Option = None; let mut version: Option = None; let cwd = env::current_dir()?; if let Some(dir) = cwd.file_name().and_then(OsStr::to_str) { if let Some((n, v)) = dir.split_once('-') { name = Some(n.to_string()); if let Ok(v) = v.parse() { version = Some(v); } } } if let Some(name) = matches.get_one::("name") { specs.name = name.to_string(); } else if let Some(n) = name { specs.name = n; } if let Some(version) = matches.get_one::("package-version") { specs.version = version.parse()?; } else if let Some(v) = version { specs.version = v; } if let Some(release) = matches.get_one::("release") { specs.release = *release as u8; } if let Some(deps) = matches.get_many::("dependencies") { let deps = deps .map(|d| Dependency { name: d.to_string(), version: (None, None), }) .collect::>(); specs.dependencies = deps; } Ok(specs) }