Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion crates/uv/src/commands/project/install_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,17 @@ impl<'lock> Installable<'lock> for InstallTarget<'lock> {
match self {
Self::Project { name, .. } => Some(name),
Self::Projects { .. } => None,
Self::Workspace { .. } => None,
Self::Workspace { lock, .. } => {
// If the workspace contains a single member at the root, it will be omitted from
// the list of workspace members encoded in the lockfile. In that case, identify
// the root project by its source so that install options (e.g.,
// `--no-emit-workspace`) can filter it correctly.
if lock.members().is_empty() {
lock.root().map(Package::name)
} else {
None
}
}
Self::NonProjectWorkspace { .. } => None,
Self::Script { .. } => None,
}
Expand Down
50 changes: 50 additions & 0 deletions crates/uv/tests/it/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2265,6 +2265,56 @@ fn requirements_txt_no_emit() -> Result<()> {
Ok(())
}

/// `--no-emit-workspace` should be respected when `--all-packages` is passed,
/// even if the workspace has a single member (i.e., no additional packages).
///
/// See: <https://github.com/astral-sh/uv/issues/18070>
#[test]
fn requirements_txt_no_emit_workspace_all_packages() -> Result<()> {
let context = uv_test::test_context!("3.12");

let pyproject_toml = context.temp_dir.child("pyproject.toml");
pyproject_toml.write_str(
r#"
[project]
name = "project"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["anyio==3.7.0"]

[build-system]
requires = ["uv_build>=0.8.22,<10000"]
build-backend = "uv_build"
"#,
)?;

// `--no-emit-workspace --all-packages` on a single-member workspace should not emit `-e .`.
uv_snapshot!(context.filters(), context.export().arg("--no-emit-workspace").arg("--all-packages"), @r"
success: true
exit_code: 0
----- stdout -----
# This file was autogenerated by uv via the following command:
# uv export --cache-dir [CACHE_DIR] --no-emit-workspace --all-packages
anyio==3.7.0 \
--hash=sha256:275d9973793619a5374e1c89a4f4ad3f4b0a5510a2b5b939444bee8f4c4d37ce \
--hash=sha256:eddca883c4175f14df8aedce21054bfca3adb70ffe76a9f607aef9d7fa2ea7f0
# via project
idna==3.6 \
--hash=sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca \
--hash=sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f
# via anyio
sniffio==1.3.1 \
--hash=sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2 \
--hash=sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc
# via anyio

----- stderr -----
Resolved 4 packages in [TIME]
");

Ok(())
}

#[test]
fn requirements_txt_only_emit() -> Result<()> {
let context = uv_test::test_context!("3.12");
Expand Down
Loading