Skip to content

Commit

Permalink
Reject Git CLI arguments with non-Git sources (#5377)
Browse files Browse the repository at this point in the history
## Summary

Closes #5335.
  • Loading branch information
charliermarsh committed Jul 23, 2024
1 parent aced05d commit 76566b0
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 2 deletions.
2 changes: 1 addition & 1 deletion crates/uv-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2012,7 +2012,7 @@ pub struct AddArgs {

/// Add source requirements to the `project.dependencies` section of the `pyproject.toml`.
///
/// Without this flag uv will try to use `tool.uv.sources` for any sources.
/// Without this flag, uv will try to use `tool.uv.sources` for any sources.
#[arg(long)]
pub raw_sources: bool,

Expand Down
22 changes: 21 additions & 1 deletion crates/uv-workspace/src/pyproject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,14 +233,20 @@ pub enum Source {

#[derive(Error, Debug)]
pub enum SourceError {
#[error("Cannot resolve git reference `{0}`")]
#[error("Failed to resolve Git reference: `{0}`")]
UnresolvedReference(String),
#[error("Workspace dependency `{0}` must refer to local directory, not a Git repository")]
WorkspacePackageGit(String),
#[error("Workspace dependency `{0}` must refer to local directory, not a URL")]
WorkspacePackageUrl(String),
#[error("Workspace dependency `{0}` must refer to local directory, not a file")]
WorkspacePackageFile(String),
#[error("`{0}` did not resolve to a Git repository, but a Git reference (`--rev {1}`) was provided.")]
UnusedRev(String, String),
#[error("`{0}` did not resolve to a Git repository, but a Git reference (`--tag {1}`) was provided.")]
UnusedTag(String, String),
#[error("`{0}` did not resolve to a Git repository, but a Git reference (`--branch {1}`) was provided.")]
UnusedBranch(String, String),
}

impl Source {
Expand All @@ -253,6 +259,20 @@ impl Source {
tag: Option<String>,
branch: Option<String>,
) -> Result<Option<Source>, SourceError> {
// If we resolved to a non-Git source, and the user specified a Git reference, error.
if !matches!(source, RequirementSource::Git { .. }) {
if let Some(rev) = rev {
return Err(SourceError::UnusedRev(name.to_string(), rev));
}
if let Some(tag) = tag {
return Err(SourceError::UnusedTag(name.to_string(), tag));
}
if let Some(branch) = branch {
return Err(SourceError::UnusedBranch(name.to_string(), branch));
}
}

// If the source is a workspace package, error if the user tried to specify a source.
if workspace {
return match source {
RequirementSource::Registry { .. } | RequirementSource::Directory { .. } => {
Expand Down
58 changes: 58 additions & 0 deletions crates/uv/tests/edit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,64 @@ fn add_git() -> Result<()> {
Ok(())
}

#[test]
fn add_git_error() -> Result<()> {
let context = TestContext::new("3.12");

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

uv_snapshot!(context.filters(), context.lock(), @r###"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
warning: `uv lock` is experimental and may change without warning
Resolved 1 package in [TIME]
"###);

uv_snapshot!(context.filters(), context.sync().arg("--frozen"), @r###"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
warning: `uv sync` is experimental and may change without warning
Prepared 1 package in [TIME]
Installed 1 package in [TIME]
+ project==0.1.0 (from file://[TEMP_DIR]/)
"###);

// Provide a tag without a Git source.
uv_snapshot!(context.filters(), context.add(&[]).arg("flask").arg("--tag").arg("0.0.1").arg("--preview"), @r###"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
error: `flask` did not resolve to a Git repository, but a Git reference (`--tag 0.0.1`) was provided.
"###);

// Provide a tag with a non-Git source.
uv_snapshot!(context.filters(), context.add(&[]).arg("flask @ https://files.pythonhosted.org/packages/61/80/ffe1da13ad9300f87c93af113edd0638c75138c42a0994becfacac078c06/flask-3.0.3-py3-none-any.whl").arg("--branch").arg("0.0.1").arg("--preview"), @r###"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
error: `flask` did not resolve to a Git repository, but a Git reference (`--branch 0.0.1`) was provided.
"###);

Ok(())
}

/// Add a Git requirement using the `--raw-sources` API.
#[test]
fn add_git_raw() -> Result<()> {
Expand Down

0 comments on commit 76566b0

Please sign in to comment.