mirror of
https://github.com/rust-lang/rustlings.git
synced 2024-12-26 15:26:29 +00:00
Make cargo run
work
This commit is contained in:
parent
8ad18de54c
commit
14f3585816
6 changed files with 214 additions and 4 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,5 +1,6 @@
|
||||||
target/
|
target/
|
||||||
tests/fixture/*/Cargo.lock
|
/tests/fixture/*/Cargo.lock
|
||||||
|
/dev/Cargo.lock
|
||||||
|
|
||||||
*.swp
|
*.swp
|
||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
|
|
|
@ -4,6 +4,7 @@ exclude = [
|
||||||
"tests/fixture/failure",
|
"tests/fixture/failure",
|
||||||
"tests/fixture/state",
|
"tests/fixture/state",
|
||||||
"tests/fixture/success",
|
"tests/fixture/success",
|
||||||
|
"dev",
|
||||||
]
|
]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
|
@ -18,6 +19,7 @@ edition = "2021"
|
||||||
[package]
|
[package]
|
||||||
name = "rustlings"
|
name = "rustlings"
|
||||||
description = "Small exercises to get you used to reading and writing Rust code!"
|
description = "Small exercises to get you used to reading and writing Rust code!"
|
||||||
|
default-run = "rustlings"
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
104
dev/Cargo.toml
Normal file
104
dev/Cargo.toml
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
bin = [
|
||||||
|
{ name = "intro1", path = "../exercises/00_intro/intro1.rs" },
|
||||||
|
{ name = "intro2", path = "../exercises/00_intro/intro2.rs" },
|
||||||
|
{ name = "variables1", path = "../exercises/01_variables/variables1.rs" },
|
||||||
|
{ name = "variables2", path = "../exercises/01_variables/variables2.rs" },
|
||||||
|
{ name = "variables3", path = "../exercises/01_variables/variables3.rs" },
|
||||||
|
{ name = "variables4", path = "../exercises/01_variables/variables4.rs" },
|
||||||
|
{ name = "variables5", path = "../exercises/01_variables/variables5.rs" },
|
||||||
|
{ name = "variables6", path = "../exercises/01_variables/variables6.rs" },
|
||||||
|
{ name = "functions1", path = "../exercises/02_functions/functions1.rs" },
|
||||||
|
{ name = "functions2", path = "../exercises/02_functions/functions2.rs" },
|
||||||
|
{ name = "functions3", path = "../exercises/02_functions/functions3.rs" },
|
||||||
|
{ name = "functions4", path = "../exercises/02_functions/functions4.rs" },
|
||||||
|
{ name = "functions5", path = "../exercises/02_functions/functions5.rs" },
|
||||||
|
{ name = "if1", path = "../exercises/03_if/if1.rs" },
|
||||||
|
{ name = "if2", path = "../exercises/03_if/if2.rs" },
|
||||||
|
{ name = "if3", path = "../exercises/03_if/if3.rs" },
|
||||||
|
{ name = "quiz1", path = "../exercises/quiz1.rs" },
|
||||||
|
{ name = "primitive_types1", path = "../exercises/04_primitive_types/primitive_types1.rs" },
|
||||||
|
{ name = "primitive_types2", path = "../exercises/04_primitive_types/primitive_types2.rs" },
|
||||||
|
{ name = "primitive_types3", path = "../exercises/04_primitive_types/primitive_types3.rs" },
|
||||||
|
{ name = "primitive_types4", path = "../exercises/04_primitive_types/primitive_types4.rs" },
|
||||||
|
{ name = "primitive_types5", path = "../exercises/04_primitive_types/primitive_types5.rs" },
|
||||||
|
{ name = "primitive_types6", path = "../exercises/04_primitive_types/primitive_types6.rs" },
|
||||||
|
{ name = "vecs1", path = "../exercises/05_vecs/vecs1.rs" },
|
||||||
|
{ name = "vecs2", path = "../exercises/05_vecs/vecs2.rs" },
|
||||||
|
{ name = "move_semantics1", path = "../exercises/06_move_semantics/move_semantics1.rs" },
|
||||||
|
{ name = "move_semantics2", path = "../exercises/06_move_semantics/move_semantics2.rs" },
|
||||||
|
{ name = "move_semantics3", path = "../exercises/06_move_semantics/move_semantics3.rs" },
|
||||||
|
{ name = "move_semantics4", path = "../exercises/06_move_semantics/move_semantics4.rs" },
|
||||||
|
{ name = "move_semantics5", path = "../exercises/06_move_semantics/move_semantics5.rs" },
|
||||||
|
{ name = "move_semantics6", path = "../exercises/06_move_semantics/move_semantics6.rs" },
|
||||||
|
{ name = "structs1", path = "../exercises/07_structs/structs1.rs" },
|
||||||
|
{ name = "structs2", path = "../exercises/07_structs/structs2.rs" },
|
||||||
|
{ name = "structs3", path = "../exercises/07_structs/structs3.rs" },
|
||||||
|
{ name = "enums1", path = "../exercises/08_enums/enums1.rs" },
|
||||||
|
{ name = "enums2", path = "../exercises/08_enums/enums2.rs" },
|
||||||
|
{ name = "enums3", path = "../exercises/08_enums/enums3.rs" },
|
||||||
|
{ name = "strings1", path = "../exercises/09_strings/strings1.rs" },
|
||||||
|
{ name = "strings2", path = "../exercises/09_strings/strings2.rs" },
|
||||||
|
{ name = "strings3", path = "../exercises/09_strings/strings3.rs" },
|
||||||
|
{ name = "strings4", path = "../exercises/09_strings/strings4.rs" },
|
||||||
|
{ name = "modules1", path = "../exercises/10_modules/modules1.rs" },
|
||||||
|
{ name = "modules2", path = "../exercises/10_modules/modules2.rs" },
|
||||||
|
{ name = "modules3", path = "../exercises/10_modules/modules3.rs" },
|
||||||
|
{ name = "hashmaps1", path = "../exercises/11_hashmaps/hashmaps1.rs" },
|
||||||
|
{ name = "hashmaps2", path = "../exercises/11_hashmaps/hashmaps2.rs" },
|
||||||
|
{ name = "hashmaps3", path = "../exercises/11_hashmaps/hashmaps3.rs" },
|
||||||
|
{ name = "quiz2", path = "../exercises/quiz2.rs" },
|
||||||
|
{ name = "options1", path = "../exercises/12_options/options1.rs" },
|
||||||
|
{ name = "options2", path = "../exercises/12_options/options2.rs" },
|
||||||
|
{ name = "options3", path = "../exercises/12_options/options3.rs" },
|
||||||
|
{ name = "errors1", path = "../exercises/13_error_handling/errors1.rs" },
|
||||||
|
{ name = "errors2", path = "../exercises/13_error_handling/errors2.rs" },
|
||||||
|
{ name = "errors3", path = "../exercises/13_error_handling/errors3.rs" },
|
||||||
|
{ name = "errors4", path = "../exercises/13_error_handling/errors4.rs" },
|
||||||
|
{ name = "errors5", path = "../exercises/13_error_handling/errors5.rs" },
|
||||||
|
{ name = "errors6", path = "../exercises/13_error_handling/errors6.rs" },
|
||||||
|
{ name = "generics1", path = "../exercises/14_generics/generics1.rs" },
|
||||||
|
{ name = "generics2", path = "../exercises/14_generics/generics2.rs" },
|
||||||
|
{ name = "traits1", path = "../exercises/15_traits/traits1.rs" },
|
||||||
|
{ name = "traits2", path = "../exercises/15_traits/traits2.rs" },
|
||||||
|
{ name = "traits3", path = "../exercises/15_traits/traits3.rs" },
|
||||||
|
{ name = "traits4", path = "../exercises/15_traits/traits4.rs" },
|
||||||
|
{ name = "traits5", path = "../exercises/15_traits/traits5.rs" },
|
||||||
|
{ name = "quiz3", path = "../exercises/quiz3.rs" },
|
||||||
|
{ name = "lifetimes1", path = "../exercises/16_lifetimes/lifetimes1.rs" },
|
||||||
|
{ name = "lifetimes2", path = "../exercises/16_lifetimes/lifetimes2.rs" },
|
||||||
|
{ name = "lifetimes3", path = "../exercises/16_lifetimes/lifetimes3.rs" },
|
||||||
|
{ name = "tests1", path = "../exercises/17_tests/tests1.rs" },
|
||||||
|
{ name = "tests2", path = "../exercises/17_tests/tests2.rs" },
|
||||||
|
{ name = "tests3", path = "../exercises/17_tests/tests3.rs" },
|
||||||
|
{ name = "tests4", path = "../exercises/17_tests/tests4.rs" },
|
||||||
|
{ name = "iterators1", path = "../exercises/18_iterators/iterators1.rs" },
|
||||||
|
{ name = "iterators2", path = "../exercises/18_iterators/iterators2.rs" },
|
||||||
|
{ name = "iterators3", path = "../exercises/18_iterators/iterators3.rs" },
|
||||||
|
{ name = "iterators4", path = "../exercises/18_iterators/iterators4.rs" },
|
||||||
|
{ name = "iterators5", path = "../exercises/18_iterators/iterators5.rs" },
|
||||||
|
{ name = "box1", path = "../exercises/19_smart_pointers/box1.rs" },
|
||||||
|
{ name = "rc1", path = "../exercises/19_smart_pointers/rc1.rs" },
|
||||||
|
{ name = "arc1", path = "../exercises/19_smart_pointers/arc1.rs" },
|
||||||
|
{ name = "cow1", path = "../exercises/19_smart_pointers/cow1.rs" },
|
||||||
|
{ name = "threads1", path = "../exercises/20_threads/threads1.rs" },
|
||||||
|
{ name = "threads2", path = "../exercises/20_threads/threads2.rs" },
|
||||||
|
{ name = "threads3", path = "../exercises/20_threads/threads3.rs" },
|
||||||
|
{ name = "macros1", path = "../exercises/21_macros/macros1.rs" },
|
||||||
|
{ name = "macros2", path = "../exercises/21_macros/macros2.rs" },
|
||||||
|
{ name = "macros3", path = "../exercises/21_macros/macros3.rs" },
|
||||||
|
{ name = "macros4", path = "../exercises/21_macros/macros4.rs" },
|
||||||
|
{ name = "clippy1", path = "../exercises/22_clippy/clippy1.rs" },
|
||||||
|
{ name = "clippy2", path = "../exercises/22_clippy/clippy2.rs" },
|
||||||
|
{ name = "clippy3", path = "../exercises/22_clippy/clippy3.rs" },
|
||||||
|
{ name = "using_as", path = "../exercises/23_conversions/using_as.rs" },
|
||||||
|
{ name = "from_into", path = "../exercises/23_conversions/from_into.rs" },
|
||||||
|
{ name = "from_str", path = "../exercises/23_conversions/from_str.rs" },
|
||||||
|
{ name = "try_from_into", path = "../exercises/23_conversions/try_from_into.rs" },
|
||||||
|
{ name = "as_ref_mut", path = "../exercises/23_conversions/as_ref_mut.rs" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[package]
|
||||||
|
name = "rustlings"
|
||||||
|
version = "0.0.0"
|
||||||
|
edition = "2021"
|
||||||
|
publish = false
|
56
src/bin/gen-dev-cargo-toml.rs
Normal file
56
src/bin/gen-dev-cargo-toml.rs
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
use anyhow::{bail, Context, Result};
|
||||||
|
use serde::Deserialize;
|
||||||
|
use std::{
|
||||||
|
fs::{self, create_dir},
|
||||||
|
io::ErrorKind,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct Exercise {
|
||||||
|
name: String,
|
||||||
|
path: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct InfoToml {
|
||||||
|
exercises: Vec<Exercise>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
let exercises = toml_edit::de::from_str::<InfoToml>(
|
||||||
|
&fs::read_to_string("info.toml").context("Failed to read `info.toml`")?,
|
||||||
|
)
|
||||||
|
.context("Failed to deserialize `info.toml`")?
|
||||||
|
.exercises;
|
||||||
|
|
||||||
|
let mut buf = Vec::with_capacity(1 << 14);
|
||||||
|
|
||||||
|
buf.extend_from_slice(b"bin = [\n");
|
||||||
|
|
||||||
|
for exercise in exercises {
|
||||||
|
buf.extend_from_slice(b" { name = \"");
|
||||||
|
buf.extend_from_slice(exercise.name.as_bytes());
|
||||||
|
buf.extend_from_slice(b"\", path = \"../");
|
||||||
|
buf.extend_from_slice(exercise.path.as_bytes());
|
||||||
|
buf.extend_from_slice(b"\" },\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.extend_from_slice(
|
||||||
|
br#"]
|
||||||
|
|
||||||
|
[package]
|
||||||
|
name = "rustlings"
|
||||||
|
version = "0.0.0"
|
||||||
|
edition = "2021"
|
||||||
|
publish = false
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Err(e) = create_dir("dev") {
|
||||||
|
if e.kind() != ErrorKind::AlreadyExists {
|
||||||
|
bail!("Failed to create the `dev` directory: {e}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::write("dev/Cargo.toml", buf).context("Failed to write `dev/Cargo.toml`")
|
||||||
|
}
|
|
@ -91,9 +91,17 @@ pub struct ContextLine {
|
||||||
|
|
||||||
impl Exercise {
|
impl Exercise {
|
||||||
fn cargo_cmd(&self, command: &str, args: &[&str]) -> Result<Output> {
|
fn cargo_cmd(&self, command: &str, args: &[&str]) -> Result<Output> {
|
||||||
Command::new("cargo")
|
let mut cmd = Command::new("cargo");
|
||||||
.arg(command)
|
cmd.arg(command);
|
||||||
.arg("--color")
|
|
||||||
|
// A hack to make `cargo run` work when developing Rustlings.
|
||||||
|
// Use `dev/Cargo.toml` when in the directory of the repository.
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
if std::path::Path::new("tests").exists() {
|
||||||
|
cmd.arg("--manifest-path").arg("dev/Cargo.toml");
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.arg("--color")
|
||||||
.arg("always")
|
.arg("always")
|
||||||
.arg("-q")
|
.arg("-q")
|
||||||
.arg("--bin")
|
.arg("--bin")
|
||||||
|
|
39
tests/dev_cargo_bins.rs
Normal file
39
tests/dev_cargo_bins.rs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
// Makes sure that `dev/Cargo.toml` is synced with `info.toml`.
|
||||||
|
// When this test fails, you just need to run `cargo run --bin gen-dev-cargo-toml`.
|
||||||
|
|
||||||
|
use serde::Deserialize;
|
||||||
|
use std::fs;
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct Exercise {
|
||||||
|
name: String,
|
||||||
|
path: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct InfoToml {
|
||||||
|
exercises: Vec<Exercise>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn dev_cargo_bins() {
|
||||||
|
let content = fs::read_to_string("exercises/Cargo.toml").unwrap();
|
||||||
|
|
||||||
|
let exercises = toml_edit::de::from_str::<InfoToml>(&fs::read_to_string("info.toml").unwrap())
|
||||||
|
.unwrap()
|
||||||
|
.exercises;
|
||||||
|
|
||||||
|
let mut start_ind = 0;
|
||||||
|
for exercise in exercises {
|
||||||
|
let name_start = start_ind + content[start_ind..].find('"').unwrap() + 1;
|
||||||
|
let name_end = name_start + content[name_start..].find('"').unwrap();
|
||||||
|
assert_eq!(exercise.name, &content[name_start..name_end]);
|
||||||
|
|
||||||
|
// +3 to skip `../` at the begeinning of the path.
|
||||||
|
let path_start = name_end + content[name_end + 1..].find('"').unwrap() + 5;
|
||||||
|
let path_end = path_start + content[path_start..].find('"').unwrap();
|
||||||
|
assert_eq!(exercise.path, &content[path_start..path_end]);
|
||||||
|
|
||||||
|
start_ind = path_end + 1;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue