diff --git a/crates/uv-resolver/src/lock.rs b/crates/uv-resolver/src/lock.rs index 61606c79b..9bf0e1c3d 100644 --- a/crates/uv-resolver/src/lock.rs +++ b/crates/uv-resolver/src/lock.rs @@ -862,9 +862,15 @@ impl Distribution { distribution_types::SourceDist::Directory(dir_dist) } Source::Git(url, git) => { + // Remove the fragment and query from the URL; they're already present in the + // `GitSource`. + let mut url = url.to_url(); + url.set_fragment(None); + url.set_query(None); + // Reconstruct the `GitUrl` from the `GitSource`. let git_url = uv_git::GitUrl::from_commit( - url.to_url(), + url, GitReference::from(git.kind.clone()), git.precise, ); @@ -1613,13 +1619,14 @@ impl TryFrom for Source { match wire { Registry { registry } => Ok(Source::Registry(registry)), Git { git } => { - let mut url = Url::parse(&git) + let url = Url::parse(&git) .map_err(|err| SourceParseError::InvalidUrl { given: git.to_string(), err, }) .map_err(LockErrorKind::InvalidGitSourceUrl)?; - let git_source = GitSource::from_url(&mut url) + + let git_source = GitSource::from_url(&url) .map_err(|err| match err { GitSourceError::InvalidSha => SourceParseError::InvalidSha { given: git.to_string(), @@ -1629,6 +1636,7 @@ impl TryFrom for Source { }, }) .map_err(LockErrorKind::InvalidGitSourceUrl)?; + Ok(Source::Git(UrlString::from(url), git_source)) } Direct { url, subdirectory } => Ok(Source::Direct(url, DirectSource { subdirectory })), @@ -1663,12 +1671,9 @@ enum GitSourceError { } impl GitSource { - /// Extracts a git source reference from the query pairs and the hash + /// Extracts a Git source reference from the query pairs and the hash /// fragment in the given URL. - /// - /// This also removes the query pairs and hash fragment from the given - /// URL in place. - fn from_url(url: &mut Url) -> Result { + fn from_url(url: &Url) -> Result { let mut kind = GitSourceKind::DefaultBranch; let mut subdirectory = None; for (key, val) in url.query_pairs() { @@ -1683,8 +1688,6 @@ impl GitSource { let precise = GitSha::from_str(url.fragment().ok_or(GitSourceError::MissingSha)?) .map_err(|_| GitSourceError::InvalidSha)?; - url.set_query(None); - url.set_fragment(None); Ok(GitSource { precise, subdirectory, diff --git a/crates/uv/tests/edit.rs b/crates/uv/tests/edit.rs index 3236d76a0..8c2f005c0 100644 --- a/crates/uv/tests/edit.rs +++ b/crates/uv/tests/edit.rs @@ -188,7 +188,7 @@ fn add_git() -> Result<()> { Installed 2 packages in [TIME] - project==0.1.0 (from file://[TEMP_DIR]/) + project==0.1.0 (from file://[TEMP_DIR]/) - + uv-public-pypackage==0.1.0 (from git+https://github.com/astral-test/uv-public-pypackage@0dacfd662c64cb4ceb16e6cf65a157a8b715b979?tag=0.0.1#0dacfd662c64cb4ceb16e6cf65a157a8b715b979) + + uv-public-pypackage==0.1.0 (from git+https://github.com/astral-test/uv-public-pypackage@0dacfd662c64cb4ceb16e6cf65a157a8b715b979) "###); let pyproject_toml = fs_err::read_to_string(context.temp_dir.join("pyproject.toml"))?; @@ -396,7 +396,7 @@ fn add_git_raw() -> Result<()> { Installed 2 packages in [TIME] - project==0.1.0 (from file://[TEMP_DIR]/) + project==0.1.0 (from file://[TEMP_DIR]/) - + uv-public-pypackage==0.1.0 (from git+https://github.com/astral-test/uv-public-pypackage@0dacfd662c64cb4ceb16e6cf65a157a8b715b979?rev=0.0.1#0dacfd662c64cb4ceb16e6cf65a157a8b715b979) + + uv-public-pypackage==0.1.0 (from git+https://github.com/astral-test/uv-public-pypackage@0dacfd662c64cb4ceb16e6cf65a157a8b715b979) "###); let pyproject_toml = fs_err::read_to_string(context.temp_dir.join("pyproject.toml"))?; @@ -547,7 +547,7 @@ fn add_unnamed() -> Result<()> { Prepared 2 packages in [TIME] Installed 2 packages in [TIME] + project==0.1.0 (from file://[TEMP_DIR]/) - + uv-public-pypackage==0.1.0 (from git+https://github.com/astral-test/uv-public-pypackage@0dacfd662c64cb4ceb16e6cf65a157a8b715b979?tag=0.0.1#0dacfd662c64cb4ceb16e6cf65a157a8b715b979) + + uv-public-pypackage==0.1.0 (from git+https://github.com/astral-test/uv-public-pypackage@0dacfd662c64cb4ceb16e6cf65a157a8b715b979) "###); let pyproject_toml = fs_err::read_to_string(context.temp_dir.join("pyproject.toml"))?; @@ -1460,7 +1460,7 @@ fn update() -> Result<()> { - project==0.1.0 (from file://[TEMP_DIR]/) + project==0.1.0 (from file://[TEMP_DIR]/) - requests==2.31.0 - + requests==2.32.3 (from git+https://github.com/psf/requests@0e322af87745eff34caffe4df68456ebc20d9068?tag=v2.32.3#0e322af87745eff34caffe4df68456ebc20d9068) + + requests==2.32.3 (from git+https://github.com/psf/requests@0e322af87745eff34caffe4df68456ebc20d9068) "###); let pyproject_toml = fs_err::read_to_string(context.temp_dir.join("pyproject.toml"))?; @@ -1639,7 +1639,7 @@ fn update_source_replace_url() -> Result<()> { + charset-normalizer==3.3.2 + idna==3.6 + project==0.1.0 (from file://[TEMP_DIR]/) - + requests==2.32.3 (from git+https://github.com/psf/requests@0e322af87745eff34caffe4df68456ebc20d9068?tag=v2.32.3#0e322af87745eff34caffe4df68456ebc20d9068) + + requests==2.32.3 (from git+https://github.com/psf/requests@0e322af87745eff34caffe4df68456ebc20d9068) + urllib3==2.2.1 "###); diff --git a/crates/uv/tests/lock.rs b/crates/uv/tests/lock.rs index c5ae85c65..39730be2c 100644 --- a/crates/uv/tests/lock.rs +++ b/crates/uv/tests/lock.rs @@ -261,6 +261,18 @@ fn lock_sdist_git() -> Result<()> { }); } + // Re-run with `--locked`. + uv_snapshot!(context.filters(), context.lock().arg("--locked"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + warning: `uv lock` is experimental and may change without warning + warning: `uv.sources` is experimental and may change without warning + Resolved 2 packages in [TIME] + "###); + // Install from the lockfile. uv_snapshot!(context.filters(), context.sync().arg("--frozen"), @r###" success: true @@ -459,7 +471,7 @@ fn lock_sdist_git_pep508() -> Result<()> { "#, )?; - // deterministic! { context => + deterministic! { context => uv_snapshot!(context.filters(), context.lock(), @r###" success: true exit_code: 0 @@ -496,7 +508,18 @@ fn lock_sdist_git_pep508() -> Result<()> { "### ); }); - // } + } + + // Re-run with `--locked`. + uv_snapshot!(context.filters(), context.lock().arg("--locked"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + warning: `uv lock` is experimental and may change without warning + Resolved 2 packages in [TIME] + "###); // Re-lock with a precise commit that maps to the same tag. let pyproject_toml = context.temp_dir.child("pyproject.toml"); @@ -510,7 +533,7 @@ fn lock_sdist_git_pep508() -> Result<()> { "#, )?; - // deterministic! { context => + deterministic! { context => uv_snapshot!(context.filters(), context.lock(), @r###" success: true exit_code: 0 @@ -547,7 +570,7 @@ fn lock_sdist_git_pep508() -> Result<()> { "### ); }); - // } + } // Re-lock with a different commit. let pyproject_toml = context.temp_dir.child("pyproject.toml"); @@ -561,7 +584,7 @@ fn lock_sdist_git_pep508() -> Result<()> { "#, )?; - // deterministic! { context => + deterministic! { context => uv_snapshot!(context.filters(), context.lock(), @r###" success: true exit_code: 0 @@ -598,7 +621,7 @@ fn lock_sdist_git_pep508() -> Result<()> { "### ); }); - // } + } // Re-lock with a different tag (which matches the new commit). let pyproject_toml = context.temp_dir.child("pyproject.toml"); @@ -612,7 +635,7 @@ fn lock_sdist_git_pep508() -> Result<()> { "#, )?; - // deterministic! { context => + deterministic! { context => uv_snapshot!(context.filters(), context.lock(), @r###" success: true exit_code: 0 @@ -649,7 +672,7 @@ fn lock_sdist_git_pep508() -> Result<()> { "### ); }); - // } + } Ok(()) }