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
7 changes: 7 additions & 0 deletions crates/uv-build-frontend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ impl SourceBuild {
source: &Path,
subdirectory: Option<&Path>,
install_path: &Path,
stop_discovery_at: Option<&Path>,
fallback_package_name: Option<&PackageName>,
fallback_package_version: Option<&Version>,
interpreter: &Interpreter,
Expand Down Expand Up @@ -322,6 +323,7 @@ impl SourceBuild {
fallback_package_name,
locations,
&no_sources,
stop_discovery_at,
build_context.cache(),
workspace_cache,
credentials_cache,
Expand Down Expand Up @@ -458,6 +460,7 @@ impl SourceBuild {
version_id,
locations,
no_sources,
stop_discovery_at,
workspace_cache,
build_stack,
build_kind,
Expand Down Expand Up @@ -574,6 +577,7 @@ impl SourceBuild {
package_name: Option<&PackageName>,
locations: &IndexLocations,
no_sources: &NoSources,
stop_discovery_at: Option<&Path>,
cache: &Cache,
workspace_cache: &WorkspaceCache,
credentials_cache: &CredentialsCache,
Expand Down Expand Up @@ -655,6 +659,7 @@ impl SourceBuild {
locations,
no_sources,
true,
stop_discovery_at,
cache,
workspace_cache,
credentials_cache,
Expand Down Expand Up @@ -998,6 +1003,7 @@ async fn create_pep517_build_environment(
version_id: Option<&str>,
locations: &IndexLocations,
no_sources: NoSources,
stop_discovery_at: Option<&Path>,
workspace_cache: &WorkspaceCache,
build_stack: &BuildStack,
build_kind: BuildKind,
Expand Down Expand Up @@ -1104,6 +1110,7 @@ async fn create_pep517_build_environment(
build_context
.source_tree_editable_policy()
.workspace_member_editable(None),
stop_discovery_at,
build_context.cache(),
workspace_cache,
credentials_cache,
Expand Down
2 changes: 2 additions & 0 deletions crates/uv-dispatch/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,7 @@ impl BuildContext for BuildDispatch<'_> {
source: &'data Path,
subdirectory: Option<&'data Path>,
install_path: &'data Path,
stop_discovery_at: Option<&'data Path>,
version_id: Option<&'data str>,
dist: Option<&'data SourceDist>,
sources: &'data NoSources,
Expand Down Expand Up @@ -554,6 +555,7 @@ impl BuildContext for BuildDispatch<'_> {
source,
subdirectory,
install_path,
stop_discovery_at,
dist_name,
dist_version,
self.interpreter,
Expand Down
15 changes: 8 additions & 7 deletions crates/uv-distribution/src/metadata/build_requires.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,18 @@ impl BuildRequires {
locations: &IndexLocations,
sources: &NoSources,
editable: bool,
stop_discovery_at: Option<&Path>,
cache: &Cache,
workspace_cache: &WorkspaceCache,
credentials_cache: &CredentialsCache,
) -> Result<Self, MetadataError> {
let discovery = if sources.all() {
DiscoveryOptions {
members: MemberDiscovery::None,
..Default::default()
}
} else {
DiscoveryOptions::default()
let discovery = DiscoveryOptions {
stop_discovery_at: stop_discovery_at.map(Path::to_path_buf),
members: if sources.all() {
MemberDiscovery::None
} else {
MemberDiscovery::default()
},
};
let Some(project_workspace) = ProjectWorkspace::from_maybe_project_root(
install_path,
Expand Down
39 changes: 37 additions & 2 deletions crates/uv-distribution/src/source/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2909,6 +2909,23 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
Ok(hashes)
}

/// For Git directories, we check them out into the cache, so we need to avoid workspace
/// discovery that goes outside the cache.
fn stop_discovery_at<'path>(
source: &BuildableSource<'_>,
source_root: &'path Path,
) -> Option<&'path Path> {
if matches!(
source,
BuildableSource::Dist(SourceDist::GitDirectory(_))
| BuildableSource::Url(SourceUrl::GitDirectory(_))
) {
Some(source_root)
} else {
None
}
}

/// Build a source distribution, storing the built wheel in the cache.
///
/// Returns the un-normalized disk filename, the parsed, normalized filename and the metadata
Expand Down Expand Up @@ -2990,6 +3007,14 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
BuildKind::Wheel
};

let install_path = if let Some(subdirectory) = subdirectory {
source_root.join(subdirectory)
} else {
source_root.to_path_buf()
};

let stop_discovery_at = Self::stop_discovery_at(source, source_root);

let build_key = BuildKey {
base_python: base_python.into_boxed_path(),
source_root: source_root.to_path_buf().into_boxed_path(),
Expand All @@ -3015,7 +3040,8 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
.setup_build(
source_root,
subdirectory,
source_root,
&install_path,
stop_discovery_at,
Some(&source.to_string()),
source.as_dist(),
&no_sources,
Expand Down Expand Up @@ -3134,13 +3160,22 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
BuildKind::Wheel
};

let install_path = if let Some(subdirectory) = subdirectory {
source_root.join(subdirectory)
} else {
source_root.to_path_buf()
};

let stop_discovery_at = Self::stop_discovery_at(source, source_root);

// Set up the builder.
let mut builder = self
.build_context
.setup_build(
source_root,
subdirectory,
source_root,
&install_path,
stop_discovery_at,
Some(&source.to_string()),
source.as_dist(),
&no_sources,
Expand Down
1 change: 1 addition & 0 deletions crates/uv-types/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ pub trait BuildContext {
source: &'a Path,
subdirectory: Option<&'a Path>,
install_path: &'a Path,
stop_discovery_at: Option<&'a Path>,
version_id: Option<&'a str>,
dist: Option<&'a SourceDist>,
sources: &'a NoSources,
Expand Down
2 changes: 2 additions & 0 deletions crates/uv/src/commands/build_frontend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1016,6 +1016,7 @@ async fn build_sdist(
source_tree,
subdirectory,
source.path(),
None,
version_id,
dist,
sources,
Expand Down Expand Up @@ -1122,6 +1123,7 @@ async fn build_wheel(
source_tree,
subdirectory,
source.path(),
None,
version_id,
dist,
&sources,
Expand Down
106 changes: 106 additions & 0 deletions crates/uv/tests/pip_install/pip_install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2382,6 +2382,112 @@ fn install_git_public_https() {
context.assert_installed("uv_public_pypackage", "0.1.0");
}

/// Install a package from a Git workspace subdirectory with a workspace build requirement.
#[test]
#[cfg(feature = "test-git")]
fn install_git_workspace_build_requirement() -> Result<()> {
let context = uv_test::test_context!(DEFAULT_PYTHON_VERSION);

let repository = context.temp_dir.child("repository");
repository.child("pyproject.toml").write_str(indoc! {r#"
[tool.uv.workspace]
members = ["packages/*"]

[tool.uv.sources]
uv-test-stop-discovery-at-build-dependency = { workspace = true }
"#})?;

repository
.child("packages/build-dependency/pyproject.toml")
.write_str(indoc! {r#"
[project]
name = "uv-test-stop-discovery-at-build-dependency"
version = "0.1.0"
requires-python = ">=3.12"

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
"#})?;
repository
.child(
"packages/build-dependency/src/uv_test_stop_discovery_at_build_dependency/__init__.py",
)
.touch()?;

repository
.child("packages/project/pyproject.toml")
.write_str(indoc! {r#"
[project]
name = "project"
dynamic = ["version"]
requires-python = ">=3.12"

[build-system]
requires = ["hatchling", "uv-test-stop-discovery-at-build-dependency"]
build-backend = "hatchling.build"
Comment thread
konstin marked this conversation as resolved.

[tool.hatch.version]
path = "src/project/__init__.py"
"#})?;
repository
.child("packages/project/src/project/__init__.py")
.write_str(r#"__version__ = "0.1.0""#)?;

Command::new("git")
.arg("init")
.arg(repository.path())
.assert()
.success();
Command::new("git")
.arg("-C")
.arg(repository.path())
.arg("add")
.arg(".")
.assert()
.success();
Command::new("git")
.arg("-C")
.arg(repository.path())
.arg("-c")
.arg("user.name=ferris")
.arg("-c")
.arg("user.email=ferris@example.com")
.arg("commit")
.arg("-m")
.arg("Initial commit")
.env("GIT_AUTHOR_DATE", "2000-01-01T00:00:00Z")
.env("GIT_COMMITTER_DATE", "2000-01-01T00:00:00Z")
.assert()
.success();

let repository_url = Url::from_directory_path(repository.path())
.map_err(|()| anyhow!("failed to convert repository path to file URL"))?;
let repository_url = repository_url.as_str().trim_end_matches('/');

let mut filters = context.filters();
filters.push((r"@[0-9a-f]{40}", "@[COMMIT]"));
uv_snapshot!(filters, context
.pip_install()
.arg(format!(
"project @ git+{repository_url}#subdirectory=packages/project"
)), @"
success: true
exit_code: 0
----- stdout -----

----- stderr -----
Resolved 1 package in [TIME]
Prepared 1 package in [TIME]
Installed 1 package in [TIME]
+ project==0.1.0 (from git+file://[TEMP_DIR]/repository@[COMMIT]#subdirectory=packages/project)
");

context.assert_installed("project", "0.1.0");

Ok(())
}

/// Install a package from a public GitHub repository, omitting the `git+` prefix
#[test]
#[cfg(feature = "test-git")]
Expand Down
Loading