use case_clause::case;
use clap::{Arg, ArgMatches, Command as ClapCommand};
use quick_xml::{
Reader, Writer,
events::{BytesEnd, BytesStart, BytesText, Event},
};
use std::{
fs::{read_to_string, write},
io::{Cursor, ErrorKind},
};
use toml_edit::{DocumentMut, value};
pub fn env_to_matches(env_args: Vec<String>) -> ArgMatches {
ClapCommand::new("ros_add")
.version("0.1.0")
.author("GueLaKais <koroyeldiores@gmail.com>")
.about("adds dependencies to ros rust packages and package.xml")
.arg(
Arg::new("dependency")
.required(true)
.help("Name of the dependency to add")
.index(1),
)
.get_matches_from(
case!(
env_args.iter().any(|arg| arg == "ros-add") => env_args.iter().take(1).chain(env_args.iter().skip(2)).cloned().collect::<Vec<String>>(),
true => env_args
)
)
}
pub fn add_dependency_to_package_xml(path: String, dependency_name: &str) -> Result<(), ErrorKind> {
let mut reader = read_to_string(path.as_str())
.map(|content| Reader::from_str(Box::leak(content.into_boxed_str())))
.map_err(|_| ErrorKind::NotFound)?;
reader.config_mut().trim_text(true);
let mut writer = Writer::new_with_indent(Cursor::new(Vec::new()), b' ', 2);
let mut buf = Vec::new();
let mut found_package_end = false;
loop {
match reader.read_event_into(&mut buf) {
Ok(Event::End(ref e)) if e.name().as_ref() == b"package" => {
let start = BytesStart::new("depend");
writer
.write_event(Event::Start(start))
.map_err(|_| ErrorKind::WriteZero)?;
writer
.write_event(Event::Text(BytesText::new(dependency_name)))
.map_err(|_| ErrorKind::WriteZero)?;
writer
.write_event(Event::End(BytesEnd::new("depend")))
.map_err(|_| ErrorKind::WriteZero)?;
writer
.write_event(Event::End(e.clone()))
.map_err(|_| ErrorKind::WriteZero)?;
found_package_end = true;
}
Ok(Event::Eof) => break,
Ok(e) => writer.write_event(e).map_err(|_| ErrorKind::WriteZero)?,
Err(_) => return Err(ErrorKind::Deadlock),
}
buf.clear();
}
if !found_package_end {
return Err(ErrorKind::InvalidData);
}
write(path.as_str(), writer.into_inner().into_inner()).map_err(|e| e.kind())?;
println!("Successfully added dependency '{dependency_name}' to {path}");
Ok(())
}
pub fn add_dependency_to_cargo_toml(path: String, dependency_name: &str) -> Result<(), ErrorKind> {
let mut doc = read_to_string(path.as_str())
.map_err(|e| e.kind())?
.parse::<DocumentMut>()
.expect("invalid TOML");
println!("Dependency '{dependency_name}' already exists in Cargo.toml",);
if doc["dependencies"].get(dependency_name).is_some() {
return Ok(());
}
doc["dependencies"][dependency_name] = value("*");
write(path.as_str(), doc.to_string()).map_err(|e| e.kind())?;
Ok(())
}