We've been considering removing workspace-hack for a couple reasons: - Lukas ran into a situation where its build script seemed to be causing spurious rebuilds. This seems more likely to be a cargo bug than an issue with workspace-hack itself (given that it has an empty build script), but we don't necessarily want to take the time to hunt that down right now. - Marshall mentioned hakari interacts poorly with automated crate updates (in our case provided by rennovate) because you'd need to have `cargo hakari generate && cargo hakari manage-deps` after their changes and we prefer to not have actions that make commits. Currently removing workspace-hack causes our workspace to grow from ~1700 to ~2000 crates being built (depending on platform), which is mainly a problem when you're building the whole workspace or running tests across the the normal and remote binaries (which is where feature-unification nets us the most sharing). It doesn't impact incremental times noticeably when you're just iterating on `-p zed`, and we'll hopefully get these savings back in the future when rust-lang/cargo#14774 (which re-implements the functionality of hakari) is finished. Release Notes: - N/A
76 lines
2.2 KiB
Rust
76 lines
2.2 KiB
Rust
use std::collections::BTreeMap;
|
|
use std::fs;
|
|
use std::path::Path;
|
|
|
|
use anyhow::{Context as _, Result};
|
|
use cargo_toml::{Dependency, Manifest};
|
|
use clap::Parser;
|
|
|
|
use crate::workspace::load_workspace;
|
|
|
|
#[derive(Parser)]
|
|
pub struct PackageConformityArgs {}
|
|
|
|
pub fn run_package_conformity(_args: PackageConformityArgs) -> Result<()> {
|
|
let workspace = load_workspace()?;
|
|
|
|
let mut non_workspace_dependencies = BTreeMap::new();
|
|
|
|
for package in workspace.workspace_packages() {
|
|
let is_extension = package
|
|
.manifest_path
|
|
.parent()
|
|
.and_then(|parent| parent.parent())
|
|
.is_some_and(|grandparent_dir| grandparent_dir.ends_with("extensions"));
|
|
|
|
let cargo_toml = read_cargo_toml(&package.manifest_path)?;
|
|
|
|
let is_using_workspace_lints = cargo_toml.lints.is_some_and(|lints| lints.workspace);
|
|
if !is_using_workspace_lints {
|
|
eprintln!(
|
|
"{package:?} is not using workspace lints",
|
|
package = package.name
|
|
);
|
|
}
|
|
|
|
// Extensions should not use workspace dependencies.
|
|
if is_extension || package.name == "zed_extension_api" {
|
|
continue;
|
|
}
|
|
|
|
for dependencies in [
|
|
&cargo_toml.dependencies,
|
|
&cargo_toml.dev_dependencies,
|
|
&cargo_toml.build_dependencies,
|
|
] {
|
|
for (name, dependency) in dependencies {
|
|
if let Dependency::Inherited(_) = dependency {
|
|
continue;
|
|
}
|
|
|
|
non_workspace_dependencies
|
|
.entry(name.to_owned())
|
|
.or_insert_with(Vec::new)
|
|
.push(package.name.clone());
|
|
}
|
|
}
|
|
}
|
|
|
|
for (dependency, packages) in non_workspace_dependencies {
|
|
eprintln!(
|
|
"{dependency} is being used as a non-workspace dependency: {}",
|
|
packages.join(", ")
|
|
);
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Returns the contents of the `Cargo.toml` file at the given path.
|
|
fn read_cargo_toml(path: impl AsRef<Path>) -> Result<Manifest> {
|
|
let path = path.as_ref();
|
|
let cargo_toml_bytes = fs::read(path)?;
|
|
Manifest::from_slice(&cargo_toml_bytes)
|
|
.with_context(|| format!("reading Cargo.toml at {path:?}"))
|
|
}
|