mirror of https://github.com/astral-sh/uv
Add `uv sync --check` flag (#12342)
## Summary Closes #12338 ## Test Plan `cargo test` --------- Co-authored-by: Zanie Blue <contact@zanie.dev>
This commit is contained in:
parent
26d40cb8a5
commit
a80353de2b
|
|
@ -3285,6 +3285,15 @@ pub struct SyncArgs {
|
||||||
value_parser = parse_maybe_string,
|
value_parser = parse_maybe_string,
|
||||||
)]
|
)]
|
||||||
pub python: Option<Maybe<String>>,
|
pub python: Option<Maybe<String>>,
|
||||||
|
|
||||||
|
/// Check if the Python environment is synchronized with the project.
|
||||||
|
///
|
||||||
|
/// If the environment is not up to date, uv will exit with an error.
|
||||||
|
#[arg(long, overrides_with("no_check"))]
|
||||||
|
pub check: bool,
|
||||||
|
|
||||||
|
#[arg(long, overrides_with("check"), hide = true)]
|
||||||
|
pub no_check: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,9 @@
|
||||||
pub enum DryRun {
|
pub enum DryRun {
|
||||||
/// The operation should execute in dry run mode.
|
/// The operation should execute in dry run mode.
|
||||||
Enabled,
|
Enabled,
|
||||||
|
/// The operation should execute in dry run mode and check if the current environment is
|
||||||
|
/// synced.
|
||||||
|
Check,
|
||||||
/// The operation should execute in normal mode.
|
/// The operation should execute in normal mode.
|
||||||
#[default]
|
#[default]
|
||||||
Disabled,
|
Disabled,
|
||||||
|
|
@ -19,6 +22,6 @@ impl DryRun {
|
||||||
|
|
||||||
/// Returns `true` if dry run mode is enabled.
|
/// Returns `true` if dry run mode is enabled.
|
||||||
pub const fn enabled(&self) -> bool {
|
pub const fn enabled(&self) -> bool {
|
||||||
matches!(self, DryRun::Enabled)
|
matches!(self, DryRun::Enabled) || matches!(self, DryRun::Check)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -438,7 +438,7 @@ pub(crate) async fn install(
|
||||||
.context("Failed to determine installation plan")?;
|
.context("Failed to determine installation plan")?;
|
||||||
|
|
||||||
if dry_run.enabled() {
|
if dry_run.enabled() {
|
||||||
report_dry_run(resolution, plan, modifications, start, printer)?;
|
report_dry_run(dry_run, resolution, plan, modifications, start, printer)?;
|
||||||
return Ok(Changelog::default());
|
return Ok(Changelog::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -665,6 +665,7 @@ pub(crate) fn report_target_environment(
|
||||||
|
|
||||||
/// Report on the results of a dry-run installation.
|
/// Report on the results of a dry-run installation.
|
||||||
fn report_dry_run(
|
fn report_dry_run(
|
||||||
|
dry_run: DryRun,
|
||||||
resolution: &Resolution,
|
resolution: &Resolution,
|
||||||
plan: Plan,
|
plan: Plan,
|
||||||
modifications: Modifications,
|
modifications: Modifications,
|
||||||
|
|
@ -788,6 +789,10 @@ fn report_dry_run(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if matches!(dry_run, DryRun::Check) {
|
||||||
|
return Err(Error::OutdatedEnvironment);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -859,4 +864,7 @@ pub(crate) enum Error {
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Anyhow(#[from] anyhow::Error),
|
Anyhow(#[from] anyhow::Error),
|
||||||
|
|
||||||
|
#[error("The environment is outdated; run `{}` to update the environment", "uv sync".cyan())]
|
||||||
|
OutdatedEnvironment,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1075,6 +1075,8 @@ impl SyncSettings {
|
||||||
package,
|
package,
|
||||||
script,
|
script,
|
||||||
python,
|
python,
|
||||||
|
check,
|
||||||
|
no_check,
|
||||||
} = args;
|
} = args;
|
||||||
let install_mirrors = filesystem
|
let install_mirrors = filesystem
|
||||||
.clone()
|
.clone()
|
||||||
|
|
@ -1086,10 +1088,17 @@ impl SyncSettings {
|
||||||
filesystem,
|
filesystem,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let check = flag(check, no_check).unwrap_or_default();
|
||||||
|
let dry_run = if check {
|
||||||
|
DryRun::Check
|
||||||
|
} else {
|
||||||
|
DryRun::from_args(dry_run)
|
||||||
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
locked,
|
locked,
|
||||||
frozen,
|
frozen,
|
||||||
dry_run: DryRun::from_args(dry_run),
|
dry_run,
|
||||||
script,
|
script,
|
||||||
active: flag(active, no_active),
|
active: flag(active, no_active),
|
||||||
extras: ExtrasSpecification::from_args(
|
extras: ExtrasSpecification::from_args(
|
||||||
|
|
|
||||||
|
|
@ -352,6 +352,68 @@ fn mixed_requires_python() -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check() -> Result<()> {
|
||||||
|
let context = TestContext::new("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"]
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// Running `uv sync --check` should fail.
|
||||||
|
uv_snapshot!(context.filters(), context.sync().arg("--check"), @r###"
|
||||||
|
success: false
|
||||||
|
exit_code: 2
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
Discovered existing environment at: .venv
|
||||||
|
Resolved 2 packages in [TIME]
|
||||||
|
Would create lockfile at: uv.lock
|
||||||
|
Would download 1 package
|
||||||
|
Would install 1 package
|
||||||
|
+ iniconfig==2.0.0
|
||||||
|
error: The environment is outdated; run `uv sync` to update the environment
|
||||||
|
"###);
|
||||||
|
|
||||||
|
// Sync the environment.
|
||||||
|
uv_snapshot!(context.filters(), context.sync(), @r###"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
Resolved 2 packages in [TIME]
|
||||||
|
Prepared 1 package in [TIME]
|
||||||
|
Installed 1 package in [TIME]
|
||||||
|
+ iniconfig==2.0.0
|
||||||
|
"###);
|
||||||
|
|
||||||
|
assert!(context.temp_dir.child("uv.lock").exists());
|
||||||
|
|
||||||
|
// Running `uv sync --check` should pass now that the environment is up to date.
|
||||||
|
uv_snapshot!(context.filters(), context.sync().arg("--check"), @r###"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
Discovered existing environment at: .venv
|
||||||
|
Resolved 2 packages in [TIME]
|
||||||
|
Found up-to-date lockfile at: uv.lock
|
||||||
|
Audited 1 package in [TIME]
|
||||||
|
Would make no changes
|
||||||
|
"###);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Sync development dependencies in a (legacy) non-project workspace root.
|
/// Sync development dependencies in a (legacy) non-project workspace root.
|
||||||
#[test]
|
#[test]
|
||||||
fn sync_legacy_non_project_dev_dependencies() -> Result<()> {
|
fn sync_legacy_non_project_dev_dependencies() -> Result<()> {
|
||||||
|
|
|
||||||
|
|
@ -1513,6 +1513,10 @@ uv sync [OPTIONS]
|
||||||
<p>To view the location of the cache directory, run <code>uv cache dir</code>.</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>
|
<p>May also be set with the <code>UV_CACHE_DIR</code> environment variable.</p>
|
||||||
|
</dd><dt id="uv-sync--check"><a href="#uv-sync--check"><code>--check</code></a></dt><dd><p>Check if the Python environment is synchronized with the project.</p>
|
||||||
|
|
||||||
|
<p>If the environment is not up to date, uv will exit with an error.</p>
|
||||||
|
|
||||||
</dd><dt id="uv-sync--color"><a href="#uv-sync--color"><code>--color</code></a> <i>color-choice</i></dt><dd><p>Control the use of color in output.</p>
|
</dd><dt id="uv-sync--color"><a href="#uv-sync--color"><code>--color</code></a> <i>color-choice</i></dt><dd><p>Control the use of color in output.</p>
|
||||||
|
|
||||||
<p>By default, uv will automatically detect support for colors when writing to a terminal.</p>
|
<p>By default, uv will automatically detect support for colors when writing to a terminal.</p>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue