Skip to content

feat: Add 'open-namespaces' feature #13591

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 15, 2024
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
4 changes: 2 additions & 2 deletions crates/cargo-util-schemas/src/manifest/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1209,7 +1209,7 @@ str_newtype!(PackageName);
impl<T: AsRef<str>> PackageName<T> {
/// Validated package name
pub fn new(name: T) -> Result<Self, NameValidationError> {
restricted_names::validate_package_name(name.as_ref(), "package name")?;
restricted_names::validate_package_name(name.as_ref())?;
Ok(Self(name))
}
}
Expand All @@ -1231,7 +1231,7 @@ str_newtype!(RegistryName);
impl<T: AsRef<str>> RegistryName<T> {
/// Validated registry name
pub fn new(name: T) -> Result<Self, NameValidationError> {
restricted_names::validate_package_name(name.as_ref(), "registry name")?;
restricted_names::validate_registry_name(name.as_ref())?;
Ok(Self(name))
}
}
Expand Down
30 changes: 23 additions & 7 deletions crates/cargo-util-schemas/src/restricted_names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,18 @@ enum ErrorKind {
FeatureNameStartsWithDepColon(String),
}

/// Check the base requirements for a package name.
///
/// This can be used for other things than package names, to enforce some
/// level of sanity. Note that package names have other restrictions
/// elsewhere. `cargo new` has a few restrictions, such as checking for
/// reserved names. crates.io has even more restrictions.
pub(crate) fn validate_package_name(name: &str, what: &'static str) -> Result<()> {
pub(crate) fn validate_package_name(name: &str) -> Result<()> {
for part in name.split("::") {
validate_name(part, "package name")?;
}
Ok(())
}

pub(crate) fn validate_registry_name(name: &str) -> Result<()> {
validate_name(name, "registry name")
}

pub(crate) fn validate_name(name: &str, what: &'static str) -> Result<()> {
if name.is_empty() {
return Err(ErrorKind::Empty(what).into());
}
Expand Down Expand Up @@ -84,6 +89,17 @@ pub(crate) fn validate_package_name(name: &str, what: &'static str) -> Result<()

/// Ensure a package name is [valid][validate_package_name]
pub(crate) fn sanitize_package_name(name: &str, placeholder: char) -> String {
let mut slug = String::new();
for part in name.split("::") {
if !slug.is_empty() {
slug.push_str("::");
}
slug.push_str(&sanitize_name(part, placeholder));
}
slug
}

pub(crate) fn sanitize_name(name: &str, placeholder: char) -> String {
let mut slug = String::new();
let mut chars = name.chars();
while let Some(ch) = chars.next() {
Expand Down
3 changes: 3 additions & 0 deletions src/cargo/core/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,9 @@ features! {

/// Allow setting trim-paths in a profile to control the sanitisation of file paths in build outputs.
(unstable, trim_paths, "", "reference/unstable.html#profile-trim-paths-option"),

/// Allow multiple packages to participate in the same API namespace
(unstable, open_namespaces, "", "reference/unstable.html#open-namespaces"),
}

/// Status and metadata for a single unstable feature.
Expand Down
13 changes: 13 additions & 0 deletions src/cargo/util/toml/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,16 @@ pub fn prepare_for_publish(
package_root: &Path,
) -> CargoResult<manifest::TomlManifest> {
let gctx = ws.gctx();

if me
.cargo_features
.iter()
.flat_map(|f| f.iter())
.any(|f| f == "open-namespaces")
{
anyhow::bail!("cannot publish with `open-namespaces`")
}

let mut package = me.package().unwrap().clone();
package.workspace = None;
let current_resolver = package
Expand Down Expand Up @@ -587,6 +597,9 @@ pub fn to_real_manifest(
};

let package_name = package.name.trim();
if package_name.contains(':') {
features.require(Feature::open_namespaces())?;
}

let resolved_path = package_root.join("Cargo.toml");

Expand Down
15 changes: 15 additions & 0 deletions src/doc/src/reference/unstable.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ For the latest nightly, see the [nightly version] of this page.
* [host-config](#host-config) --- Allows setting `[target]`-like configuration settings for host build targets.
* [target-applies-to-host](#target-applies-to-host) --- Alters whether certain flags will be passed to host build targets.
* [gc](#gc) --- Global cache garbage collection.
* [open-namespaces](#open-namespaces) --- Allow multiple packages to participate in the same API namespace
* rustdoc
* [rustdoc-map](#rustdoc-map) --- Provides mappings for documentation to link to external sites like [docs.rs](https://docs.rs/).
* [scrape-examples](#scrape-examples) --- Shows examples within documentation.
Expand Down Expand Up @@ -1518,6 +1519,20 @@ cargo clean gc --max-download-age=1week
cargo clean gc --max-git-size=0 --max-download-size=100MB
```

## open-namespaces

* Tracking Issue: [#13576](https://github.com/rust-lang/cargo/issues/13576)

Allow multiple packages to participate in the same API namespace

This can be enabled like so:
```toml
cargo-features = ["open-namespaces"]

[package]
# ...
```

# Stabilized and removed features

## Compile progress
Expand Down
8 changes: 4 additions & 4 deletions tests/testsuite/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,18 +467,18 @@ fn cargo_compile_with_empty_package_name() {
#[cargo_test]
fn cargo_compile_with_invalid_package_name() {
let p = project()
.file("Cargo.toml", &basic_manifest("foo::bar", "0.0.0"))
.file("Cargo.toml", &basic_manifest("foo@bar", "0.0.0"))
.build();

p.cargo("build")
.with_status(101)
.with_stderr(
"\
[ERROR] invalid character `:` in package name: `foo::bar`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters)
[ERROR] invalid character `@` in package name: `foo@bar`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters)
--> Cargo.toml:3:16
|
3 | name = \"foo::bar\"
| ^^^^^^^^^^
3 | name = \"foo@bar\"
| ^^^^^^^^^
|
",
)
Expand Down
1 change: 1 addition & 0 deletions tests/testsuite/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ mod net_config;
mod new;
mod offline;
mod old_cargos;
mod open_namespaces;
mod out_dir;
mod owner;
mod package;
Expand Down
Loading