mirror of
https://codeberg.org/Toasterson/ips.git
synced 2026-04-10 13:20:42 +00:00
Intial set function Parsing
This commit is contained in:
commit
b57d63cebf
9 changed files with 318 additions and 0 deletions
86
.gitignore
vendored
Normal file
86
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
# Created by .ignore support plugin (hsz.mobi)
|
||||||
|
### JetBrains template
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff
|
||||||
|
.idea/**/workspace.xml
|
||||||
|
.idea/**/tasks.xml
|
||||||
|
.idea/**/usage.statistics.xml
|
||||||
|
.idea/**/dictionaries
|
||||||
|
.idea/**/shelf
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
.idea/**/contentModel.xml
|
||||||
|
|
||||||
|
# Sensitive or high-churn files
|
||||||
|
.idea/**/dataSources/
|
||||||
|
.idea/**/dataSources.ids
|
||||||
|
.idea/**/dataSources.local.xml
|
||||||
|
.idea/**/sqlDataSources.xml
|
||||||
|
.idea/**/dynamic.xml
|
||||||
|
.idea/**/uiDesigner.xml
|
||||||
|
.idea/**/dbnavigator.xml
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
.idea/**/gradle.xml
|
||||||
|
.idea/**/libraries
|
||||||
|
|
||||||
|
# Gradle and Maven with auto-import
|
||||||
|
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||||
|
# since they will be recreated, and may cause churn. Uncomment if using
|
||||||
|
# auto-import.
|
||||||
|
# .idea/artifacts
|
||||||
|
# .idea/compiler.xml
|
||||||
|
# .idea/jarRepositories.xml
|
||||||
|
# .idea/modules.xml
|
||||||
|
# .idea/*.iml
|
||||||
|
# .idea/modules
|
||||||
|
# *.iml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
cmake-build-*/
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
.idea/**/mongoSettings.xml
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
.idea/replstate.xml
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
|
||||||
|
# Editor-based Rest Client
|
||||||
|
.idea/httpRequests
|
||||||
|
|
||||||
|
# Android studio 3.1+ serialized cache file
|
||||||
|
.idea/caches/build_file_checksums.ser
|
||||||
|
|
||||||
|
### Rust template
|
||||||
|
# Generated by Cargo
|
||||||
|
# will have compiled files and executables
|
||||||
|
/target/
|
||||||
|
|
||||||
|
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||||
|
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
|
||||||
|
Cargo.lock
|
||||||
|
|
||||||
|
# These are backup files generated by rustfmt
|
||||||
|
**/*.rs.bk
|
||||||
|
|
||||||
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
12
.idea/libips.iml
generated
Normal file
12
.idea/libips.iml
generated
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="WEB_MODULE" version="4">
|
||||||
|
<component name="Go" enabled="true" />
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
6
.idea/misc.xml
generated
Normal file
6
.idea/misc.xml
generated
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="JavaScriptSettings">
|
||||||
|
<option name="languageLevel" value="ES6" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/libips.iml" filepath="$PROJECT_DIR$/.idea/libips.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
10
Cargo.toml
Normal file
10
Cargo.toml
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
[package]
|
||||||
|
name = "libips"
|
||||||
|
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]
|
||||||
|
regex = "1.3.7"
|
||||||
135
src/actions/mod.rs
Normal file
135
src/actions/mod.rs
Normal file
|
|
@ -0,0 +1,135 @@
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::BufRead;
|
||||||
|
use std::io::BufReader;
|
||||||
|
use std::error;
|
||||||
|
use std::fmt;
|
||||||
|
use regex::Regex;
|
||||||
|
use regex::RegexSet;
|
||||||
|
|
||||||
|
pub struct Attr {
|
||||||
|
pub Key: String,
|
||||||
|
pub Values: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Manifest {
|
||||||
|
pub Attributes: Vec<Attr>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Manifest {
|
||||||
|
pub fn new() -> Manifest {
|
||||||
|
return Manifest{
|
||||||
|
Attributes: Vec::new(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ManifestError {
|
||||||
|
EmptyVec,
|
||||||
|
// We will defer to the parse error implementation for their error.
|
||||||
|
// Supplying extra info requires adding more data to the type.
|
||||||
|
Read(std::io::Error),
|
||||||
|
Regex(regex::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ManifestError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
ManifestError::EmptyVec =>
|
||||||
|
write!(f, "please use a vector with at least one element"),
|
||||||
|
// This is a wrapper, so defer to the underlying types' implementation of `fmt`.
|
||||||
|
ManifestError::Read(ref e) => e.fmt(f),
|
||||||
|
ManifestError::Regex(ref e) => e.fmt(f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl error::Error for ManifestError {
|
||||||
|
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||||
|
match *self {
|
||||||
|
ManifestError::EmptyVec => None,
|
||||||
|
// The cause is the underlying implementation error type. Is implicitly
|
||||||
|
// cast to the trait object `&error::Error`. This works because the
|
||||||
|
// underlying type already implements the `Error` trait.
|
||||||
|
ManifestError::Read(ref e) => Some(e),
|
||||||
|
ManifestError::Regex(ref e) => Some(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ParseManifestFile(filename: String) -> Result<Manifest, ManifestError> {
|
||||||
|
let mut manifest = Manifest::new();
|
||||||
|
let f = match File::open(filename) {
|
||||||
|
Ok(file) => file,
|
||||||
|
Err(e) => return Err(ManifestError::Read(e)),
|
||||||
|
};
|
||||||
|
let file = BufReader::new(&f);
|
||||||
|
for lineRead in file.lines() {
|
||||||
|
let line = match lineRead {
|
||||||
|
Ok(l) => l,
|
||||||
|
Err(e) => return Err(ManifestError::Read(e)),
|
||||||
|
};
|
||||||
|
if isAttrLine(&line) {
|
||||||
|
match ParseAttrLine(line) {
|
||||||
|
Ok(attr) => manifest.Attributes.push(attr),
|
||||||
|
Err(e) => return Err(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ok(manifest);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ParseManifestString(manifest: String) -> Result<Manifest, ManifestError> {
|
||||||
|
let mut m = Manifest::new();
|
||||||
|
for line in manifest.lines() {
|
||||||
|
if isAttrLine(&String::from(line)) {
|
||||||
|
let attr = match ParseAttrLine(String::from(line)) {
|
||||||
|
Ok(attr) => m.Attributes.push(attr),
|
||||||
|
Err(e) => return Err(e)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ok(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn isAttrLine(line: &String) -> bool {
|
||||||
|
if line.trim().starts_with("set ") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ParseAttrLine(line: String) -> Result<Attr, ManifestError> {
|
||||||
|
let name_regex = match Regex::new(r"name=([^ ]+) value=") {
|
||||||
|
Ok(re) => re,
|
||||||
|
Err(e) => return Err(ManifestError::Regex(e))
|
||||||
|
};
|
||||||
|
let mut name = String::new();
|
||||||
|
for cap in name_regex.captures_iter(line.trim_start()) {
|
||||||
|
name = String::from(&cap[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut values = Vec::new();
|
||||||
|
let value_no_space_regex = match Regex::new(r#"value="(.+)""#) {
|
||||||
|
Ok(re) => re,
|
||||||
|
Err(e) => return Err(ManifestError::Regex(e)),
|
||||||
|
};
|
||||||
|
|
||||||
|
let value_space_regex = match Regex::new(r#"value=([^"][^ ]+[^"])"#) {
|
||||||
|
Ok(re) => re,
|
||||||
|
Err(e) => return Err(ManifestError::Regex(e)),
|
||||||
|
};
|
||||||
|
|
||||||
|
for cap in value_no_space_regex.captures_iter(line.trim_start()) {
|
||||||
|
values.push(String::from(&cap[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
for cap in value_space_regex.captures_iter(line.trim_start()) {
|
||||||
|
values.push(String::from(&cap[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Attr{
|
||||||
|
Key: name,
|
||||||
|
Values: values,
|
||||||
|
})
|
||||||
|
}
|
||||||
47
src/lib.rs
Normal file
47
src/lib.rs
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
mod actions;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
|
||||||
|
use crate::actions::ParseManifestString;
|
||||||
|
use crate::actions::Manifest;
|
||||||
|
use crate::actions::ManifestError;
|
||||||
|
use std::error;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_works() {
|
||||||
|
assert_eq!(2 + 2, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_manifest() {
|
||||||
|
let manifest_string = String::from("set name=pkg.fmri value=pkg://openindiana.org/web/server/nginx@1.18.0,5.11-2020.0.1.0:20200421T195136Z
|
||||||
|
set name=com.oracle.info.name value=nginx value=test
|
||||||
|
set name=userland.info.git-remote value=git://github.com/OpenIndiana/oi-userland.git
|
||||||
|
set name=userland.info.git-branch value=HEAD
|
||||||
|
set name=userland.info.git-rev value=1665491ba61bd494bf73e2916cd2250f3024260e
|
||||||
|
set name=pkg.summary value=\"Nginx Webserver\"
|
||||||
|
set name=info.classification value=\"org.opensolaris.category.2008:Web Services/Application and Web Servers\"
|
||||||
|
set name=info.upstream-url value=http://nginx.net/
|
||||||
|
set name=info.source-url value=http://nginx.org/download/nginx-1.18.0.tar.gz
|
||||||
|
set name=org.opensolaris.consolidation value=userland
|
||||||
|
set name=com.oracle.info.version value=1.18.0
|
||||||
|
set name=variant.arch value=i386");
|
||||||
|
let mut manifest = Manifest::new();
|
||||||
|
match ParseManifestString(manifest_string){
|
||||||
|
Ok(m) => manifest = m,
|
||||||
|
Err(_) => assert!(false, "caught error")
|
||||||
|
};
|
||||||
|
for attr in manifest.Attributes {
|
||||||
|
println!("Name: {}", attr.Key);
|
||||||
|
for val in attr.Values {
|
||||||
|
println!("Value: {}", val)
|
||||||
|
}
|
||||||
|
println!();
|
||||||
|
}
|
||||||
|
//assert_eq!(manifest.Attributes.len(), 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Loading…
Add table
Reference in a new issue