mirror of
https://github.com/astral-sh/uv.git
synced 2025-10-29 11:07:59 +00:00
Running uv lock --check with outdated lockfile will print that --check was passed, instead of --locked (#16322)
Hello, # Summary This PR fixes the confusing error message when running `uv lock --check` with an outdated lockfile. Previously, the error message incorrectly stated that `--locked` was provided, even when the user used `--check`. Now, the error message correctly indicates which flag was used: either `--check` or `--locked`. This closes #14105. # Test plan - I updated the existing integration test (`check_outdated_lock` in `lock.rs`) to verify the new error message includes the correct flag. - I ran existing tests to ensure I have no introduced regressions for other commands.
This commit is contained in:
parent
509a1e8ff6
commit
225bffbb6c
15 changed files with 194 additions and 105 deletions
|
|
@ -3719,20 +3719,34 @@ pub struct LockArgs {
|
|||
/// missing or needs to be updated, uv will exit with an error.
|
||||
///
|
||||
/// Equivalent to `--locked`.
|
||||
#[arg(long, alias = "locked", env = EnvVars::UV_LOCKED, value_parser = clap::builder::BoolishValueParser::new(), conflicts_with_all = ["check_exists", "upgrade"])]
|
||||
#[arg(long, env = EnvVars::UV_LOCKED, value_parser = clap::builder::BoolishValueParser::new(), conflicts_with_all = ["check_exists", "upgrade", "locked"])]
|
||||
pub check: bool,
|
||||
|
||||
/// Check if the lockfile is up-to-date.
|
||||
///
|
||||
/// Asserts that the `uv.lock` would remain unchanged after a resolution. If the lockfile is
|
||||
/// missing or needs to be updated, uv will exit with an error.
|
||||
///
|
||||
/// Equivalent to `--check`.
|
||||
#[arg(long, env = EnvVars::UV_LOCKED, value_parser = clap::builder::BoolishValueParser::new(), conflicts_with_all = ["check_exists", "upgrade", "check"], hide = true)]
|
||||
pub locked: bool,
|
||||
|
||||
/// Assert that a `uv.lock` exists without checking if it is up-to-date.
|
||||
///
|
||||
/// Equivalent to `--frozen`.
|
||||
#[arg(long, alias = "frozen", env = EnvVars::UV_FROZEN, value_parser = clap::builder::BoolishValueParser::new(), conflicts_with = "check")]
|
||||
#[arg(long, alias = "frozen", env = EnvVars::UV_FROZEN, value_parser = clap::builder::BoolishValueParser::new(), conflicts_with_all = ["check", "locked"])]
|
||||
pub check_exists: bool,
|
||||
|
||||
/// Perform a dry run, without writing the lockfile.
|
||||
///
|
||||
/// In dry-run mode, uv will resolve the project's dependencies and report on the resulting
|
||||
/// changes, but will not write the lockfile to disk.
|
||||
#[arg(long, conflicts_with = "check_exists", conflicts_with = "check")]
|
||||
#[arg(
|
||||
long,
|
||||
conflicts_with = "check_exists",
|
||||
conflicts_with = "check",
|
||||
conflicts_with = "locked"
|
||||
)]
|
||||
pub dry_run: bool,
|
||||
|
||||
/// Lock the specified Python script, rather than the current project.
|
||||
|
|
|
|||
|
|
@ -59,13 +59,13 @@ use crate::commands::project::{
|
|||
use crate::commands::reporters::{PythonDownloadReporter, ResolverReporter};
|
||||
use crate::commands::{ExitStatus, ScriptPath, diagnostics, project};
|
||||
use crate::printer::Printer;
|
||||
use crate::settings::ResolverInstallerSettings;
|
||||
use crate::settings::{LockCheck, ResolverInstallerSettings};
|
||||
|
||||
/// Add one or more packages to the project requirements.
|
||||
#[allow(clippy::fn_params_excessive_bools)]
|
||||
pub(crate) async fn add(
|
||||
project_dir: &Path,
|
||||
locked: bool,
|
||||
lock_check: LockCheck,
|
||||
frozen: bool,
|
||||
active: Option<bool>,
|
||||
no_sync: bool,
|
||||
|
|
@ -177,9 +177,9 @@ pub(crate) async fn add(
|
|||
"`--package` is a no-op for Python scripts with inline metadata, which always run in isolation"
|
||||
);
|
||||
}
|
||||
if locked {
|
||||
if let LockCheck::Enabled(lock_check) = lock_check {
|
||||
warn_user_once!(
|
||||
"`--locked` is a no-op for Python scripts with inline metadata, which always run in isolation"
|
||||
"`{lock_check}` is a no-op for Python scripts with inline metadata, which always run in isolation"
|
||||
);
|
||||
}
|
||||
if frozen {
|
||||
|
|
@ -728,7 +728,7 @@ pub(crate) async fn add(
|
|||
&edits,
|
||||
lock_state,
|
||||
sync_state,
|
||||
locked,
|
||||
lock_check,
|
||||
no_install_project,
|
||||
no_install_workspace,
|
||||
no_install_local,
|
||||
|
|
@ -959,7 +959,7 @@ async fn lock_and_sync(
|
|||
edits: &[DependencyEdit],
|
||||
lock_state: UniversalState,
|
||||
sync_state: PlatformState,
|
||||
locked: bool,
|
||||
lock_check: LockCheck,
|
||||
no_install_project: bool,
|
||||
no_install_workspace: bool,
|
||||
no_install_local: bool,
|
||||
|
|
@ -977,8 +977,8 @@ async fn lock_and_sync(
|
|||
preview: Preview,
|
||||
) -> Result<(), ProjectError> {
|
||||
let mut lock = project::lock::LockOperation::new(
|
||||
if locked {
|
||||
LockMode::Locked(target.interpreter())
|
||||
if let LockCheck::Enabled(lock_check) = lock_check {
|
||||
LockMode::Locked(target.interpreter(), lock_check)
|
||||
} else {
|
||||
LockMode::Write(target.interpreter())
|
||||
},
|
||||
|
|
@ -1099,8 +1099,8 @@ async fn lock_and_sync(
|
|||
// If the file was modified, we have to lock again, though the only expected change is
|
||||
// the addition of the minimum version specifiers.
|
||||
lock = project::lock::LockOperation::new(
|
||||
if locked {
|
||||
LockMode::Locked(target.interpreter())
|
||||
if let LockCheck::Enabled(lock_check) = lock_check {
|
||||
LockMode::Locked(target.interpreter(), lock_check)
|
||||
} else {
|
||||
LockMode::Write(target.interpreter())
|
||||
},
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ use crate::commands::project::{
|
|||
};
|
||||
use crate::commands::{ExitStatus, OutputWriter, diagnostics};
|
||||
use crate::printer::Printer;
|
||||
use crate::settings::ResolverSettings;
|
||||
use crate::settings::{LockCheck, ResolverSettings};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
|
|
@ -65,7 +65,7 @@ pub(crate) async fn export(
|
|||
extras: ExtrasSpecification,
|
||||
groups: DependencyGroups,
|
||||
editable: Option<EditableMode>,
|
||||
locked: bool,
|
||||
lock_check: LockCheck,
|
||||
frozen: bool,
|
||||
include_annotations: bool,
|
||||
include_header: bool,
|
||||
|
|
@ -172,8 +172,8 @@ pub(crate) async fn export(
|
|||
// Determine the lock mode.
|
||||
let mode = if frozen {
|
||||
LockMode::Frozen
|
||||
} else if locked {
|
||||
LockMode::Locked(interpreter.as_ref().unwrap())
|
||||
} else if let LockCheck::Enabled(lock_check) = lock_check {
|
||||
LockMode::Locked(interpreter.as_ref().unwrap(), lock_check)
|
||||
} else if matches!(target, ExportTarget::Script(_))
|
||||
&& !LockTarget::from(&target).lock_path().is_file()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ use crate::commands::project::{
|
|||
use crate::commands::reporters::{PythonDownloadReporter, ResolverReporter};
|
||||
use crate::commands::{ExitStatus, ScriptPath, diagnostics, pip};
|
||||
use crate::printer::Printer;
|
||||
use crate::settings::ResolverSettings;
|
||||
use crate::settings::{LockCheck, LockCheckSource, ResolverSettings};
|
||||
|
||||
/// The result of running a lock operation.
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
@ -81,7 +81,7 @@ impl LockResult {
|
|||
#[allow(clippy::fn_params_excessive_bools)]
|
||||
pub(crate) async fn lock(
|
||||
project_dir: &Path,
|
||||
locked: bool,
|
||||
lock_check: LockCheck,
|
||||
frozen: bool,
|
||||
dry_run: DryRun,
|
||||
refresh: Refresh,
|
||||
|
|
@ -177,8 +177,8 @@ pub(crate) async fn lock(
|
|||
.into_interpreter(),
|
||||
};
|
||||
|
||||
if locked {
|
||||
LockMode::Locked(&interpreter)
|
||||
if let LockCheck::Enabled(lock_check) = lock_check {
|
||||
LockMode::Locked(&interpreter, lock_check)
|
||||
} else if dry_run.enabled() {
|
||||
LockMode::DryRun(&interpreter)
|
||||
} else {
|
||||
|
|
@ -257,7 +257,7 @@ pub(super) enum LockMode<'env> {
|
|||
/// Perform a resolution, but don't write the lockfile to disk.
|
||||
DryRun(&'env Interpreter),
|
||||
/// Error if the lockfile is not up-to-date with the project requirements.
|
||||
Locked(&'env Interpreter),
|
||||
Locked(&'env Interpreter, LockCheckSource),
|
||||
/// Use the existing lockfile without performing a resolution.
|
||||
Frozen,
|
||||
}
|
||||
|
|
@ -336,7 +336,7 @@ impl<'env> LockOperation<'env> {
|
|||
.ok_or_else(|| ProjectError::MissingLockfile)?;
|
||||
Ok(LockResult::Unchanged(existing))
|
||||
}
|
||||
LockMode::Locked(interpreter) => {
|
||||
LockMode::Locked(interpreter, lock_source) => {
|
||||
// Read the existing lockfile.
|
||||
let existing = target
|
||||
.read()
|
||||
|
|
@ -367,6 +367,7 @@ impl<'env> LockOperation<'env> {
|
|||
return Err(ProjectError::LockMismatch(
|
||||
prev.map(Box::new),
|
||||
Box::new(cur),
|
||||
lock_source,
|
||||
));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,7 +57,9 @@ use crate::commands::project::install_target::InstallTarget;
|
|||
use crate::commands::reporters::{PythonDownloadReporter, ResolverReporter};
|
||||
use crate::commands::{capitalize, conjunction, pip};
|
||||
use crate::printer::Printer;
|
||||
use crate::settings::{InstallerSettingsRef, ResolverInstallerSettings, ResolverSettings};
|
||||
use crate::settings::{
|
||||
InstallerSettingsRef, LockCheckSource, ResolverInstallerSettings, ResolverSettings,
|
||||
};
|
||||
|
||||
pub(crate) mod add;
|
||||
pub(crate) mod environment;
|
||||
|
|
@ -76,9 +78,9 @@ pub(crate) mod version;
|
|||
#[derive(thiserror::Error, Debug)]
|
||||
pub(crate) enum ProjectError {
|
||||
#[error(
|
||||
"The lockfile at `uv.lock` needs to be updated, but `--locked` was provided. To update the lockfile, run `uv lock`."
|
||||
"The lockfile at `uv.lock` needs to be updated, but `{2}` was provided. To update the lockfile, run `uv lock`."
|
||||
)]
|
||||
LockMismatch(Option<Box<Lock>>, Box<Lock>),
|
||||
LockMismatch(Option<Box<Lock>>, Box<Lock>, LockCheckSource),
|
||||
|
||||
#[error(
|
||||
"Unable to find lockfile at `uv.lock`. To create a lockfile, run `uv lock` or `uv sync`."
|
||||
|
|
|
|||
|
|
@ -36,13 +36,13 @@ use crate::commands::project::{
|
|||
};
|
||||
use crate::commands::{ExitStatus, diagnostics, project};
|
||||
use crate::printer::Printer;
|
||||
use crate::settings::ResolverInstallerSettings;
|
||||
use crate::settings::{LockCheck, ResolverInstallerSettings};
|
||||
|
||||
/// Remove one or more packages from the project requirements.
|
||||
#[allow(clippy::fn_params_excessive_bools)]
|
||||
pub(crate) async fn remove(
|
||||
project_dir: &Path,
|
||||
locked: bool,
|
||||
lock_check: LockCheck,
|
||||
frozen: bool,
|
||||
active: Option<bool>,
|
||||
no_sync: bool,
|
||||
|
|
@ -70,9 +70,9 @@ pub(crate) async fn remove(
|
|||
"`--package` is a no-op for Python scripts with inline metadata, which always run in isolation"
|
||||
);
|
||||
}
|
||||
if locked {
|
||||
if let LockCheck::Enabled(lock_check) = lock_check {
|
||||
warn_user_once!(
|
||||
"`--locked` is a no-op for Python scripts with inline metadata, which always run in isolation"
|
||||
"`{lock_check}` is a no-op for Python scripts with inline metadata, which always run in isolation",
|
||||
);
|
||||
}
|
||||
if frozen {
|
||||
|
|
@ -291,8 +291,8 @@ pub(crate) async fn remove(
|
|||
.ok();
|
||||
|
||||
// Determine the lock mode.
|
||||
let mode = if locked {
|
||||
LockMode::Locked(target.interpreter())
|
||||
let mode = if let LockCheck::Enabled(lock_check) = lock_check {
|
||||
LockMode::Locked(target.interpreter(), lock_check)
|
||||
} else {
|
||||
LockMode::Write(target.interpreter())
|
||||
};
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ use crate::commands::project::{
|
|||
use crate::commands::reporters::PythonDownloadReporter;
|
||||
use crate::commands::{ExitStatus, diagnostics, project};
|
||||
use crate::printer::Printer;
|
||||
use crate::settings::{ResolverInstallerSettings, ResolverSettings};
|
||||
use crate::settings::{LockCheck, ResolverInstallerSettings, ResolverSettings};
|
||||
|
||||
/// Run a command.
|
||||
#[allow(clippy::fn_params_excessive_bools)]
|
||||
|
|
@ -83,7 +83,7 @@ pub(crate) async fn run(
|
|||
command: Option<RunCommand>,
|
||||
requirements: Vec<RequirementsSource>,
|
||||
show_resolution: bool,
|
||||
locked: bool,
|
||||
lock_check: LockCheck,
|
||||
frozen: bool,
|
||||
active: Option<bool>,
|
||||
no_sync: bool,
|
||||
|
|
@ -264,8 +264,8 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl
|
|||
// Determine the lock mode.
|
||||
let mode = if frozen {
|
||||
LockMode::Frozen
|
||||
} else if locked {
|
||||
LockMode::Locked(environment.interpreter())
|
||||
} else if let LockCheck::Enabled(lock_check) = lock_check {
|
||||
LockMode::Locked(environment.interpreter(), lock_check)
|
||||
} else {
|
||||
LockMode::Write(environment.interpreter())
|
||||
};
|
||||
|
|
@ -356,9 +356,9 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl
|
|||
Some(environment.into_interpreter())
|
||||
} else {
|
||||
// If no lockfile is found, warn against `--locked` and `--frozen`.
|
||||
if locked {
|
||||
if let LockCheck::Enabled(lock_check) = lock_check {
|
||||
warn_user!(
|
||||
"No lockfile found for Python script (ignoring `--locked`); run `{}` to generate a lockfile",
|
||||
"No lockfile found for Python script (ignoring `{lock_check}`); run `{}` to generate a lockfile",
|
||||
"uv lock --script".green(),
|
||||
);
|
||||
}
|
||||
|
|
@ -588,8 +588,8 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl
|
|||
for flag in groups.history().as_flags_pretty() {
|
||||
warn_user!("`{flag}` has no effect when used alongside `--no-project`");
|
||||
}
|
||||
if locked {
|
||||
warn_user!("`--locked` has no effect when used alongside `--no-project`");
|
||||
if let LockCheck::Enabled(lock_check) = lock_check {
|
||||
warn_user!("`{lock_check}` has no effect when used alongside `--no-project`");
|
||||
}
|
||||
if frozen {
|
||||
warn_user!("`--frozen` has no effect when used alongside `--no-project`");
|
||||
|
|
@ -605,8 +605,8 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl
|
|||
for flag in groups.history().as_flags_pretty() {
|
||||
warn_user!("`{flag}` has no effect when used outside of a project");
|
||||
}
|
||||
if locked {
|
||||
warn_user!("`--locked` has no effect when used outside of a project");
|
||||
if let LockCheck::Enabled(lock_check) = lock_check {
|
||||
warn_user!("`{lock_check}` has no effect when used outside of a project",);
|
||||
}
|
||||
if no_sync {
|
||||
warn_user!("`--no-sync` has no effect when used outside of a project");
|
||||
|
|
@ -740,8 +740,8 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl
|
|||
// Determine the lock mode.
|
||||
let mode = if frozen {
|
||||
LockMode::Frozen
|
||||
} else if locked {
|
||||
LockMode::Locked(venv.interpreter())
|
||||
} else if let LockCheck::Enabled(lock_check) = lock_check {
|
||||
LockMode::Locked(venv.interpreter(), lock_check)
|
||||
} else if isolated {
|
||||
LockMode::DryRun(venv.interpreter())
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -50,13 +50,15 @@ use crate::commands::project::{
|
|||
};
|
||||
use crate::commands::{ExitStatus, diagnostics};
|
||||
use crate::printer::Printer;
|
||||
use crate::settings::{InstallerSettingsRef, ResolverInstallerSettings, ResolverSettings};
|
||||
use crate::settings::{
|
||||
InstallerSettingsRef, LockCheck, LockCheckSource, ResolverInstallerSettings, ResolverSettings,
|
||||
};
|
||||
|
||||
/// Sync the project environment.
|
||||
#[allow(clippy::fn_params_excessive_bools)]
|
||||
pub(crate) async fn sync(
|
||||
project_dir: &Path,
|
||||
locked: bool,
|
||||
lock_check: LockCheck,
|
||||
frozen: bool,
|
||||
dry_run: DryRun,
|
||||
active: Option<bool>,
|
||||
|
|
@ -217,9 +219,9 @@ pub(crate) async fn sync(
|
|||
));
|
||||
}
|
||||
|
||||
if locked {
|
||||
if let LockCheck::Enabled(lock_check) = lock_check {
|
||||
return Err(anyhow::anyhow!(
|
||||
"`uv sync --locked` requires a script lockfile; run `{}` to lock the script",
|
||||
"`uv sync {lock_check}` requires a script lockfile; run `{}` to lock the script",
|
||||
format!("uv lock --script {}", script.path.user_display()).green(),
|
||||
));
|
||||
}
|
||||
|
|
@ -304,8 +306,8 @@ pub(crate) async fn sync(
|
|||
// Determine the lock mode.
|
||||
let mode = if frozen {
|
||||
LockMode::Frozen
|
||||
} else if locked {
|
||||
LockMode::Locked(environment.interpreter())
|
||||
} else if let LockCheck::Enabled(lock_check) = lock_check {
|
||||
LockMode::Locked(environment.interpreter(), lock_check)
|
||||
} else if dry_run.enabled() {
|
||||
LockMode::DryRun(environment.interpreter())
|
||||
} else {
|
||||
|
|
@ -338,16 +340,18 @@ pub(crate) async fn sync(
|
|||
.report(err)
|
||||
.map_or(Ok(ExitStatus::Failure), |err| Err(err.into()));
|
||||
}
|
||||
Err(ProjectError::LockMismatch(prev, cur)) => {
|
||||
Err(ProjectError::LockMismatch(prev, cur, lock_source)) => {
|
||||
if dry_run.enabled() {
|
||||
// The lockfile is mismatched, but we're in dry-run mode. We should proceed with the
|
||||
// sync operation, but exit with a non-zero status.
|
||||
Outcome::LockMismatch(prev, cur)
|
||||
Outcome::LockMismatch(prev, cur, lock_source)
|
||||
} else {
|
||||
writeln!(
|
||||
printer.stderr(),
|
||||
"{}",
|
||||
ProjectError::LockMismatch(prev, cur).to_string().bold()
|
||||
ProjectError::LockMismatch(prev, cur, lock_source)
|
||||
.to_string()
|
||||
.bold()
|
||||
)?;
|
||||
return Ok(ExitStatus::Failure);
|
||||
}
|
||||
|
|
@ -415,11 +419,13 @@ pub(crate) async fn sync(
|
|||
|
||||
match outcome {
|
||||
Outcome::Success(..) => Ok(ExitStatus::Success),
|
||||
Outcome::LockMismatch(prev, cur) => {
|
||||
Outcome::LockMismatch(prev, cur, lock_source) => {
|
||||
writeln!(
|
||||
printer.stderr(),
|
||||
"{}",
|
||||
ProjectError::LockMismatch(prev, cur).to_string().bold()
|
||||
ProjectError::LockMismatch(prev, cur, lock_source)
|
||||
.to_string()
|
||||
.bold()
|
||||
)?;
|
||||
Ok(ExitStatus::Failure)
|
||||
}
|
||||
|
|
@ -433,7 +439,7 @@ enum Outcome {
|
|||
/// The `lock` operation was successful.
|
||||
Success(LockResult),
|
||||
/// The `lock` operation successfully resolved, but failed due to a mismatch (e.g., with `--locked`).
|
||||
LockMismatch(Option<Box<Lock>>, Box<Lock>),
|
||||
LockMismatch(Option<Box<Lock>>, Box<Lock>, LockCheckSource),
|
||||
}
|
||||
|
||||
impl Outcome {
|
||||
|
|
@ -444,7 +450,7 @@ impl Outcome {
|
|||
LockResult::Changed(_, lock) => lock,
|
||||
LockResult::Unchanged(lock) => lock,
|
||||
},
|
||||
Self::LockMismatch(_prev, cur) => cur,
|
||||
Self::LockMismatch(_prev, cur, _lock_source) => cur,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1272,7 +1278,7 @@ impl From<(&LockTarget<'_>, &LockMode<'_>, &Outcome)> for LockReport {
|
|||
LockResult::Unchanged(..) => match mode {
|
||||
// When `--frozen` is used, we don't check the lockfile
|
||||
LockMode::Frozen => LockAction::Use,
|
||||
LockMode::DryRun(_) | LockMode::Locked(_) | LockMode::Write(_) => {
|
||||
LockMode::DryRun(_) | LockMode::Locked(_, _) | LockMode::Write(_) => {
|
||||
LockAction::Check
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ use crate::commands::project::{
|
|||
use crate::commands::reporters::LatestVersionReporter;
|
||||
use crate::commands::{ExitStatus, diagnostics};
|
||||
use crate::printer::Printer;
|
||||
use crate::settings::LockCheck;
|
||||
use crate::settings::ResolverSettings;
|
||||
|
||||
/// Run a command.
|
||||
|
|
@ -36,7 +37,7 @@ use crate::settings::ResolverSettings;
|
|||
pub(crate) async fn tree(
|
||||
project_dir: &Path,
|
||||
groups: DependencyGroups,
|
||||
locked: bool,
|
||||
lock_check: LockCheck,
|
||||
frozen: bool,
|
||||
universal: bool,
|
||||
depth: u8,
|
||||
|
|
@ -125,8 +126,8 @@ pub(crate) async fn tree(
|
|||
// Determine the lock mode.
|
||||
let mode = if frozen {
|
||||
LockMode::Frozen
|
||||
} else if locked {
|
||||
LockMode::Locked(interpreter.as_ref().unwrap())
|
||||
} else if let LockCheck::Enabled(lock_check) = lock_check {
|
||||
LockMode::Locked(interpreter.as_ref().unwrap(), lock_check)
|
||||
} else if matches!(target, LockTarget::Script(_)) && !target.lock_path().is_file() {
|
||||
// If we're locking a script, avoid creating a lockfile if it doesn't already exist.
|
||||
LockMode::DryRun(interpreter.as_ref().unwrap())
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ use crate::commands::project::{
|
|||
};
|
||||
use crate::commands::{ExitStatus, diagnostics, project};
|
||||
use crate::printer::Printer;
|
||||
use crate::settings::ResolverInstallerSettings;
|
||||
use crate::settings::{LockCheck, ResolverInstallerSettings};
|
||||
|
||||
/// Display version information for uv itself (`uv self version`)
|
||||
pub(crate) fn self_version(
|
||||
|
|
@ -63,7 +63,7 @@ pub(crate) async fn project_version(
|
|||
package: Option<PackageName>,
|
||||
explicit_project: bool,
|
||||
dry_run: bool,
|
||||
locked: bool,
|
||||
lock_check: LockCheck,
|
||||
frozen: bool,
|
||||
active: Option<bool>,
|
||||
no_sync: bool,
|
||||
|
|
@ -297,7 +297,7 @@ pub(crate) async fn project_version(
|
|||
Box::pin(lock_and_sync(
|
||||
project,
|
||||
project_dir,
|
||||
locked,
|
||||
lock_check,
|
||||
frozen,
|
||||
active,
|
||||
no_sync,
|
||||
|
|
@ -502,7 +502,7 @@ async fn print_frozen_version(
|
|||
async fn lock_and_sync(
|
||||
project: VirtualProject,
|
||||
project_dir: &Path,
|
||||
locked: bool,
|
||||
lock_check: LockCheck,
|
||||
frozen: bool,
|
||||
active: Option<bool>,
|
||||
no_sync: bool,
|
||||
|
|
@ -579,8 +579,8 @@ async fn lock_and_sync(
|
|||
};
|
||||
|
||||
// Determine the lock mode.
|
||||
let mode = if locked {
|
||||
LockMode::Locked(target.interpreter())
|
||||
let mode = if let LockCheck::Enabled(lock_check) = lock_check {
|
||||
LockMode::Locked(target.interpreter(), lock_check)
|
||||
} else {
|
||||
LockMode::Write(target.interpreter())
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1844,7 +1844,7 @@ async fn run_project(
|
|||
command,
|
||||
requirements,
|
||||
args.show_resolution || globals.verbose > 0,
|
||||
args.locked,
|
||||
args.lock_check,
|
||||
args.frozen,
|
||||
args.active,
|
||||
args.no_sync,
|
||||
|
|
@ -1895,7 +1895,7 @@ async fn run_project(
|
|||
|
||||
Box::pin(commands::sync(
|
||||
project_dir,
|
||||
args.locked,
|
||||
args.lock_check,
|
||||
args.frozen,
|
||||
args.dry_run,
|
||||
args.active,
|
||||
|
|
@ -1951,7 +1951,7 @@ async fn run_project(
|
|||
|
||||
Box::pin(commands::lock(
|
||||
project_dir,
|
||||
args.locked,
|
||||
args.lock_check,
|
||||
args.frozen,
|
||||
args.dry_run,
|
||||
args.refresh,
|
||||
|
|
@ -2056,7 +2056,7 @@ async fn run_project(
|
|||
|
||||
Box::pin(commands::add(
|
||||
project_dir,
|
||||
args.locked,
|
||||
args.lock_check,
|
||||
args.frozen,
|
||||
args.active,
|
||||
args.no_sync,
|
||||
|
|
@ -2114,7 +2114,7 @@ async fn run_project(
|
|||
|
||||
Box::pin(commands::remove(
|
||||
project_dir,
|
||||
args.locked,
|
||||
args.lock_check,
|
||||
args.frozen,
|
||||
args.active,
|
||||
args.no_sync,
|
||||
|
|
@ -2158,7 +2158,7 @@ async fn run_project(
|
|||
args.package,
|
||||
explicit_project,
|
||||
args.dry_run,
|
||||
args.locked,
|
||||
args.lock_check,
|
||||
args.frozen,
|
||||
args.active,
|
||||
args.no_sync,
|
||||
|
|
@ -2195,7 +2195,7 @@ async fn run_project(
|
|||
Box::pin(commands::tree(
|
||||
project_dir,
|
||||
args.groups,
|
||||
args.locked,
|
||||
args.lock_check,
|
||||
args.frozen,
|
||||
args.universal,
|
||||
args.depth,
|
||||
|
|
@ -2249,7 +2249,7 @@ async fn run_project(
|
|||
args.extras,
|
||||
args.groups,
|
||||
args.editable,
|
||||
args.locked,
|
||||
args.lock_check,
|
||||
args.frozen,
|
||||
args.include_annotations,
|
||||
args.include_header,
|
||||
|
|
|
|||
|
|
@ -347,10 +347,37 @@ impl InitSettings {
|
|||
}
|
||||
}
|
||||
|
||||
/// The source of a lock check operation.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub(crate) enum LockCheckSource {
|
||||
/// The user invoked `uv <command> --locked`
|
||||
Locked,
|
||||
/// The user invoked `uv <command> --check`
|
||||
Check,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for LockCheckSource {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Locked => write!(f, "--locked"),
|
||||
Self::Check => write!(f, "--check"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Has lock check been enabled?
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub(crate) enum LockCheck {
|
||||
/// Lockfile check is enabled.
|
||||
Enabled(LockCheckSource),
|
||||
/// Lockfile check is disabled.
|
||||
Disabled,
|
||||
}
|
||||
|
||||
/// The resolved settings to use for a `run` invocation.
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct RunSettings {
|
||||
pub(crate) locked: bool,
|
||||
pub(crate) lock_check: LockCheck,
|
||||
pub(crate) frozen: bool,
|
||||
pub(crate) extras: ExtrasSpecification,
|
||||
pub(crate) groups: DependencyGroups,
|
||||
|
|
@ -439,7 +466,11 @@ impl RunSettings {
|
|||
.unwrap_or_default();
|
||||
|
||||
Self {
|
||||
locked,
|
||||
lock_check: if locked {
|
||||
LockCheck::Enabled(LockCheckSource::Locked)
|
||||
} else {
|
||||
LockCheck::Disabled
|
||||
},
|
||||
frozen,
|
||||
extras: ExtrasSpecification::from_args(
|
||||
extra.unwrap_or_default(),
|
||||
|
|
@ -1263,7 +1294,7 @@ impl PythonPinSettings {
|
|||
#[allow(clippy::struct_excessive_bools, dead_code)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct SyncSettings {
|
||||
pub(crate) locked: bool,
|
||||
pub(crate) lock_check: LockCheck,
|
||||
pub(crate) frozen: bool,
|
||||
pub(crate) dry_run: DryRun,
|
||||
pub(crate) script: Option<PathBuf>,
|
||||
|
|
@ -1345,10 +1376,15 @@ impl SyncSettings {
|
|||
} else {
|
||||
DryRun::from_args(dry_run)
|
||||
};
|
||||
let lock_check = if locked {
|
||||
LockCheck::Enabled(LockCheckSource::Locked)
|
||||
} else {
|
||||
LockCheck::Disabled
|
||||
};
|
||||
|
||||
Self {
|
||||
output_format,
|
||||
locked,
|
||||
lock_check,
|
||||
frozen,
|
||||
dry_run,
|
||||
script,
|
||||
|
|
@ -1401,7 +1437,7 @@ impl SyncSettings {
|
|||
#[allow(clippy::struct_excessive_bools, dead_code)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct LockSettings {
|
||||
pub(crate) locked: bool,
|
||||
pub(crate) lock_check: LockCheck,
|
||||
pub(crate) frozen: bool,
|
||||
pub(crate) dry_run: DryRun,
|
||||
pub(crate) script: Option<PathBuf>,
|
||||
|
|
@ -1421,6 +1457,7 @@ impl LockSettings {
|
|||
) -> Self {
|
||||
let LockArgs {
|
||||
check,
|
||||
locked,
|
||||
check_exists,
|
||||
dry_run,
|
||||
script,
|
||||
|
|
@ -1435,8 +1472,16 @@ impl LockSettings {
|
|||
.map(|fs| fs.install_mirrors.clone())
|
||||
.unwrap_or_default();
|
||||
|
||||
let lock_check = if check {
|
||||
LockCheck::Enabled(LockCheckSource::Check)
|
||||
} else if locked {
|
||||
LockCheck::Enabled(LockCheckSource::Locked)
|
||||
} else {
|
||||
LockCheck::Disabled
|
||||
};
|
||||
|
||||
Self {
|
||||
locked: check,
|
||||
lock_check,
|
||||
frozen: check_exists,
|
||||
dry_run: DryRun::from_args(dry_run),
|
||||
script,
|
||||
|
|
@ -1454,7 +1499,7 @@ impl LockSettings {
|
|||
#[allow(clippy::struct_excessive_bools, dead_code)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct AddSettings {
|
||||
pub(crate) locked: bool,
|
||||
pub(crate) lock_check: LockCheck,
|
||||
pub(crate) frozen: bool,
|
||||
pub(crate) active: Option<bool>,
|
||||
pub(crate) no_sync: bool,
|
||||
|
|
@ -1603,7 +1648,11 @@ impl AddSettings {
|
|||
let bounds = bounds.or(filesystem.as_ref().and_then(|fs| fs.add.add_bounds));
|
||||
|
||||
Self {
|
||||
locked,
|
||||
lock_check: if locked {
|
||||
LockCheck::Enabled(LockCheckSource::Locked)
|
||||
} else {
|
||||
LockCheck::Disabled
|
||||
},
|
||||
frozen,
|
||||
active: flag(active, no_active, "active"),
|
||||
no_sync,
|
||||
|
|
@ -1646,7 +1695,7 @@ impl AddSettings {
|
|||
#[allow(clippy::struct_excessive_bools, dead_code)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct RemoveSettings {
|
||||
pub(crate) locked: bool,
|
||||
pub(crate) lock_check: LockCheck,
|
||||
pub(crate) frozen: bool,
|
||||
pub(crate) active: Option<bool>,
|
||||
pub(crate) no_sync: bool,
|
||||
|
|
@ -1707,7 +1756,11 @@ impl RemoveSettings {
|
|||
.collect();
|
||||
|
||||
Self {
|
||||
locked,
|
||||
lock_check: if locked {
|
||||
LockCheck::Enabled(LockCheckSource::Locked)
|
||||
} else {
|
||||
LockCheck::Disabled
|
||||
},
|
||||
frozen,
|
||||
active: flag(active, no_active, "active"),
|
||||
no_sync,
|
||||
|
|
@ -1737,7 +1790,7 @@ pub(crate) struct VersionSettings {
|
|||
pub(crate) short: bool,
|
||||
pub(crate) output_format: VersionFormat,
|
||||
pub(crate) dry_run: bool,
|
||||
pub(crate) locked: bool,
|
||||
pub(crate) lock_check: LockCheck,
|
||||
pub(crate) frozen: bool,
|
||||
pub(crate) active: Option<bool>,
|
||||
pub(crate) no_sync: bool,
|
||||
|
|
@ -1785,7 +1838,11 @@ impl VersionSettings {
|
|||
short,
|
||||
output_format,
|
||||
dry_run,
|
||||
locked,
|
||||
lock_check: if locked {
|
||||
LockCheck::Enabled(LockCheckSource::Locked)
|
||||
} else {
|
||||
LockCheck::Disabled
|
||||
},
|
||||
frozen,
|
||||
active: flag(active, no_active, "active"),
|
||||
no_sync,
|
||||
|
|
@ -1807,7 +1864,7 @@ impl VersionSettings {
|
|||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct TreeSettings {
|
||||
pub(crate) groups: DependencyGroups,
|
||||
pub(crate) locked: bool,
|
||||
pub(crate) lock_check: LockCheck,
|
||||
pub(crate) frozen: bool,
|
||||
pub(crate) universal: bool,
|
||||
pub(crate) depth: u8,
|
||||
|
|
@ -1870,7 +1927,11 @@ impl TreeSettings {
|
|||
only_group,
|
||||
all_groups,
|
||||
),
|
||||
locked,
|
||||
lock_check: if locked {
|
||||
LockCheck::Enabled(LockCheckSource::Locked)
|
||||
} else {
|
||||
LockCheck::Disabled
|
||||
},
|
||||
frozen,
|
||||
universal,
|
||||
depth: tree.depth,
|
||||
|
|
@ -1906,7 +1967,7 @@ pub(crate) struct ExportSettings {
|
|||
pub(crate) hashes: bool,
|
||||
pub(crate) install_options: InstallOptions,
|
||||
pub(crate) output_file: Option<PathBuf>,
|
||||
pub(crate) locked: bool,
|
||||
pub(crate) lock_check: LockCheck,
|
||||
pub(crate) frozen: bool,
|
||||
pub(crate) include_annotations: bool,
|
||||
pub(crate) include_header: bool,
|
||||
|
|
@ -2001,7 +2062,11 @@ impl ExportSettings {
|
|||
no_emit_package,
|
||||
),
|
||||
output_file,
|
||||
locked,
|
||||
lock_check: if locked {
|
||||
LockCheck::Enabled(LockCheckSource::Locked)
|
||||
} else {
|
||||
LockCheck::Disabled
|
||||
},
|
||||
frozen,
|
||||
include_annotations: flag(annotate, no_annotate, "annotate").unwrap_or(true),
|
||||
include_header: flag(header, no_header, "header").unwrap_or(true),
|
||||
|
|
|
|||
|
|
@ -13193,7 +13193,7 @@ fn check_outdated_lock() -> Result<()> {
|
|||
|
||||
----- stderr -----
|
||||
Resolved 2 packages in [TIME]
|
||||
The lockfile at `uv.lock` needs to be updated, but `--locked` was provided. To update the lockfile, run `uv lock`.
|
||||
The lockfile at `uv.lock` needs to be updated, but `--check` was provided. To update the lockfile, run `uv lock`.
|
||||
");
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7780,7 +7780,7 @@ fn preview_features() {
|
|||
short: false,
|
||||
output_format: Text,
|
||||
dry_run: false,
|
||||
locked: false,
|
||||
lock_check: Disabled,
|
||||
frozen: false,
|
||||
active: None,
|
||||
no_sync: false,
|
||||
|
|
@ -7894,7 +7894,7 @@ fn preview_features() {
|
|||
short: false,
|
||||
output_format: Text,
|
||||
dry_run: false,
|
||||
locked: false,
|
||||
lock_check: Disabled,
|
||||
frozen: false,
|
||||
active: None,
|
||||
no_sync: false,
|
||||
|
|
@ -8008,7 +8008,7 @@ fn preview_features() {
|
|||
short: false,
|
||||
output_format: Text,
|
||||
dry_run: false,
|
||||
locked: false,
|
||||
lock_check: Disabled,
|
||||
frozen: false,
|
||||
active: None,
|
||||
no_sync: false,
|
||||
|
|
@ -8122,7 +8122,7 @@ fn preview_features() {
|
|||
short: false,
|
||||
output_format: Text,
|
||||
dry_run: false,
|
||||
locked: false,
|
||||
lock_check: Disabled,
|
||||
frozen: false,
|
||||
active: None,
|
||||
no_sync: false,
|
||||
|
|
@ -8236,7 +8236,7 @@ fn preview_features() {
|
|||
short: false,
|
||||
output_format: Text,
|
||||
dry_run: false,
|
||||
locked: false,
|
||||
lock_check: Disabled,
|
||||
frozen: false,
|
||||
active: None,
|
||||
no_sync: false,
|
||||
|
|
@ -8352,7 +8352,7 @@ fn preview_features() {
|
|||
short: false,
|
||||
output_format: Text,
|
||||
dry_run: false,
|
||||
locked: false,
|
||||
lock_check: Disabled,
|
||||
frozen: false,
|
||||
active: None,
|
||||
no_sync: false,
|
||||
|
|
@ -9596,7 +9596,7 @@ fn upgrade_project_cli_config_interaction() -> anyhow::Result<()> {
|
|||
),
|
||||
}
|
||||
LockSettings {
|
||||
locked: false,
|
||||
lock_check: Disabled,
|
||||
frozen: false,
|
||||
dry_run: Disabled,
|
||||
script: None,
|
||||
|
|
@ -9715,7 +9715,7 @@ fn upgrade_project_cli_config_interaction() -> anyhow::Result<()> {
|
|||
),
|
||||
}
|
||||
LockSettings {
|
||||
locked: false,
|
||||
lock_check: Disabled,
|
||||
frozen: false,
|
||||
dry_run: Disabled,
|
||||
script: None,
|
||||
|
|
@ -9857,7 +9857,7 @@ fn upgrade_project_cli_config_interaction() -> anyhow::Result<()> {
|
|||
),
|
||||
}
|
||||
LockSettings {
|
||||
locked: false,
|
||||
lock_check: Disabled,
|
||||
frozen: false,
|
||||
dry_run: Disabled,
|
||||
script: None,
|
||||
|
|
@ -9974,7 +9974,7 @@ fn upgrade_project_cli_config_interaction() -> anyhow::Result<()> {
|
|||
),
|
||||
}
|
||||
LockSettings {
|
||||
locked: false,
|
||||
lock_check: Disabled,
|
||||
frozen: false,
|
||||
dry_run: Disabled,
|
||||
script: None,
|
||||
|
|
@ -10081,7 +10081,7 @@ fn upgrade_project_cli_config_interaction() -> anyhow::Result<()> {
|
|||
),
|
||||
}
|
||||
LockSettings {
|
||||
locked: false,
|
||||
lock_check: Disabled,
|
||||
frozen: false,
|
||||
dry_run: Disabled,
|
||||
script: None,
|
||||
|
|
@ -10189,7 +10189,7 @@ fn upgrade_project_cli_config_interaction() -> anyhow::Result<()> {
|
|||
),
|
||||
}
|
||||
LockSettings {
|
||||
locked: false,
|
||||
lock_check: Disabled,
|
||||
frozen: false,
|
||||
dry_run: Disabled,
|
||||
script: None,
|
||||
|
|
|
|||
|
|
@ -1634,7 +1634,7 @@ uv lock [OPTIONS]
|
|||
<p>May also be set with the <code>UV_INSECURE_HOST</code> environment variable.</p></dd><dt id="uv-lock--cache-dir"><a href="#uv-lock--cache-dir"><code>--cache-dir</code></a> <i>cache-dir</i></dt><dd><p>Path to the cache directory.</p>
|
||||
<p>Defaults to <code>$XDG_CACHE_HOME/uv</code> or <code>$HOME/.cache/uv</code> on macOS and Linux, and <code>%LOCALAPPDATA%\uv\cache</code> on Windows.</p>
|
||||
<p>To view the location of the cache directory, run <code>uv cache dir</code>.</p>
|
||||
<p>May also be set with the <code>UV_CACHE_DIR</code> environment variable.</p></dd><dt id="uv-lock--check"><a href="#uv-lock--check"><code>--check</code></a>, <code>--locked</code></dt><dd><p>Check if the lockfile is up-to-date.</p>
|
||||
<p>May also be set with the <code>UV_CACHE_DIR</code> environment variable.</p></dd><dt id="uv-lock--check"><a href="#uv-lock--check"><code>--check</code></a></dt><dd><p>Check if the lockfile is up-to-date.</p>
|
||||
<p>Asserts that the <code>uv.lock</code> would remain unchanged after a resolution. If the lockfile is missing or needs to be updated, uv will exit with an error.</p>
|
||||
<p>Equivalent to <code>--locked</code>.</p>
|
||||
<p>May also be set with the <code>UV_LOCKED</code> environment variable.</p></dd><dt id="uv-lock--check-exists"><a href="#uv-lock--check-exists"><code>--check-exists</code></a>, <code>--frozen</code></dt><dd><p>Assert that a <code>uv.lock</code> exists without checking if it is up-to-date.</p>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue