diff options
| author | mo8it <mo8it@proton.me> | 2024-07-05 13:39:50 +0200 |
|---|---|---|
| committer | mo8it <mo8it@proton.me> | 2024-07-05 13:39:50 +0200 |
| commit | 7123c7ae3a9605fbe962e4ef0a0f1424cd16fef8 (patch) | |
| tree | c67f7e62bb9a179ae4fdbab492501cb6847e64c7 /src/dev/new.rs | |
| parent | 77b687d501771c24bd83294d97b8e6f9ffa92d6b (diff) | |
| parent | 4d9c346a173bb722b929f3ea3c00f84954483e24 (diff) | |
Merge remote-tracking branch 'upstream/main' into fix-enum-variant-inconsistency
Diffstat (limited to 'src/dev/new.rs')
| -rw-r--r-- | src/dev/new.rs | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/src/dev/new.rs b/src/dev/new.rs new file mode 100644 index 0000000..fefc4fc --- /dev/null +++ b/src/dev/new.rs @@ -0,0 +1,145 @@ +use anyhow::{bail, Context, Result}; +use std::{ + env::set_current_dir, + fs::{self, create_dir}, + path::Path, + process::Command, +}; + +use crate::CURRENT_FORMAT_VERSION; + +// Create a directory relative to the current directory and print its path. +fn create_rel_dir(dir_name: &str, current_dir: &str) -> Result<()> { + create_dir(dir_name) + .with_context(|| format!("Failed to create the directory {current_dir}/{dir_name}"))?; + println!("Created the directory {current_dir}/{dir_name}"); + Ok(()) +} + +// Write a file relative to the current directory and print its path. +fn write_rel_file<C>(file_name: &str, current_dir: &str, content: C) -> Result<()> +where + C: AsRef<[u8]>, +{ + fs::write(file_name, content) + .with_context(|| format!("Failed to create the file {current_dir}/{file_name}"))?; + // Space to align with `create_rel_dir`. + println!("Created the file {current_dir}/{file_name}"); + Ok(()) +} + +pub fn new(path: &Path, no_git: bool) -> Result<()> { + let dir_path_str = path.to_string_lossy(); + + create_dir(path).with_context(|| format!("Failed to create the directory {dir_path_str}"))?; + println!("Created the directory {dir_path_str}"); + + set_current_dir(path) + .with_context(|| format!("Failed to set {dir_path_str} as the current directory"))?; + + if !no_git + && !Command::new("git") + .arg("init") + .status() + .context("Failed to run `git init`")? + .success() + { + bail!("`git init` didn't run successfully. See the possible error message above"); + } + + write_rel_file(".gitignore", &dir_path_str, GITIGNORE)?; + + create_rel_dir("exercises", &dir_path_str)?; + create_rel_dir("solutions", &dir_path_str)?; + + write_rel_file( + "info.toml", + &dir_path_str, + format!("{INFO_FILE_BEFORE_FORMAT_VERSION}{CURRENT_FORMAT_VERSION}{INFO_FILE_AFTER_FORMAT_VERSION}"), + )?; + + write_rel_file("Cargo.toml", &dir_path_str, CARGO_TOML)?; + + write_rel_file("README.md", &dir_path_str, README)?; + + create_rel_dir(".vscode", &dir_path_str)?; + write_rel_file( + ".vscode/extensions.json", + &dir_path_str, + crate::init::VS_CODE_EXTENSIONS_JSON, + )?; + + println!("\nInitialization done ✓"); + + Ok(()) +} + +pub const GITIGNORE: &[u8] = b".rustlings-state.txt +Cargo.lock +target +.vscode +!.vscode/extensions.json +"; + +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 = "???" + +# Rustlings expects the exercise to contain tests and run them. +# You can optionally disable testing by setting `test` to `false` (the default is `true`). +# In that case, the exercise will be considered done when it just successfully compiles. +# test = true + +# Rustlings will always run Clippy on exercises. +# You can optionally set `strict_clippy` to `true` (the default is `false`) to only consider +# the exercise as done when there are no warnings left. +# strict_clippy = false + +# A multi-line hint to be shown to users on request. +hint = """???""" +"#; + +const CARGO_TOML: &[u8] = + br#"# Don't edit the `bin` list manually! It is updated by `rustlings dev update` +bin = [] + +[package] +name = "exercises" +edition = "2021" +# Don't publish the exercises on crates.io! +publish = false + +[dependencies] +"#; + +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 🚀 +"; |
