mirror of
https://github.com/RGBCube/dix
synced 2025-07-27 11:47:46 +00:00
main, util: move get_version to util.rs
This commit is contained in:
parent
fb59cccda7
commit
9d0b52a535
2 changed files with 69 additions and 60 deletions
62
src/main.rs
62
src/main.rs
|
@ -3,11 +3,8 @@ mod util;
|
|||
use clap::Parser;
|
||||
use core::str;
|
||||
use log::{debug, error};
|
||||
use regex::Regex;
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
string::ToString,
|
||||
sync::OnceLock,
|
||||
thread,
|
||||
};
|
||||
use yansi::Paint;
|
||||
|
@ -153,7 +150,7 @@ fn main() {
|
|||
let mut post = HashMap::<&str, HashSet<&str>>::new();
|
||||
|
||||
for p in &package_list_pre {
|
||||
match get_version(&**p) {
|
||||
match util::get_version(&**p) {
|
||||
Ok((name, version)) => {
|
||||
pre.entry(name).or_default().insert(version);
|
||||
}
|
||||
|
@ -164,7 +161,7 @@ fn main() {
|
|||
}
|
||||
|
||||
for p in &package_list_post {
|
||||
match get_version(&**p) {
|
||||
match util::get_version(&**p) {
|
||||
Ok((name, version)) => {
|
||||
post.entry(name).or_default().insert(version);
|
||||
}
|
||||
|
@ -247,58 +244,3 @@ fn main() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a reference to the compiled regex pattern.
|
||||
// The regex is compiled only once.
|
||||
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")
|
||||
})
|
||||
}
|
||||
|
||||
/// Parses a nix store path to extract the packages name and version
|
||||
///
|
||||
/// 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 store path regex.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * Result<(&'a str, &'a str)> - The Package's name and version, or an error if
|
||||
/// one or both cannot be retrieved.
|
||||
fn get_version<'a>(pack: impl Into<&'a str>) -> Result<(&'a str, &'a str)> {
|
||||
let path = pack.into();
|
||||
|
||||
// We can strip the path since it _always_ follows the format
|
||||
// /nix/store/<...>-<program_name>-......
|
||||
// This part is exactly 44 chars long, so we just remove it.
|
||||
let stripped_path = &path[44..];
|
||||
debug!("Stripped path: {stripped_path}");
|
||||
|
||||
// Match the regex against the input
|
||||
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('-') {
|
||||
version = &version[1..];
|
||||
}
|
||||
|
||||
if name.is_empty() {
|
||||
return Err(AppError::ParseError {
|
||||
message: format!("Failed to extract name from path: {path}"),
|
||||
context: "get_version".to_string(),
|
||||
source: None,
|
||||
});
|
||||
}
|
||||
|
||||
return Ok((name, version));
|
||||
}
|
||||
|
||||
Err(AppError::ParseError {
|
||||
message: format!("Path does not match expected nix store format: {path}"),
|
||||
context: "get_version".to_string(),
|
||||
source: None,
|
||||
})
|
||||
}
|
||||
|
|
67
src/util.rs
67
src/util.rs
|
@ -1,5 +1,18 @@
|
|||
use crate::error::AppError;
|
||||
use log::{debug, error};
|
||||
use regex::Regex;
|
||||
use std::cmp::Ordering;
|
||||
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
string::ToString,
|
||||
sync::OnceLock,
|
||||
thread,
|
||||
};
|
||||
|
||||
// Use type alias for Result with our custom error type
|
||||
type Result<T> = std::result::Result<T, AppError>;
|
||||
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
enum VersionComponent {
|
||||
Number(u64),
|
||||
|
@ -114,3 +127,57 @@ mod test {
|
|||
);
|
||||
}
|
||||
}
|
||||
/// Parses a nix store path to extract the packages name and version
|
||||
///
|
||||
/// 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 store path regex.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * Result<(&'a str, &'a str)> - The Package's name and version, or an error if
|
||||
/// one or both cannot be retrieved.
|
||||
pub fn get_version<'a>(pack: impl Into<&'a str>) -> Result<(&'a str, &'a str)> {
|
||||
let path = pack.into();
|
||||
|
||||
// We can strip the path since it _always_ follows the format
|
||||
// /nix/store/<...>-<program_name>-......
|
||||
// This part is exactly 44 chars long, so we just remove it.
|
||||
let stripped_path = &path[44..];
|
||||
debug!("Stripped path: {stripped_path}");
|
||||
|
||||
// Match the regex against the input
|
||||
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('-') {
|
||||
version = &version[1..];
|
||||
}
|
||||
|
||||
if name.is_empty() {
|
||||
return Err(AppError::ParseError {
|
||||
message: format!("Failed to extract name from path: {path}"),
|
||||
context: "get_version".to_string(),
|
||||
source: None,
|
||||
});
|
||||
}
|
||||
|
||||
return Ok((name, version));
|
||||
}
|
||||
|
||||
Err(AppError::ParseError {
|
||||
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.
|
||||
// The regex is compiled only once.
|
||||
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")
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue