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
43 changes: 31 additions & 12 deletions src/cargo/ops/cargo_new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,16 +174,18 @@ fn check_name(
// If --name is already used to override, no point in suggesting it
// again as a fix.
let name_help = if show_name_help {
"\nIf you need a package name to not match the directory name, consider using --name flag."
"\nnote: the directory name is used as the package name\
\nhelp: to override the package name, pass `--name <pkgname>`"
} else {
""
};
let bin_help = || {
let mut help = String::from(name_help);
if has_bin && !name.is_empty() {
// Only suggest `bin.name` for valid crate names because it is used for `--crate`
if has_bin && validate_crate_name(name) {
help.push_str(&format!(
"\n\
If you need a binary with the name \"{name}\", use a valid package \
help: to name the binary \"{name}\", use a valid package \
name, and set the binary name to be different from the package. \
This can be done by setting the binary filename to `src/bin/{name}.rs` \
or change the name in Cargo.toml with:\n\
Expand All @@ -204,22 +206,22 @@ fn check_name(

if restricted_names::is_keyword(name) {
anyhow::bail!(
"the name `{}` cannot be used as a package name, it is a Rust keyword{}",
"invalid package name `{}`: it is a Rust keyword{}",
name,
bin_help()
);
}
if restricted_names::is_conflicting_artifact_name(name) {
if has_bin {
anyhow::bail!(
"the name `{}` cannot be used as a package name, \
"invalid package name `{}`: \
it conflicts with cargo's build directory names{}",
name,
name_help
);
} else {
shell.warn(format!(
"the name `{}` will not support binary \
"package `{}` will not support binary \
executables with that name, \
it conflicts with cargo's build directory names",
name
Expand All @@ -228,14 +230,14 @@ fn check_name(
}
if name == "test" {
anyhow::bail!(
"the name `test` cannot be used as a package name, \
"invalid package name `test`: \
it conflicts with Rust's built-in test library{}",
bin_help()
);
}
if ["core", "std", "alloc", "proc_macro", "proc-macro"].contains(&name) {
shell.warn(format!(
"the name `{}` is part of Rust's standard library\n\
"package name `{}` may be confused with the package with that name in Rust's standard library\n\
It is recommended to use a different name to avoid problems.{}",
name,
bin_help()
Expand All @@ -244,35 +246,52 @@ fn check_name(
if restricted_names::is_windows_reserved(name) {
if cfg!(windows) {
anyhow::bail!(
"cannot use name `{}`, it is a reserved Windows filename{}",
"invalid package name `{}`: it is a reserved Windows filename{}",
name,
name_help
);
} else {
shell.warn(format!(
"the name `{}` is a reserved Windows filename\n\
"package name `{}` is a reserved Windows filename\n\
This package will not work on Windows platforms.",
name
))?;
}
}
if restricted_names::is_non_ascii_name(name) {
shell.warn(format!(
"the name `{}` contains non-ASCII characters\n\
"invalid package name `{}`: contains non-ASCII characters\n\
Non-ASCII crate names are not supported by Rust.",
name
))?;
}
let name_in_lowercase = name.to_lowercase();
if name != name_in_lowercase {
shell.warn(format!(
"the name `{name}` is not snake_case or kebab-case which is recommended for package names, consider `{name_in_lowercase}`"
"package name `{name}` is not snake_case or kebab-case which is recommended for package names, consider `{name_in_lowercase}`"
))?;
}

Ok(())
}

// Taken from <https://github.com/rust-lang/rust/blob/693f365667a97b24cb40173bc2801eb66ea53020/compiler/rustc_session/src/output.rs#L49-L79>
fn validate_crate_name(name: &str) -> bool {
if name.is_empty() {
return false;
}

for c in name.chars() {
if c.is_alphanumeric() || c == '-' || c == '_' {
continue;
} else {
return false;
}
}

true
}

/// Checks if the path contains any invalid PATH env characters.
fn check_path(path: &Path, shell: &mut Shell) -> CargoResult<()> {
// warn if the path contains characters that will break `env::join_paths`
Expand Down
18 changes: 4 additions & 14 deletions tests/testsuite/cargo_init/invalid_dir_name/stderr.term.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 12 additions & 10 deletions tests/testsuite/cargo_init/reserved_name/stderr.term.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
62 changes: 32 additions & 30 deletions tests/testsuite/new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,13 +168,8 @@ fn invalid_characters() {
.with_stderr_data(str![[r#"
[CREATING] binary (application) `foo.rs` package
[ERROR] invalid character `.` in package name: `foo.rs`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters)
If you need a package name to not match the directory name, consider using --name flag.
If you need a binary with the name "foo.rs", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/foo.rs.rs` or change the name in Cargo.toml with:

[[bin]]
name = "foo.rs"
path = "src/main.rs"

[NOTE] the directory name is used as the package name
[HELP] to override the package name, pass `--name <pkgname>`

"#]])
.run();
Expand All @@ -186,9 +181,10 @@ fn reserved_name() {
.with_status(101)
.with_stderr_data(str![[r#"
[CREATING] binary (application) `test` package
[ERROR] the name `test` cannot be used as a package name, it conflicts with Rust's built-in test library
If you need a package name to not match the directory name, consider using --name flag.
If you need a binary with the name "test", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/test.rs` or change the name in Cargo.toml with:
[ERROR] invalid package name `test`: it conflicts with Rust's built-in test library
[NOTE] the directory name is used as the package name
[HELP] to override the package name, pass `--name <pkgname>`
[HELP] to name the binary "test", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/test.rs` or change the name in Cargo.toml with:

[[bin]]
name = "test"
Expand All @@ -205,16 +201,17 @@ fn reserved_binary_name() {
.with_status(101)
.with_stderr_data(str![[r#"
[CREATING] binary (application) `incremental` package
[ERROR] the name `incremental` cannot be used as a package name, it conflicts with cargo's build directory names
If you need a package name to not match the directory name, consider using --name flag.
[ERROR] invalid package name `incremental`: it conflicts with cargo's build directory names
[NOTE] the directory name is used as the package name
[HELP] to override the package name, pass `--name <pkgname>`

"#]])
.run();

cargo_process("new --lib incremental")
.with_stderr_data(str![[r#"
[CREATING] library `incremental` package
[WARNING] the name `incremental` will not support binary executables with that name, it conflicts with cargo's build directory names
[WARNING] package `incremental` will not support binary executables with that name, it conflicts with cargo's build directory names
[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

"#]])
Expand All @@ -227,9 +224,10 @@ fn keyword_name() {
.with_status(101)
.with_stderr_data(str![[r#"
[CREATING] binary (application) `pub` package
[ERROR] the name `pub` cannot be used as a package name, it is a Rust keyword
If you need a package name to not match the directory name, consider using --name flag.
If you need a binary with the name "pub", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/pub.rs` or change the name in Cargo.toml with:
[ERROR] invalid package name `pub`: it is a Rust keyword
[NOTE] the directory name is used as the package name
[HELP] to override the package name, pass `--name <pkgname>`
[HELP] to name the binary "pub", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/pub.rs` or change the name in Cargo.toml with:

[[bin]]
name = "pub"
Expand All @@ -244,10 +242,11 @@ If you need a binary with the name "pub", use a valid package name, and set the
fn std_name() {
cargo_process("new core").with_stderr_data(str![[r#"
[CREATING] binary (application) `core` package
[WARNING] the name `core` is part of Rust's standard library
[WARNING] package name `core` may be confused with the package with that name in Rust's standard library
It is recommended to use a different name to avoid problems.
If you need a package name to not match the directory name, consider using --name flag.
If you need a binary with the name "core", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/core.rs` or change the name in Cargo.toml with:
[NOTE] the directory name is used as the package name
[HELP] to override the package name, pass `--name <pkgname>`
[HELP] to name the binary "core", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/core.rs` or change the name in Cargo.toml with:

[[bin]]
name = "core"
Expand Down Expand Up @@ -369,7 +368,7 @@ fn explicit_invalid_name_not_suggested() {
.with_stderr_data(str![[r#"
[CREATING] binary (application) `10-invalid` package
[ERROR] invalid character `1` in package name: `10-invalid`, the name cannot start with a digit
If you need a binary with the name "10-invalid", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/10-invalid.rs` or change the name in Cargo.toml with:
[HELP] to name the binary "10-invalid", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/10-invalid.rs` or change the name in Cargo.toml with:

[[bin]]
name = "10-invalid"
Expand Down Expand Up @@ -441,15 +440,16 @@ fn restricted_windows_name() {
.with_status(101)
.with_stderr_data(str![[r#"
[CREATING] binary (application) `nul` package
[ERROR] cannot use name `nul`, it is a reserved Windows filename
If you need a package name to not match the directory name, consider using --name flag.
[ERROR] invalid package name `nul`: it is a reserved Windows filename
[NOTE] the directory name is used as the package name
[HELP] to override the package name, pass `--name <pkgname>`

"#]])
.run();
} else {
cargo_process("new nul").with_stderr_data(str![[r#"
[CREATING] binary (application) `nul` package
[WARNING] the name `nul` is a reserved Windows filename
[WARNING] package name `nul` is a reserved Windows filename
This package will not work on Windows platforms.
[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

Expand All @@ -461,9 +461,9 @@ This package will not work on Windows platforms.
fn non_ascii_name() {
cargo_process("new Привет").with_stderr_data(str![[r#"
[CREATING] binary (application) `Привет` package
[WARNING] the name `Привет` contains non-ASCII characters
[WARNING] invalid package name `Привет`: contains non-ASCII characters
Non-ASCII crate names are not supported by Rust.
[WARNING] the name `Привет` is not snake_case or kebab-case which is recommended for package names, consider `привет`
[WARNING] package name `Привет` is not snake_case or kebab-case which is recommended for package names, consider `привет`
[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

"#]]).run();
Expand All @@ -477,8 +477,9 @@ fn non_ascii_name_invalid() {
.with_stderr_data(str![[r#"
[CREATING] binary (application) `ⒶⒷⒸ` package
[ERROR] invalid character `Ⓐ` in package name: `ⒶⒷⒸ`, the first character must be a Unicode XID start character (most letters or `_`)
If you need a package name to not match the directory name, consider using --name flag.
If you need a binary with the name "ⒶⒷⒸ", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/ⒶⒷⒸ.rs` or change the name in Cargo.toml with:
[NOTE] the directory name is used as the package name
[HELP] to override the package name, pass `--name <pkgname>`
[HELP] to name the binary "ⒶⒷⒸ", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/ⒶⒷⒸ.rs` or change the name in Cargo.toml with:

[[bin]]
name = "ⒶⒷⒸ"
Expand All @@ -493,8 +494,9 @@ If you need a binary with the name "ⒶⒷⒸ", use a valid package name, and se
.with_stderr_data(str![[r#"
[CREATING] binary (application) `a¼` package
[ERROR] invalid character `¼` in package name: `a¼`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters)
If you need a package name to not match the directory name, consider using --name flag.
If you need a binary with the name "a¼", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/a¼.rs` or change the name in Cargo.toml with:
[NOTE] the directory name is used as the package name
[HELP] to override the package name, pass `--name <pkgname>`
[HELP] to name the binary "a¼", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/a¼.rs` or change the name in Cargo.toml with:

[[bin]]
name = "a¼"
Expand All @@ -510,7 +512,7 @@ fn non_snake_case_name() {
cargo_process("new UPPERcase_name")
.with_stderr_data(str![[r#"
[CREATING] binary (application) `UPPERcase_name` package
[WARNING] the name `UPPERcase_name` is not snake_case or kebab-case which is recommended for package names, consider `uppercase_name`
[WARNING] package name `UPPERcase_name` is not snake_case or kebab-case which is recommended for package names, consider `uppercase_name`
[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

"#]])
Expand Down