diff options
Diffstat (limited to 'src/dev')
| -rw-r--r-- | src/dev/check.rs | 81 | ||||
| -rw-r--r-- | src/dev/init.rs | 23 | ||||
| -rw-r--r-- | src/dev/update.rs | 53 |
3 files changed, 140 insertions, 17 deletions
diff --git a/src/dev/check.rs b/src/dev/check.rs index 5910a75..bc8e459 100644 --- a/src/dev/check.rs +++ b/src/dev/check.rs @@ -1,16 +1,83 @@ +use anyhow::{bail, Context, Result}; use std::fs; -use anyhow::{Context, Result}; +use crate::{ + info_file::{ExerciseInfo, InfoFile}, + DEVELOPING_OFFIFICAL_RUSTLINGS, +}; -use crate::{info_file::InfoFile, init::cargo_toml}; +pub fn bins_start_end_ind(cargo_toml: &str) -> Result<(usize, usize)> { + let start_ind = cargo_toml + .find("bin = [") + .context("Failed to find the start of the `bin` list (`bin = [`)")? + + 7; + let end_ind = start_ind + + cargo_toml + .get(start_ind..) + .and_then(|slice| slice.as_bytes().iter().position(|c| *c == b']')) + .context("Failed to find the end of the `bin` list (`]`)")?; + + Ok((start_ind, end_ind)) +} + +pub fn append_bins( + buf: &mut Vec<u8>, + exercise_infos: &[ExerciseInfo], + exercise_path_prefix: &[u8], +) { + buf.push(b'\n'); + for exercise_info in exercise_infos { + buf.extend_from_slice(b" { name = \""); + buf.extend_from_slice(exercise_info.name.as_bytes()); + buf.extend_from_slice(b"\", path = \""); + buf.extend_from_slice(exercise_path_prefix); + buf.extend_from_slice(b"exercises/"); + if let Some(dir) = &exercise_info.dir { + buf.extend_from_slice(dir.as_bytes()); + buf.push(b'/'); + } + buf.extend_from_slice(exercise_info.name.as_bytes()); + buf.extend_from_slice(b".rs\" },\n"); + } +} + +fn check_cargo_toml( + exercise_infos: &[ExerciseInfo], + current_cargo_toml: &str, + exercise_path_prefix: &[u8], +) -> Result<()> { + let (bins_start_ind, bins_end_ind) = bins_start_end_ind(current_cargo_toml)?; + + let old_bins = ¤t_cargo_toml.as_bytes()[bins_start_ind..bins_end_ind]; + let mut new_bins = Vec::with_capacity(1 << 13); + append_bins(&mut new_bins, exercise_infos, exercise_path_prefix); + + if old_bins != new_bins { + bail!("`Cargo.toml` is outdated. Run `rustlings dev update` to update it"); + } + + Ok(()) +} + +pub fn check() -> Result<()> { + let info_file = InfoFile::parse()?; -pub fn check(info_file: InfoFile) -> Result<()> { // TODO: Add checks - // TODO: Keep dependencies! - fs::write("Cargo.toml", cargo_toml(&info_file.exercises)) - .context("Failed to update the file `Cargo.toml`")?; - println!("Updated `Cargo.toml`"); + if DEVELOPING_OFFIFICAL_RUSTLINGS { + check_cargo_toml( + &info_file.exercises, + include_str!("../../dev/Cargo.toml"), + b"../", + ) + .context("The file `dev/Cargo.toml` is outdated. Please run `cargo run -- dev update` to update it")?; + } else { + let current_cargo_toml = + fs::read_to_string("Cargo.toml").context("Failed to read the file `Cargo.toml`")?; + check_cargo_toml(&info_file.exercises, ¤t_cargo_toml, b"").context( + "The file `Cargo.toml` is outdated. Please run `rustlings dev update` to update it", + )?; + } println!("\nEverything looks fine!"); diff --git a/src/dev/init.rs b/src/dev/init.rs index 0993522..3ce5055 100644 --- a/src/dev/init.rs +++ b/src/dev/init.rs @@ -1,6 +1,5 @@ -use std::fs::{self, create_dir}; - use anyhow::{Context, Result}; +use std::fs::{self, create_dir}; use crate::CURRENT_FORMAT_VERSION; @@ -19,11 +18,8 @@ pub fn init() -> Result<()> { ) .context("Failed to create the file `rustlings/info.toml`")?; - fs::write( - "rustlings/Cargo.toml", - format!("{CARGO_TOML_COMMENT}{}", crate::init::CARGO_TOML_PACKAGE), - ) - .context("Failed to create the file `rustlings/Cargo.toml`")?; + fs::write("rustlings/Cargo.toml", CARGO_TOML) + .context("Failed to create the file `rustlings/Cargo.toml`")?; fs::write("rustlings/.gitignore", crate::init::GITIGNORE) .context("Failed to create the file `rustlings/.gitignore`")?; @@ -80,10 +76,17 @@ mode = "test" hint = """???""" "#; -const CARGO_TOML_COMMENT: &str = - "# You shouldn't edit this file manually! It is updated by `rustlings dev check` +const CARGO_TOML: &[u8] = + br#"# Don't edit the `bin` list manually! It is updated by `rustlings dev update` +bin = [] -"; +[package] +name = "rustlings" +edition = "2021" +publish = false + +[dependencies] +"#; const README: &str = "# Rustlings 🦀 diff --git a/src/dev/update.rs b/src/dev/update.rs new file mode 100644 index 0000000..981934d --- /dev/null +++ b/src/dev/update.rs @@ -0,0 +1,53 @@ +use std::fs; + +use anyhow::{Context, Result}; + +use crate::{ + info_file::{ExerciseInfo, InfoFile}, + DEVELOPING_OFFIFICAL_RUSTLINGS, +}; + +use super::check::{append_bins, bins_start_end_ind}; + +fn update_cargo_toml( + exercise_infos: &[ExerciseInfo], + current_cargo_toml: &str, + cargo_toml_path: &str, + exercise_path_prefix: &[u8], +) -> Result<()> { + let (bins_start_ind, bins_end_ind) = bins_start_end_ind(current_cargo_toml)?; + + let mut new_cargo_toml = Vec::with_capacity(1 << 13); + new_cargo_toml.extend_from_slice(current_cargo_toml[..bins_start_ind].as_bytes()); + append_bins(&mut new_cargo_toml, exercise_infos, exercise_path_prefix); + new_cargo_toml.extend_from_slice(current_cargo_toml[bins_end_ind..].as_bytes()); + + fs::write(cargo_toml_path, new_cargo_toml).context("Failed to write the `Cargo.toml` file")?; + + Ok(()) +} + +pub fn update() -> Result<()> { + let info_file = InfoFile::parse()?; + + if DEVELOPING_OFFIFICAL_RUSTLINGS { + update_cargo_toml( + &info_file.exercises, + include_str!("../../dev/Cargo.toml"), + "dev/Cargo.toml", + b"../", + ) + .context("Failed to update the file `dev/Cargo.toml`")?; + + println!("Updated `dev/Cargo.toml`"); + } else { + let current_cargo_toml = + fs::read_to_string("Cargo.toml").context("Failed to read the file `Cargo.toml`")?; + update_cargo_toml(&info_file.exercises, ¤t_cargo_toml, "Cargo.toml", b"") + .context("Failed to update the file `Cargo.toml`")?; + + println!("Updated `Cargo.toml`"); + } + + Ok(()) +} |
