diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index cd9b346b0..de62dbd1c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -92,7 +92,7 @@ jobs: toolchain: stable - name: Run tests - run: cd rust-tooling && cargo test + run: cd rust-tooling/ci-tests && cargo test rustformat: name: Check Rust Formatting diff --git a/rust-tooling/Cargo.lock b/rust-tooling/Cargo.lock index ee7edff04..9d878f58f 100644 --- a/rust-tooling/Cargo.lock +++ b/rust-tooling/Cargo.lock @@ -112,6 +112,17 @@ dependencies = [ "phf_codegen", ] +[[package]] +name = "ci-tests" +version = "0.1.0" +dependencies = [ + "convert_case", + "ignore", + "models", + "serde_json", + "utils", +] + [[package]] name = "convert_case" version = "0.6.0" @@ -189,9 +200,9 @@ dependencies = [ [[package]] name = "dyn-clone" -version = "1.0.13" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbfc4744c1b8f2a09adc0e55242f60b1af195d88596bd8700be74418c056c555" +checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" [[package]] name = "equivalent" @@ -200,26 +211,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] -name = "exercism_tooling" +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "generator" version = "0.1.0" dependencies = [ "convert_case", "glob", - "ignore", "inquire", - "once_cell", - "serde", + "models", "serde_json", "tera", + "utils", "uuid", ] -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - [[package]] name = "generic-array" version = "0.14.7" @@ -375,9 +385,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "libm" @@ -387,9 +397,9 @@ checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -409,9 +419,9 @@ checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" [[package]] name = "mio" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" dependencies = [ "libc", "log", @@ -419,6 +429,18 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "models" +version = "0.1.0" +dependencies = [ + "ignore", + "once_cell", + "serde", + "serde_json", + "utils", + "uuid", +] + [[package]] name = "newline-converter" version = "0.2.2" @@ -455,9 +477,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", @@ -620,9 +642,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.3.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags", ] @@ -699,9 +721,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.105" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ "indexmap", "itoa", @@ -767,9 +789,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.0" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" [[package]] name = "syn" @@ -910,15 +932,19 @@ checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" + +[[package]] +name = "utils" +version = "0.1.0" [[package]] name = "uuid" -version = "1.4.1" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" dependencies = [ "getrandom", ] diff --git a/rust-tooling/Cargo.toml b/rust-tooling/Cargo.toml index a60bfb872..d636e848f 100644 --- a/rust-tooling/Cargo.toml +++ b/rust-tooling/Cargo.toml @@ -1,17 +1,3 @@ -[package] -name = "exercism_tooling" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -convert_case = "0.6.0" -glob = "0.3.1" -ignore = "0.4.20" -inquire = "0.6.2" -once_cell = "1.18.0" -serde = { version = "1.0.188", features = ["derive"] } -serde_json = { version = "1.0.105", features = ["preserve_order"] } -tera = "1.19.1" -uuid = { version = "1.4.1", features = ["v4"] } +[workspace] +members = ["generator", "ci-tests", "utils", "models"] +resolver = "2" diff --git a/rust-tooling/ci-tests/Cargo.toml b/rust-tooling/ci-tests/Cargo.toml new file mode 100644 index 000000000..ba6030c47 --- /dev/null +++ b/rust-tooling/ci-tests/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "ci-tests" +version = "0.1.0" +edition = "2021" +description = "Tests to be run in CI to make sure the repo is in good shape" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +# This crate is built in CI to run the tests. +# Be considerate when adding dependencies to keep compile times reasonable. +[dependencies] +convert_case = "0.6.0" +ignore = "0.4.20" +models = { version = "0.1.0", path = "../models" } +serde_json = "1.0.108" +utils = { version = "0.1.0", path = "../utils" } diff --git a/rust-tooling/ci-tests/src/lib.rs b/rust-tooling/ci-tests/src/lib.rs new file mode 100644 index 000000000..9255357f4 --- /dev/null +++ b/rust-tooling/ci-tests/src/lib.rs @@ -0,0 +1,5 @@ +//! dummy lib.rs +//! +//! This crate only exists for the tests. +//! The lib.rs may be used for shared code amoung the tests, +//! if that ever turns out to be useful. diff --git a/rust-tooling/tests/bash_script_conventions.rs b/rust-tooling/ci-tests/tests/bash_script_conventions.rs similarity index 96% rename from rust-tooling/tests/bash_script_conventions.rs rename to rust-tooling/ci-tests/tests/bash_script_conventions.rs index a6a9091ab..95f0792ce 100644 --- a/rust-tooling/tests/bash_script_conventions.rs +++ b/rust-tooling/ci-tests/tests/bash_script_conventions.rs @@ -1,12 +1,11 @@ use std::path::PathBuf; use convert_case::{Case, Casing}; -use exercism_tooling::fs_utils; /// Runs a function for each bash script in the bin directory. /// The function is passed the path of the script. fn for_all_scripts(f: fn(&str)) { - fs_utils::cd_into_repo_root(); + utils::fs::cd_into_repo_root(); for entry in std::fs::read_dir("bin").unwrap() { let path = entry.unwrap().path(); diff --git a/rust-tooling/tests/count_ignores.rs b/rust-tooling/ci-tests/tests/count_ignores.rs similarity index 96% rename from rust-tooling/tests/count_ignores.rs rename to rust-tooling/ci-tests/tests/count_ignores.rs index 9b7349624..e10919a64 100644 --- a/rust-tooling/tests/count_ignores.rs +++ b/rust-tooling/ci-tests/tests/count_ignores.rs @@ -1,4 +1,4 @@ -use exercism_tooling::exercise_config::{ +use models::exercise_config::{ get_all_concept_exercise_paths, get_all_practice_exercise_paths, PracticeExercise, }; diff --git a/rust-tooling/tests/difficulties.rs b/rust-tooling/ci-tests/tests/difficulties.rs similarity index 89% rename from rust-tooling/tests/difficulties.rs rename to rust-tooling/ci-tests/tests/difficulties.rs index 3808829ed..2fd3b2ea6 100644 --- a/rust-tooling/tests/difficulties.rs +++ b/rust-tooling/ci-tests/tests/difficulties.rs @@ -1,6 +1,6 @@ //! Make sure exercise difficulties are set correctly -use exercism_tooling::track_config::TRACK_CONFIG; +use models::track_config::TRACK_CONFIG; #[test] fn difficulties_are_valid() { diff --git a/rust-tooling/tests/no_authors_in_cargo_toml.rs b/rust-tooling/ci-tests/tests/no_authors_in_cargo_toml.rs similarity index 89% rename from rust-tooling/tests/no_authors_in_cargo_toml.rs rename to rust-tooling/ci-tests/tests/no_authors_in_cargo_toml.rs index 2e312c671..7cbece376 100644 --- a/rust-tooling/tests/no_authors_in_cargo_toml.rs +++ b/rust-tooling/ci-tests/tests/no_authors_in_cargo_toml.rs @@ -1,4 +1,4 @@ -use exercism_tooling::exercise_config::get_all_exercise_paths; +use models::exercise_config::get_all_exercise_paths; /// The package manifest of each exercise should not contain an `authors` field. /// The authors are already specified in the track configuration. diff --git a/rust-tooling/tests/no_trailing_whitespace.rs b/rust-tooling/ci-tests/tests/no_trailing_whitespace.rs similarity index 92% rename from rust-tooling/tests/no_trailing_whitespace.rs rename to rust-tooling/ci-tests/tests/no_trailing_whitespace.rs index 9fc3254c7..aa368e3ff 100644 --- a/rust-tooling/tests/no_trailing_whitespace.rs +++ b/rust-tooling/ci-tests/tests/no_trailing_whitespace.rs @@ -1,7 +1,5 @@ use std::path::Path; -use exercism_tooling::fs_utils; - fn contains_trailing_whitespace(p: &Path) -> bool { let contents = std::fs::read_to_string(p).unwrap(); for line in contents.lines() { @@ -14,7 +12,7 @@ fn contains_trailing_whitespace(p: &Path) -> bool { #[test] fn no_trailing_whitespace() { - fs_utils::cd_into_repo_root(); + utils::fs::cd_into_repo_root(); for entry in ignore::Walk::new("./") { let entry = entry.unwrap(); diff --git a/rust-tooling/generator/Cargo.toml b/rust-tooling/generator/Cargo.toml new file mode 100644 index 000000000..c92ed589b --- /dev/null +++ b/rust-tooling/generator/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "generator" +version = "0.1.0" +edition = "2021" +description = "Generates exercise boilerplate, especially test cases" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +convert_case = "0.6.0" +glob = "0.3.1" +inquire = "0.6.2" +models = { version = "0.1.0", path = "../models" } +serde_json = { version = "1.0.105", features = ["preserve_order"] } +tera = "1.19.1" +utils = { version = "0.1.0", path = "../utils" } +uuid = { version = "1.4.1", features = ["v4"] } diff --git a/rust-tooling/src/default_test_template.tera b/rust-tooling/generator/default_test_template.tera similarity index 100% rename from rust-tooling/src/default_test_template.tera rename to rust-tooling/generator/default_test_template.tera diff --git a/rust-tooling/src/bin/generate_exercise.rs b/rust-tooling/generator/src/bin/generate_exercise.rs similarity index 97% rename from rust-tooling/src/bin/generate_exercise.rs rename to rust-tooling/generator/src/bin/generate_exercise.rs index b22fa1562..0abc88db2 100644 --- a/rust-tooling/src/bin/generate_exercise.rs +++ b/rust-tooling/generator/src/bin/generate_exercise.rs @@ -1,12 +1,10 @@ use std::path::PathBuf; use convert_case::{Case, Casing}; -use exercism_tooling::{ - exercise_generation, fs_utils, - track_config::{self, TRACK_CONFIG}, -}; +use generator::exercise_generation; use glob::glob; use inquire::{validator::Validation, Select, Text}; +use models::track_config::{self, TRACK_CONFIG}; enum Difficulty { Easy, @@ -39,7 +37,7 @@ impl std::fmt::Display for Difficulty { } fn main() { - fs_utils::cd_into_repo_root(); + utils::fs::cd_into_repo_root(); let is_update = std::env::args().any(|arg| arg == "update"); diff --git a/rust-tooling/src/exercise_generation.rs b/rust-tooling/generator/src/exercise_generation.rs similarity index 91% rename from rust-tooling/src/exercise_generation.rs rename to rust-tooling/generator/src/exercise_generation.rs index 3421abbf7..f85687f2c 100644 --- a/rust-tooling/src/exercise_generation.rs +++ b/rust-tooling/generator/src/exercise_generation.rs @@ -4,10 +4,10 @@ use std::{ process::{Command, Stdio}, }; -use tera::Context; +use tera::{Context, Tera}; -use crate::{ - exercise_config::{get_excluded_tests, get_test_emplate}, +use models::{ + exercise_config::get_excluded_tests, problem_spec::{get_additional_test_cases, get_canonical_data, SingleTestCase, TestCase}, }; @@ -76,7 +76,7 @@ fn generate_example_rs(fn_name: &str) -> String { ) } -static TEST_TEMPLATE: &str = include_str!("default_test_template.tera"); +static TEST_TEMPLATE: &str = include_str!("../default_test_template.tera"); fn extend_single_cases(single_cases: &mut Vec, cases: Vec) { for case in cases { @@ -101,7 +101,7 @@ fn generate_tests(slug: &str, fn_names: Vec) -> String { cases }; let excluded_tests = get_excluded_tests(slug); - let mut template = get_test_emplate(slug).unwrap(); + let mut template = get_test_template(slug).unwrap(); if template.get_template_names().next().is_none() { template .add_raw_template("test_template.tera", TEST_TEMPLATE) @@ -143,3 +143,7 @@ fn generate_tests(slug: &str, fn_names: Vec) -> String { rendered.into() } } + +pub fn get_test_template(slug: &str) -> Option { + Some(Tera::new(format!("exercises/practice/{slug}/.meta/*.tera").as_str()).unwrap()) +} diff --git a/rust-tooling/generator/src/lib.rs b/rust-tooling/generator/src/lib.rs new file mode 100644 index 000000000..0657ebb64 --- /dev/null +++ b/rust-tooling/generator/src/lib.rs @@ -0,0 +1 @@ +pub mod exercise_generation; diff --git a/rust-tooling/models/Cargo.toml b/rust-tooling/models/Cargo.toml new file mode 100644 index 000000000..505f22dea --- /dev/null +++ b/rust-tooling/models/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "models" +version = "0.1.0" +edition = "2021" +description = "Data structures for exercism stuff" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +ignore = "0.4.20" +once_cell = "1.18.0" +serde = { version = "1.0.188", features = ["derive"] } +serde_json = { version = "1.0.105", features = ["preserve_order"] } +utils = { version = "0.1.0", path = "../utils" } +uuid = { version = "1.6.1", features = ["v4"] } diff --git a/rust-tooling/src/exercise_config.rs b/rust-tooling/models/src/exercise_config.rs similarity index 88% rename from rust-tooling/src/exercise_config.rs rename to rust-tooling/models/src/exercise_config.rs index c41d2807a..2ab4ff4b0 100644 --- a/rust-tooling/src/exercise_config.rs +++ b/rust-tooling/models/src/exercise_config.rs @@ -1,9 +1,8 @@ //! This module provides a data structure for exercise configuration stored in -//! `.meta/config`. It is capable of serializing and deserializing th +//! `.meta/config`. It is capable of serializing and deserializing the //! configuration, for example with `serde_json`. use serde::{Deserialize, Serialize}; -use tera::Tera; use crate::track_config::TRACK_CONFIG; @@ -62,23 +61,23 @@ pub struct Custom { } pub fn get_all_concept_exercise_paths() -> impl Iterator { - let crate_dir = env!("CARGO_MANIFEST_DIR"); + use utils::fs::REPO_ROOT_DIR; TRACK_CONFIG .exercises .concept .iter() - .map(move |e| format!("{crate_dir}/../exercises/concept/{}", e.slug)) + .map(move |e| format!("{REPO_ROOT_DIR}/exercises/concept/{}", e.slug)) } pub fn get_all_practice_exercise_paths() -> impl Iterator { - let crate_dir = env!("CARGO_MANIFEST_DIR"); + use utils::fs::REPO_ROOT_DIR; TRACK_CONFIG .exercises .practice .iter() - .map(move |e| format!("{crate_dir}/../exercises/practice/{}", e.slug)) + .map(move |e| format!("{REPO_ROOT_DIR}/exercises/practice/{}", e.slug)) } pub fn get_all_exercise_paths() -> impl Iterator { @@ -120,8 +119,3 @@ pub fn get_excluded_tests(slug: &str) -> Vec { excluded_tests } - -/// Returns the uuids of the tests excluded in .meta/tests.toml -pub fn get_test_emplate(slug: &str) -> Option { - Some(Tera::new(format!("exercises/practice/{slug}/.meta/*.tera").as_str()).unwrap()) -} diff --git a/rust-tooling/src/lib.rs b/rust-tooling/models/src/lib.rs similarity index 59% rename from rust-tooling/src/lib.rs rename to rust-tooling/models/src/lib.rs index 727eaca9a..6833d8f0e 100644 --- a/rust-tooling/src/lib.rs +++ b/rust-tooling/models/src/lib.rs @@ -1,5 +1,3 @@ -pub mod problem_spec; pub mod exercise_config; +pub mod problem_spec; pub mod track_config; -pub mod exercise_generation; -pub mod fs_utils; diff --git a/rust-tooling/src/problem_spec.rs b/rust-tooling/models/src/problem_spec.rs similarity index 98% rename from rust-tooling/src/problem_spec.rs rename to rust-tooling/models/src/problem_spec.rs index 56a5c4fe7..1c8c23161 100644 --- a/rust-tooling/src/problem_spec.rs +++ b/rust-tooling/models/src/problem_spec.rs @@ -72,7 +72,7 @@ pub fn get_additional_test_cases(slug: &str) -> Vec { #[test] fn deserialize_canonical_data() { - crate::fs_utils::cd_into_repo_root(); + utils::fs::cd_into_repo_root(); for entry in ignore::Walk::new("problem-specifications/exercises") .filter_map(|e| e.ok()) .filter(|e| e.file_name().to_str().unwrap() == "canonical-data.json") diff --git a/rust-tooling/src/track_config.rs b/rust-tooling/models/src/track_config.rs similarity index 98% rename from rust-tooling/src/track_config.rs rename to rust-tooling/models/src/track_config.rs index 01c425982..fc0bda868 100644 --- a/rust-tooling/src/track_config.rs +++ b/rust-tooling/models/src/track_config.rs @@ -12,7 +12,7 @@ use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; pub static TRACK_CONFIG: Lazy = Lazy::new(|| { - let config = include_str!("../../config.json"); + let config = include_str!("../../../config.json"); serde_json::from_str(config).expect("should deserialize the track config") }); diff --git a/rust-tooling/utils/Cargo.toml b/rust-tooling/utils/Cargo.toml new file mode 100644 index 000000000..a0cba9a27 --- /dev/null +++ b/rust-tooling/utils/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "utils" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/rust-tooling/src/fs_utils.rs b/rust-tooling/utils/src/fs.rs similarity index 56% rename from rust-tooling/src/fs_utils.rs rename to rust-tooling/utils/src/fs.rs index 6af30496a..6a86bca2b 100644 --- a/rust-tooling/src/fs_utils.rs +++ b/rust-tooling/utils/src/fs.rs @@ -1,12 +1,18 @@ //! This module contains utilities for working with the files in this repo. +pub static REPO_ROOT_DIR: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../.."); + +#[test] +fn repo_root_dir_is_correct() { + let git_database = std::path::PathBuf::from(REPO_ROOT_DIR).join(".git"); + assert!(git_database.is_dir()) +} + /// Changes the current working directory to the root of the repository. /// /// This is intended to be used by executables which operate on files /// of the repository, so they can use relative paths and still work /// when called from anywhere within the repository. pub fn cd_into_repo_root() { - static RUST_TOOLING_DIR: &str = env!("CARGO_MANIFEST_DIR"); - let repo_root_dir = std::path::PathBuf::from(RUST_TOOLING_DIR).join(".."); - std::env::set_current_dir(repo_root_dir).unwrap(); + std::env::set_current_dir(REPO_ROOT_DIR).unwrap(); } diff --git a/rust-tooling/utils/src/lib.rs b/rust-tooling/utils/src/lib.rs new file mode 100644 index 000000000..d521fbd77 --- /dev/null +++ b/rust-tooling/utils/src/lib.rs @@ -0,0 +1 @@ +pub mod fs;