From eaefb7f66101310c99246ff34e332315c89c5b97 Mon Sep 17 00:00:00 2001 From: Vitaly _Vi Shukela Date: Tue, 29 Sep 2015 16:54:05 +0300 Subject: [PATCH 1/3] Implement "cargo new ." (#21) Allows "new" command even if path exists, if the path is empty or almost empty directory. Also more narrow duplicates: #1990, #1065, #526. --- src/cargo/ops/cargo_new.rs | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/src/cargo/ops/cargo_new.rs b/src/cargo/ops/cargo_new.rs index 5b36097b394..0e38c2f8129 100644 --- a/src/cargo/ops/cargo_new.rs +++ b/src/cargo/ops/cargo_new.rs @@ -45,9 +45,41 @@ struct CargoNewConfig { version_control: Option, } +fn can_we_use_this_path_for_a_new_project (path: &Path) -> bool { + if let Some(path_metadata) = fs::metadata(&path).ok() { + if path_metadata.is_dir() { + if let Some(already_existing_files) = fs::read_dir(&path).ok() { + for entry in already_existing_files { + if let Some(entry2) = entry.ok() { + if let Some(preexisting_file) = entry2.file_name().to_str() { + if preexisting_file == ".git" { continue } + if preexisting_file == ".hg" { continue } + if preexisting_file == ".gitignore" { continue } + if preexisting_file == ".hgignore" { continue } + if preexisting_file == ".svn" { continue } + return false // directory with unknown file + } else { + return false // directory with a non-UTF8 filename + } + } else { + return false // directory where some file can't be enumerated + } + } + true // directory with only VCS-related files + } else { + false // can't enumerate files + } + } else { + false // not a directory + } + } else { + true // does not exist + } +} + pub fn new(opts: NewOptions, config: &Config) -> CargoResult<()> { let path = config.cwd().join(opts.path); - if fs::metadata(&path).is_ok() { + if ! can_we_use_this_path_for_a_new_project(&path) { return Err(human(format!("Destination `{}` already exists", path.display()))) } @@ -132,7 +164,9 @@ fn mk(config: &Config, path: &Path, name: &str, try!(file(&path.join(".hgignore"), ignore.as_bytes())); }, VersionControl::NoVcs => { - try!(fs::create_dir(path)); + if ! fs::metadata(path).is_ok() { + try!(fs::create_dir(path)); + } }, }; From a9e894de8c94b646de9462076bff5d65b96d688f Mon Sep 17 00:00:00 2001 From: Vitaly _Vi Shukela Date: Tue, 29 Sep 2015 16:55:00 +0300 Subject: [PATCH 2/3] Suggest "new ." instead of just "new" for "cargo init" --- src/bin/cargo.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/bin/cargo.rs b/src/bin/cargo.rs index bfa763852e0..6f0a60a4764 100644 --- a/src/bin/cargo.rs +++ b/src/bin/cargo.rs @@ -158,6 +158,10 @@ fn execute(flags: Flags, config: &Config) -> CliResult> { } fn find_closest(cmd: &str) -> Option { + if cmd == "init" { + return Some("new .".to_string()) + } + let cmds = list_commands(); // Only consider candidates with a lev_distance of 3 or less so we don't // suggest out-of-the-blue options. From 20f1709012b43c0e891f801455794f059c0dba3e Mon Sep 17 00:00:00 2001 From: Vitaly _Vi Shukela Date: Tue, 29 Sep 2015 17:15:47 +0300 Subject: [PATCH 3/3] Update test: use non-empty directory for "cargo new -> already exists" The test was testing that "cargo new" fails when the directory already exists. Now it also creates a file in this directory. There should be more tests for this, this is a quick fix. --- tests/test_cargo_new.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_cargo_new.rs b/tests/test_cargo_new.rs index 398e07bec3f..a7335fb6d57 100644 --- a/tests/test_cargo_new.rs +++ b/tests/test_cargo_new.rs @@ -85,6 +85,7 @@ Usage: test!(existing { let dst = paths::root().join("foo"); fs::create_dir(&dst).unwrap(); + File::create(&dst.join("Cargo.toml")).unwrap().write_all(b"qqq").unwrap(); assert_that(cargo_process("new").arg("foo"), execs().with_status(101) .with_stderr(format!("Destination `{}` already exists\n",