mirror of https://github.com/astral-sh/uv
Respect resolved Git SHAs in `uv lock` (#3956)
## Summary This PR ensures that if a lockfile already contains a resolved reference (e.g., you locked with `main` previously, and it locked to a specific commit), and you run `uv lock`, we use the same SHA, even if it's not the latest SHA for that tag. This avoids upgrading Git dependencies without `--upgrade`. Closes #3920.
This commit is contained in:
parent
b7d77c04cc
commit
c04a95e037
|
|
@ -2,7 +2,9 @@ use std::str::FromStr;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
pub use crate::git::GitReference;
|
pub use crate::git::GitReference;
|
||||||
pub use crate::resolver::{GitResolver, GitResolverError, RepositoryReference};
|
pub use crate::resolver::{
|
||||||
|
GitResolver, GitResolverError, RepositoryReference, ResolvedRepositoryReference,
|
||||||
|
};
|
||||||
pub use crate::sha::{GitOid, GitSha, OidParseError};
|
pub use crate::sha::{GitOid, GitSha, OidParseError};
|
||||||
pub use crate::source::{Fetch, GitSource, Reporter};
|
pub use crate::source::{Fetch, GitSource, Reporter};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,15 @@ pub enum GitResolverError {
|
||||||
pub struct GitResolver(Arc<DashMap<RepositoryReference, GitSha>>);
|
pub struct GitResolver(Arc<DashMap<RepositoryReference, GitSha>>);
|
||||||
|
|
||||||
impl GitResolver {
|
impl GitResolver {
|
||||||
|
/// Initialize a [`GitResolver`] with a set of resolved references.
|
||||||
|
pub fn from_refs(refs: Vec<ResolvedRepositoryReference>) -> Self {
|
||||||
|
Self(Arc::new(
|
||||||
|
refs.into_iter()
|
||||||
|
.map(|ResolvedRepositoryReference { reference, sha }| (reference, sha))
|
||||||
|
.collect(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the [`GitSha`] for the given [`RepositoryReference`], if it exists.
|
/// Returns the [`GitSha`] for the given [`RepositoryReference`], if it exists.
|
||||||
pub fn get(&self, reference: &RepositoryReference) -> Option<Ref<RepositoryReference, GitSha>> {
|
pub fn get(&self, reference: &RepositoryReference) -> Option<Ref<RepositoryReference, GitSha>> {
|
||||||
self.0.get(reference)
|
self.0.get(reference)
|
||||||
|
|
@ -136,11 +145,20 @@ impl GitResolver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct ResolvedRepositoryReference {
|
||||||
|
/// An abstract reference to a Git repository, including the URL and the commit (e.g., a branch,
|
||||||
|
/// tag, or revision).
|
||||||
|
pub reference: RepositoryReference,
|
||||||
|
/// The precise commit SHA of the reference.
|
||||||
|
pub sha: GitSha,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct RepositoryReference {
|
pub struct RepositoryReference {
|
||||||
/// The URL of the Git repository, with any query parameters and fragments removed.
|
/// The URL of the Git repository, with any query parameters and fragments removed.
|
||||||
pub url: RepositoryUrl,
|
pub url: RepositoryUrl,
|
||||||
/// The reference to the commit to use, which could be a branch, tag or revision.
|
/// The reference to the commit to use, which could be a branch, tag, or revision.
|
||||||
pub reference: GitReference,
|
pub reference: GitReference,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,17 @@ use requirements_txt::RequirementsTxt;
|
||||||
use uv_client::{BaseClientBuilder, Connectivity};
|
use uv_client::{BaseClientBuilder, Connectivity};
|
||||||
use uv_configuration::Upgrade;
|
use uv_configuration::Upgrade;
|
||||||
use uv_distribution::ProjectWorkspace;
|
use uv_distribution::ProjectWorkspace;
|
||||||
|
use uv_git::ResolvedRepositoryReference;
|
||||||
use uv_resolver::{Lock, Preference, PreferenceError};
|
use uv_resolver::{Lock, Preference, PreferenceError};
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct LockedRequirements {
|
||||||
|
/// The pinned versions from the lockfile.
|
||||||
|
pub preferences: Vec<Preference>,
|
||||||
|
/// The pinned Git SHAs from the lockfile.
|
||||||
|
pub git: Vec<ResolvedRepositoryReference>,
|
||||||
|
}
|
||||||
|
|
||||||
/// Load the preferred requirements from an existing `requirements.txt`, applying the upgrade strategy.
|
/// Load the preferred requirements from an existing `requirements.txt`, applying the upgrade strategy.
|
||||||
pub async fn read_requirements_txt(
|
pub async fn read_requirements_txt(
|
||||||
output_file: Option<&Path>,
|
output_file: Option<&Path>,
|
||||||
|
|
@ -58,10 +67,10 @@ pub async fn read_requirements_txt(
|
||||||
pub async fn read_lockfile(
|
pub async fn read_lockfile(
|
||||||
project: &ProjectWorkspace,
|
project: &ProjectWorkspace,
|
||||||
upgrade: &Upgrade,
|
upgrade: &Upgrade,
|
||||||
) -> Result<Vec<Preference>> {
|
) -> Result<LockedRequirements> {
|
||||||
// As an optimization, skip reading the lockfile is we're upgrading all packages anyway.
|
// As an optimization, skip reading the lockfile is we're upgrading all packages anyway.
|
||||||
if upgrade.is_all() {
|
if upgrade.is_all() {
|
||||||
return Ok(Vec::new());
|
return Ok(LockedRequirements::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
// If an existing lockfile exists, build up a set of preferences.
|
// If an existing lockfile exists, build up a set of preferences.
|
||||||
|
|
@ -71,32 +80,36 @@ pub async fn read_lockfile(
|
||||||
Ok(lock) => lock,
|
Ok(lock) => lock,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
eprint!("Failed to parse lockfile; ignoring locked requirements: {err}");
|
eprint!("Failed to parse lockfile; ignoring locked requirements: {err}");
|
||||||
return Ok(Vec::new());
|
return Ok(LockedRequirements::default());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
|
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
|
||||||
return Ok(Vec::new());
|
return Ok(LockedRequirements::default());
|
||||||
}
|
}
|
||||||
Err(err) => return Err(err.into()),
|
Err(err) => return Err(err.into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Map each entry in the lockfile to a preference.
|
let mut preferences = Vec::new();
|
||||||
let preferences: Vec<Preference> = lock
|
let mut git = Vec::new();
|
||||||
.distributions()
|
|
||||||
.iter()
|
|
||||||
.map(Preference::from_lock)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
// Apply the upgrade strategy to the requirements.
|
for dist in lock.distributions() {
|
||||||
Ok(match upgrade {
|
// Skip the distribution if it's not included in the upgrade strategy.
|
||||||
// Respect all pinned versions from the existing lockfile.
|
if match upgrade {
|
||||||
Upgrade::None => preferences,
|
Upgrade::None => false,
|
||||||
// Ignore all pinned versions from the existing lockfile.
|
Upgrade::All => true,
|
||||||
Upgrade::All => vec![],
|
Upgrade::Packages(packages) => packages.contains(dist.name()),
|
||||||
// Ignore pinned versions for the specified packages.
|
} {
|
||||||
Upgrade::Packages(packages) => preferences
|
continue;
|
||||||
.into_iter()
|
}
|
||||||
.filter(|preference| !packages.contains(preference.name()))
|
|
||||||
.collect(),
|
// Map each entry in the lockfile to a preference.
|
||||||
})
|
preferences.push(Preference::from_lock(dist));
|
||||||
|
|
||||||
|
// Map each entry in the lockfile to a Git SHA.
|
||||||
|
if let Some(git_ref) = dist.as_git_ref() {
|
||||||
|
git.push(git_ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(LockedRequirements { preferences, git })
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ use std::path::{Path, PathBuf};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use cache_key::RepositoryUrl;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use toml_edit::{value, Array, ArrayOfTables, InlineTable, Item, Table, Value};
|
use toml_edit::{value, Array, ArrayOfTables, InlineTable, Item, Table, Value};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
@ -21,7 +22,7 @@ use pep440_rs::Version;
|
||||||
use pep508_rs::{MarkerEnvironment, VerbatimUrl};
|
use pep508_rs::{MarkerEnvironment, VerbatimUrl};
|
||||||
use platform_tags::{TagCompatibility, TagPriority, Tags};
|
use platform_tags::{TagCompatibility, TagPriority, Tags};
|
||||||
use pypi_types::{HashDigest, ParsedArchiveUrl, ParsedGitUrl};
|
use pypi_types::{HashDigest, ParsedArchiveUrl, ParsedGitUrl};
|
||||||
use uv_git::{GitReference, GitSha};
|
use uv_git::{GitReference, GitSha, RepositoryReference, ResolvedRepositoryReference};
|
||||||
use uv_normalize::{ExtraName, PackageName};
|
use uv_normalize::{ExtraName, PackageName};
|
||||||
|
|
||||||
use crate::resolution::AnnotatedDist;
|
use crate::resolution::AnnotatedDist;
|
||||||
|
|
@ -478,6 +479,25 @@ impl Distribution {
|
||||||
}
|
}
|
||||||
best.map(|(_, i)| i)
|
best.map(|(_, i)| i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the [`PackageName`] of the distribution.
|
||||||
|
pub fn name(&self) -> &PackageName {
|
||||||
|
&self.id.name
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the [`ResolvedRepositoryReference`] for the distribution, if it is a Git source.
|
||||||
|
pub fn as_git_ref(&self) -> Option<ResolvedRepositoryReference> {
|
||||||
|
match &self.id.source.kind {
|
||||||
|
SourceKind::Git(git) => Some(ResolvedRepositoryReference {
|
||||||
|
reference: RepositoryReference {
|
||||||
|
url: RepositoryUrl::new(&self.id.source.url),
|
||||||
|
reference: GitReference::from(git.kind.clone()),
|
||||||
|
},
|
||||||
|
sha: git.precise,
|
||||||
|
}),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, serde::Deserialize)]
|
#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, serde::Deserialize)]
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ use uv_dispatch::BuildDispatch;
|
||||||
use uv_distribution::ProjectWorkspace;
|
use uv_distribution::ProjectWorkspace;
|
||||||
use uv_git::GitResolver;
|
use uv_git::GitResolver;
|
||||||
use uv_interpreter::PythonEnvironment;
|
use uv_interpreter::PythonEnvironment;
|
||||||
use uv_requirements::upgrade::read_lockfile;
|
use uv_requirements::upgrade::{read_lockfile, LockedRequirements};
|
||||||
use uv_resolver::{ExcludeNewer, FlatIndex, InMemoryIndex, Lock, OptionsBuilder};
|
use uv_resolver::{ExcludeNewer, FlatIndex, InMemoryIndex, Lock, OptionsBuilder};
|
||||||
use uv_types::{BuildIsolation, EmptyInstalledPackages, HashStrategy, InFlight};
|
use uv_types::{BuildIsolation, EmptyInstalledPackages, HashStrategy, InFlight};
|
||||||
use uv_warnings::warn_user;
|
use uv_warnings::warn_user;
|
||||||
|
|
@ -105,7 +105,6 @@ pub(super) async fn do_lock(
|
||||||
let config_settings = ConfigSettings::default();
|
let config_settings = ConfigSettings::default();
|
||||||
let extras = ExtrasSpecification::default();
|
let extras = ExtrasSpecification::default();
|
||||||
let flat_index = FlatIndex::default();
|
let flat_index = FlatIndex::default();
|
||||||
let git = GitResolver::default();
|
|
||||||
let in_flight = InFlight::default();
|
let in_flight = InFlight::default();
|
||||||
let index = InMemoryIndex::default();
|
let index = InMemoryIndex::default();
|
||||||
let index_locations = IndexLocations::default();
|
let index_locations = IndexLocations::default();
|
||||||
|
|
@ -119,7 +118,10 @@ pub(super) async fn do_lock(
|
||||||
let options = OptionsBuilder::new().exclude_newer(exclude_newer).build();
|
let options = OptionsBuilder::new().exclude_newer(exclude_newer).build();
|
||||||
|
|
||||||
// If an existing lockfile exists, build up a set of preferences.
|
// If an existing lockfile exists, build up a set of preferences.
|
||||||
let preferences = read_lockfile(project, &upgrade).await?;
|
let LockedRequirements { preferences, git } = read_lockfile(project, &upgrade).await?;
|
||||||
|
|
||||||
|
// Create the Git resolver.
|
||||||
|
let git = GitResolver::from_refs(git);
|
||||||
|
|
||||||
// Create a build dispatch.
|
// Create a build dispatch.
|
||||||
let build_dispatch = BuildDispatch::new(
|
let build_dispatch = BuildDispatch::new(
|
||||||
|
|
|
||||||
|
|
@ -348,7 +348,7 @@ fn lock_sdist_git() -> Result<()> {
|
||||||
[project]
|
[project]
|
||||||
name = "project"
|
name = "project"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = ["anyio @ git+https://github.com/agronholm/anyio@3.7.0"]
|
dependencies = ["uv-public-pypackage @ git+https://github.com/astral-test/uv-public-pypackage@0.0.1"]
|
||||||
"#,
|
"#,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
|
@ -359,7 +359,7 @@ fn lock_sdist_git() -> Result<()> {
|
||||||
|
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
warning: `uv lock` is experimental and may change without warning.
|
warning: `uv lock` is experimental and may change without warning.
|
||||||
Resolved 4 packages in [TIME]
|
Resolved 2 packages in [TIME]
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
let lock = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?;
|
let lock = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?;
|
||||||
|
|
@ -371,29 +371,6 @@ fn lock_sdist_git() -> Result<()> {
|
||||||
lock, @r###"
|
lock, @r###"
|
||||||
version = 1
|
version = 1
|
||||||
|
|
||||||
[[distribution]]
|
|
||||||
name = "anyio"
|
|
||||||
version = "3.7.0"
|
|
||||||
source = "git+https://github.com/agronholm/anyio?rev=3.7.0#f7a880ffac4766efb39e6fb60fc28d944f5d2f65"
|
|
||||||
sdist = { url = "https://github.com/agronholm/anyio?rev=3.7.0#f7a880ffac4766efb39e6fb60fc28d944f5d2f65" }
|
|
||||||
|
|
||||||
[[distribution.dependencies]]
|
|
||||||
name = "idna"
|
|
||||||
version = "3.6"
|
|
||||||
source = "registry+https://pypi.org/simple"
|
|
||||||
|
|
||||||
[[distribution.dependencies]]
|
|
||||||
name = "sniffio"
|
|
||||||
version = "1.3.1"
|
|
||||||
source = "registry+https://pypi.org/simple"
|
|
||||||
|
|
||||||
[[distribution]]
|
|
||||||
name = "idna"
|
|
||||||
version = "3.6"
|
|
||||||
source = "registry+https://pypi.org/simple"
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/bf/3f/ea4b9117521a1e9c50344b909be7886dd00a519552724809bb1f486986c2/idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca", size = 175426 }
|
|
||||||
wheels = [{ url = "https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f", size = 61567 }]
|
|
||||||
|
|
||||||
[[distribution]]
|
[[distribution]]
|
||||||
name = "project"
|
name = "project"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
@ -401,16 +378,15 @@ fn lock_sdist_git() -> Result<()> {
|
||||||
sdist = { url = "file://[TEMP_DIR]/" }
|
sdist = { url = "file://[TEMP_DIR]/" }
|
||||||
|
|
||||||
[[distribution.dependencies]]
|
[[distribution.dependencies]]
|
||||||
name = "anyio"
|
name = "uv-public-pypackage"
|
||||||
version = "3.7.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/agronholm/anyio?rev=3.7.0#f7a880ffac4766efb39e6fb60fc28d944f5d2f65"
|
source = "git+https://github.com/astral-test/uv-public-pypackage?rev=0.0.1#0dacfd662c64cb4ceb16e6cf65a157a8b715b979"
|
||||||
|
|
||||||
[[distribution]]
|
[[distribution]]
|
||||||
name = "sniffio"
|
name = "uv-public-pypackage"
|
||||||
version = "1.3.1"
|
version = "0.1.0"
|
||||||
source = "registry+https://pypi.org/simple"
|
source = "git+https://github.com/astral-test/uv-public-pypackage?rev=0.0.1#0dacfd662c64cb4ceb16e6cf65a157a8b715b979"
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372 }
|
sdist = { url = "https://github.com/astral-test/uv-public-pypackage?rev=0.0.1#0dacfd662c64cb4ceb16e6cf65a157a8b715b979" }
|
||||||
wheels = [{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 }]
|
|
||||||
"###
|
"###
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
@ -423,12 +399,10 @@ fn lock_sdist_git() -> Result<()> {
|
||||||
|
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
warning: `uv sync` is experimental and may change without warning.
|
warning: `uv sync` is experimental and may change without warning.
|
||||||
Downloaded 4 packages in [TIME]
|
Downloaded 2 packages in [TIME]
|
||||||
Installed 4 packages in [TIME]
|
Installed 2 packages in [TIME]
|
||||||
+ anyio==3.7.0 (from git+https://github.com/agronholm/anyio@f7a880ffac4766efb39e6fb60fc28d944f5d2f65)
|
|
||||||
+ idna==3.6
|
|
||||||
+ project==0.1.0 (from file://[TEMP_DIR]/)
|
+ project==0.1.0 (from file://[TEMP_DIR]/)
|
||||||
+ sniffio==1.3.1
|
+ uv-public-pypackage==0.1.0 (from git+https://github.com/astral-test/uv-public-pypackage@0dacfd662c64cb4ceb16e6cf65a157a8b715b979)
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -915,3 +889,159 @@ fn lock_preference() -> Result<()> {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Respect locked versions with `uv lock`, unless `--upgrade` is passed.
|
||||||
|
#[test]
|
||||||
|
fn lock_git_sha() -> Result<()> {
|
||||||
|
let context = TestContext::new("3.12");
|
||||||
|
|
||||||
|
// Lock to a specific commit on `main`.
|
||||||
|
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||||
|
pyproject_toml.write_str(
|
||||||
|
r#"
|
||||||
|
[project]
|
||||||
|
name = "project"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = ["uv-public-pypackage @ git+https://github.com/astral-test/uv-public-pypackage@0dacfd662c64cb4ceb16e6cf65a157a8b715b979"]
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
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 2 packages in [TIME]
|
||||||
|
"###);
|
||||||
|
|
||||||
|
let lock = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?;
|
||||||
|
|
||||||
|
insta::with_settings!({
|
||||||
|
filters => context.filters(),
|
||||||
|
}, {
|
||||||
|
assert_snapshot!(
|
||||||
|
lock, @r###"
|
||||||
|
version = 1
|
||||||
|
|
||||||
|
[[distribution]]
|
||||||
|
name = "project"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "editable+file://[TEMP_DIR]/"
|
||||||
|
sdist = { url = "file://[TEMP_DIR]/" }
|
||||||
|
|
||||||
|
[[distribution.dependencies]]
|
||||||
|
name = "uv-public-pypackage"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/astral-test/uv-public-pypackage?rev=0dacfd662c64cb4ceb16e6cf65a157a8b715b979#0dacfd662c64cb4ceb16e6cf65a157a8b715b979"
|
||||||
|
|
||||||
|
[[distribution]]
|
||||||
|
name = "uv-public-pypackage"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/astral-test/uv-public-pypackage?rev=0dacfd662c64cb4ceb16e6cf65a157a8b715b979#0dacfd662c64cb4ceb16e6cf65a157a8b715b979"
|
||||||
|
sdist = { url = "https://github.com/astral-test/uv-public-pypackage?rev=0dacfd662c64cb4ceb16e6cf65a157a8b715b979#0dacfd662c64cb4ceb16e6cf65a157a8b715b979" }
|
||||||
|
"###
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Rewrite the lockfile, as if it were locked against `main`.
|
||||||
|
let lock = lock.replace("rev=0dacfd662c64cb4ceb16e6cf65a157a8b715b979", "rev=main");
|
||||||
|
fs_err::write(context.temp_dir.join("uv.lock"), lock)?;
|
||||||
|
|
||||||
|
// Lock `anyio` against `main`.
|
||||||
|
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||||
|
pyproject_toml.write_str(
|
||||||
|
r#"
|
||||||
|
[project]
|
||||||
|
name = "project"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = ["uv-public-pypackage @ git+https://github.com/astral-test/uv-public-pypackage@main"]
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
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 2 packages in [TIME]
|
||||||
|
"###);
|
||||||
|
|
||||||
|
let lock = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?;
|
||||||
|
|
||||||
|
// The lockfile should resolve to `0dacfd662c64cb4ceb16e6cf65a157a8b715b979`, even though it's
|
||||||
|
// not the latest commit on `main`.
|
||||||
|
insta::with_settings!({
|
||||||
|
filters => context.filters(),
|
||||||
|
}, {
|
||||||
|
assert_snapshot!(
|
||||||
|
lock, @r###"
|
||||||
|
version = 1
|
||||||
|
|
||||||
|
[[distribution]]
|
||||||
|
name = "project"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "editable+file://[TEMP_DIR]/"
|
||||||
|
sdist = { url = "file://[TEMP_DIR]/" }
|
||||||
|
|
||||||
|
[[distribution.dependencies]]
|
||||||
|
name = "uv-public-pypackage"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/astral-test/uv-public-pypackage?rev=main#0dacfd662c64cb4ceb16e6cf65a157a8b715b979"
|
||||||
|
|
||||||
|
[[distribution]]
|
||||||
|
name = "uv-public-pypackage"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/astral-test/uv-public-pypackage?rev=main#0dacfd662c64cb4ceb16e6cf65a157a8b715b979"
|
||||||
|
sdist = { url = "https://github.com/astral-test/uv-public-pypackage?rev=main#0dacfd662c64cb4ceb16e6cf65a157a8b715b979" }
|
||||||
|
"###
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Relock with `--upgrade`.
|
||||||
|
uv_snapshot!(context.filters(), context.lock().arg("--upgrade-package").arg("uv-public-pypackage"), @r###"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
warning: `uv lock` is experimental and may change without warning.
|
||||||
|
Resolved 2 packages in [TIME]
|
||||||
|
"###);
|
||||||
|
|
||||||
|
let lock = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?;
|
||||||
|
|
||||||
|
// The lockfile should resolve to `b270df1a2fb5d012294e9aaf05e7e0bab1e6a389`, the latest commit
|
||||||
|
// on `main`.
|
||||||
|
insta::with_settings!({
|
||||||
|
filters => context.filters(),
|
||||||
|
}, {
|
||||||
|
assert_snapshot!(
|
||||||
|
lock, @r###"
|
||||||
|
version = 1
|
||||||
|
|
||||||
|
[[distribution]]
|
||||||
|
name = "project"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "editable+file://[TEMP_DIR]/"
|
||||||
|
sdist = { url = "file://[TEMP_DIR]/" }
|
||||||
|
|
||||||
|
[[distribution.dependencies]]
|
||||||
|
name = "uv-public-pypackage"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/astral-test/uv-public-pypackage?rev=main#b270df1a2fb5d012294e9aaf05e7e0bab1e6a389"
|
||||||
|
|
||||||
|
[[distribution]]
|
||||||
|
name = "uv-public-pypackage"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/astral-test/uv-public-pypackage?rev=main#b270df1a2fb5d012294e9aaf05e7e0bab1e6a389"
|
||||||
|
sdist = { url = "https://github.com/astral-test/uv-public-pypackage?rev=main#b270df1a2fb5d012294e9aaf05e7e0bab1e6a389" }
|
||||||
|
"###
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue