From 681ee5e8269d89d6d253cb4f0c8f6816a0524b54 Mon Sep 17 00:00:00 2001 From: cy Date: Sun, 13 Apr 2025 14:52:12 -0400 Subject: [PATCH] make nar --- Cargo.lock | 508 +++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 4 + src/main.rs | 15 +- src/nixcp.rs | 2 +- src/path_info.rs | 26 +-- src/uploader.rs | 79 ++++++++ 6 files changed, 607 insertions(+), 27 deletions(-) create mode 100644 src/uploader.rs diff --git a/Cargo.lock b/Cargo.lock index 5cf46a7..0e910ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -82,6 +82,20 @@ version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" +[[package]] +name = "async-compression" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59a194f9d963d8099596278594b3107448656ba73831c9d8c783e613ce86da64" +dependencies = [ + "futures-core", + "memchr", + "pin-project-lite", + "tokio", + "zstd", + "zstd-safe", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -115,12 +129,38 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64ct" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3" + [[package]] name = "bitflags" version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +[[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 = "bstr" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4" +dependencies = [ + "memchr", + "regex-automata", + "serde", +] + [[package]] name = "bumpalo" version = "3.17.0" @@ -139,6 +179,8 @@ version = "1.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a" dependencies = [ + "jobserver", + "libc", "shlex", ] @@ -194,6 +236,12 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + [[package]] name = "core-foundation" version = "0.9.4" @@ -210,6 +258,78 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "data-encoding" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "zeroize", +] + +[[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 = "displaydoc" version = "0.2.5" @@ -221,6 +341,30 @@ dependencies = [ "syn", ] +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +dependencies = [ + "curve25519-dalek", + "ed25519", + "serde", + "sha2", + "subtle", + "zeroize", +] + [[package]] name = "encoding_rs" version = "0.8.35" @@ -230,6 +374,17 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "enum-primitive-derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba7795da175654fe16979af73f81f26a8ea27638d8d9823d317016888a63dc4c" +dependencies = [ + "num-traits", + "quote", + "syn", +] + [[package]] name = "env_filter" version = "0.1.3" @@ -275,6 +430,12 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + [[package]] name = "fnv" version = "1.0.7" @@ -305,6 +466,21 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.31" @@ -312,6 +488,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -320,6 +497,34 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "futures-sink" version = "0.3.31" @@ -338,10 +543,26 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ + "futures-channel", "futures-core", + "futures-io", + "futures-macro", + "futures-sink", "futures-task", + "memchr", "pin-project-lite", "pin-utils", + "slab", +] + +[[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]] @@ -373,6 +594,12 @@ version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +[[package]] +name = "glob" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" + [[package]] name = "h2" version = "0.4.8" @@ -708,6 +935,16 @@ dependencies = [ "syn", ] +[[package]] +name = "jobserver" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +dependencies = [ + "getrandom 0.3.2", + "libc", +] + [[package]] name = "js-sys" version = "0.3.77" @@ -724,6 +961,16 @@ version = "0.2.171" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" +[[package]] +name = "libmimalloc-sys" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec9d6fac27761dabcd4ee73571cdb06b7022dc99089acbe5435691edffaac0f4" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "linux-raw-sys" version = "0.9.3" @@ -758,6 +1005,15 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "mimalloc" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "995942f432bbb4822a7e9c3faa87a695185b0d09273ba85f097b54f4e458f2af" +dependencies = [ + "libmimalloc-sys", +] + [[package]] name = "mime" version = "0.3.17" @@ -801,22 +1057,103 @@ dependencies = [ "tempfile", ] +[[package]] +name = "nix-compat" +version = "0.1.0" +source = "git+https://github.com/tvlfyi/tvix.git#ac27df9ae51f69c1b746b7c8c2ad22f5a857ca52" +dependencies = [ + "bitflags", + "bstr", + "bytes", + "data-encoding", + "ed25519", + "ed25519-dalek", + "enum-primitive-derive", + "futures", + "glob", + "mimalloc", + "nix-compat-derive", + "nom", + "num-traits", + "num_enum", + "pin-project-lite", + "serde", + "serde_json", + "sha2", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "nix-compat-derive" +version = "0.1.0" +source = "git+https://github.com/tvlfyi/tvix.git#ac27df9ae51f69c1b746b7c8c2ad22f5a857ca52" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "nixcp" version = "0.1.0" dependencies = [ "anyhow", + "async-compression", "clap", + "ed25519-dalek", "env_logger", "log", + "nix-compat", "regex", "reqwest", "serde", "serde_json", + "sha2", "tokio", "url", ] +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_enum" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "object" version = "0.36.7" @@ -917,6 +1254,16 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.32" @@ -938,6 +1285,15 @@ dependencies = [ "portable-atomic", ] +[[package]] +name = "proc-macro-crate" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +dependencies = [ + "toml_edit", +] + [[package]] name = "proc-macro2" version = "1.0.94" @@ -962,6 +1318,15 @@ version = "5.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.15", +] + [[package]] name = "redox_syscall" version = "0.5.10" @@ -1064,6 +1429,15 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "1.0.3" @@ -1166,6 +1540,12 @@ dependencies = [ "libc", ] +[[package]] +name = "semver" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" + [[package]] name = "serde" version = "1.0.219" @@ -1210,6 +1590,17 @@ dependencies = [ "serde", ] +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "shlex" version = "1.3.0" @@ -1225,6 +1616,15 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "rand_core", +] + [[package]] name = "slab" version = "0.4.9" @@ -1250,6 +1650,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -1333,6 +1743,26 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tinystr" version = "0.7.6" @@ -1405,6 +1835,23 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" + +[[package]] +name = "toml_edit" +version = "0.22.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + [[package]] name = "tower" version = "0.5.2" @@ -1439,9 +1886,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tracing-core" version = "0.1.33" @@ -1457,6 +1916,12 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "typenum" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" + [[package]] name = "unicode-ident" version = "1.0.18" @@ -1505,6 +1970,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + [[package]] name = "want" version = "0.3.1" @@ -1791,6 +2262,15 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +[[package]] +name = "winnow" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63d3fcd9bba44b03821e7d699eeee959f3126dcc4aa8e4ae18ec617c2a5cea10" +dependencies = [ + "memchr", +] + [[package]] name = "wit-bindgen-rt" version = "0.39.0" @@ -1884,3 +2364,31 @@ dependencies = [ "quote", "syn", ] + +[[package]] +name = "zstd" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.15+zstd.1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/Cargo.toml b/Cargo.toml index fe2d773..039a587 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,12 +5,16 @@ edition = "2024" [dependencies] anyhow = "1.0.97" +async-compression = { version = "0.4.22", features = ["tokio", "zstd"] } clap = { version = "4.5.34", features = ["derive"] } +ed25519-dalek = "2.1.1" env_logger = "0.11.7" log = "0.4.27" +nix-compat = { git = "https://github.com/tvlfyi/tvix.git", version = "0.1.0" } regex = "1.11.1" reqwest = "0.12.15" serde = { version = "1.0.219", features = [ "derive" ]} serde_json = "1.0.140" +sha2 = "0.10.8" tokio = { version = "1.44.1", features = [ "full" ]} url = { version = "2.5.4", features = [ "serde" ]} diff --git a/src/main.rs b/src/main.rs index e2773cc..5df47d8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,7 @@ use nixcp::NixCp; mod cli; mod nixcp; mod path_info; +mod uploader; #[derive(Parser, Debug)] #[command(version, name = "nixcp")] @@ -21,21 +22,9 @@ struct Cli { to: String, /// Upstream cache to check against. Can be specified multiple times. - /// cache.nixos.org is always included (unless --no-nixos-cache is passed) + /// cache.nixos.org is always included #[arg(long = "upstream-cache", short)] upstream_caches: Vec, - - /// Concurrent upstream cache checkers - #[arg(long, default_value_t = 32)] - upstream_checker_concurrency: u8, - - /// Concurrent uploaders - #[arg(long, default_value_t = 4)] - uploader_concurrency: u8, - - /// Concurrent nix-store commands to run - #[arg(long, default_value_t = 32)] - nix_store_concurrency: u8, } #[derive(Debug, Subcommand)] diff --git a/src/nixcp.rs b/src/nixcp.rs index 057af55..01db3eb 100644 --- a/src/nixcp.rs +++ b/src/nixcp.rs @@ -72,7 +72,7 @@ impl NixCp { let _permit = permits.acquire().await.unwrap(); if !path.check_upstream_hit(upstream_caches.as_slice()).await { - tx.send(path.to_string()).await.unwrap(); + tx.send(path.absolute_path()).await.unwrap(); } }) }); diff --git a/src/path_info.rs b/src/path_info.rs index e1cf25a..0afb00c 100644 --- a/src/path_info.rs +++ b/src/path_info.rs @@ -2,6 +2,8 @@ use std::{collections::HashSet, path::Path}; use anyhow::{Context, Result}; use log::trace; +use nix_compat::nixhash::CAHash; +use nix_compat::store_path::StorePath; use regex::Regex; use serde::{Deserialize, Serialize}; use tokio::process::Command; @@ -11,9 +13,11 @@ use url::Url; #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PathInfo { - deriver: String, - path: String, + pub deriver: StorePath, + pub path: StorePath, signatures: Vec, + pub references: Vec>, + pub ca: Option, } impl PathInfo { /// get PathInfo for a package or a store path @@ -34,7 +38,7 @@ impl PathInfo { .arg("--query") .arg("--requisites") .arg("--include-outputs") - .arg(&self.deriver) + .arg(self.deriver.to_string()) .output() .await .expect("nix-store cmd failed"); @@ -48,10 +52,6 @@ impl PathInfo { Ok(closure) } - pub fn get_path(&self) -> &Path { - &Path::new(&self.path) - } - /// checks if the path is signed by any upstream. if it is, we assume a cache hit. /// the name of the cache in the signature does not have to be the domain of the cache. /// in fact, it can be any random string. but, most often it is, and this saves us @@ -81,8 +81,8 @@ impl PathInfo { } pub async fn check_upstream_hit(&self, upstreams: &[Url]) -> bool { - let basename = self.get_path().file_name().unwrap().to_str().unwrap(); - let hash = basename.split_once("-").unwrap().0; + let hash = + String::from_utf8(self.path.digest().to_vec()).expect("should be a valid string"); for upstream in upstreams { let upstream = upstream @@ -101,14 +101,13 @@ impl PathInfo { } false } -} -impl ToString for PathInfo { - fn to_string(&self) -> String { - self.path.clone() + pub fn absolute_path(&self) -> String { + self.path.to_absolute_path() } } +/* #[cfg(test)] mod tests { use super::*; @@ -159,3 +158,4 @@ mod tests { ); } } +*/ diff --git a/src/uploader.rs b/src/uploader.rs new file mode 100644 index 0000000..04c4d2e --- /dev/null +++ b/src/uploader.rs @@ -0,0 +1,79 @@ +use anyhow::Result; +use async_compression::{Level, tokio::bufread::ZstdEncoder}; +use ed25519_dalek; +use nix_compat::{ + narinfo::{self, NarInfo}, + nixbase32, + store_path::StorePath, +}; +use sha2::{Digest, Sha256}; +use std::fs; +use tokio::{io::AsyncReadExt, process::Command}; + +use crate::path_info::PathInfo; + +pub struct Uploader { + signing_key: narinfo::SigningKey, + path: PathInfo, + compression: Option, +} + +impl Uploader { + pub fn new(key_file: &str, path: PathInfo) -> Result { + let key = fs::read_to_string(key_file)?; + let signing_key = narinfo::parse_keypair(key.as_str())?.0; + Ok(Self { + signing_key, + path, + // TODO: support other algorithms + compression: Some("zstd".to_string()), + }) + } + + pub async fn make_nar(&self) -> Result> { + Ok(Command::new("nix") + .arg("nar") + .arg("dump-path") + .arg(self.path.absolute_path()) + .output() + .await? + .stdout) + } + + pub fn narinfo_from_nar(&self, nar: &[u8]) -> Result { + let mut hasher = Sha256::new(); + hasher.update(nar); + let nar_hash: [u8; 32] = hasher.finalize().into(); + let nar_info = NarInfo { + flags: narinfo::Flags::empty(), + store_path: self.path.path.as_ref(), + nar_hash, + nar_size: nar.len() as u64, + references: self.path.references.iter().map(StorePath::as_ref).collect(), + signatures: Vec::new(), + ca: self.path.ca.clone(), + system: None, + deriver: Some(self.path.deriver.as_ref()), + compression: self.compression.as_ref().map(String::as_str), + file_hash: None, + file_size: None, + url: "", + }; + Ok(nar_info) + } + + fn nar_url(&self, compressed_nar_hash: &[u8]) -> String { + let compressed_nar_hash = nixbase32::encode(compressed_nar_hash); + format!("nar/{compressed_nar_hash}.nar.zst") + } + + async fn compress_nar(&self, nar: &[u8]) -> Vec { + let mut encoder = ZstdEncoder::with_quality(nar, Level::Default); + let mut compressed = Vec::with_capacity(nar.len()); + encoder + .read_to_end(&mut compressed) + .await + .expect("should compress just fine"); + compressed + } +}