mirror of
https://github.com/msfjarvis/adx.git
synced 2024-06-03 04:08:57 +05:30
103 lines
3.7 KiB
Rust
103 lines
3.7 KiB
Rust
use crate::{channel::Channel, package::MavenPackage};
|
|
use color_eyre::{eyre::eyre, Help, Result};
|
|
use roxmltree::{Document, NodeType};
|
|
use semver::Version;
|
|
use std::convert::TryFrom;
|
|
|
|
/// Downloads the Maven master index for Google's Maven Repository
|
|
/// and returns the XML as a String
|
|
async fn get_maven_index() -> Result<String> {
|
|
Ok(
|
|
surf::get("https://dl.google.com/dl/android/maven2/master-index.xml")
|
|
.recv_string()
|
|
.await
|
|
.map_err(|e| eyre!(e))?,
|
|
)
|
|
}
|
|
|
|
/// Downloads the group index for the given group.
|
|
async fn get_group_index(group: &str) -> Result<String> {
|
|
Ok(surf::get(format!(
|
|
"https://dl.google.com/dl/android/maven2/{}/group-index.xml",
|
|
group.replace(".", "/")
|
|
))
|
|
.recv_string()
|
|
.await
|
|
.map_err(|e| eyre!(e))?)
|
|
}
|
|
|
|
/// Parses a given master-index.xml and filters the found packages based on
|
|
// `search_term`.
|
|
fn filter_groups(doc: Document, search_term: &str) -> Vec<String> {
|
|
let mut groups = vec![];
|
|
for node in doc
|
|
.descendants()
|
|
// Only keep elements
|
|
.filter(|node| node.node_type() == NodeType::Element)
|
|
// Skip the first one since it is junk
|
|
.skip(1)
|
|
{
|
|
let tag = node.tag_name().name();
|
|
if tag.contains(search_term) {
|
|
groups.push(tag.to_string());
|
|
}
|
|
}
|
|
groups
|
|
}
|
|
|
|
/// Given a list of groups, returns a `Vec<MavenPackage>` of all artifacts.
|
|
async fn parse_packages(groups: Vec<String>, channel: Channel) -> Result<Vec<MavenPackage>> {
|
|
let mut packages = Vec::new();
|
|
for group_name in groups.iter() {
|
|
let group_index = get_group_index(group_name).await?;
|
|
let doc = Document::parse(&group_index)
|
|
.map_err(|e| eyre!(e).with_note(|| format!("group_name={}", group_name)))?;
|
|
let mut is_next_root = false;
|
|
let mut group = "";
|
|
doc.descendants().for_each(|node| match node.node_type() {
|
|
NodeType::Root => is_next_root = true,
|
|
NodeType::Element => {
|
|
if is_next_root {
|
|
group = node.tag_name().name();
|
|
is_next_root = false;
|
|
} else if !group.is_empty() {
|
|
let mut versions: Vec<Version> = node
|
|
.attribute("versions")
|
|
.unwrap()
|
|
.split(',')
|
|
.map(|v| Version::parse(v))
|
|
// Only take values that were correctly parsed
|
|
.take_while(|x| x.is_ok())
|
|
// Unwrap values that were previously determined to be safe
|
|
.map(|x| x.unwrap())
|
|
.collect();
|
|
versions.retain(|x| {
|
|
if let Ok(c) = Channel::try_from(x.to_owned()) {
|
|
c >= channel
|
|
} else {
|
|
false
|
|
}
|
|
});
|
|
if !versions.is_empty() {
|
|
versions.sort_by(|a, b| b.partial_cmp(a).unwrap());
|
|
packages.push(MavenPackage {
|
|
group_id: String::from(group),
|
|
artifact_id: node.tag_name().name().to_string(),
|
|
latest_version: versions.get(0).unwrap().to_string(),
|
|
})
|
|
}
|
|
}
|
|
}
|
|
_ => (),
|
|
});
|
|
}
|
|
Ok(packages)
|
|
}
|
|
|
|
pub(crate) async fn parse(search_term: &str, channel: Channel) -> Result<Vec<MavenPackage>> {
|
|
let maven_index = get_maven_index().await?;
|
|
let doc = Document::parse(&maven_index)?;
|
|
let groups = filter_groups(doc, search_term);
|
|
Ok(parse_packages(groups, channel).await?)
|
|
}
|