mirror of
https://github.com/RGBCube/dix
synced 2025-07-28 12:17:45 +00:00
feat: refactor get_name_and_path to parse_name_and_path
This commit is contained in:
parent
af7f63d3f6
commit
c73c1ab330
1 changed files with 34 additions and 45 deletions
79
src/util.rs
79
src/util.rs
|
@ -92,61 +92,50 @@ pub fn compare_versions(this: &str, that: &str) -> cmp::Ordering {
|
||||||
this.cmp(that)
|
this.cmp(that)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a nix store path to extract the packages name and version
|
/// Parses a Nix store path to extract the packages name and possibly its
|
||||||
|
/// version.
|
||||||
///
|
///
|
||||||
/// This function first drops the inputs first 44 chars, since that is exactly
|
/// This function first drops the inputs first 44 chars, since that is exactly
|
||||||
/// the length of the /nix/store/... prefix. Then it matches that against our
|
/// the length of the `/nix/store/0004yybkm5hnwjyxv129js3mjp7kbrax-` prefix.
|
||||||
/// store path regex.
|
/// Then it matches that against our store path regex.
|
||||||
///
|
pub fn parse_name_and_version(
|
||||||
/// # Returns
|
path: &StorePath,
|
||||||
///
|
) -> Result<(&str, Option<&str>)> {
|
||||||
/// * Result<(&'a str, &'a str)> - The Package's name and version, or an error
|
static STORE_PATH_REGEX: LazyLock<Regex> = LazyLock::new(|| {
|
||||||
/// if one or both cannot be retrieved.
|
Regex::new("(.+?)(-([0-9].*?))?$")
|
||||||
pub fn get_version<'a>(pack: impl Into<&'a str>) -> Result<(&'a str, &'a str)> {
|
.expect("failed to compile regex pattern for nix store paths")
|
||||||
let path = pack.into();
|
});
|
||||||
|
|
||||||
// We can strip the path since it _always_ follows the format
|
let path = path.to_str().with_context(|| {
|
||||||
// /nix/store/<...>-<program_name>-......
|
format!(
|
||||||
|
"failed to convert path '{path}' to valid unicode",
|
||||||
|
path = path.display(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// We can strip the path since it _always_ follows the format:
|
||||||
|
//
|
||||||
|
// /nix/store/0004yybkm5hnwjyxv129js3mjp7kbrax-...
|
||||||
|
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
// This part is exactly 44 chars long, so we just remove it.
|
// This part is exactly 44 chars long, so we just remove it.
|
||||||
let stripped_path = &path[44..];
|
assert_eq!(&path[..11], "/nix/store/");
|
||||||
debug!("Stripped path: {stripped_path}");
|
assert_eq!(&path[43..44], "-");
|
||||||
|
let path = &path[44..];
|
||||||
|
|
||||||
// Match the regex against the input
|
log::debug!("stripped path: {path}");
|
||||||
if let Some(cap) = store_path_regex().captures(stripped_path) {
|
|
||||||
// Handle potential missing captures safely
|
|
||||||
let name = cap.get(1).map_or("", |m| m.as_str());
|
|
||||||
let mut version = cap.get(2).map_or("<none>", |m| m.as_str());
|
|
||||||
|
|
||||||
if version.starts_with('-') {
|
let captures = STORE_PATH_REGEX.captures(path).ok_or_else(|| {
|
||||||
version = &version[1..];
|
anyhow!("path '{path}' does not match expected Nix store format")
|
||||||
}
|
})?;
|
||||||
|
|
||||||
if name.is_empty() {
|
let name = captures.get(1).map_or("", |m| m.as_str());
|
||||||
return Err(AppError::ParseError {
|
if name.is_empty() {
|
||||||
message: format!("Failed to extract name from path: {path}"),
|
bail!("failed to extract name from path '{path}'");
|
||||||
context: "get_version".to_string(),
|
|
||||||
source: None,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok((name, version));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(AppError::ParseError {
|
let version = captures.get(2).map(|m| m.as_str().trim_start_matches('-'));
|
||||||
message: format!("Path does not match expected nix store format: {path}"),
|
|
||||||
context: "get_version".to_string(),
|
|
||||||
source: None,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a reference to the compiled regex pattern.
|
Ok((name, version))
|
||||||
// The regex is compiled only once.
|
|
||||||
pub fn store_path_regex() -> &'static Regex {
|
|
||||||
static REGEX: OnceLock<Regex> = OnceLock::new();
|
|
||||||
REGEX.get_or_init(|| {
|
|
||||||
Regex::new(r"(.+?)(-([0-9].*?))?$")
|
|
||||||
.expect("Failed to compile regex pattern for nix store paths")
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: move this somewhere else, this does not really
|
// TODO: move this somewhere else, this does not really
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue