Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ serde_json = "1.0.122"
serde.workspace = true
toml_edit.workspace = true

[dev-dependencies]
tempfile = "3.12.0"

[profile.release]
panic = "abort"

Expand Down
41 changes: 22 additions & 19 deletions src/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::{
env::set_current_dir,
fs::{self, create_dir},
io::{self, Write},
path::Path,
path::{Path, PathBuf},
process::{Command, Stdio},
};

Expand All @@ -22,14 +22,27 @@ pub fn init() -> Result<()> {
let mut stdout = io::stdout().lock();
let mut init_git = true;

if Path::new("Cargo.toml").exists() {
let manifest_path = Command::new("cargo")
.args(["locate-project", "--message-format=plain"])
.output()?;
if manifest_path.status.success() {
let manifest_path: PathBuf = String::from_utf8_lossy(&manifest_path.stdout).trim().into();

if Path::new("exercises").exists() && Path::new("solutions").exists() {
bail!(IN_INITIALIZED_DIR_ERR);
}

stdout.write_all(CARGO_TOML_EXISTS_PROMPT_MSG)?;
press_enter_prompt(&mut stdout)?;
init_git = false;
if fs::read_to_string(manifest_path)?.contains("[workspace]") {
// make sure "rustlings" is added to `workspace.members` by making
// cargo initialize a new project
let output = Command::new("cargo").args(["new", "rustlings"]).output()?;
if !output.status.success() {
bail!("Failed to initilize new workspace member");
}
fs::remove_dir_all("rustlings")?;
init_git = false;
} else {
bail!(IN_NON_WORKSPACE_CARGO_PROJECT_ERR);
}
}

stdout.write_all(b"This command will create the directory `rustlings/` which will contain the exercises.\nPress ENTER to continue ")?;
Expand Down Expand Up @@ -128,19 +141,9 @@ You probably already initialized Rustlings.
Run `cd rustlings`
Then run `rustlings` again";

const CARGO_TOML_EXISTS_PROMPT_MSG: &[u8] = br#"You are about to initialize Rustlings in a directory that already contains a `Cargo.toml` file!

=> It is recommended to abort with CTRL+C and initialize Rustlings in another directory <=

If you know what you are doing and want to initialize Rustlings in a Cargo workspace,
then you need to add its directory to `members` in the `workspace` section of the `Cargo.toml` file:

```toml
[workspace]
members = ["rustlings"]
```

Press ENTER if you are sure that you want to continue after reading the warning above "#;
const IN_NON_WORKSPACE_CARGO_PROJECT_ERR: &str = "\
The current directory is already part of a cargo project.
Please initialize rustlings in a different directory.";

const POST_INIT_MSG: &str = "Run `cd rustlings` to go into the generated directory.
Then run `rustlings` to get started.";
14 changes: 7 additions & 7 deletions tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,28 +155,28 @@ fn hint() {

#[test]
fn init() {
let _ = fs::remove_dir_all("tests/rustlings");
let test_dir = tempfile::TempDir::new().unwrap();
let initialized_dir = test_dir.path().join("rustlings");
let test_dir = test_dir.path().to_str().unwrap();

Cmd::default().current_dir("tests").fail();
Cmd::default().current_dir(test_dir).fail();

Cmd::default()
.current_dir("tests")
.current_dir(test_dir)
.args(&["init"])
.success();

// Running `init` after a successful initialization.
Cmd::default()
.current_dir("tests")
.current_dir(test_dir)
.args(&["init"])
.output(PartialStderr("`cd rustlings`"))
.fail();

// Running `init` in the initialized directory.
Cmd::default()
.current_dir("tests/rustlings")
.current_dir(initialized_dir.to_str().unwrap())
.args(&["init"])
.output(PartialStderr("already initialized"))
.fail();

fs::remove_dir_all("tests/rustlings").unwrap();
}