Skip to content

Commit 2fe739f

Browse files
committed
Auto merge of #13591 - epage:namespace, r=weihanglo
feat: Add 'open-namespaces' feature ### What does this PR try to resolve? This is a step towards #13576 ### How should we test and review this PR? ### Additional information
2 parents 36108cb + 9ea3f26 commit 2fe739f

File tree

8 files changed

+419
-13
lines changed

8 files changed

+419
-13
lines changed

crates/cargo-util-schemas/src/manifest/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1215,7 +1215,7 @@ str_newtype!(PackageName);
12151215
impl<T: AsRef<str>> PackageName<T> {
12161216
/// Validated package name
12171217
pub fn new(name: T) -> Result<Self, NameValidationError> {
1218-
restricted_names::validate_package_name(name.as_ref(), "package name")?;
1218+
restricted_names::validate_package_name(name.as_ref())?;
12191219
Ok(Self(name))
12201220
}
12211221
}
@@ -1237,7 +1237,7 @@ str_newtype!(RegistryName);
12371237
impl<T: AsRef<str>> RegistryName<T> {
12381238
/// Validated registry name
12391239
pub fn new(name: T) -> Result<Self, NameValidationError> {
1240-
restricted_names::validate_package_name(name.as_ref(), "registry name")?;
1240+
restricted_names::validate_registry_name(name.as_ref())?;
12411241
Ok(Self(name))
12421242
}
12431243
}

crates/cargo-util-schemas/src/restricted_names.rs

+23-7
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,18 @@ enum ErrorKind {
3333
FeatureNameStartsWithDepColon(String),
3434
}
3535

36-
/// Check the base requirements for a package name.
37-
///
38-
/// This can be used for other things than package names, to enforce some
39-
/// level of sanity. Note that package names have other restrictions
40-
/// elsewhere. `cargo new` has a few restrictions, such as checking for
41-
/// reserved names. crates.io has even more restrictions.
42-
pub(crate) fn validate_package_name(name: &str, what: &'static str) -> Result<()> {
36+
pub(crate) fn validate_package_name(name: &str) -> Result<()> {
37+
for part in name.split("::") {
38+
validate_name(part, "package name")?;
39+
}
40+
Ok(())
41+
}
42+
43+
pub(crate) fn validate_registry_name(name: &str) -> Result<()> {
44+
validate_name(name, "registry name")
45+
}
46+
47+
pub(crate) fn validate_name(name: &str, what: &'static str) -> Result<()> {
4348
if name.is_empty() {
4449
return Err(ErrorKind::Empty(what).into());
4550
}
@@ -84,6 +89,17 @@ pub(crate) fn validate_package_name(name: &str, what: &'static str) -> Result<()
8489

8590
/// Ensure a package name is [valid][validate_package_name]
8691
pub(crate) fn sanitize_package_name(name: &str, placeholder: char) -> String {
92+
let mut slug = String::new();
93+
for part in name.split("::") {
94+
if !slug.is_empty() {
95+
slug.push_str("::");
96+
}
97+
slug.push_str(&sanitize_name(part, placeholder));
98+
}
99+
slug
100+
}
101+
102+
pub(crate) fn sanitize_name(name: &str, placeholder: char) -> String {
87103
let mut slug = String::new();
88104
let mut chars = name.chars();
89105
while let Some(ch) = chars.next() {

src/cargo/core/features.rs

+3
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,9 @@ features! {
504504

505505
/// Allow setting trim-paths in a profile to control the sanitisation of file paths in build outputs.
506506
(unstable, trim_paths, "", "reference/unstable.html#profile-trim-paths-option"),
507+
508+
/// Allow multiple packages to participate in the same API namespace
509+
(unstable, open_namespaces, "", "reference/unstable.html#open-namespaces"),
507510
}
508511

509512
/// Status and metadata for a single unstable feature.

src/cargo/util/toml/mod.rs

+13
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,16 @@ pub fn prepare_for_publish(
220220
package_root: &Path,
221221
) -> CargoResult<manifest::TomlManifest> {
222222
let gctx = ws.gctx();
223+
224+
if me
225+
.cargo_features
226+
.iter()
227+
.flat_map(|f| f.iter())
228+
.any(|f| f == "open-namespaces")
229+
{
230+
anyhow::bail!("cannot publish with `open-namespaces`")
231+
}
232+
223233
let mut package = me.package().unwrap().clone();
224234
package.workspace = None;
225235
let current_resolver = package
@@ -580,6 +590,9 @@ pub fn to_real_manifest(
580590
};
581591

582592
let package_name = package.name.trim();
593+
if package_name.contains(':') {
594+
features.require(Feature::open_namespaces())?;
595+
}
583596

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

src/doc/src/reference/unstable.md

+15
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ For the latest nightly, see the [nightly version] of this page.
8787
* [host-config](#host-config) --- Allows setting `[target]`-like configuration settings for host build targets.
8888
* [target-applies-to-host](#target-applies-to-host) --- Alters whether certain flags will be passed to host build targets.
8989
* [gc](#gc) --- Global cache garbage collection.
90+
* [open-namespaces](#open-namespaces) --- Allow multiple packages to participate in the same API namespace
9091
* rustdoc
9192
* [rustdoc-map](#rustdoc-map) --- Provides mappings for documentation to link to external sites like [docs.rs](https://docs.rs/).
9293
* [scrape-examples](#scrape-examples) --- Shows examples within documentation.
@@ -1518,6 +1519,20 @@ cargo clean gc --max-download-age=1week
15181519
cargo clean gc --max-git-size=0 --max-download-size=100MB
15191520
```
15201521

1522+
## open-namespaces
1523+
1524+
* Tracking Issue: [#13576](https://github.com/rust-lang/cargo/issues/13576)
1525+
1526+
Allow multiple packages to participate in the same API namespace
1527+
1528+
This can be enabled like so:
1529+
```toml
1530+
cargo-features = ["open-namespaces"]
1531+
1532+
[package]
1533+
# ...
1534+
```
1535+
15211536
# Stabilized and removed features
15221537

15231538
## Compile progress

tests/testsuite/build.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -467,18 +467,18 @@ fn cargo_compile_with_empty_package_name() {
467467
#[cargo_test]
468468
fn cargo_compile_with_invalid_package_name() {
469469
let p = project()
470-
.file("Cargo.toml", &basic_manifest("foo::bar", "0.0.0"))
470+
.file("Cargo.toml", &basic_manifest("foo@bar", "0.0.0"))
471471
.build();
472472

473473
p.cargo("build")
474474
.with_status(101)
475475
.with_stderr(
476476
"\
477-
[ERROR] invalid character `:` in package name: `foo::bar`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters)
477+
[ERROR] invalid character `@` in package name: `foo@bar`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters)
478478
--> Cargo.toml:3:16
479479
|
480-
3 | name = \"foo::bar\"
481-
| ^^^^^^^^^^
480+
3 | name = \"foo@bar\"
481+
| ^^^^^^^^^
482482
|
483483
",
484484
)

tests/testsuite/main.rs

+1
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ mod net_config;
127127
mod new;
128128
mod offline;
129129
mod old_cargos;
130+
mod open_namespaces;
130131
mod out_dir;
131132
mod owner;
132133
mod package;

0 commit comments

Comments
 (0)