prepare better repository resolution

This commit is contained in:
Hautvast, S. (Sander) 2025-09-16 21:45:28 +02:00
parent 935bfb4139
commit ab651b9b97
8 changed files with 134 additions and 99 deletions

View file

@ -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(),

79
src/maven/common_model.rs Normal file
View file

@ -0,0 +1,79 @@
use crate::xml::dom_parser::Node;
#[derive(Debug)]
pub struct Repository {
pub releases: Option<RepositoryPolicy>,
pub snapshots: Option<RepositoryPolicy>,
pub id: Option<String>,
pub name: Option<String>,
pub url: Option<String>,
pub layout: String,
}
#[derive(Debug)]
pub struct RepositoryPolicy {
pub enabled: bool,
pub update_policy: Option<String>,
pub checksum_policy: Option<String>,
}
pub fn get_repositories(element: Node) -> Vec<Repository> {
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,
}
}

View file

@ -1,5 +1,6 @@
use std::{env, sync::LazyLock};
pub mod common_model;
pub mod metadata;
pub mod pom;
pub mod pom_parser;

View file

@ -4,7 +4,7 @@ use std::path::PathBuf;
/// the maven object model
#[derive(PartialEq, Debug)]
#[derive(Debug)]
pub struct Pom {
pub parent: Option<Parent>,
pub group_id: Option<String>,
@ -19,6 +19,7 @@ pub struct Pom {
pub module_names: Vec<String>,
pub modules: Vec<Pom>,
pub directory: PathBuf,
pub repositories: Vec<Repository>,
}
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 {

View file

@ -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<String>) -> Result<Pom, SaxErro
let mut dependency_management = vec![];
let mut properties = HashMap::new(); // useless assignments...
let mut module_names = vec![]; // not useless assignment...
let mut repositories = vec![]; // not useless assignment...
for child in get_document(xml.into().as_str())?.root.children {
match child.name.as_str() {
@ -31,9 +33,16 @@ pub fn get_pom(home_dir: PathBuf, xml: impl Into<String>) -> Result<Pom, SaxErro
"dependencyManagement" => 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<String>) -> Result<Pom, SaxErro
module_names,
modules: vec![],
directory: home_dir,
repositories,
})
}
fn add_modules(element: Node, modules: &mut Vec<String>){
fn add_modules(element: Node, modules: &mut Vec<String>) {
for module in element.children {
modules.push(module.text.expect("Cannot read module name"));
}

View file

@ -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<Project, String> {
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<Dependency> {
pom.dependencies
.iter()

View file

@ -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<String>, dir: &Path) {
fn analyse_source(packages: &HashSet<String>, 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);

View file

@ -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<Property> {
properties
}
fn get_repositories(element: Node) -> Vec<Repository> {
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<String>,
}
#[derive(Debug)]
pub struct Repository {
pub releases: Option<RepositoryPolicy>,
pub snapshots: Option<RepositoryPolicy>,
pub id: Option<String>,
pub name: Option<String>,
pub url: Option<String>,
pub layout: String,
}
#[derive(Debug)]
pub struct RepositoryPolicy {
pub enabled: bool,
pub update_policy: Option<String>,
pub checksum_policy: Option<String>,
}