Merge pull request #42 from nixops4/store-path-binding
Add `StorePath::from_parts(hash, name)`
This commit is contained in:
commit
42f668b812
5 changed files with 113 additions and 1 deletions
29
Cargo.lock
generated
29
Cargo.lock
generated
|
|
@ -132,6 +132,12 @@ version = "0.3.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
|
checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hex-literal"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "home"
|
name = "home"
|
||||||
version = "0.5.11"
|
version = "0.5.11"
|
||||||
|
|
@ -301,12 +307,14 @@ version = "0.2.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"ctor",
|
"ctor",
|
||||||
|
"hex-literal",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"nix-bindings-store-sys",
|
"nix-bindings-store-sys",
|
||||||
"nix-bindings-util",
|
"nix-bindings-util",
|
||||||
"nix-bindings-util-sys",
|
"nix-bindings-util-sys",
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
|
"zerocopy",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -316,6 +324,7 @@ dependencies = [
|
||||||
"bindgen",
|
"bindgen",
|
||||||
"nix-bindings-util-sys",
|
"nix-bindings-util-sys",
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
|
"zerocopy",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -611,3 +620,23 @@ name = "wit-bindgen"
|
||||||
version = "0.46.0"
|
version = "0.46.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
|
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy"
|
||||||
|
version = "0.8.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4ea879c944afe8a2b25fef16bb4ba234f47c694565e97383b36f3a878219065c"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy-derive"
|
||||||
|
version = "0.8.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf955aa904d6040f70dc8e9384444cb1030aed272ba3cb09bbc4ab9e7c1f34f5"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ path = "src/lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nix-bindings-util-sys = { path = "../nix-bindings-util-sys", version = "0.2.1" }
|
nix-bindings-util-sys = { path = "../nix-bindings-util-sys", version = "0.2.1" }
|
||||||
|
zerocopy = { version = "0.8", features = ["derive"] }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
bindgen = "0.69"
|
bindgen = "0.69"
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,22 @@ impl bindgen::callbacks::ParseCallbacks for StripNixPrefix {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct AddZerocopyDerives {}
|
||||||
|
impl bindgen::callbacks::ParseCallbacks for AddZerocopyDerives {
|
||||||
|
fn add_derives(&self, info: &bindgen::callbacks::DeriveInfo<'_>) -> Vec<String> {
|
||||||
|
if info.name == "store_path_hash_part" {
|
||||||
|
vec![
|
||||||
|
"zerocopy::FromBytes".to_string(),
|
||||||
|
"zerocopy::IntoBytes".to_string(),
|
||||||
|
"zerocopy::Immutable".to_string(),
|
||||||
|
]
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("cargo:rerun-if-changed=include/nix-c-store.h");
|
println!("cargo:rerun-if-changed=include/nix-c-store.h");
|
||||||
println!("cargo:rustc-link-lib=nixstorec");
|
println!("cargo:rustc-link-lib=nixstorec");
|
||||||
|
|
@ -29,6 +45,7 @@ fn main() {
|
||||||
.clang_args(args)
|
.clang_args(args)
|
||||||
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
|
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
|
||||||
.parse_callbacks(Box::new(StripNixPrefix))
|
.parse_callbacks(Box::new(StripNixPrefix))
|
||||||
|
.parse_callbacks(Box::new(AddZerocopyDerives {}))
|
||||||
// Blocklist symbols from nix-bindings-util-sys
|
// Blocklist symbols from nix-bindings-util-sys
|
||||||
.blocklist_file(".*nix_api_util\\.h")
|
.blocklist_file(".*nix_api_util\\.h")
|
||||||
.generate()
|
.generate()
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,11 @@ nix-bindings-util = { path = "../nix-bindings-util", version = "0.2.1" }
|
||||||
nix-bindings-util-sys = { path = "../nix-bindings-util-sys", version = "0.2.1" }
|
nix-bindings-util-sys = { path = "../nix-bindings-util-sys", version = "0.2.1" }
|
||||||
nix-bindings-store-sys = { path = "../nix-bindings-store-sys", version = "0.2.1" }
|
nix-bindings-store-sys = { path = "../nix-bindings-store-sys", version = "0.2.1" }
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
|
zerocopy = "0.8"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
ctor = "0.2"
|
ctor = "0.2"
|
||||||
|
hex-literal = "0.4"
|
||||||
tempfile = "3.10"
|
tempfile = "3.10"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,24 @@
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::{Context as _, Result};
|
||||||
use nix_bindings_store_sys as raw;
|
use nix_bindings_store_sys as raw;
|
||||||
|
#[cfg(nix_at_least = "2.33")]
|
||||||
|
use nix_bindings_util::{check_call, context::Context};
|
||||||
use nix_bindings_util::{
|
use nix_bindings_util::{
|
||||||
result_string_init,
|
result_string_init,
|
||||||
string_return::{callback_get_result_string, callback_get_result_string_data},
|
string_return::{callback_get_result_string, callback_get_result_string_data},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// The size of a store path hash in bytes (20 bytes, decoded from nix32).
|
||||||
|
pub const STORE_PATH_HASH_SIZE: usize = 20;
|
||||||
|
|
||||||
|
#[cfg(nix_at_least = "2.33")]
|
||||||
|
const _: () = assert!(std::mem::size_of::<raw::store_path_hash_part>() == STORE_PATH_HASH_SIZE);
|
||||||
|
|
||||||
pub struct StorePath {
|
pub struct StorePath {
|
||||||
raw: NonNull<raw::StorePath>,
|
raw: NonNull<raw::StorePath>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StorePath {
|
impl StorePath {
|
||||||
/// Get the name of the store path.
|
/// Get the name of the store path.
|
||||||
///
|
///
|
||||||
|
|
@ -26,6 +35,43 @@ impl StorePath {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the hash part of the store path.
|
||||||
|
///
|
||||||
|
/// This returns the decoded hash (not the nix32-encoded string).
|
||||||
|
#[cfg(nix_at_least = "2.33")]
|
||||||
|
pub fn hash(&self) -> Result<[u8; STORE_PATH_HASH_SIZE]> {
|
||||||
|
let mut result = [0u8; STORE_PATH_HASH_SIZE];
|
||||||
|
let hash_part: &mut raw::store_path_hash_part = zerocopy::transmute_mut!(&mut result);
|
||||||
|
|
||||||
|
let mut ctx = Context::new();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
check_call!(raw::store_path_hash(&mut ctx, self.as_ptr(), hash_part))?;
|
||||||
|
}
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a StorePath from hash and name components.
|
||||||
|
#[cfg(nix_at_least = "2.33")]
|
||||||
|
pub fn from_parts(hash: &[u8; STORE_PATH_HASH_SIZE], name: &str) -> Result<Self> {
|
||||||
|
let hash_part: &raw::store_path_hash_part = zerocopy::transmute_ref!(hash);
|
||||||
|
|
||||||
|
let mut ctx = Context::new();
|
||||||
|
|
||||||
|
let out_path = unsafe {
|
||||||
|
check_call!(raw::store_create_from_parts(
|
||||||
|
&mut ctx,
|
||||||
|
hash_part,
|
||||||
|
name.as_ptr() as *const i8,
|
||||||
|
name.len()
|
||||||
|
))?
|
||||||
|
};
|
||||||
|
|
||||||
|
NonNull::new(out_path)
|
||||||
|
.map(|ptr| unsafe { Self::new_raw(ptr) })
|
||||||
|
.context("store_create_from_parts returned null")
|
||||||
|
}
|
||||||
|
|
||||||
/// This is a low level function that you shouldn't have to call unless you are developing the Nix bindings.
|
/// This is a low level function that you shouldn't have to call unless you are developing the Nix bindings.
|
||||||
///
|
///
|
||||||
/// Construct a new `StorePath` by first cloning the C store path.
|
/// Construct a new `StorePath` by first cloning the C store path.
|
||||||
|
|
@ -81,6 +127,9 @@ impl Drop for StorePath {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use hex_literal::hex;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(nix_at_least = "2.26" /* get_storedir */)]
|
#[cfg(nix_at_least = "2.26" /* get_storedir */)]
|
||||||
fn store_path_name() {
|
fn store_path_name() {
|
||||||
|
|
@ -91,4 +140,18 @@ mod tests {
|
||||||
let store_path = store.parse_store_path(store_path_string.as_str()).unwrap();
|
let store_path = store.parse_store_path(store_path_string.as_str()).unwrap();
|
||||||
assert_eq!(store_path.name().unwrap(), "bash-interactive-5.2p26");
|
assert_eq!(store_path.name().unwrap(), "bash-interactive-5.2p26");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(nix_at_least = "2.33")]
|
||||||
|
fn store_path_round_trip() {
|
||||||
|
let original_hash: [u8; STORE_PATH_HASH_SIZE] =
|
||||||
|
hex!("0123456789abcdef0011223344556677deadbeef");
|
||||||
|
let original_name = "foo.drv";
|
||||||
|
|
||||||
|
let store_path = StorePath::from_parts(&original_hash, original_name).unwrap();
|
||||||
|
|
||||||
|
// Round trip gets back what we started with
|
||||||
|
assert_eq!(store_path.hash().unwrap(), original_hash);
|
||||||
|
assert_eq!(store_path.name().unwrap(), original_name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue