forked from lix-project/lix-installer
Just store one string in StorePath
This commit is contained in:
parent
72580f5e65
commit
0652538579
|
@ -9,6 +9,7 @@ use base64::Engine;
|
|||
use bytes::Buf;
|
||||
use ed25519_dalek::VerifyingKey;
|
||||
use reqwest::Url;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sha2::Digest;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
use tracing::{span, Span};
|
||||
|
@ -104,8 +105,7 @@ impl FetchAndUnpackNixSubstituter {
|
|||
) -> Result<NarInfo, ActionError> {
|
||||
for substituter in &self.substituters {
|
||||
let narinfo_url = substituter
|
||||
.join(&format!("{}.narinfo", &output.digest))
|
||||
// TODO: Give more useful error message here
|
||||
.join(&format!("{}.narinfo", &output.digest()))
|
||||
.map_err(|err| UrlOrPathError::Url("".to_string(), err))
|
||||
.map_err(ActionErrorKind::UrlOrPathError)
|
||||
.map_err(Self::error)?;
|
||||
|
@ -137,7 +137,7 @@ impl FetchAndUnpackNixSubstituter {
|
|||
}
|
||||
|
||||
Err(Self::error(SubstitutionError::NonexistantNarInfo(
|
||||
output.full_path.clone(),
|
||||
output.full_path().clone(),
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ impl Action for FetchAndUnpackNixSubstituter {
|
|||
"Fetch {} from substituters to `{}`",
|
||||
self.targets
|
||||
.iter()
|
||||
.map(|t| format!("`{}`", t.full_path))
|
||||
.map(|t| format!("`{}`", t.full_path()))
|
||||
.collect::<Vec<String>>()
|
||||
.join(", "),
|
||||
self.dest.display()
|
||||
|
@ -281,9 +281,7 @@ impl Action for FetchAndUnpackNixSubstituter {
|
|||
return Err(Self::error(SubstitutionError::BadNar(narinfo.url.clone())));
|
||||
}
|
||||
|
||||
// TODO: Figure out a better way to make relative
|
||||
// Maybe simplify StorePath?
|
||||
let out_dir = self.dest.join("nix-/store").join(output.full_name);
|
||||
let out_dir = self.dest.join("nix-/store").join(output.full_name());
|
||||
|
||||
let decoder = nix_nar::Decoder::new(decompressed_nar.reader())
|
||||
.map_err(|e| SubstitutionError::Unpack(narinfo.url.clone(), e))
|
||||
|
@ -297,14 +295,14 @@ impl Action for FetchAndUnpackNixSubstituter {
|
|||
// File format isn't documented anywhere but implementation is simple:
|
||||
// https://git.lix.systems/lix-project/lix/src/commit/d461cc1d7b2f489c3886f147166ba5b5e0e37541/src/libstore/store-api.cc#L846
|
||||
// Unwrapping because string can't fail methods in std::fmt::Write
|
||||
write!(reginfo, "{}\n", output.full_path).unwrap();
|
||||
write!(reginfo, "{}\n", output.full_path()).unwrap();
|
||||
write!(reginfo, "sha256:{}\n", narinfo.nar_hash).unwrap();
|
||||
write!(reginfo, "{}\n", narinfo.nar_size).unwrap();
|
||||
// Leave deriver empty, same as lix binary tarballs
|
||||
reginfo.push('\n');
|
||||
write!(reginfo, "{}\n", narinfo.references.len()).unwrap();
|
||||
for reference in &narinfo.references {
|
||||
write!(reginfo, "{}\n", reference.full_path).unwrap();
|
||||
write!(reginfo, "{}\n", reference.full_path()).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -355,21 +353,30 @@ fn parse_key(key: &str) -> Result<(String, VerifyingKey), SubstitutionError> {
|
|||
}
|
||||
|
||||
/// Utility struct representing a store path
|
||||
#[derive(Clone, Eq, Debug)]
|
||||
struct StorePath {
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
struct StorePath(String);
|
||||
|
||||
impl StorePath {
|
||||
/// The full name of a path, not including STORE_DIR,
|
||||
/// e.g. `n50jk09x9hshwx1lh6k3qaiygc7yxbv9-lix-2.90.0-rc1`
|
||||
pub fn full_name(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
|
||||
/// The base32 hash part of a store path,
|
||||
/// e.g. `n50jk09x9hshwx1lh6k3qaiygc7yxbv9`
|
||||
pub fn digest(&self) -> &str {
|
||||
&self.0.split_once('-').unwrap().0
|
||||
}
|
||||
|
||||
/// Full path of the output including STORE_DIR,
|
||||
/// as seen in StorePath in narinfo
|
||||
/// e.g. `/nix/store/n50jk09x9hshwx1lh6k3qaiygc7yxbv9-lix-2.90.0-rc1`
|
||||
pub full_path: String,
|
||||
/// The base32 hash part of a store path,
|
||||
/// e.g. `n50jk09x9hshwx1lh6k3qaiygc7yxbv9`
|
||||
pub digest: String,
|
||||
/// The full name of a path, not including STORE_DIR,
|
||||
/// e.g. `n50jk09x9hshwx1lh6k3qaiygc7yxbv9-lix-2.90.0-rc1`
|
||||
pub full_name: String,
|
||||
}
|
||||
pub fn full_path(&self) -> String {
|
||||
format!("{}{}", STORE_DIR, &self.0)
|
||||
}
|
||||
|
||||
impl StorePath {
|
||||
pub fn from_full_path(full_path: &str) -> Option<Self> {
|
||||
if !full_path.starts_with(STORE_DIR) {
|
||||
return None;
|
||||
|
@ -377,6 +384,18 @@ impl StorePath {
|
|||
|
||||
let (_, full_name) = full_path.split_at(STORE_DIR.len());
|
||||
|
||||
Self::from_full_name(full_name)
|
||||
}
|
||||
|
||||
pub fn from_path(path: &Path) -> Result<Self, SubstitutionError> {
|
||||
let path_str = path
|
||||
.to_str()
|
||||
.ok_or_else(|| SubstitutionError::InvalidStorePath(path.to_owned()))?;
|
||||
Self::from_full_path(path_str)
|
||||
.ok_or_else(|| SubstitutionError::InvalidStorePath(path.to_owned()))
|
||||
}
|
||||
|
||||
pub fn from_full_name(full_name: &str) -> Option<Self> {
|
||||
let (digest, name) = full_name.split_once('-')?;
|
||||
|
||||
if digest.len() != 32
|
||||
|
@ -397,75 +416,7 @@ impl StorePath {
|
|||
return None;
|
||||
}
|
||||
|
||||
Some(Self {
|
||||
full_path: full_path.to_string(),
|
||||
digest: digest.to_string(),
|
||||
full_name: full_name.to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn from_path(path: &Path) -> Result<Self, SubstitutionError> {
|
||||
let path_str = path
|
||||
.to_str()
|
||||
.ok_or_else(|| SubstitutionError::InvalidStorePath(path.to_owned()))?;
|
||||
Self::from_full_path(path_str)
|
||||
.ok_or_else(|| SubstitutionError::InvalidStorePath(path.to_owned()))
|
||||
}
|
||||
|
||||
pub fn from_full_name(full_name: &str) -> Option<Self> {
|
||||
Self::from_full_path(
|
||||
&Path::new(STORE_DIR)
|
||||
.join(&full_name)
|
||||
.into_os_string()
|
||||
.into_string()
|
||||
.ok()?,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.full_path == other.full_path
|
||||
}
|
||||
}
|
||||
|
||||
impl serde::Serialize for StorePath {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
self.full_path.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> serde::Deserialize<'de> for StorePath {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_string(StorePathVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
struct StorePathVisitor;
|
||||
impl serde::de::Visitor<'_> for StorePathVisitor {
|
||||
type Value = StorePath;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("a valid nix store path starting with /nix/store")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
StorePath::from_full_path(value).ok_or_else(|| E::custom("invalid store path"))
|
||||
Some(Self(full_name.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -592,13 +543,13 @@ impl NarInfo {
|
|||
// https://git.lix.systems/lix-project/lix/src/commit/d461cc1d7b2f489c3886f147166ba5b5e0e37541/src/libstore/path-info.cc#L25
|
||||
let fingerprint = format!(
|
||||
"1;{};sha256:{};{};{}",
|
||||
self.store_path.full_path,
|
||||
self.store_path.full_path(),
|
||||
self.nar_hash,
|
||||
self.nar_size,
|
||||
self.references
|
||||
.iter()
|
||||
.map(|reference| reference.full_path.as_ref())
|
||||
.collect::<Vec<&str>>()
|
||||
.map(|reference| reference.full_path())
|
||||
.collect::<Vec<String>>()
|
||||
.join(",")
|
||||
);
|
||||
|
||||
|
|
Loading…
Reference in a new issue