diff --git a/crates/uv/src/commands/project/lock.rs b/crates/uv/src/commands/project/lock.rs index ef73149e03719..55e50d3a23218 100644 --- a/crates/uv/src/commands/project/lock.rs +++ b/crates/uv/src/commands/project/lock.rs @@ -208,6 +208,22 @@ pub(crate) async fn lock( .await { Ok(lock) => { + if let Some(frozen_source) = frozen { + match frozen_source { + FrozenSource::Cli => { + warn_user!( + "The lockfile at `uv.lock` was only checked for validity, not whether it is up-to-date, because `--frozen` was provided; use `--check` instead" + ); + } + FrozenSource::Env | FrozenSource::Configuration => { + warn_user!( + "The lockfile at `uv.lock` was only checked for validity, not whether it is up-to-date, because {} was provided; use `--no-frozen` or `--check` instead", + MissingLockfileSource::from(frozen_source) + ); + } + } + } + if dry_run.enabled() { // In `--dry-run` mode, show all changes. if let LockResult::Changed(previous, lock) = &lock { @@ -335,6 +351,7 @@ impl<'env> LockOperation<'env> { .read() .await? .ok_or(ProjectError::MissingLockfile(source))?; + // Check if the discovered workspace members match the locked workspace members. if let LockTarget::Workspace(workspace) = target { for package_name in workspace.packages().keys() { diff --git a/crates/uv/tests/it/lock.rs b/crates/uv/tests/it/lock.rs index 59f683b9f0970..22cdd752bc275 100644 --- a/crates/uv/tests/it/lock.rs +++ b/crates/uv/tests/it/lock.rs @@ -33446,3 +33446,54 @@ fn lock_tilde_equal_version_u64_max_rejected() -> Result<()> { Ok(()) } + +/// Test that `uv lock --frozen` and `UV_FROZEN=1` show a warning. +/// +/// See: +#[test] +fn lock_frozen_warning() -> Result<()> { + let context = uv_test::test_context!("3.12"); + + let pyproject_toml = context.temp_dir.child("pyproject.toml"); + pyproject_toml.write_str( + r#" + [project] + name = "project" + version = "0.1.0" + requires-python = ">=3.12" + dependencies = ["iniconfig==2.0.0"] + "#, + )?; + + // Create the initial lockfile. + uv_snapshot!(context.filters(), context.lock(), @" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 2 packages in [TIME] + "); + + // Running `uv lock --frozen` should show a warning. + uv_snapshot!(context.filters(), context.lock().arg("--frozen"), @" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + warning: The lockfile at `uv.lock` was only checked for validity, not whether it is up-to-date, because `--frozen` was provided; use `--check` instead + "); + + // Running `uv lock` with `UV_FROZEN=1` should show a warning. + uv_snapshot!(context.filters(), context.lock().env(EnvVars::UV_FROZEN, "1"), @" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + warning: The lockfile at `uv.lock` was only checked for validity, not whether it is up-to-date, because `UV_FROZEN=1` was provided; use `--no-frozen` or `--check` instead + "); + + Ok(()) +}