about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFlorian Klink <flokli@flokli.de>2023-01-04T15·20+0100
committerflokli <flokli@flokli.de>2023-01-04T20·23+0000
commit8449f6cd0c97f341f75ac3201499ebb0c2161e6b (patch)
tree1574521f75f0b28d4c5a6294224cee5a5db743d7
parent34be6466d4a5da7dd3ad55ce80c951f21e45520c (diff)
feat(tvix/store): implement Nixpath::from_absolute_path r/5586
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>
-rw-r--r--tvix/store/src/nixpath.rs40
1 files changed, 39 insertions, 1 deletions
diff --git a/tvix/store/src/nixpath.rs b/tvix/store/src/nixpath.rs
index ed0d39864d..e7329b527c 100644
--- a/tvix/store/src/nixpath.rs
+++ b/tvix/store/src/nixpath.rs
@@ -8,6 +8,11 @@ pub const DIGEST_SIZE: usize = 20;
 // manually and have an assert in the tests.
 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.
 #[derive(Debug, PartialEq, Eq, Error)]
 pub enum ParseNixPathError {
@@ -17,6 +22,8 @@ pub enum ParseNixPathError {
     InvalidHashEncoding(DecodeError),
     #[error("Invalid name {0}")]
     InvalidName(String),
+    #[error("Tried to parse an absolute path which was missing the store dir prefix.")]
+    MissingStoreDir(),
 }
 
 #[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> {
         for c in s.chars() {
             if c.is_ascii_alphanumeric()
@@ -91,7 +107,7 @@ mod tests {
     use crate::nixbase32::NIXBASE32;
     use crate::nixpath::{DIGEST_SIZE, ENCODED_DIGEST_SIZE};
 
-    use super::NixPath;
+    use super::{NixPath, ParseNixPathError};
 
     #[test]
     fn encoded_digest_size() {
@@ -141,4 +157,26 @@ mod tests {
         NixPath::from_string("00bgd045z0d4icpbc2yyz4gx48ak44lanet-tools-1.60_p20170221182432")
             .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")
+        );
+    }
 }