diff --git a/Cargo.lock b/Cargo.lock index aee2282..4d5600c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -759,6 +759,17 @@ dependencies = [ "cc", ] +[[package]] +name = "codespan-reporting" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81" +dependencies = [ + "serde", + "termcolor", + "unicode-width", +] + [[package]] name = "colorchoice" version = "1.0.3" @@ -907,6 +918,65 @@ dependencies = [ "syn", ] +[[package]] +name = "cxx" +version = "1.0.157" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6354e975ea4ec28033ec3a36fa9baa1a02e3eb22ad740eeb4929370d4f5ba8" +dependencies = [ + "cc", + "cxxbridge-cmd", + "cxxbridge-flags", + "cxxbridge-macro", + "foldhash", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.157" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b4400e26ea4b99417e4263b1ce2d8452404d750ba0809a7bd043072593d430d" +dependencies = [ + "cc", + "codespan-reporting", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-cmd" +version = "1.0.157" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31860c98f69fc14da5742c5deaf78983e846c7b27804ca8c8319e32eef421bde" +dependencies = [ + "clap", + "codespan-reporting", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.157" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0402a66013f3b8d3d9f2d7c9994656cc81e671054822b0728d7454d9231892f" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.157" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c0b38f32d68f3324a981645ee39b2d686af36d03c98a386df3716108c9feae" +dependencies = [ + "proc-macro2", + "quote", + "rustversion", + "syn", +] + [[package]] name = "data-encoding" version = "2.9.0" @@ -1772,6 +1842,15 @@ dependencies = [ "libc", ] +[[package]] +name = "link-cplusplus" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a6f6da007f968f9def0d65a05b187e2960183de70c160204ecfccf0ee330212" +dependencies = [ + "cc", +] + [[package]] name = "linux-raw-sys" version = "0.4.15" @@ -1945,9 +2024,12 @@ dependencies = [ "aws-config", "aws-sdk-s3", "clap", + "cxx", + "cxx-build", "ed25519-dalek", "futures", "nix-compat", + "pkg-config", "regex", "reqwest", "serde", @@ -2538,6 +2620,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "scratch" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f6280af86e5f559536da57a45ebc84948833b3bee313a7dd25232e09c878a52" + [[package]] name = "sct" version = "0.7.1" @@ -2841,6 +2929,15 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + [[package]] name = "thiserror" version = "2.0.12" @@ -3106,6 +3203,12 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +[[package]] +name = "unicode-width" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" + [[package]] name = "untrusted" version = "0.9.0" @@ -3311,6 +3414,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index f7bc3f0..8adf37e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,3 +21,8 @@ tokio = { version = "1.44.1", features = [ "full" ]} tracing = "0.1.41" tracing-subscriber = { version = "0.3.19", features = ["env-filter"]} url = { version = "2.5.4", features = [ "serde" ]} +cxx = "1.0" + +[build-dependencies] +cxx-build = "1.0" +pkg-config = "0.3.32" diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..2bbe451 --- /dev/null +++ b/build.rs @@ -0,0 +1,21 @@ +fn main() { + cxx_build::bridge("src/bindings/mod.rs") + .file("src/bindings/nix.cpp") + .flag("-std=c++2a") + .flag("-O2") + .flag("-include") + .flag("nix/config.h") + .flag("-I") + .flag(concat!(env!("NIX_INCLUDE_PATH"), "/nix")) + .compile("nixbinding"); + println!("cargo:rerun-if-changed=src/bindings"); + + pkg_config::Config::new() + .atleast_version("2.4") + .probe("nix-store") + .unwrap(); + pkg_config::Config::new() + .atleast_version("2.4") + .probe("nix-main") + .unwrap(); +} diff --git a/flake.nix b/flake.nix index c263f49..e9165c2 100644 --- a/flake.nix +++ b/flake.nix @@ -22,6 +22,7 @@ }; toolchain = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml; craneLib = (crane.mkLib pkgs).overrideToolchain(_: toolchain); + lib = pkgs.lib; in { devShells.default = pkgs.mkShell { @@ -29,9 +30,12 @@ pkg-config ]; buildInputs = with pkgs; [ - openssl toolchain + openssl + nix + boost ]; + NIX_INCLUDE_PATH = "${lib.getDev pkgs.nix}/include"; }; packages.default = craneLib.buildPackage { diff --git a/src/bindings/mod.rs b/src/bindings/mod.rs index f636f4c..61a32af 100644 --- a/src/bindings/mod.rs +++ b/src/bindings/mod.rs @@ -181,7 +181,7 @@ mod ffi { } unsafe extern "C++" { - include!("nix.hpp"); + include!("nixcp/src/bindings/nix.hpp"); // ========= // CNixStore @@ -190,16 +190,6 @@ mod ffi { /// Mid-level wrapper for the Unix Domain Socket Nix Store. type CNixStore; - /// Returns the path of the Nix store itself. - fn store_dir(self: Pin<&mut CNixStore>) -> String; - - /* - /// Verifies that a path is indeed in the Nix store, then return the base store path. - /// - /// Use parse_store_path instead. - fn to_store_path(self: Pin<&mut CNixStore>, path: &str) -> Result; - */ - /// Queries information about a valid path. fn query_path_info( self: Pin<&mut CNixStore>, @@ -218,30 +208,6 @@ mod ffi { include_derivers: bool, ) -> Result>>; - /// Computes the closure of a list of valid paths. - /// - /// This is the multi-path variant of `compute_fs_closure`. - /// If `flip_directions` is true, the set of paths that can reach `store_path` is - /// returned. - /// - /// It's easier and more efficient to just pass a vector of slices - /// instead of wrangling with concrete "extern rust" / "extern C++" - /// types. - fn compute_fs_closure_multi( - self: Pin<&mut CNixStore>, - base_names: &[&[u8]], - flip_direction: bool, - include_outputs: bool, - include_derivers: bool, - ) -> Result>>; - - /// Creates a NAR dump from a path. - fn nar_from_path( - self: Pin<&mut CNixStore>, - base_name: Vec, - sender: Box, - ) -> Result<()>; - /// Obtains a handle to the Nix store. fn open_nix_store() -> Result>; @@ -252,22 +218,10 @@ mod ffi { /// Mid-level wrapper for the `nix::ValidPathInfo` struct. type CPathInfo; - /// Returns the SHA-256 hash of the store path. - fn nar_sha256_hash(self: Pin<&mut CPathInfo>) -> &[u8]; - - /// Returns the size of the NAR. - fn nar_size(self: Pin<&mut CPathInfo>) -> u64; - /// Returns the references of the store path. fn references(self: Pin<&mut CPathInfo>) -> UniquePtr>; /// Returns the possibly invalid signatures attached to the store path. fn sigs(self: Pin<&mut CPathInfo>) -> UniquePtr>; - - /// Returns the CA field of the store path. - fn ca(self: Pin<&mut CPathInfo>) -> String; - - /// Returns the derivation that built this path - fn deriver(self: Pin<&mut CPathInfo>) -> String; } } diff --git a/src/bindings/nix.cpp b/src/bindings/nix.cpp index 7783b4b..3914de1 100644 --- a/src/bindings/nix.cpp +++ b/src/bindings/nix.cpp @@ -24,7 +24,7 @@ limitations under the License. // Rust types directly where possible, so that the interfaces are // satisfying to use from the Rust side via cxx.rs. -#include "attic/src/nix_store/bindings/nix.hpp" +#include "nixcp/src/bindings/nix.hpp" static std::mutex g_init_nix_mutex; static bool g_init_nix_done = false; @@ -34,14 +34,6 @@ static nix::StorePath store_path_from_rust(RBasePathSlice base_name) { return nix::StorePath(sv); } -static bool hash_is_sha256(const nix::Hash &hash) { -#ifdef ATTIC_NIX_2_20 - return hash.algo == nix::HashAlgorithm::SHA256; -#else - return hash.type == nix::htSHA256; -#endif -} - // ======== // RustSink // ======== @@ -65,20 +57,6 @@ void RustSink::eof() { CPathInfo::CPathInfo(nix::ref pi) : pi(pi) {} -RHashSlice CPathInfo::nar_sha256_hash() { - auto &hash = this->pi->narHash; - - if (!hash_is_sha256(hash)) { - throw nix::Error("Only SHA-256 hashes are supported at the moment"); - } - - return RHashSlice(hash.hash, hash.hashSize); -} - -uint64_t CPathInfo::nar_size() { - return this->pi->narSize; -} - std::unique_ptr> CPathInfo::sigs() { std::vector result; for (auto&& elem : this->pi->sigs) { @@ -95,22 +73,6 @@ std::unique_ptr> CPathInfo::references() { return std::make_unique>(result); } -RString CPathInfo::ca() { - if (this->pi->ca) { - return RString(nix::renderContentAddress(this->pi->ca)); - } else { - return RString(""); - } -} - -RString CPathInfo::deriver() { - if (this->pi->deriver) { - return RString((this->pi->deriver).to_string()); - } else { - return RString(""); - } -} - // ========= // CNixStore // ========= @@ -127,10 +89,6 @@ CNixStore::CNixStore() { this->store = nix::openStore(nix::settings.storeUri.get(), params); } -RString CNixStore::store_dir() { - return RString(this->store->storeDir); -} - std::unique_ptr CNixStore::query_path_info(RBasePathSlice base_name) { auto store_path = store_path_from_rust(base_name); @@ -150,32 +108,6 @@ std::unique_ptr> CNixStore::compute_fs_closure(RBasePat return std::make_unique>(result); } -std::unique_ptr> CNixStore::compute_fs_closure_multi(RSlice base_names, bool flip_direction, bool include_outputs, bool include_derivers) { - std::set path_set, out; - for (auto&& base_name : base_names) { - path_set.insert(store_path_from_rust(base_name)); - } - - this->store->computeFSClosure(path_set, out, flip_direction, include_outputs, include_derivers); - - std::vector result; - for (auto&& elem : out) { - result.push_back(std::string(elem.to_string())); - } - return std::make_unique>(result); -} - -void CNixStore::nar_from_path(RVec base_name, RBox sender) { - RustSink sink(std::move(sender)); - - std::string_view sv((const char *)base_name.data(), base_name.size()); - nix::StorePath store_path(sv); - - // exceptions will be thrown into Rust - this->store->narFromPath(store_path, sink); - sink.eof(); -} - std::unique_ptr open_nix_store() { return std::make_unique(); } diff --git a/src/bindings/nix.hpp b/src/bindings/nix.hpp index bbab4c5..9f4964a 100644 --- a/src/bindings/nix.hpp +++ b/src/bindings/nix.hpp @@ -63,11 +63,8 @@ class CPathInfo { nix::ref pi; public: CPathInfo(nix::ref pi); - RHashSlice nar_sha256_hash(); - uint64_t nar_size(); std::unique_ptr> sigs(); std::unique_ptr> references(); - RString ca(); }; class CNixStore { @@ -82,15 +79,9 @@ public: bool flip_direction, bool include_outputs, bool include_derivers); - std::unique_ptr> compute_fs_closure_multi( - RSlice base_names, - bool flip_direction, - bool include_outputs, - bool include_derivers); - void nar_from_path(RVec base_name, RBox sender); }; std::unique_ptr open_nix_store(); // Relies on our definitions -#include "attic/src/nix_store/bindings/mod.rs.h" +#include "nixcp/src/bindings/mod.rs.h" diff --git a/src/path_info.rs b/src/path_info.rs index 3e69ad9..3d54b17 100644 --- a/src/path_info.rs +++ b/src/path_info.rs @@ -14,7 +14,6 @@ use crate::store::Store; #[derive(Debug, Clone)] pub struct PathInfo { - pub deriver: Option>, pub path: StorePath, pub signatures: Vec, pub references: Vec>, diff --git a/src/store.rs b/src/store.rs index e988535..54f185c 100644 --- a/src/store.rs +++ b/src/store.rs @@ -46,7 +46,6 @@ impl Store { task::spawn_blocking(move || { let mut c_path_info = inner.store().query_path_info(path.to_string().as_bytes())?; - let deriver = c_path_info.pin_mut().deriver(); let signatures = c_path_info .pin_mut() .sigs() @@ -65,11 +64,6 @@ impl Store { Ok(PathInfo { path, - deriver: if deriver.is_empty() { - None - } else { - Some(StorePath::from_bytes(deriver.as_bytes())?) - }, signatures, references, }) diff --git a/src/uploader.rs b/src/uploader.rs index b0520ac..95e03df 100644 --- a/src/uploader.rs +++ b/src/uploader.rs @@ -159,7 +159,7 @@ impl<'a> Uploader<'a> { signatures: Vec::new(), ca: None, system: None, - deriver: self.path.deriver.as_ref().map(|x| x.as_ref()), + deriver: None, compression: Some("zstd"), file_hash: None, file_size: None,