mirror of
https://github.com/astral-sh/uv.git
synced 2025-10-02 06:51:14 +00:00
Respect exclusions in uv init
(#5318)
## Summary Avoid adding to the workspace. Closes https://github.com/astral-sh/uv/issues/5254.
This commit is contained in:
parent
13dd8853d9
commit
2f768b8bb0
3 changed files with 84 additions and 15 deletions
|
@ -330,6 +330,21 @@ impl Workspace {
|
||||||
&self.pyproject_toml
|
&self.pyproject_toml
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if the path is excluded by the workspace.
|
||||||
|
pub fn excludes(&self, project_path: &Path) -> Result<bool, WorkspaceError> {
|
||||||
|
if let Some(workspace) = self
|
||||||
|
.pyproject_toml
|
||||||
|
.tool
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|tool| tool.uv.as_ref())
|
||||||
|
.and_then(|uv| uv.workspace.as_ref())
|
||||||
|
{
|
||||||
|
is_excluded_from_workspace(project_path, &self.install_path, workspace)
|
||||||
|
} else {
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Collect the workspace member projects from the `members` and `excludes` entries.
|
/// Collect the workspace member projects from the `members` and `excludes` entries.
|
||||||
async fn collect_members(
|
async fn collect_members(
|
||||||
workspace_root: PathBuf,
|
workspace_root: PathBuf,
|
||||||
|
|
|
@ -115,22 +115,32 @@ pub(crate) async fn init(
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(workspace) = workspace {
|
if let Some(workspace) = workspace {
|
||||||
// Add the package to the workspace.
|
if workspace.excludes(&path)? {
|
||||||
let mut pyproject = PyProjectTomlMut::from_toml(workspace.pyproject_toml())?;
|
// If the member is excluded by the workspace, ignore it.
|
||||||
pyproject.add_workspace(path.strip_prefix(workspace.install_path())?)?;
|
writeln!(
|
||||||
|
printer.stderr(),
|
||||||
|
"Project `{}` is excluded by 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())?;
|
||||||
|
pyproject.add_workspace(path.strip_prefix(workspace.install_path())?)?;
|
||||||
|
|
||||||
// Save the modified `pyproject.toml`.
|
// Save the modified `pyproject.toml`.
|
||||||
fs_err::write(
|
fs_err::write(
|
||||||
workspace.install_path().join("pyproject.toml"),
|
workspace.install_path().join("pyproject.toml"),
|
||||||
pyproject.to_string(),
|
pyproject.to_string(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
writeln!(
|
writeln!(
|
||||||
printer.stderr(),
|
printer.stderr(),
|
||||||
"Adding `{}` as member of workspace `{}`",
|
"Adding `{}` as member of workspace `{}`",
|
||||||
name.cyan(),
|
name.cyan(),
|
||||||
workspace.install_path().simplified_display().cyan()
|
workspace.install_path().simplified_display().cyan()
|
||||||
)?;
|
)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match explicit_path {
|
match explicit_path {
|
||||||
|
|
|
@ -727,7 +727,7 @@ fn init_virtual_workspace() -> Result<()> {
|
||||||
|
|
||||||
/// Run `uv init` from within a workspace. The path is already included via `members`.
|
/// Run `uv init` from within a workspace. The path is already included via `members`.
|
||||||
#[test]
|
#[test]
|
||||||
fn init_matches_member() -> Result<()> {
|
fn init_matches_members() -> Result<()> {
|
||||||
let context = TestContext::new("3.12");
|
let context = TestContext::new("3.12");
|
||||||
|
|
||||||
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||||
|
@ -766,3 +766,47 @@ fn init_matches_member() -> Result<()> {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Run `uv init` from within a workspace. The path is already included via `members`.
|
||||||
|
#[test]
|
||||||
|
fn init_matches_exclude() -> Result<()> {
|
||||||
|
let context = TestContext::new("3.12");
|
||||||
|
|
||||||
|
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||||
|
pyproject_toml.write_str(indoc! {
|
||||||
|
r"
|
||||||
|
[tool.uv.workspace]
|
||||||
|
exclude = ['packages/foo']
|
||||||
|
members = ['packages/*']
|
||||||
|
",
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let packages = context.temp_dir.join("packages");
|
||||||
|
fs_err::create_dir_all(packages)?;
|
||||||
|
|
||||||
|
uv_snapshot!(context.filters(), context.init().current_dir(context.temp_dir.join("packages")).arg("foo"), @r###"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
warning: `uv init` is experimental and may change without warning
|
||||||
|
Project `foo` is excluded by workspace `[TEMP_DIR]/`
|
||||||
|
Initialized project `foo` at `[TEMP_DIR]/packages/foo`
|
||||||
|
"###);
|
||||||
|
|
||||||
|
let workspace = fs_err::read_to_string(context.temp_dir.join("pyproject.toml"))?;
|
||||||
|
insta::with_settings!({
|
||||||
|
filters => context.filters(),
|
||||||
|
}, {
|
||||||
|
assert_snapshot!(
|
||||||
|
workspace, @r###"
|
||||||
|
[tool.uv.workspace]
|
||||||
|
exclude = ['packages/foo']
|
||||||
|
members = ['packages/*']
|
||||||
|
"###
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue