diff --git a/cli/src/lib.rs b/cli/src/lib.rs index 0ec8f9a3f7..35b2f99598 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -1452,6 +1452,22 @@ fn process_command(opts: Opts) -> Result<()> { } } +/// Cargo does not support nested workspaces. If `start` lives inside a +/// directory tree containing any `Cargo.toml`, refuse to create a new +/// Anchor workspace here and point at `anchor new`, which is the +/// supported flow for adding a program to an existing project. +fn reject_if_inside_cargo_project(start: PathBuf) -> Result<()> { + if let Some(parent) = Manifest::discover_from_path(start)? { + return Err(anyhow!( + "Cannot run `anchor init` inside an existing Cargo project at `{}`.\nTo add a new \ + program to the existing project, run `anchor new ` from the workspace root. To \ + create a fresh Anchor workspace, run `anchor init` outside any Cargo project tree.", + parent.path().display() + )); + } + Ok(()) +} + #[allow(clippy::too_many_arguments)] fn init( cfg_override: &ConfigOverride, @@ -1466,8 +1482,11 @@ fn init( force: bool, install_agent_skills: bool, ) -> Result<()> { - if !force && Config::discover(cfg_override)?.is_some() { - return Err(anyhow!("Workspace already initialized")); + if !force { + if Config::discover(cfg_override)?.is_some() { + return Err(anyhow!("Workspace already initialized")); + } + reject_if_inside_cargo_project(std::env::current_dir()?)?; } // We need to format different cases for the dir and the name