Start parsing narinfo for download

This commit is contained in:
Artemis Tosini 2024-07-13 19:11:11 +00:00
parent 570cc523a6
commit 6411d628c4
Signed by: artemist
GPG key ID: EE5227935FE3FF18
8 changed files with 319 additions and 120 deletions

294
Cargo.lock generated
View file

@ -90,6 +90,20 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "async-compression"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd066d0b4ef8ecb03a55319dc13aa6910616d0f44008a045bb1835af830abff5"
dependencies = [
"futures-core",
"memchr",
"pin-project-lite",
"tokio",
"zstd",
"zstd-safe",
]
[[package]] [[package]]
name = "async-trait" name = "async-trait"
version = "0.1.80" version = "0.1.80"
@ -520,15 +534,6 @@ version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2"
[[package]]
name = "encoding_rs"
version = "0.8.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59"
dependencies = [
"cfg-if",
]
[[package]] [[package]]
name = "enum-as-inner" name = "enum-as-inner"
version = "0.6.0" version = "0.6.0"
@ -715,25 +720,6 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "h2"
version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8"
dependencies = [
"bytes 1.6.0",
"fnv",
"futures-core",
"futures-sink",
"futures-util",
"http",
"indexmap 2.2.6",
"slab",
"tokio",
"tokio-util",
"tracing",
]
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.12.3" version = "0.12.3"
@ -781,9 +767,9 @@ dependencies = [
[[package]] [[package]]
name = "http" name = "http"
version = "0.2.12" version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258"
dependencies = [ dependencies = [
"bytes 1.6.0", "bytes 1.6.0",
"fnv", "fnv",
@ -792,12 +778,24 @@ dependencies = [
[[package]] [[package]]
name = "http-body" name = "http-body"
version = "0.4.6" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
dependencies = [ dependencies = [
"bytes 1.6.0", "bytes 1.6.0",
"http", "http",
]
[[package]]
name = "http-body-util"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f"
dependencies = [
"bytes 1.6.0",
"futures-util",
"http",
"http-body",
"pin-project-lite", "pin-project-lite",
] ]
@ -807,48 +805,61 @@ version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
[[package]]
name = "httpdate"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]] [[package]]
name = "hyper" name = "hyper"
version = "0.14.28" version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05"
dependencies = [ dependencies = [
"bytes 1.6.0", "bytes 1.6.0",
"futures-channel", "futures-channel",
"futures-core",
"futures-util", "futures-util",
"h2",
"http", "http",
"http-body", "http-body",
"httparse", "httparse",
"httpdate",
"itoa", "itoa",
"pin-project-lite", "pin-project-lite",
"socket2", "smallvec",
"tokio", "tokio",
"tower-service",
"tracing",
"want", "want",
] ]
[[package]] [[package]]
name = "hyper-rustls" name = "hyper-rustls"
version = "0.24.2" version = "0.27.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155"
dependencies = [ dependencies = [
"futures-util", "futures-util",
"http", "http",
"hyper", "hyper",
"hyper-util",
"rustls", "rustls",
"rustls-native-certs",
"rustls-pki-types",
"tokio", "tokio",
"tokio-rustls", "tokio-rustls",
"tower-service",
]
[[package]]
name = "hyper-util"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956"
dependencies = [
"bytes 1.6.0",
"futures-channel",
"futures-util",
"http",
"http-body",
"hyper",
"pin-project-lite",
"socket2",
"tokio",
"tower",
"tower-service",
"tracing",
] ]
[[package]] [[package]]
@ -1302,6 +1313,26 @@ version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "pin-project"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
version = "0.2.14" version = "0.2.14"
@ -1374,6 +1405,53 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "quinn"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad"
dependencies = [
"bytes 1.6.0",
"pin-project-lite",
"quinn-proto",
"quinn-udp",
"rustc-hash",
"rustls",
"thiserror",
"tokio",
"tracing",
]
[[package]]
name = "quinn-proto"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe"
dependencies = [
"bytes 1.6.0",
"rand",
"ring",
"rustc-hash",
"rustls",
"slab",
"thiserror",
"tinyvec",
"tracing",
]
[[package]]
name = "quinn-udp"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46"
dependencies = [
"libc",
"once_cell",
"socket2",
"tracing",
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.36" version = "1.0.36"
@ -1488,20 +1566,21 @@ checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
[[package]] [[package]]
name = "reqwest" name = "reqwest"
version = "0.11.27" version = "0.12.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37"
dependencies = [ dependencies = [
"base64 0.21.7", "async-compression",
"base64 0.22.1",
"bytes 1.6.0", "bytes 1.6.0",
"encoding_rs",
"futures-core", "futures-core",
"futures-util", "futures-util",
"h2",
"http", "http",
"http-body", "http-body",
"http-body-util",
"hyper", "hyper",
"hyper-rustls", "hyper-rustls",
"hyper-util",
"ipnet", "ipnet",
"js-sys", "js-sys",
"log", "log",
@ -1509,14 +1588,15 @@ dependencies = [
"once_cell", "once_cell",
"percent-encoding", "percent-encoding",
"pin-project-lite", "pin-project-lite",
"quinn",
"rustls", "rustls",
"rustls-native-certs", "rustls-native-certs",
"rustls-pemfile", "rustls-pemfile",
"rustls-pki-types",
"serde", "serde",
"serde_json", "serde_json",
"serde_urlencoded", "serde_urlencoded",
"sync_wrapper", "sync_wrapper",
"system-configuration",
"tokio", "tokio",
"tokio-rustls", "tokio-rustls",
"tokio-socks", "tokio-socks",
@ -1551,6 +1631,12 @@ version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]] [[package]]
name = "rustc_version" name = "rustc_version"
version = "0.4.0" version = "0.4.0"
@ -1575,44 +1661,55 @@ dependencies = [
[[package]] [[package]]
name = "rustls" name = "rustls"
version = "0.21.12" version = "0.23.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" checksum = "4828ea528154ae444e5a642dbb7d5623354030dc9822b83fd9bb79683c7399d0"
dependencies = [ dependencies = [
"log", "once_cell",
"ring", "ring",
"rustls-pki-types",
"rustls-webpki", "rustls-webpki",
"sct", "subtle",
"zeroize",
] ]
[[package]] [[package]]
name = "rustls-native-certs" name = "rustls-native-certs"
version = "0.6.3" version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" checksum = "a88d6d420651b496bdd98684116959239430022a115c1240e6c3993be0b15fba"
dependencies = [ dependencies = [
"openssl-probe", "openssl-probe",
"rustls-pemfile", "rustls-pemfile",
"rustls-pki-types",
"schannel", "schannel",
"security-framework", "security-framework",
] ]
[[package]] [[package]]
name = "rustls-pemfile" name = "rustls-pemfile"
version = "1.0.4" version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d"
dependencies = [ dependencies = [
"base64 0.21.7", "base64 0.22.1",
"rustls-pki-types",
] ]
[[package]] [[package]]
name = "rustls-webpki" name = "rustls-pki-types"
version = "0.101.7" version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d"
[[package]]
name = "rustls-webpki"
version = "0.102.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9a6fccd794a42c2c105b513a2f62bc3fd8f3ba57a4593677ceb0bd035164d78"
dependencies = [ dependencies = [
"ring", "ring",
"rustls-pki-types",
"untrusted", "untrusted",
] ]
@ -1652,16 +1749,6 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "sct"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414"
dependencies = [
"ring",
"untrusted",
]
[[package]] [[package]]
name = "security-framework" name = "security-framework"
version = "2.11.0" version = "2.11.0"
@ -1915,9 +2002,9 @@ dependencies = [
[[package]] [[package]]
name = "sync_wrapper" name = "sync_wrapper"
version = "0.1.2" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394"
[[package]] [[package]]
name = "sysctl" name = "sysctl"
@ -1933,27 +2020,6 @@ dependencies = [
"walkdir", "walkdir",
] ]
[[package]]
name = "system-configuration"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
dependencies = [
"bitflags 1.3.2",
"core-foundation",
"system-configuration-sys",
]
[[package]]
name = "system-configuration-sys"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]] [[package]]
name = "tar" name = "tar"
version = "0.4.40" version = "0.4.40"
@ -2114,11 +2180,12 @@ dependencies = [
[[package]] [[package]]
name = "tokio-rustls" name = "tokio-rustls"
version = "0.24.1" version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4"
dependencies = [ dependencies = [
"rustls", "rustls",
"rustls-pki-types",
"tokio", "tokio",
] ]
@ -2147,6 +2214,27 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "tower"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
dependencies = [
"futures-core",
"futures-util",
"pin-project",
"pin-project-lite",
"tokio",
"tower-layer",
"tower-service",
]
[[package]]
name = "tower-layer"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
[[package]] [[package]]
name = "tower-service" name = "tower-service"
version = "0.3.2" version = "0.3.2"
@ -2633,9 +2721,9 @@ checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
[[package]] [[package]]
name = "winreg" name = "winreg"
version = "0.50.0" version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"windows-sys 0.48.0", "windows-sys 0.48.0",

View file

@ -31,7 +31,7 @@ eyre = { version = "0.6.8", default-features = false, features = [ "track-caller
glob = { version = "0.3.0", default-features = false } glob = { version = "0.3.0", default-features = false }
nix = { version = "0.28.0", default-features = false, features = ["user", "fs", "process", "term"] } nix = { version = "0.28.0", default-features = false, features = ["user", "fs", "process", "term"] }
owo-colors = { version = "4.0.0", default-features = false, features = [ "supports-colors" ] } owo-colors = { version = "4.0.0", default-features = false, features = [ "supports-colors" ] }
reqwest = { version = "0.11.11", default-features = false, features = ["rustls-tls-native-roots", "stream", "socks"] } reqwest = { version = "0.12.5", default-features = false, features = ["rustls-tls-native-roots", "stream", "socks", "zstd"] }
serde = { version = "1.0.144", default-features = false, features = [ "std", "derive" ] } serde = { version = "1.0.144", default-features = false, features = [ "std", "derive" ] }
serde_json = { version = "1.0.85", default-features = false, features = [ "std" ] } serde_json = { version = "1.0.85", default-features = false, features = [ "std" ] }
serde_with = { version = "3", default-features = false, features = [ "std", "macros" ] } serde_with = { version = "3", default-features = false, features = [ "std", "macros" ] }

View file

@ -1,18 +1,18 @@
use std::{ use std::{
collections::HashMap, collections::{HashMap, HashSet},
io::BufRead, io::BufRead,
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
use base64::Engine; use base64::Engine;
use ed25519_dalek::{SignatureError, VerifyingKey}; use ed25519_dalek::VerifyingKey;
use reqwest::Url; use reqwest::Url;
use tracing::{span, Span}; use tracing::{span, Span};
use crate::{ use crate::{
action::{Action, ActionDescription, ActionError, ActionErrorKind, ActionTag, StatefulAction}, action::{Action, ActionDescription, ActionError, ActionErrorKind, ActionTag, StatefulAction},
parse_ssl_cert, parse_ssl_cert,
settings::UrlOrPath, settings::UrlOrPathError,
}; };
/// Fetch an output and its dependencies from a set of substituters, /// Fetch an output and its dependencies from a set of substituters,
@ -51,17 +51,13 @@ const STORE_DIR: &str = "/nix/store/";
impl FetchAndUnpackNixSubstituter { impl FetchAndUnpackNixSubstituter {
#[tracing::instrument(level = "debug", skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn plan( pub async fn plan(
target: UrlOrPath, target: PathBuf,
dest: PathBuf, dest: PathBuf,
trusted_keys: Vec<String>, trusted_keys: Vec<String>,
substituters: Vec<Url>, substituters: Vec<Url>,
proxy: Option<Url>, proxy: Option<Url>,
ssl_cert_file: Option<PathBuf>, ssl_cert_file: Option<PathBuf>,
) -> Result<StatefulAction<Self>, ActionError> { ) -> Result<StatefulAction<Self>, ActionError> {
let UrlOrPath::Path(target_path) = target else {
return Err(Self::error(SubstitutionError::InvalidStorePath));
};
let trusted_keys_parsed = trusted_keys let trusted_keys_parsed = trusted_keys
.iter() .iter()
.map(|key| parse_key(key)) .map(|key| parse_key(key))
@ -80,7 +76,7 @@ impl FetchAndUnpackNixSubstituter {
} }
Ok(Self { Ok(Self {
target: StorePath::from_path(&target_path) target: StorePath::from_path(&target)
.ok_or_else(|| Self::error(SubstitutionError::InvalidStorePath))?, .ok_or_else(|| Self::error(SubstitutionError::InvalidStorePath))?,
trusted_keys: trusted_keys_parsed, trusted_keys: trusted_keys_parsed,
dest, dest,
@ -90,6 +86,51 @@ impl FetchAndUnpackNixSubstituter {
} }
.into()) .into())
} }
#[tracing::instrument(level = "trace", skip(self, client))]
async fn fetch_narinfo(
&self,
client: &reqwest::Client,
output: &StorePath,
) -> Result<NarInfo, ActionError> {
for substituter in &self.substituters {
let narinfo_url = substituter
.join(&format!("{}.narinfo", &output.digest))
// TODO: Give more useful error message here
.map_err(|err| UrlOrPathError::Url("".to_string(), err))
.map_err(ActionErrorKind::UrlOrPathError)
.map_err(Self::error)?;
let response = client
.get(narinfo_url)
.send()
.await
.map_err(ActionErrorKind::Reqwest)
.map_err(Self::error)?;
if !response.status().is_success() {
continue;
}
let narinfo = NarInfo::parse_and_verify(
&self.trusted_keys,
substituter,
&output,
&response
.bytes()
.await
.map_err(ActionErrorKind::Reqwest)
.map_err(Self::error)?,
)
.map_err(Self::error)?;
return Ok(narinfo);
}
Err(Self::error(SubstitutionError::NonexistantNarInfo(
output.full_path.clone(),
)))
}
} }
#[async_trait::async_trait] #[async_trait::async_trait]
@ -133,7 +174,43 @@ impl Action for FetchAndUnpackNixSubstituter {
#[tracing::instrument(level = "debug", skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn execute(&mut self) -> Result<(), ActionError> { async fn execute(&mut self) -> Result<(), ActionError> {
Ok(()) let mut client_builder = reqwest::Client::builder();
if let Some(proxy) = &self.proxy {
client_builder = client_builder.proxy(
reqwest::Proxy::all(proxy.clone())
.map_err(ActionErrorKind::Reqwest)
.map_err(Self::error)?,
)
}
if let Some(ssl_cert_file) = &self.ssl_cert_file {
let ssl_cert = parse_ssl_cert(ssl_cert_file).await.map_err(Self::error)?;
client_builder = client_builder.add_root_certificate(ssl_cert);
}
let client = client_builder
.build()
.map_err(ActionErrorKind::Reqwest)
.map_err(Self::error)?;
let mut outputs_remaining = vec![self.target.clone()];
let mut outputs_done = HashSet::new();
loop {
let Some(output) = outputs_remaining.pop() else {
break;
};
// Make sure we don't download the same output twice
if !outputs_done.insert(output.clone()) {
continue;
}
let narinfo = self.fetch_narinfo(&client, &output).await?;
for reference in &narinfo.references {
outputs_remaining.push(reference.clone());
}
}
todo!()
} }
fn revert_description(&self) -> Vec<ActionDescription> { fn revert_description(&self) -> Vec<ActionDescription> {
@ -232,6 +309,12 @@ impl StorePath {
} }
} }
impl std::hash::Hash for StorePath {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.full_path.hash(state);
}
}
impl PartialEq for StorePath { impl PartialEq for StorePath {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.full_path == other.full_path self.full_path == other.full_path
@ -348,10 +431,16 @@ impl NarInfo {
}, },
"NarSize" => nar_size = u64::from_str_radix(value, 10).ok(), "NarSize" => nar_size = u64::from_str_radix(value, 10).ok(),
"References" => { "References" => {
references = value references = Some(if value.is_empty() {
.split(' ') // split on empty strings still returns one value
.map(StorePath::from_full_name) Vec::new()
.collect::<Option<Vec<_>>>() } else {
value
.split(' ')
.map(StorePath::from_full_name)
.map(|value| value.ok_or_else(|| SubstitutionError::BadNarInfo))
.collect::<Result<Vec<_>, _>>()?
});
}, },
"Sig" => { "Sig" => {
let (signer, base64_signature) = value let (signer, base64_signature) = value
@ -388,7 +477,7 @@ impl NarInfo {
// Fingerprint format not documented, but implemented in lix: // Fingerprint format not documented, but implemented in lix:
// https://git.lix.systems/lix-project/lix/src/commit/d461cc1d7b2f489c3886f147166ba5b5e0e37541/src/libstore/path-info.cc#L25 // https://git.lix.systems/lix-project/lix/src/commit/d461cc1d7b2f489c3886f147166ba5b5e0e37541/src/libstore/path-info.cc#L25
let fingerprint = format!( let fingerprint = format!(
"1;{};{};{};{}", "1;{};sha256:{};{};{}",
self.store_path.full_path, self.store_path.full_path,
self.nar_hash, self.nar_hash,
self.nar_size, self.nar_size,
@ -447,6 +536,8 @@ pub enum SubstitutionError {
BadNarInfo, BadNarInfo,
#[error("Bad narinfo signature")] #[error("Bad narinfo signature")]
BadSignature, BadSignature,
#[error("No substituter has path {0}")]
NonexistantNarInfo(String),
#[error("Invalid nix store path")] #[error("Invalid nix store path")]
InvalidStorePath, InvalidStorePath,
} }

View file

@ -59,7 +59,7 @@ impl ProvisionNix {
let fetch_nix = if settings.use_substituters { let fetch_nix = if settings.use_substituters {
FetchNix::FromSubstituter( FetchNix::FromSubstituter(
FetchAndUnpackNixSubstituter::plan( FetchAndUnpackNixSubstituter::plan(
settings.nix_package_url.clone(), settings.substitution_target.clone(),
PathBuf::from(SCRATCH_DIR), PathBuf::from(SCRATCH_DIR),
settings.substituter_trusted_keys.clone(), settings.substituter_trusted_keys.clone(),
settings.substituters.clone(), settings.substituters.clone(),

View file

@ -168,6 +168,17 @@ pub struct CommonSettings {
)] )]
pub substituter_trusted_keys: Vec<String>, pub substituter_trusted_keys: Vec<String>,
/// Output to download when use_substituters is set
#[cfg_attr(
feature = "cli",
clap(
long,
env = "NIX_INSTALLER_SUBSTITUTION_TARGET",
default_value = "/nix/store/rp7y16q2py2n9y19jvxkjr83lp77bh7y-lix-2.90.0"
)
)]
pub substitution_target: PathBuf,
/// Download Lix from a substituter instead of an install tarball /// Download Lix from a substituter instead of an install tarball
#[cfg_attr(feature = "cli", clap(long, env = "NIX_INSTALLER_USE_SUBSTITUTER"))] #[cfg_attr(feature = "cli", clap(long, env = "NIX_INSTALLER_USE_SUBSTITUTER"))]
pub use_substituters: bool, pub use_substituters: bool,
@ -323,6 +334,7 @@ impl CommonSettings {
.iter() .iter()
.map(|s| s.to_string()) .map(|s| s.to_string())
.collect(), .collect(),
substitution_target: "/nix/store/rp7y16q2py2n9y19jvxkjr83lp77bh7y-lix-2.90.0".into(),
use_substituters: false, use_substituters: false,
nix_package_url: url.parse()?, nix_package_url: url.parse()?,
proxy: Default::default(), proxy: Default::default(),
@ -344,6 +356,7 @@ impl CommonSettings {
nix_build_user_count, nix_build_user_count,
substituters, substituters,
substituter_trusted_keys, substituter_trusted_keys,
substitution_target,
use_substituters, use_substituters,
nix_package_url, nix_package_url,
proxy, proxy,
@ -383,6 +396,10 @@ impl CommonSettings {
"substituter_trusted_keys".into(), "substituter_trusted_keys".into(),
serde_json::to_value(substituter_trusted_keys)?, serde_json::to_value(substituter_trusted_keys)?,
); );
map.insert(
"substitution_target".into(),
serde_json::to_value(substitution_target)?,
);
map.insert( map.insert(
"use_substituters".into(), "use_substituters".into(),
serde_json::to_value(use_substituters)?, serde_json::to_value(use_substituters)?,

View file

@ -419,6 +419,7 @@
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=", "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=",
"cache.lix.systems:aBnZUw8zA7H35Cz2RyKFVs3H4PlGTLawyY5KRbvJR8o=" "cache.lix.systems:aBnZUw8zA7H35Cz2RyKFVs3H4PlGTLawyY5KRbvJR8o="
], ],
"substitution_target": "/nix/store/rp7y16q2py2n9y19jvxkjr83lp77bh7y-lix-2.90.0",
"use_substituters": false, "use_substituters": false,
"nix_package_url": { "nix_package_url": {
"Url": "https://releases.nixos.org/nix/nix-2.17.0/nix-2.17.0-x86_64-linux.tar.xz" "Url": "https://releases.nixos.org/nix/nix-2.17.0/nix-2.17.0-x86_64-linux.tar.xz"

View file

@ -403,6 +403,7 @@
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=", "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=",
"cache.lix.systems:aBnZUw8zA7H35Cz2RyKFVs3H4PlGTLawyY5KRbvJR8o=" "cache.lix.systems:aBnZUw8zA7H35Cz2RyKFVs3H4PlGTLawyY5KRbvJR8o="
], ],
"substitution_target": "/nix/store/rp7y16q2py2n9y19jvxkjr83lp77bh7y-lix-2.90.0",
"use_substituters": false, "use_substituters": false,
"nix_package_url": { "nix_package_url": {
"Url": "https://releases.nixos.org/nix/nix-2.17.0/nix-2.17.0-x86_64-linux.tar.xz" "Url": "https://releases.nixos.org/nix/nix-2.17.0/nix-2.17.0-x86_64-linux.tar.xz"

View file

@ -430,6 +430,7 @@
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=", "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=",
"cache.lix.systems:aBnZUw8zA7H35Cz2RyKFVs3H4PlGTLawyY5KRbvJR8o=" "cache.lix.systems:aBnZUw8zA7H35Cz2RyKFVs3H4PlGTLawyY5KRbvJR8o="
], ],
"substitution_target": "/nix/store/rp7y16q2py2n9y19jvxkjr83lp77bh7y-lix-2.90.0",
"use_substituters": false, "use_substituters": false,
"nix_package_url": { "nix_package_url": {
"Url": "https://releases.nixos.org/nix/nix-2.17.0/nix-2.17.0-x86_64-darwin.tar.xz" "Url": "https://releases.nixos.org/nix/nix-2.17.0/nix-2.17.0-x86_64-darwin.tar.xz"