Skip to content

Commit

Permalink
Implement base paths (RFC 3529) 1/n: path dep and patch support
Browse files Browse the repository at this point in the history
  • Loading branch information
dpaoliello committed Aug 6, 2024
1 parent 403bc5b commit a0bf1fb
Show file tree
Hide file tree
Showing 6 changed files with 466 additions and 22 deletions.
2 changes: 2 additions & 0 deletions crates/cargo-util-schemas/src/manifest/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,7 @@ pub struct TomlDetailedDependency<P: Clone = String> {
// `path` is relative to the file it appears in. If that's a `Cargo.toml`, it'll be relative to
// that TOML file, and if it's a `.cargo/config` file, it'll be relative to that file.
pub path: Option<P>,
pub base: Option<String>,
pub git: Option<String>,
pub branch: Option<String>,
pub tag: Option<String>,
Expand Down Expand Up @@ -815,6 +816,7 @@ impl<P: Clone> Default for TomlDetailedDependency<P> {
registry: Default::default(),
registry_index: Default::default(),
path: Default::default(),
base: Default::default(),
git: Default::default(),
branch: Default::default(),
tag: Default::default(),
Expand Down
2 changes: 2 additions & 0 deletions src/cargo/core/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,7 @@ unstable_cli_options!(
no_index_update: bool = ("Do not update the registry index even if the cache is outdated"),
package_workspace: bool = ("Handle intra-workspace dependencies when packaging"),
panic_abort_tests: bool = ("Enable support to run tests with -Cpanic=abort"),
path_bases: bool = ("Allow paths that resolve relatively to a base specified in the config"),
profile_rustflags: bool = ("Enable the `rustflags` option in profiles in .cargo/config.toml file"),
public_dependency: bool = ("Respect a dependency's `public` field in Cargo.toml to control public/private dependencies"),
publish_timeout: bool = ("Enable the `publish.timeout` key in .cargo/config.toml file"),
Expand Down Expand Up @@ -1280,6 +1281,7 @@ impl CliUnstable {
"package-workspace" => self.package_workspace= parse_empty(k, v)?,
"panic-abort-tests" => self.panic_abort_tests = parse_empty(k, v)?,
"public-dependency" => self.public_dependency = parse_empty(k, v)?,
"path-bases" => self.path_bases = parse_empty(k, v)?,
"profile-rustflags" => self.profile_rustflags = parse_empty(k, v)?,
"trim-paths" => self.trim_paths = parse_empty(k, v)?,
"publish-timeout" => self.publish_timeout = parse_empty(k, v)?,
Expand Down
64 changes: 56 additions & 8 deletions src/cargo/util/toml/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -901,13 +901,17 @@ impl InheritableFields {
};
let mut dep = dep.clone();
if let manifest::TomlDependency::Detailed(detailed) = &mut dep {
if let Some(rel_path) = &detailed.path {
detailed.path = Some(resolve_relative_path(
name,
self.ws_root(),
package_root,
rel_path,
)?);
if detailed.base.is_none() {
// If this is a path dependency without a base, then update the path to be relative
// to the workspace root instead.
if let Some(rel_path) = &detailed.path {
detailed.path = Some(resolve_relative_path(
name,
self.ws_root(),
package_root,
rel_path,
)?);
}
}
}
Ok(dep)
Expand Down Expand Up @@ -2135,7 +2139,16 @@ fn to_dependency_source_id<P: ResolveToPath + Clone>(
// always end up hashing to the same value no matter where it's
// built from.
if manifest_ctx.source_id.is_path() {
let path = manifest_ctx.root.join(path);
let path = if let Some(base) = orig.base.as_ref() {
lookup_path_base(&base, manifest_ctx.gctx, manifest_ctx.root)
.with_context(|| {
format!("resolving path base for dependency ({name_in_toml})")
})?
.join(path)
} else {
// This is a standard path with no prefix.
manifest_ctx.root.join(path)
};
let path = paths::normalize_path(&path);
SourceId::for_path(&path)
} else {
Expand All @@ -2151,6 +2164,40 @@ fn to_dependency_source_id<P: ResolveToPath + Clone>(
}
}

pub(crate) fn lookup_path_base(
base: &str,
gctx: &GlobalContext,
manifest_root: &Path,
) -> CargoResult<PathBuf> {
if !gctx.cli_unstable().path_bases {
bail!("usage of path bases requires `-Z path-bases`");
}

// Look up the relevant base in the Config and use that as the root.
if let Some(path_bases) =
gctx.get::<Option<ConfigRelativePath>>(&format!("path-bases.{base}"))?
{
Ok(path_bases.resolve_path(gctx))
} else {
// Otherwise, check the built-in bases.
match base {
"workspace" => {
if let Some(workspace_root) = find_workspace_root(manifest_root, gctx)? {
Ok(workspace_root.parent().unwrap().to_path_buf())
} else {
bail!(
"the `workspace` built-in path base cannot be used outside of a workspace."
)
}
}
_ => bail!(
"path base `{base}` is undefined. \
You must add an entry for `{base}` in the Cargo configuration [path-bases] table."
),
}
}
}

pub trait ResolveToPath {
fn resolve(&self, gctx: &GlobalContext) -> PathBuf;
}
Expand Down Expand Up @@ -2865,6 +2912,7 @@ fn prepare_toml_for_publish(
let mut d = d.clone();
// Path dependencies become crates.io deps.
d.path.take();
d.base.take();
// Same with git dependencies.
d.git.take();
d.branch.take();
Expand Down
30 changes: 16 additions & 14 deletions tests/testsuite/cargo/z_help/stdout.term.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
42 changes: 42 additions & 0 deletions tests/testsuite/patch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3028,3 +3028,45 @@ foo v0.0.0 ([ROOT]/foo)

assert_eq!(p.read_file("Cargo.lock"), p.read_file("Cargo.lock.orig"));
}

#[cargo_test]
fn patch_with_base() {
let bar = project()
.at("bar")
.file("Cargo.toml", &basic_manifest("bar", "0.5.0"))
.file("src/lib.rs", "pub fn hello() {}")
.build();
Package::new("bar", "0.5.0").publish();

let p = project()
.file(
".cargo/config.toml",
&format!(
"[path-bases]\ntest = '{}'",
bar.root().parent().unwrap().display()
),
)
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.5.0"
authors = ["wycats@example.com"]
edition = "2018"
[dependencies]
bar = "0.5.0"
[patch.crates-io.bar]
path = 'bar'
base = 'test'
"#,
)
.file("src/lib.rs", "use bar::hello as _;")
.build();

p.cargo("build -v -Zpath-bases")
.masquerade_as_nightly_cargo(&["path-bases"])
.run();
}
Loading

0 comments on commit a0bf1fb

Please sign in to comment.