mirror of
https://github.com/rust-lang/rustlings.git
synced 2024-12-27 00:00:03 +03:00
Done dev init
This commit is contained in:
parent
92777c0a44
commit
25e7696565
|
@ -1,4 +1,4 @@
|
||||||
use anyhow::Result;
|
use anyhow::{Context, Result};
|
||||||
use clap::Subcommand;
|
use clap::Subcommand;
|
||||||
|
|
||||||
mod check;
|
mod check;
|
||||||
|
@ -13,8 +13,11 @@ pub enum DevCommands {
|
||||||
impl DevCommands {
|
impl DevCommands {
|
||||||
pub fn run(self) -> Result<()> {
|
pub fn run(self) -> Result<()> {
|
||||||
match self {
|
match self {
|
||||||
DevCommands::Init => init::init(),
|
DevCommands::Init => init::init().context(INIT_ERR),
|
||||||
DevCommands::Check => check::check(),
|
DevCommands::Check => check::check(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const INIT_ERR: &str = "Initialization failed.
|
||||||
|
After resolving the issue, delete the `rustlings` directory (if it was created) and try again";
|
||||||
|
|
100
src/dev/init.rs
100
src/dev/init.rs
|
@ -1,5 +1,101 @@
|
||||||
use anyhow::Result;
|
use std::fs::{self, create_dir};
|
||||||
|
|
||||||
|
use anyhow::{Context, Result};
|
||||||
|
|
||||||
|
use crate::CURRENT_FORMAT_VERSION;
|
||||||
|
|
||||||
pub fn init() -> Result<()> {
|
pub fn init() -> Result<()> {
|
||||||
todo!()
|
create_dir("rustlings").context("Failed to create the directory `rustlings`")?;
|
||||||
|
|
||||||
|
create_dir("rustlings/exercises")
|
||||||
|
.context("Failed to create the directory `rustlings/exercises`")?;
|
||||||
|
|
||||||
|
create_dir("rustlings/solutions")
|
||||||
|
.context("Failed to create the directory `rustlings/solutions`")?;
|
||||||
|
|
||||||
|
fs::write(
|
||||||
|
"rustlings/info.toml",
|
||||||
|
format!("{INFO_FILE_BEFORE_FORMAT_VERSION}{CURRENT_FORMAT_VERSION}{INFO_FILE_AFTER_FORMAT_VERSION}"),
|
||||||
|
)
|
||||||
|
.context("Failed to create the file `rustlings/info.toml`")?;
|
||||||
|
|
||||||
|
fs::write(
|
||||||
|
"rustligns/Cargo.toml",
|
||||||
|
format!("{CARGO_TOML_COMMENT}{}", crate::init::CARGO_TOML_PACKAGE),
|
||||||
|
)
|
||||||
|
.context("Failed to create the file `rustlings/Cargo.toml`")?;
|
||||||
|
|
||||||
|
fs::write("rustlings/.gitignore", crate::init::GITIGNORE)
|
||||||
|
.context("Failed to create the file `rustlings/.gitignore`")?;
|
||||||
|
|
||||||
|
fs::write("rustlings/README.md", README)
|
||||||
|
.context("Failed to create the file `rustlings/README.md`")?;
|
||||||
|
|
||||||
|
create_dir("rustlings/.vscode")
|
||||||
|
.context("Failed to create the directory `rustligns/.vscode`")?;
|
||||||
|
fs::write(
|
||||||
|
"rustlings/.vscode/extensions.json",
|
||||||
|
crate::init::VS_CODE_EXTENSIONS_JSON,
|
||||||
|
)
|
||||||
|
.context("Failed to create the file `rustlings/.vscode/extensions.json`")?;
|
||||||
|
|
||||||
|
println!("{INIT_DONE}");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const INFO_FILE_BEFORE_FORMAT_VERSION: &str =
|
||||||
|
"# The format version is an indicator of the compatibility of third-party exercises with the
|
||||||
|
# Rustlings program.
|
||||||
|
# The format version is not the same as the version of the Rustlings program.
|
||||||
|
# In case Rustlings makes an unavoidable breaking change to the expected format of third-party
|
||||||
|
# exercises, you would need to raise this version and adapt to the new format.
|
||||||
|
# Otherwise, the newest version of the Rustlings program won't be able to run these exercises.
|
||||||
|
format_version = ";
|
||||||
|
|
||||||
|
const INFO_FILE_AFTER_FORMAT_VERSION: &str = r#"
|
||||||
|
|
||||||
|
# Optional multi-line message to be shown to users when just starting with the exercises.
|
||||||
|
welcome_message = """Welcome to these third-party Rustlings exercises."""
|
||||||
|
|
||||||
|
# Optional multi-line message to be shown to users after finishing all exercises.
|
||||||
|
final_message = """We hope that you found the exercises helpful :D"""
|
||||||
|
|
||||||
|
# Repeat this section for every exercise.
|
||||||
|
[[exercises]]
|
||||||
|
# Exercise name which is the exercise file name without the `.rs` extension.
|
||||||
|
name = "???"
|
||||||
|
|
||||||
|
# Optional directory name to be provided if you want to organize exercises in directories.
|
||||||
|
# If `dir` is specified, the exercise path is `exercises/DIR/NAME.rs`
|
||||||
|
# Otherwise, the path is `exercises/NAME.rs`
|
||||||
|
# dir = "???"
|
||||||
|
|
||||||
|
# A mutli-line hint to be shown to users on request.
|
||||||
|
hint = """???"""
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const CARGO_TOML_COMMENT: &str =
|
||||||
|
"# You shouldn't edit this file manually! It is updated by `rustlings dev check`
|
||||||
|
|
||||||
|
";
|
||||||
|
|
||||||
|
const README: &str = "# Rustlings 🦀
|
||||||
|
|
||||||
|
Welcome to these third-party Rustlings exercises 😃
|
||||||
|
|
||||||
|
First,
|
||||||
|
[install Rustlings using the official instructions in the README of the Rustlings project](https://github.com/rust-lang/rustlings) ✅
|
||||||
|
|
||||||
|
Then, open your terminal in this directory and run `rustlings` to get started with the exercises 🚀
|
||||||
|
";
|
||||||
|
|
||||||
|
const INIT_DONE: &str = r#"Initialization done!
|
||||||
|
You can start developing third-party Rustlings exercises in the `rustlings` directory :D
|
||||||
|
|
||||||
|
If the initialization was done in a Rust project which is a Cargo workspace, you need to add the
|
||||||
|
path to the `rustlings` directory to the `workspace.exclude` list in the project's `Cargo.toml`
|
||||||
|
file. For example:
|
||||||
|
|
||||||
|
[workspace]
|
||||||
|
exclude = ["rustlings"]"#;
|
||||||
|
|
63
src/init.rs
63
src/init.rs
|
@ -1,14 +1,14 @@
|
||||||
use anyhow::{bail, Context, Result};
|
use anyhow::{bail, Context, Result};
|
||||||
use std::{
|
use std::{
|
||||||
env::set_current_dir,
|
env::set_current_dir,
|
||||||
fs::{create_dir, OpenOptions},
|
fs::{self, create_dir},
|
||||||
io::{self, ErrorKind, Write},
|
io::ErrorKind,
|
||||||
path::Path,
|
path::Path,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{embedded::EMBEDDED_FILES, info_file::ExerciseInfo};
|
use crate::{embedded::EMBEDDED_FILES, info_file::ExerciseInfo};
|
||||||
|
|
||||||
fn create_cargo_toml(exercise_infos: &[ExerciseInfo]) -> io::Result<()> {
|
fn cargo_toml(exercise_infos: &[ExerciseInfo]) -> Vec<u8> {
|
||||||
let mut cargo_toml = Vec::with_capacity(1 << 13);
|
let mut cargo_toml = Vec::with_capacity(1 << 13);
|
||||||
cargo_toml.extend_from_slice(b"bin = [\n");
|
cargo_toml.extend_from_slice(b"bin = [\n");
|
||||||
for exercise_info in exercise_infos {
|
for exercise_info in exercise_infos {
|
||||||
|
@ -23,39 +23,10 @@ fn create_cargo_toml(exercise_infos: &[ExerciseInfo]) -> io::Result<()> {
|
||||||
cargo_toml.extend_from_slice(b".rs\" },\n");
|
cargo_toml.extend_from_slice(b".rs\" },\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
cargo_toml.extend_from_slice(
|
cargo_toml.extend_from_slice(b"]\n\n");
|
||||||
br#"]
|
cargo_toml.extend_from_slice(CARGO_TOML_PACKAGE.as_bytes());
|
||||||
|
|
||||||
[package]
|
cargo_toml
|
||||||
name = "rustlings"
|
|
||||||
edition = "2021"
|
|
||||||
publish = false
|
|
||||||
"#,
|
|
||||||
);
|
|
||||||
OpenOptions::new()
|
|
||||||
.create_new(true)
|
|
||||||
.write(true)
|
|
||||||
.open("Cargo.toml")?
|
|
||||||
.write_all(&cargo_toml)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_gitignore() -> io::Result<()> {
|
|
||||||
OpenOptions::new()
|
|
||||||
.create_new(true)
|
|
||||||
.write(true)
|
|
||||||
.open(".gitignore")?
|
|
||||||
.write_all(GITIGNORE)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_vscode_dir() -> Result<()> {
|
|
||||||
create_dir(".vscode").context("Failed to create the directory `.vscode`")?;
|
|
||||||
OpenOptions::new()
|
|
||||||
.create_new(true)
|
|
||||||
.write(true)
|
|
||||||
.open(".vscode/extensions.json")?
|
|
||||||
.write_all(VS_CODE_EXTENSIONS_JSON)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(exercise_infos: &[ExerciseInfo]) -> Result<()> {
|
pub fn init(exercise_infos: &[ExerciseInfo]) -> Result<()> {
|
||||||
|
@ -78,21 +49,31 @@ pub fn init(exercise_infos: &[ExerciseInfo]) -> Result<()> {
|
||||||
.init_exercises_dir()
|
.init_exercises_dir()
|
||||||
.context("Failed to initialize the `rustlings/exercises` directory")?;
|
.context("Failed to initialize the `rustlings/exercises` directory")?;
|
||||||
|
|
||||||
create_cargo_toml(exercise_infos)
|
fs::write("Cargo.toml", cargo_toml(exercise_infos))
|
||||||
.context("Failed to create the file `rustlings/Cargo.toml`")?;
|
.context("Failed to create the file `rustlings/Cargo.toml`")?;
|
||||||
|
|
||||||
create_gitignore().context("Failed to create the file `rustlings/.gitignore`")?;
|
fs::write(".gitignore", GITIGNORE)
|
||||||
|
.context("Failed to create the file `rustlings/.gitignore`")?;
|
||||||
|
|
||||||
create_vscode_dir().context("Failed to create the file `rustlings/.vscode/extensions.json`")?;
|
create_dir(".vscode").context("Failed to create the directory `rustlings/.vscode`")?;
|
||||||
|
fs::write(".vscode/extensions.json", VS_CODE_EXTENSIONS_JSON)
|
||||||
|
.context("Failed to create the file `rustlings/.vscode/extensions.json`")?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
const GITIGNORE: &[u8] = b"/target
|
pub const CARGO_TOML_PACKAGE: &str = r#"[package]
|
||||||
/.rustlings-state.txt
|
name = "rustlings"
|
||||||
|
edition = "2021"
|
||||||
|
publish = false
|
||||||
|
"#;
|
||||||
|
|
||||||
|
pub const GITIGNORE: &[u8] = b"Cargo.lock
|
||||||
|
.rustlings-state.txt
|
||||||
|
target
|
||||||
";
|
";
|
||||||
|
|
||||||
const VS_CODE_EXTENSIONS_JSON: &[u8] = br#"{"recommendations":["rust-lang.rust-analyzer"]}"#;
|
pub const VS_CODE_EXTENSIONS_JSON: &[u8] = br#"{"recommendations":["rust-lang.rust-analyzer"]}"#;
|
||||||
|
|
||||||
const PROBABLY_IN_RUSTLINGS_DIR_ERR: &str =
|
const PROBABLY_IN_RUSTLINGS_DIR_ERR: &str =
|
||||||
"A directory with the name `exercises` and a file with the name `Cargo.toml` already exist
|
"A directory with the name `exercises` and a file with the name `Cargo.toml` already exist
|
||||||
|
|
Loading…
Reference in a new issue