841edc3718
## Summary These are really different from the rest of the existing crate as evidenced by the bifurcation in the requirements.
103 lines
3.2 KiB
Rust
103 lines
3.2 KiB
Rust
use std::path::PathBuf;
|
|
|
|
use anstream::println;
|
|
use anyhow::{bail, Result};
|
|
use pretty_assertions::StrComparison;
|
|
use schemars::{schema_for, JsonSchema};
|
|
use serde::Deserialize;
|
|
|
|
use uv_settings::Options as SettingsOptions;
|
|
use uv_workspace::pyproject::ToolUv as WorkspaceOptions;
|
|
|
|
use crate::generate_all::Mode;
|
|
use crate::ROOT_DIR;
|
|
|
|
#[derive(Deserialize, JsonSchema)]
|
|
#[serde(deny_unknown_fields)]
|
|
#[allow(dead_code)]
|
|
// The names and docstrings of this struct and the types it contains are used as `title` and
|
|
// `description` in uv.schema.json, see https://github.com/SchemaStore/schemastore/blob/master/editor-features.md#title-as-an-expected-object-type
|
|
/// Metadata and configuration for uv.
|
|
struct CombinedOptions {
|
|
#[serde(flatten)]
|
|
options: SettingsOptions,
|
|
#[serde(flatten)]
|
|
workspace: WorkspaceOptions,
|
|
}
|
|
|
|
#[derive(clap::Args)]
|
|
pub(crate) struct Args {
|
|
/// Write the generated output to stdout (rather than to `uv.schema.json`).
|
|
#[arg(long, default_value_t, value_enum)]
|
|
pub(crate) mode: Mode,
|
|
}
|
|
|
|
pub(crate) fn main(args: &Args) -> Result<()> {
|
|
let schema = schema_for!(CombinedOptions);
|
|
let schema_string = serde_json::to_string_pretty(&schema).unwrap();
|
|
let filename = "uv.schema.json";
|
|
let schema_path = PathBuf::from(ROOT_DIR).join(filename);
|
|
|
|
match args.mode {
|
|
Mode::DryRun => {
|
|
println!("{schema_string}");
|
|
}
|
|
Mode::Check => match fs_err::read_to_string(schema_path) {
|
|
Ok(current) => {
|
|
if current == schema_string {
|
|
println!("Up-to-date: {filename}");
|
|
} else {
|
|
let comparison = StrComparison::new(¤t, &schema_string);
|
|
bail!("{filename} changed, please run `cargo dev generate-json-schema`:\n{comparison}");
|
|
}
|
|
}
|
|
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
|
|
bail!("{filename} not found, please run `cargo dev generate-json-schema`");
|
|
}
|
|
Err(err) => {
|
|
bail!("{filename} changed, please run `cargo dev generate-json-schema`:\n{err}");
|
|
}
|
|
},
|
|
Mode::Write => match fs_err::read_to_string(&schema_path) {
|
|
Ok(current) => {
|
|
if current == schema_string {
|
|
println!("Up-to-date: {filename}");
|
|
} else {
|
|
println!("Updating: {filename}");
|
|
fs_err::write(schema_path, schema_string.as_bytes())?;
|
|
}
|
|
}
|
|
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
|
|
println!("Updating: {filename}");
|
|
fs_err::write(schema_path, schema_string.as_bytes())?;
|
|
}
|
|
Err(err) => {
|
|
bail!("{filename} changed, please run `cargo dev generate-json-schema`:\n{err}");
|
|
}
|
|
},
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use std::env;
|
|
|
|
use anyhow::Result;
|
|
|
|
use crate::generate_all::Mode;
|
|
|
|
use super::{main, Args};
|
|
|
|
#[test]
|
|
fn test_generate_json_schema() -> Result<()> {
|
|
let mode = if env::var("UV_UPDATE_SCHEMA").as_deref() == Ok("1") {
|
|
Mode::Write
|
|
} else {
|
|
Mode::Check
|
|
};
|
|
main(&Args { mode })
|
|
}
|
|
}
|