Skip to content

Commit

Permalink
Do not rename packages on cargo new.
Browse files Browse the repository at this point in the history
Prior to this commit, packages beginning with `rust` or ending with
`rs` were renamed automatically when created, unless they were
binaries. The ostensible purpose of this code was to avoid people
uploading "redundant" names to crates.io, which is a repository of
Rust packages.

This behavior was overly opinionated. It is not cargo's
responsibility to discourage users from naming their packages any
particular way. Without a sound technical reasons why packages
cannot be named a certain way, cargo should not be intervening in
users' package naming decisions.

It also did this by automatically renaming the package for the
user, as opposed to erroring. Though it printed a message about
the behavior, it did not give the user a choice to abort the
process; to overrule cargo they had to delete the new project
and start again using the `--name` argument.

`cargo new` is many users' first entrypoint to the Rust ecosystem.
This behavior teaches a user that Rust is opinionated and magical,
both of which are divisive attributes for a tool, and attributes
which do not generally describe Rust's attitude toward things like
names and formatting.

If crates.io wishes to enforce that users not upload packages with
names like this, it should be enforced by crates.io at publish
time.
  • Loading branch information
boats committed Feb 5, 2018
1 parent 16ffc05 commit 3e7c75a
Showing 1 changed file with 8 additions and 53 deletions.
61 changes: 8 additions & 53 deletions src/cargo/ops/cargo_new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,32 +91,18 @@ struct CargoNewConfig {
version_control: Option<VersionControl>,
}

fn get_name<'a>(path: &'a Path, opts: &'a NewOptions, config: &Config) -> CargoResult<&'a str> {
fn get_name<'a>(path: &'a Path, opts: &'a NewOptions) -> CargoResult<&'a str> {
if let Some(name) = opts.name {
return Ok(name);
}

if path.file_name().is_none() {
bail!("cannot auto-detect project name from path {:?} ; use --name to override",
path.as_os_str());
}

let dir_name = path.file_name().and_then(|s| s.to_str()).ok_or_else(|| {
format_err!("cannot create a project with a non-unicode name: {:?}",
path.file_name().unwrap())
let file_name = path.file_name().ok_or_else(|| {
format_err!("cannot auto-detect project name from path {:?} ; use --name to override", path.as_os_str())
})?;

if opts.bin {
Ok(dir_name)
} else {
let new_name = strip_rust_affixes(dir_name);
if new_name != dir_name {
writeln!(config.shell().err(),
"note: package will be named `{}`; use --name to override",
new_name)?;
}
Ok(new_name)
}
file_name.to_str().ok_or_else(|| {
format_err!("cannot create project with a non-unicode name: {:?}", file_name)
})
}

fn check_name(name: &str, opts: &NewOptions) -> CargoResult<()> {
Expand Down Expand Up @@ -287,7 +273,7 @@ pub fn new(opts: &NewOptions, config: &Config) -> CargoResult<()> {
bail!("can't specify both lib and binary outputs")
}

let name = get_name(&path, opts, config)?;
let name = get_name(&path, opts)?;
check_name(name, opts)?;

let mkopts = MkOptions {
Expand Down Expand Up @@ -317,7 +303,7 @@ pub fn init(opts: &NewOptions, config: &Config) -> CargoResult<()> {
bail!("can't specify both lib and binary outputs");
}

let name = get_name(&path, opts, config)?;
let name = get_name(&path, opts)?;
check_name(name, opts)?;

let mut src_paths_types = vec![];
Expand Down Expand Up @@ -381,20 +367,6 @@ pub fn init(opts: &NewOptions, config: &Config) -> CargoResult<()> {
Ok(())
}

fn strip_rust_affixes(name: &str) -> &str {
for &prefix in &["rust-", "rust_", "rs-", "rs_"] {
if name.starts_with(prefix) {
return &name[prefix.len()..];
}
}
for &suffix in &["-rust", "_rust", "-rs", "_rs"] {
if name.ends_with(suffix) {
return &name[..name.len()-suffix.len()];
}
}
name
}

fn existing_vcs_repo(path: &Path, cwd: &Path) -> bool {
GitRepo::discover(path, cwd).is_ok() || HgRepo::discover(path, cwd).is_ok()
}
Expand Down Expand Up @@ -605,20 +577,3 @@ fn global_config(config: &Config) -> CargoResult<CargoNewConfig> {
version_control: vcs,
})
}

#[cfg(test)]
mod tests {
use super::strip_rust_affixes;

#[test]
fn affixes_stripped() {
assert_eq!(strip_rust_affixes("rust-foo"), "foo");
assert_eq!(strip_rust_affixes("foo-rs"), "foo");
assert_eq!(strip_rust_affixes("rs_foo"), "foo");
// Only one affix is stripped
assert_eq!(strip_rust_affixes("rs-foo-rs"), "foo-rs");
assert_eq!(strip_rust_affixes("foo-rs-rs"), "foo-rs");
// It shouldn't touch the middle
assert_eq!(strip_rust_affixes("some-rust-crate"), "some-rust-crate");
}
}

0 comments on commit 3e7c75a

Please sign in to comment.