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 clap::Parser;
|
||||||
use core::str;
|
use core::str;
|
||||||
use log::{debug, error};
|
use log::{debug, error};
|
||||||
use regex::Regex;
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
string::ToString,
|
|
||||||
sync::OnceLock,
|
|
||||||
thread,
|
thread,
|
||||||
};
|
};
|
||||||
use yansi::Paint;
|
use yansi::Paint;
|
||||||
|
@ -153,7 +150,7 @@ fn main() {
|
||||||
let mut post = HashMap::<&str, HashSet<&str>>::new();
|
let mut post = HashMap::<&str, HashSet<&str>>::new();
|
||||||
|
|
||||||
for p in &package_list_pre {
|
for p in &package_list_pre {
|
||||||
match get_version(&**p) {
|
match util::get_version(&**p) {
|
||||||
Ok((name, version)) => {
|
Ok((name, version)) => {
|
||||||
pre.entry(name).or_default().insert(version);
|
pre.entry(name).or_default().insert(version);
|
||||||
}
|
}
|
||||||
|
@ -164,7 +161,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
for p in &package_list_post {
|
for p in &package_list_post {
|
||||||
match get_version(&**p) {
|
match util::get_version(&**p) {
|
||||||
Ok((name, version)) => {
|
Ok((name, version)) => {
|
||||||
post.entry(name).or_default().insert(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::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)]
|
#[derive(Eq, PartialEq, Debug)]
|
||||||
enum VersionComponent {
|
enum VersionComponent {
|
||||||
Number(u64),
|
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