Avoid using path URL for workspace Git dependencies in requirements.txt (#14288)

## Summary

Closes https://github.com/astral-sh/uv/issues/13020.
This commit is contained in:
Charlie Marsh 2025-06-26 15:48:12 -04:00 committed by GitHub
parent c291d4329a
commit 05ab266200
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 50 additions and 9 deletions

View file

@ -13,7 +13,7 @@ use uv_git_types::{GitReference, GitUrl, GitUrlParseError};
use uv_normalize::{ExtraName, GroupName, PackageName};
use uv_pep440::VersionSpecifiers;
use uv_pep508::{MarkerTree, VerbatimUrl, VersionOrUrl, looks_like_git_repository};
use uv_pypi_types::{ConflictItem, ParsedUrlError, VerbatimParsedUrl};
use uv_pypi_types::{ConflictItem, ParsedGitUrl, ParsedUrlError, VerbatimParsedUrl};
use uv_redacted::DisplaySafeUrl;
use uv_workspace::Workspace;
use uv_workspace::pyproject::{PyProjectToml, Source, Sources};
@ -700,17 +700,23 @@ fn path_source(
};
if is_dir {
if let Some(git_member) = git_member {
let git = git_member.git_source.git.clone();
let subdirectory = uv_fs::relative_to(install_path, git_member.fetch_root)
.expect("Workspace member must be relative");
let subdirectory = uv_fs::normalize_path_buf(subdirectory);
let subdirectory = if subdirectory == PathBuf::new() {
None
} else {
Some(subdirectory.into_boxed_path())
};
let url = DisplaySafeUrl::from(ParsedGitUrl {
url: git.clone(),
subdirectory: subdirectory.clone(),
});
return Ok(RequirementSource::Git {
git: git_member.git_source.git.clone(),
subdirectory: if subdirectory == PathBuf::new() {
None
} else {
Some(subdirectory.into_boxed_path())
},
url,
git,
subdirectory,
url: VerbatimUrl::from_url(url),
});
}

View file

@ -177,7 +177,9 @@ impl FromStr for DisplaySafeUrl {
}
fn is_ssh_git_username(url: &Url) -> bool {
matches!(url.scheme(), "ssh" | "git+ssh") && url.username() == "git" && url.password().is_none()
matches!(url.scheme(), "ssh" | "git+ssh" | "git+https")
&& url.username() == "git"
&& url.password().is_none()
}
fn display_with_redacted_credentials(

View file

@ -17621,3 +17621,36 @@ fn pubgrub_panic_double_self_dependency_extra() -> Result<()> {
Ok(())
}
/// Sync a Git repository that depends on a package within the same repository via a `path` source.
///
/// See: <https://github.com/astral-sh/uv/issues/13020>
#[test]
#[cfg(feature = "git")]
fn git_path_transitive_dependency() -> Result<()> {
let context = TestContext::new("3.13");
let requirements_in = context.temp_dir.child("requirements.in");
requirements_in.write_str(
r"
git+https://git@github.com/astral-sh/uv-path-dependency-test.git#subdirectory=package2
",
)?;
uv_snapshot!(context.filters(), context.pip_compile().arg("requirements.in"), @r"
success: true
exit_code: 0
----- stdout -----
# This file was autogenerated by uv via the following command:
# uv pip compile --cache-dir [CACHE_DIR] requirements.in
package1 @ git+https://git@github.com/astral-sh/uv-path-dependency-test.git@28781b32cf1f260cdb2c8040628079eb265202bd#subdirectory=package1
# via package2
package2 @ git+https://git@github.com/astral-sh/uv-path-dependency-test.git@28781b32cf1f260cdb2c8040628079eb265202bd#subdirectory=package2
# via -r requirements.in
----- stderr -----
Resolved 2 packages in [TIME]
");
Ok(())
}