use glob::glob; use serde::Serialize; use std::path::Path; use toml; pub fn generate(root: &Path) -> String { let mut bins = vec![]; let root_glob = { let mut p = root.to_owned(); p.push("**"); p.push("*.rs"); p }; let mut exercise_paths: Vec<_> = glob(root_glob.to_str().unwrap()) .unwrap() .collect::>() .expect("Error traversing root"); exercise_paths.sort(); for path in &exercise_paths { let name = path .file_stem() .expect("Malformed exercise path") .to_str() .expect("Invalid UTF8 in exercise path") .to_string(); let target_path = path.strip_prefix(root).unwrap(); bins.push(Bin { name, path: target_path.to_str().unwrap().to_string(), }); } let manifest = Manifest { package: Package { name: "exercises", version: "0.1.0", authors: &["The Rustlings Maintainers"], edition: "2018", publish: false, }, bin: bins, }; format!( "# This Cargo.toml is AUTOGENERATED, you shouldn't need to edit it.\n\ # The `rustling` commands do not rely on this manifest at all, its only purpose\n\ # is to help editors analyze your code.\n\ # To regenerate it, run `cargo generate-manifest`.\n\ {}", toml::ser::to_string_pretty(&manifest).expect("Invalid toml") ) } #[derive(Serialize)] struct Manifest { package: Package, bin: Vec, } #[derive(Serialize)] struct Package { name: &'static str, version: &'static str, edition: &'static str, authors: &'static [&'static str], publish: bool, } #[derive(Serialize)] struct Bin { name: String, path: String, }