Add userland library for things related to oi userland

This commit is contained in:
Till Wegmueller 2021-04-25 18:40:06 -03:00
parent 4fd068ac5f
commit 37d7d8ee08
6 changed files with 1124 additions and 4 deletions

901
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -5,6 +5,7 @@ members = [
"pkg6depotd",
"pkg6dev",
"pkg6repo",
"userland",
]

17
userland/Cargo.toml Normal file
View file

@ -0,0 +1,17 @@
[package]
name = "userland"
version = "0.1.0"
authors = ["Till Wegmueller <toasterson@gmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
failure = "0.1.8"
pest_derive = "2.1.0"
maplit = "0.1.6"
pest = "2.1.0"
reqwest = { version = "0.11", features = ["blocking", "json"] }
semver = "0.11.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

109
userland/src/lib.rs Normal file
View file

@ -0,0 +1,109 @@
pub mod repology;
extern crate pest;
#[macro_use] extern crate pest_derive;
#[macro_use] extern crate failure;
#[macro_use] extern crate serde;
extern crate maplit;
mod errors {
use failure::Error;
use std::result::Result as StdResult;
pub type Result<T> = StdResult<T, Error>;
}
use errors::Result;
use std::collections::HashMap;
use std::fs::read_to_string;
use pest::iterators::{Pair, Pairs};
use std::path::Path;
use pest::Parser;
#[derive(Parser)]
#[grammar = "makefile.pest"]
struct MakefileParser;
#[derive(Debug, Default, PartialEq, Clone)]
pub struct Makefile {
pub variables: HashMap<String, Vec<String>>,
// pub includes: Vec<String>,
// pub targets: HashMap<String, String>,
}
impl Makefile {
pub fn parse_file(path: &Path) -> Result<Self> {
let content = read_to_string(path)?;
parse_string(content)
}
pub fn parse_string(content: String) -> Result<Self> {
parse_string(content)
}
}
fn parse_string(content: String) -> Result<Makefile> {
let mut m = Makefile::default();
let makefile_pair = MakefileParser::parse(Rule::makefile, &content)?;
for p in makefile_pair {
match p.as_rule() {
Rule::makefile => {
parse_makefile(p.into_inner(), &mut m)?;
}
_ => panic!("unexpected rule {:?} inside pair expected manifest", p.as_rule()),
}
}
Ok(m)
}
fn parse_makefile(pairs: Pairs<crate::Rule>, m: &mut Makefile) -> Result<()> {
for p in pairs {
match p.as_rule() {
Rule::variable => {
parse_variable(p.into_inner(), m)?;
}
Rule::comment_string => (),
Rule::include => (),
Rule::target => (),
Rule::EOI => (),
_ => panic!("unexpected rule {:?} inside makefile rule expected variable, comment, NEWLINE, include, target", p.as_rule()),
}
}
Ok(())
}
fn parse_variable(variable_pair: Pairs<crate::Rule>, m: &mut Makefile) -> Result<()> {
let mut var = (String::new(), Vec::<String>::new());
for p in variable_pair {
match p.as_rule() {
Rule::variable_name => {
var.0 = p.as_str().to_string();
}
Rule::variable_set => (),
Rule::variable_add => {
if m.variables.contains_key(&var.0) {
var.1 = m.variables.get(&var.0).unwrap().clone()
}
}
Rule::variable_value => {
var.1.push(p.as_str().to_string());
}
_ => panic!("unexpected rule {:?} inside makefile rule expected variable_name, variable_set, variable_add, variable_value", p.as_rule()),
}
}
m.variables.insert(var.0, var.1);
Ok(())
}
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}

View file

@ -0,0 +1,43 @@
//
// Created by intellij-pest on 2021-04-25
// makefile
// Author: Till Wegmueller <till.wegmueller@openflowlabs.com>
//
WHITESPACE = _{ " " | "\t" }
comment_string = _{
"#"
~ comment_character*
~ NEWLINE
}
comment_character = _{
!NEWLINE // if the following text is not three apostrophes
~ ANY // then consume one character
}
variable_name_character = { UPPERCASE | ASCII_DIGIT | "_" }
variable_name = @{ variable_name_character* }
variable_value_character = {
!NEWLINE
~ ANY
}
variable_value = @{ variable_value_character* }
variable_set = { "=" }
variable_add = { "+=" }
variable = { variable_name ~ ( variable_set | variable_add ) ~ variable_value? }
target_character = {
!":"
~ ANY
}
target_name = { target_character+ }
target = { target_name ~ ":" ~ variable_value }
include = { "include" ~ variable_value }
makefile = { SOI ~ (NEWLINE | comment_string | variable | include | target )+ ~ EOI }

57
userland/src/repology.rs Normal file
View file

@ -0,0 +1,57 @@
extern crate reqwest;
use reqwest::*;
use crate::errors::Result as EResult;
use semver::Version;
use serde::{Serialize, Deserialize};
const BASE_URL: &str = "https://repology.org/api/v1/";
#[derive(Debug, Clone)]
pub struct RepologyClient {
client: reqwest::Client,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Package {
repo: String,
name: Option<String>,
version: String,
sub_repo: Option<String>,
orig_version: Option<String>,
status: Option<String>,
summary: Option<String>,
family: Option<String>,
categories: Option<Vec<String>>,
licenses: Option<Vec<String>>,
maintainers: Option<Vec<String>>,
www: Option<Vec<String>>,
downloads: Option<Vec<String>>
}
pub fn project(package: &str) -> Result<Vec<Package>> {
let url = Url::parse(&format!("{}/project/{}",BASE_URL, package)).unwrap();
let json = reqwest::blocking::get(url)?
.json::<Vec<Package>>()?;
return Ok(json);
}
pub fn find_newest_version(package: &str) -> EResult<String> {
let pkgs = project(package)?;
let version_res: EResult<Vec<Version>> = pkgs.iter().map(|p| -> EResult<Version> {
let v = Version::parse(&p.version);
if v.is_ok() {
return Ok(v?);
}
Ok(Version::new(0,0,1))
}).collect();
let mut versions = version_res?;
versions.sort();
Ok(versions.last().unwrap().to_string())
}