From 41ca3572ab3da74aec1650ecf7a37327510566ed Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Mon, 22 Jul 2024 20:25:20 -0400 Subject: [PATCH] Avoid redundant members update in `uv init` (#5321) ## Summary If the path is already covered by `members`, we don't need to update it. Closes https://github.com/astral-sh/uv/issues/5320. --- crates/uv-workspace/src/workspace.rs | 7 +++++++ crates/uv/src/commands/project/init.rs | 8 ++++++++ crates/uv/tests/init.rs | 6 +++--- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/crates/uv-workspace/src/workspace.rs b/crates/uv-workspace/src/workspace.rs index 65f3927ab90a..e153d9846514 100644 --- a/crates/uv-workspace/src/workspace.rs +++ b/crates/uv-workspace/src/workspace.rs @@ -345,6 +345,13 @@ impl Workspace { } } + /// Returns `true` if the path is a workspace member. + pub fn includes(&self, project_path: &Path) -> bool { + self.packages + .values() + .any(|member| project_path == member.root()) + } + /// Collect the workspace member projects from the `members` and `excludes` entries. async fn collect_members( workspace_root: PathBuf, diff --git a/crates/uv/src/commands/project/init.rs b/crates/uv/src/commands/project/init.rs index f0267575afbf..a44625453b3d 100644 --- a/crates/uv/src/commands/project/init.rs +++ b/crates/uv/src/commands/project/init.rs @@ -123,6 +123,14 @@ pub(crate) async fn init( name.cyan(), workspace.install_path().simplified_display().cyan() )?; + } else if workspace.includes(&path) { + // If the member is already included in the workspace, skip the `members` addition. + writeln!( + printer.stderr(), + "Project `{}` is already a member of workspace `{}`", + name.cyan(), + workspace.install_path().simplified_display().cyan() + )?; } else { // Add the package to the workspace. let mut pyproject = PyProjectTomlMut::from_toml(workspace.pyproject_toml())?; diff --git a/crates/uv/tests/init.rs b/crates/uv/tests/init.rs index 7c69344a4c4b..c2654f28bc35 100644 --- a/crates/uv/tests/init.rs +++ b/crates/uv/tests/init.rs @@ -748,7 +748,7 @@ fn init_matches_members() -> Result<()> { ----- stderr ----- warning: `uv init` is experimental and may change without warning - Adding `foo` as member of workspace `[TEMP_DIR]/` + Project `foo` is already a member of workspace `[TEMP_DIR]/` Initialized project `foo` at `[TEMP_DIR]/packages/foo` "###); @@ -759,7 +759,7 @@ fn init_matches_members() -> Result<()> { assert_snapshot!( workspace, @r###" [tool.uv.workspace] - members = ['packages/*', "packages/foo"] + members = ['packages/*'] "### ); }); @@ -767,7 +767,7 @@ fn init_matches_members() -> Result<()> { Ok(()) } -/// Run `uv init` from within a workspace. The path is already included via `members`. +/// Run `uv init` from within a workspace. The path is excluded via `exclude`. #[test] fn init_matches_exclude() -> Result<()> { let context = TestContext::new("3.12");