From ab651b9b9784bec26e08023a5a59f435fbd5afbe Mon Sep 17 00:00:00 2001 From: "Hautvast, S. (Sander)" Date: Tue, 16 Sep 2025 21:45:28 +0200 Subject: [PATCH] prepare better repository resolution --- src/main.rs | 3 +- src/maven/common_model.rs | 79 +++++++++++++++++++++++++++++++++++++ src/maven/mod.rs | 1 + src/maven/pom.rs | 11 +++++- src/maven/pom_parser.rs | 12 +++++- src/maven/project.rs | 13 +++++- src/maven/reporter.rs | 31 ++++++++------- src/maven/settings.rs | 83 ++------------------------------------- 8 files changed, 134 insertions(+), 99 deletions(-) create mode 100644 src/maven/common_model.rs diff --git a/src/main.rs b/src/main.rs index d985f84..a73ac7c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,8 +11,9 @@ fn main() { } else { PathBuf::from(&args[1]) }; + let project = parse_project(&dir).unwrap(); - get_settings().unwrap(); + fs::write( PathBuf::from("index.html"), project.generate_dependency_html(), diff --git a/src/maven/common_model.rs b/src/maven/common_model.rs new file mode 100644 index 0000000..36867fa --- /dev/null +++ b/src/maven/common_model.rs @@ -0,0 +1,79 @@ +use crate::xml::dom_parser::Node; + +#[derive(Debug)] +pub struct Repository { + pub releases: Option, + pub snapshots: Option, + pub id: Option, + pub name: Option, + pub url: Option, + pub layout: String, +} + +#[derive(Debug)] +pub struct RepositoryPolicy { + pub enabled: bool, + pub update_policy: Option, + pub checksum_policy: Option, +} + +pub fn get_repositories(element: Node) -> Vec { + let mut repositories = vec![]; + + for child in element.children { + match child.name.as_str() { + "repository" => repositories.push(get_repository(child)), + _ => {} + } + } + repositories +} + +fn get_repository(element: Node) -> Repository { + let mut releases = None; + let mut snapshots = None; + let mut id = None; + let mut name = None; + let mut url = None; + let mut layout = "default".to_owned(); + + for child in element.children { + match child.name.as_str() { + "releases" => releases = Some(get_update_policy(child)), + "snapshots" => snapshots = Some(get_update_policy(child)), + "id" => id = child.text, + "name" => name = child.text, + "url" => url = child.text, + "layout" => layout = child.text.unwrap_or("default".to_owned()), + _ => {} + } + } + Repository { + releases, + snapshots, + id, + name, + url, + layout, + } +} + +fn get_update_policy(element: Node) -> RepositoryPolicy { + let mut enabled = true; + let mut update_policy = None; + let mut checksum_policy = None; + + for child in element.children { + match child.name.as_str() { + "enabled" => enabled = child.text.map(|b| b == "true").unwrap_or(true), + "update_policy" => update_policy = child.text, + "checksum_policy" => checksum_policy = child.text, + _ => {} + } + } + RepositoryPolicy { + enabled, + update_policy, + checksum_policy, + } +} diff --git a/src/maven/mod.rs b/src/maven/mod.rs index bbb0a31..5897a08 100644 --- a/src/maven/mod.rs +++ b/src/maven/mod.rs @@ -1,5 +1,6 @@ use std::{env, sync::LazyLock}; +pub mod common_model; pub mod metadata; pub mod pom; pub mod pom_parser; diff --git a/src/maven/pom.rs b/src/maven/pom.rs index ae9e87a..d39e0ff 100644 --- a/src/maven/pom.rs +++ b/src/maven/pom.rs @@ -4,7 +4,7 @@ use std::path::PathBuf; /// the maven object model -#[derive(PartialEq, Debug)] +#[derive(Debug)] pub struct Pom { pub parent: Option, pub group_id: Option, @@ -19,6 +19,7 @@ pub struct Pom { pub module_names: Vec, pub modules: Vec, pub directory: PathBuf, + pub repositories: Vec, } impl Pom {} @@ -72,11 +73,19 @@ impl Dependency { absolute_path.push(self.to_jar_path()); absolute_path } + + pub fn is_snapshot(&self) -> bool { + self.version + .as_ref() + .map(|v| v.ends_with("SNAPSHOT")) + .unwrap_or(false) + } } use std::fmt; use crate::maven::HOME; +use crate::maven::common_model::Repository; impl Display for Dependency { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/src/maven/pom_parser.rs b/src/maven/pom_parser.rs index f3ea27a..1601610 100644 --- a/src/maven/pom_parser.rs +++ b/src/maven/pom_parser.rs @@ -1,3 +1,4 @@ +use crate::maven::common_model::get_repositories; use crate::maven::pom::{Dependency, Developer, Parent, Pom}; use crate::xml::SaxError; use crate::xml::dom_parser::{Node, get_document}; @@ -17,6 +18,7 @@ pub fn get_pom(home_dir: PathBuf, xml: impl Into) -> Result) -> Result dependency_management = get_dependency_mgmt(child), "properties" => properties = get_properties(child), "modules" => add_modules(child, &mut module_names), + "repositories" => repositories = get_repositories(child), _ => {} } } + + // TODO before returning, calculate all + // * dependency versions + // * repositories + // maybe put that in a separate model struct + Ok(Pom { parent, group_id, @@ -48,10 +57,11 @@ pub fn get_pom(home_dir: PathBuf, xml: impl Into) -> Result){ +fn add_modules(element: Node, modules: &mut Vec) { for module in element.children { modules.push(module.text.expect("Cannot read module name")); } diff --git a/src/maven/project.rs b/src/maven/project.rs index e55e10d..842d494 100644 --- a/src/maven/project.rs +++ b/src/maven/project.rs @@ -1,5 +1,6 @@ use crate::maven::pom::{Dependency, Pom}; use crate::maven::pom_parser::get_pom; +use crate::maven::settings::{Settings, get_settings}; use regex::Regex; use std::fs; use std::path::Path; @@ -29,9 +30,14 @@ pub fn parse_project(project_dir: &Path) -> Result { let mut root = get_pom(project_dir.to_path_buf(), pom_file).map_err(|e| e.to_string())?; resolve_modules(project_dir, &mut root); - let project_home = project_dir.to_str().unwrap_or_else(|| "?").to_string(); //TODO unwrap can fail?? + let project_home = project_dir.to_str().unwrap_or_else(|| "?").to_string() + let settings = get_settings()?; - Ok(Project { project_home, root }) + Ok(Project { + settings, + project_home, + root, + }) } // examines modules in pom and loads them @@ -63,12 +69,15 @@ fn read_module_pom(project_dir: &Path, module: &String) -> Pom { //the (root) pom holds the child references to modules #[derive(Debug)] pub struct Project { + pub settings: Settings, pub project_home: String, pub root: Pom, } impl Project { /// get a list of dependencies for a pom in the project + /// + /// Note to self: maybe calculating the versions should be done earlier pub fn get_dependencies(&self, pom: &Pom) -> Vec { pom.dependencies .iter() diff --git a/src/maven/reporter.rs b/src/maven/reporter.rs index 0515409..92352cd 100644 --- a/src/maven/reporter.rs +++ b/src/maven/reporter.rs @@ -1,4 +1,4 @@ -use crate::maven::pom::Dependency; +use crate::maven::pom::{Dependency, Pom}; use crate::maven::project::Project; use regex::Regex; use std::collections::HashSet; @@ -13,11 +13,11 @@ const MAVEN_CENTRAL: &str = "https://repo1.maven.org/maven2/"; // TODO should not be downloading dependencies pub fn report(project: &Project) { - let pom = &project.root; + let pom = &project.root; // TODO other modules for dep in &project.get_dependencies(pom) { let path = PathBuf::from(dep.to_absolute_jar_path()); if !path.exists() { - download(dep).expect(&format!("Can't download jar file {}", dep)); + download(&pom, dep).expect(&format!("Can't download jar file {}", dep)); } let jar_file = File::open(dep.to_absolute_jar_path()).expect("Can't open jar file"); let mut archive = ZipArchive::new(jar_file).expect("Can't read jar file"); @@ -33,22 +33,23 @@ pub fn report(project: &Project) { } } - let mut src_main_java = pom.directory.clone(); - src_main_java.push("src/main/java"); //TODO other src directories - - traverse(&packages, &src_main_java); - - let mut src_test_java = pom.directory.clone(); - src_test_java.push("src/test/java"); //TODO other src directories - - traverse(&packages, &src_test_java); + analyse_source(&packages, &new_path(&pom.directory, "src/main/java")); + analyse_source(&packages, &new_path(&pom.directory, "src/test/java")); //TODO other src dirs, generated src } } +fn new_path(dir: &PathBuf, child: &str) -> PathBuf { + let mut new_dir = dir.clone(); + new_dir.push(child); + new_dir +} + use reqwest::blocking::Client; -fn download(dep: &Dependency) -> Result<(), String> { +fn download(pom: &Pom, dep: &Dependency) -> Result<(), String> { //TODO inspect settings.xml + // gather repositories + // pom.repositories let url = format!("{}{}.jar", MAVEN_CENTRAL, dep); @@ -75,13 +76,13 @@ fn download(dep: &Dependency) -> Result<(), String> { Ok(()) } -fn traverse(packages: &HashSet, dir: &Path) { +fn analyse_source(packages: &HashSet, dir: &Path) { if dir.exists() { for entry in dir.read_dir().unwrap() { let entry = entry.unwrap(); let path = entry.path(); if path.is_dir() { - traverse(packages, &path); + analyse_source(packages, &path); } else { if path.extension().unwrap() == "java" { analyse(packages, &path); diff --git a/src/maven/settings.rs b/src/maven/settings.rs index 6d86d51..57ff539 100644 --- a/src/maven/settings.rs +++ b/src/maven/settings.rs @@ -1,7 +1,10 @@ use std::{fs, path::PathBuf, str::FromStr}; use crate::{ - maven::{CUSTOM_SETTINGS_LOCATION, HOME, MAVEN_HOME}, + maven::{ + CUSTOM_SETTINGS_LOCATION, HOME, MAVEN_HOME, + common_model::{Repository, get_repositories}, + }, xml::dom_parser::{Node, get_document}, }; @@ -278,67 +281,6 @@ fn get_properties(element: Node) -> Vec { properties } -fn get_repositories(element: Node) -> Vec { - let mut repositories = vec![]; - - for child in element.children { - match child.name.as_str() { - "repository" => repositories.push(get_repository(child)), - _ => {} - } - } - repositories -} - -fn get_repository(element: Node) -> Repository { - let mut releases = None; - let mut snapshots = None; - let mut id = None; - let mut name = None; - let mut url = None; - let mut layout = "default".to_owned(); - - for child in element.children { - match child.name.as_str() { - "releases" => releases = Some(get_update_policy(child)), - "snapshots" => snapshots = Some(get_update_policy(child)), - "id" => id = child.text, - "name" => name = child.text, - "url" => url = child.text, - "layout" => layout = child.text.unwrap_or("default".to_owned()), - _ => {} - } - } - Repository { - releases, - snapshots, - id, - name, - url, - layout, - } -} - -fn get_update_policy(element: Node) -> RepositoryPolicy { - let mut enabled = true; - let mut update_policy = None; - let mut checksum_policy = None; - - for child in element.children { - match child.name.as_str() { - "enabled" => enabled = child.text.map(|b| b == "true").unwrap_or(true), - "update_policy" => update_policy = child.text, - "checksum_policy" => checksum_policy = child.text, - _ => {} - } - } - RepositoryPolicy { - enabled, - update_policy, - checksum_policy, - } -} - fn get_activation_os(element: Node) -> ActivationOs { let mut name = None; let mut family = None; @@ -496,20 +438,3 @@ pub struct Property { pub name: String, pub value: Option, } - -#[derive(Debug)] -pub struct Repository { - pub releases: Option, - pub snapshots: Option, - pub id: Option, - pub name: Option, - pub url: Option, - pub layout: String, -} - -#[derive(Debug)] -pub struct RepositoryPolicy { - pub enabled: bool, - pub update_policy: Option, - pub checksum_policy: Option, -}