mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-11-14 04:43:42 +01:00
feat(nixgen): write the hash of the schema as the first line of the output
Consumers that check whether generated options are older than their schema (komorebi-for-kde's `schema-fresh`) compare a `# schema-sha256: <hex>` first line with the hash of schema.json. That line was added by hand in the consumer's justfile with `printf` and `nix hash file`, so the tool's own output could never pass the check. Write the line from the tool. `schema_hash_header` returns it for the raw bytes of the schema file, in lowercase hex, which is the digest `nix hash file --type sha256 --base16` prints. The binary puts it before the generated code; the library functions that return generated code are unchanged, so library users get no new line unless they ask for it. Adds the sha2 dependency. Verified: cargo test passes (49, including two known SHA-256 vectors). On the komorebi-for-kde schema.json the first line equals `nix hash file --type sha256 --base16 schema.json`.
This commit is contained in:
1 parent
e28a8b7956
commit
50ce2860c9
4 files changed
+110
-2
No files matched your search
Generated
+72
@@ -88,6 +88,15 @@ version = "2.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
@@ -168,6 +177,35 @@ version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dyn-clone"
|
||||
version = "1.0.20"
|
||||
@@ -194,6 +232,16 @@ dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.32.3"
|
||||
@@ -375,6 +423,7 @@ dependencies = [
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_json_lenient",
|
||||
"sha2",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
@@ -456,6 +505,17 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sharded-slab"
|
||||
version = "0.1.7"
|
||||
@@ -562,6 +622,12 @@ dependencies = [
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.20.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.22"
|
||||
@@ -580,6 +646,12 @@ version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
|
||||
@@ -18,4 +18,5 @@ color-eyre = "0.6"
|
||||
schemars = "1.1"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = { package = "serde_json_lenient", version = "0.2" }
|
||||
sha2 = "0.10"
|
||||
thiserror = "2"
|
||||
+29
@@ -32,6 +32,22 @@ pub trait SchemaExt: JsonSchema {
|
||||
// Implement SchemaExt for all types that implement JsonSchema
|
||||
impl<T: JsonSchema> SchemaExt for T {}
|
||||
|
||||
/// The first line of a generated file: the SHA-256 of the schema file's bytes, in lowercase hex
|
||||
///
|
||||
/// This is the same digest as `nix hash file --type sha256 --base16 <schema>`, so a check can compare
|
||||
/// the header of a generated file with the hash of the schema it says it was made from.
|
||||
pub fn schema_hash_header(schema_bytes: &[u8]) -> String {
|
||||
use sha2::Digest;
|
||||
use std::fmt::Write;
|
||||
|
||||
let mut header = String::from("# schema-sha256: ");
|
||||
for byte in sha2::Sha256::digest(schema_bytes) {
|
||||
write!(header, "{byte:02x}").expect("writing to a String cannot fail");
|
||||
}
|
||||
header.push('\n');
|
||||
header
|
||||
}
|
||||
|
||||
/// Generate Nix options from a JSON schema value
|
||||
pub fn generate_from_schema(
|
||||
schema: &Value,
|
||||
@@ -56,6 +72,19 @@ mod tests {
|
||||
use super::*;
|
||||
use serde_json::json;
|
||||
|
||||
#[test]
|
||||
fn test_schema_hash_header() {
|
||||
// the SHA-256 of the empty input and of "abc"
|
||||
assert_eq!(
|
||||
schema_hash_header(b""),
|
||||
"# schema-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\n"
|
||||
);
|
||||
assert_eq!(
|
||||
schema_hash_header(b"abc"),
|
||||
"# schema-sha256: ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad\n"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generate_from_schema() {
|
||||
let schema = json!({
|
||||
|
||||
+8
-2
@@ -1,6 +1,7 @@
|
||||
use clap::Parser;
|
||||
use schemars_nixgen::GeneratorOptions;
|
||||
use schemars_nixgen::generate_from_schema;
|
||||
use schemars_nixgen::schema_hash_header;
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
use std::io::{self};
|
||||
@@ -42,8 +43,13 @@ fn main() -> color_eyre::Result<()> {
|
||||
root_description: cli.description,
|
||||
};
|
||||
|
||||
// Generate Nix code
|
||||
let nix_code = generate_from_schema(&schema, &options)?;
|
||||
// Generate Nix code, with the hash of the schema file first so a check can tell when the options
|
||||
// are older than the schema
|
||||
let nix_code = format!(
|
||||
"{}{}",
|
||||
schema_hash_header(schema_str.as_bytes()),
|
||||
generate_from_schema(&schema, &options)?
|
||||
);
|
||||
|
||||
// Write output
|
||||
if let Some(output_path) = cli.output {
|
||||
|
||||
Reference in new issue
Block a user