feat(tvix/store): implement Nixpath::from_absolute_path

This allows constructing a NixPath from an absolute path. It pops off
the STORE_DIR prefix and the trailing slash and returns an error if it
couldn't be found.

Change-Id: Ib540e353c63cc247ac15e20414b0db2caf695ef4
Reviewed-on: https://cl.tvl.fyi/c/depot/+/7751
Tested-by: BuildkiteCI
Reviewed-by: tazjin <tazjin@tvl.su>
This commit is contained in:
Florian Klink 2023-01-04 16:20:42 +01:00 committed by flokli
parent 34be6466d4
commit 8449f6cd0c

View file

@ -8,6 +8,11 @@ pub const DIGEST_SIZE: usize = 20;
// manually and have an assert in the tests. // manually and have an assert in the tests.
pub const ENCODED_DIGEST_SIZE: usize = 32; pub const ENCODED_DIGEST_SIZE: usize = 32;
// The store dir prefix, without trailing slash.
// That's usually where the Nix store is mounted at.
pub const STORE_DIR: &str = "/nix/store";
pub const STORE_DIR_WITH_SLASH: &str = "/nix/store/";
/// Errors that can occur during the validation of name characters. /// Errors that can occur during the validation of name characters.
#[derive(Debug, PartialEq, Eq, Error)] #[derive(Debug, PartialEq, Eq, Error)]
pub enum ParseNixPathError { pub enum ParseNixPathError {
@ -17,6 +22,8 @@ pub enum ParseNixPathError {
InvalidHashEncoding(DecodeError), InvalidHashEncoding(DecodeError),
#[error("Invalid name {0}")] #[error("Invalid name {0}")]
InvalidName(String), InvalidName(String),
#[error("Tried to parse an absolute path which was missing the store dir prefix.")]
MissingStoreDir(),
} }
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
@ -55,6 +62,15 @@ impl NixPath {
}) })
} }
/// Construct a NixPath from an absolute store path string.
/// That is a string starting with the store prefix (/nix/store)
pub fn from_absolute_path(s: &str) -> Result<NixPath, ParseNixPathError> {
match s.strip_prefix(STORE_DIR_WITH_SLASH) {
Some(s_stripped) => Self::from_string(s_stripped),
None => Err(ParseNixPathError::MissingStoreDir()),
}
}
fn validate_characters(s: &str) -> Result<(), ParseNixPathError> { fn validate_characters(s: &str) -> Result<(), ParseNixPathError> {
for c in s.chars() { for c in s.chars() {
if c.is_ascii_alphanumeric() if c.is_ascii_alphanumeric()
@ -91,7 +107,7 @@ mod tests {
use crate::nixbase32::NIXBASE32; use crate::nixbase32::NIXBASE32;
use crate::nixpath::{DIGEST_SIZE, ENCODED_DIGEST_SIZE}; use crate::nixpath::{DIGEST_SIZE, ENCODED_DIGEST_SIZE};
use super::NixPath; use super::{NixPath, ParseNixPathError};
#[test] #[test]
fn encoded_digest_size() { fn encoded_digest_size() {
@ -141,4 +157,26 @@ mod tests {
NixPath::from_string("00bgd045z0d4icpbc2yyz4gx48ak44lanet-tools-1.60_p20170221182432") NixPath::from_string("00bgd045z0d4icpbc2yyz4gx48ak44lanet-tools-1.60_p20170221182432")
.expect_err("No error raised."); .expect_err("No error raised.");
} }
#[test]
fn absolute_path() {
let example_nix_path_str =
"00bgd045z0d4icpbc2yyz4gx48ak44la-net-tools-1.60_p20170221182432";
let nixpath_expected = NixPath::from_string(&example_nix_path_str).expect("must parse");
let nixpath_actual = NixPath::from_absolute_path(
"/nix/store/00bgd045z0d4icpbc2yyz4gx48ak44la-net-tools-1.60_p20170221182432",
)
.expect("must parse");
assert_eq!(nixpath_expected, nixpath_actual);
}
#[test]
fn absolute_path_missing_prefix() {
assert_eq!(
ParseNixPathError::MissingStoreDir(),
NixPath::from_absolute_path("foobar-123").expect_err("must fail")
);
}
} }