mirror of https://github.com/astral-sh/uv
Respect path dependencies within Git dependencies (#9594)
## Summary If a Git repository uses a `path` dependency (rather than a `workspace`), we need to expand the path to make it relative to the Git root. Closes https://github.com/astral-sh/uv/issues/9516.
This commit is contained in:
parent
16ca0c34a1
commit
90d8105117
|
|
@ -220,6 +220,7 @@ impl LoweredRequirement {
|
|||
}
|
||||
let source = path_source(
|
||||
PathBuf::from(path),
|
||||
git_member,
|
||||
origin,
|
||||
project_dir,
|
||||
workspace.install_path(),
|
||||
|
|
@ -465,6 +466,7 @@ impl LoweredRequirement {
|
|||
}
|
||||
let source = path_source(
|
||||
PathBuf::from(path),
|
||||
None,
|
||||
RequirementOrigin::Project,
|
||||
dir,
|
||||
dir,
|
||||
|
|
@ -553,6 +555,8 @@ pub enum LoweringError {
|
|||
WorkspaceFalse,
|
||||
#[error("Editable must refer to a local directory, not a file: `{0}`")]
|
||||
EditableFile(String),
|
||||
#[error("Git repository references local file source, but only directories are supported as transitive Git dependencies: `{0}`")]
|
||||
GitFile(String),
|
||||
#[error(transparent)]
|
||||
ParsedUrl(#[from] ParsedUrlError),
|
||||
#[error("Path must be UTF-8: `{0}`")]
|
||||
|
|
@ -678,6 +682,7 @@ fn registry_source(
|
|||
/// Convert a path string to a file or directory source.
|
||||
fn path_source(
|
||||
path: impl AsRef<Path>,
|
||||
git_member: Option<&GitWorkspaceMember>,
|
||||
origin: RequirementOrigin,
|
||||
project_dir: &Path,
|
||||
workspace_root: &Path,
|
||||
|
|
@ -702,6 +707,24 @@ fn path_source(
|
|||
install_path.extension().is_none()
|
||||
};
|
||||
if is_dir {
|
||||
if let Some(git_member) = git_member {
|
||||
let subdirectory = uv_fs::normalize_path(
|
||||
&uv_fs::relative_to(install_path, git_member.fetch_root)
|
||||
.expect("Workspace member must be relative"),
|
||||
);
|
||||
return Ok(RequirementSource::Git {
|
||||
repository: git_member.git_source.git.repository().clone(),
|
||||
reference: git_member.git_source.git.reference().clone(),
|
||||
precise: git_member.git_source.git.precise(),
|
||||
subdirectory: if subdirectory == PathBuf::new() {
|
||||
None
|
||||
} else {
|
||||
Some(subdirectory)
|
||||
},
|
||||
url,
|
||||
});
|
||||
}
|
||||
|
||||
if editable {
|
||||
Ok(RequirementSource::Directory {
|
||||
install_path,
|
||||
|
|
@ -731,6 +754,10 @@ fn path_source(
|
|||
})
|
||||
}
|
||||
} else {
|
||||
// TODO(charlie): If a Git repo contains a source that points to a file, what should we do?
|
||||
if git_member.is_some() {
|
||||
return Err(LoweringError::GitFile(url.to_string()));
|
||||
}
|
||||
if editable {
|
||||
return Err(LoweringError::EditableFile(url.to_string()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5409,3 +5409,92 @@ fn mismatched_name_cached_wheel() -> 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/9516>
|
||||
#[test]
|
||||
fn sync_git_path_dependency() -> Result<()> {
|
||||
let context = TestContext::new("3.13");
|
||||
|
||||
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||
pyproject_toml.write_str(
|
||||
r#"
|
||||
[project]
|
||||
name = "foo"
|
||||
version = "0.1.0"
|
||||
requires-python = ">=3.13"
|
||||
dependencies = ["package2"]
|
||||
|
||||
[tool.uv.sources]
|
||||
package2 = { git = "https://git@github.com/astral-sh/uv-path-dependency-test.git", subdirectory = "package2" }
|
||||
"#,
|
||||
)?;
|
||||
|
||||
uv_snapshot!(context.filters(), context.lock(), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Resolved 3 packages in [TIME]
|
||||
"###);
|
||||
|
||||
let lock = context.read("uv.lock");
|
||||
|
||||
insta::with_settings!(
|
||||
{
|
||||
filters => context.filters(),
|
||||
},
|
||||
{
|
||||
assert_snapshot!(
|
||||
lock, @r###"
|
||||
version = 1
|
||||
requires-python = ">=3.13"
|
||||
|
||||
[options]
|
||||
exclude-newer = "2024-03-25T00:00:00Z"
|
||||
|
||||
[[package]]
|
||||
name = "foo"
|
||||
version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "package2" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [{ name = "package2", git = "https://github.com/astral-sh/uv-path-dependency-test.git?subdirectory=package2" }]
|
||||
|
||||
[[package]]
|
||||
name = "package1"
|
||||
version = "0.1.0"
|
||||
source = { git = "https://github.com/astral-sh/uv-path-dependency-test.git?subdirectory=package1#28781b32cf1f260cdb2c8040628079eb265202bd" }
|
||||
|
||||
[[package]]
|
||||
name = "package2"
|
||||
version = "0.1.0"
|
||||
source = { git = "https://github.com/astral-sh/uv-path-dependency-test.git?subdirectory=package2#28781b32cf1f260cdb2c8040628079eb265202bd" }
|
||||
dependencies = [
|
||||
{ name = "package1" },
|
||||
]
|
||||
"###
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
uv_snapshot!(context.filters(), context.sync(), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Resolved 3 packages in [TIME]
|
||||
Prepared 2 packages in [TIME]
|
||||
Installed 2 packages in [TIME]
|
||||
+ package1==0.1.0 (from git+https://github.com/astral-sh/uv-path-dependency-test.git@28781b32cf1f260cdb2c8040628079eb265202bd#subdirectory=package1)
|
||||
+ package2==0.1.0 (from git+https://github.com/astral-sh/uv-path-dependency-test.git@28781b32cf1f260cdb2c8040628079eb265202bd#subdirectory=package2)
|
||||
"###);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue