WIP: pest parser

This commit is contained in:
Till Wegmueller 2021-04-19 09:35:05 -03:00
parent bae6f32d88
commit 40f18ef38f
11 changed files with 430 additions and 57 deletions

View file

2
.idea/modules.xml generated
View file

@ -2,7 +2,7 @@
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/libips.iml" filepath="$PROJECT_DIR$/.idea/libips.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/ips.iml" filepath="$PROJECT_DIR$/.idea/ips.iml" />
</modules>
</component>
</project>

198
Cargo.lock generated
View file

@ -24,6 +24,17 @@ dependencies = [
"memchr",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "autocfg"
version = "1.0.1"
@ -44,6 +55,12 @@ dependencies = [
"rustc-demangle",
]
[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "block-buffer"
version = "0.9.0"
@ -66,6 +83,38 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "3.0.0-beta.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bd1061998a501ee7d4b6d449020df3266ca3124b941ec56cf2005c3779ca142"
dependencies = [
"atty",
"bitflags",
"clap_derive",
"indexmap",
"lazy_static",
"os_str_bytes",
"strsim",
"termcolor",
"textwrap",
"unicode-width",
"vec_map",
]
[[package]]
name = "clap_derive"
version = "3.0.0-beta.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "370f715b81112975b1b69db93e0b56ea4cd4e5002ac43b2da8474106a54096a1"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "cpuid-bool"
version = "0.1.2"
@ -140,12 +189,52 @@ version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce"
[[package]]
name = "hashbrown"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
[[package]]
name = "heck"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "hermit-abi"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
dependencies = [
"libc",
]
[[package]]
name = "indexmap"
version = "1.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]]
name = "keccak"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.90"
@ -202,6 +291,12 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "os_str_bytes"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afb2e1c3ee07430c2cf76151675e583e0f19985fa6efae47d6848a3e2c824f85"
[[package]]
name = "pkg6depotd"
version = "0.0.1-placeholder"
@ -209,11 +304,41 @@ version = "0.0.1-placeholder"
[[package]]
name = "pkg6dev"
version = "0.0.1-placeholder"
dependencies = [
"clap",
"failure",
"failure_derive",
"libips",
]
[[package]]
name = "pkg6repo"
version = "0.0.1-placeholder"
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.24"
@ -280,6 +405,12 @@ dependencies = [
"opaque-debug",
]
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.64"
@ -303,18 +434,54 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "termcolor"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
dependencies = [
"winapi-util",
]
[[package]]
name = "textwrap"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "203008d98caf094106cfaba70acfed15e18ed3ddb7d94e49baec153a2b462789"
dependencies = [
"unicode-width",
]
[[package]]
name = "typenum"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06"
[[package]]
name = "unicode-segmentation"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
[[package]]
name = "unicode-width"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
[[package]]
name = "unicode-xid"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "version_check"
version = "0.9.3"
@ -326,3 +493,34 @@ name = "wasmparser"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32fddd575d477c6e9702484139cf9f23dcd554b06d185ed0f56c857dd3a47aa6"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

View file

@ -21,4 +21,6 @@ failure = "0.1.8"
maplit = "0.1.6"
object = "0.23.0"
sha2 = "0.9.3"
sha3 = "0.9.1"
sha3 = "0.9.1"
pest = "2.1.3"
pest_derive = "2.1.0"

View file

@ -0,0 +1,69 @@
//
// Created by intellij-pest on 2021-04-18
// manifest
// Author: Till Wegmueller
//
action_set = @{"set"}
action_depend = @{"depend"}
action_dir = @{"dir"}
action_file = @{"file"}
action_license = @{"license"}
action_hardlink = @{"hardlink"}
action_link = @{"link"}
action_driver = @{"driver"}
action_group = @{"group"}
action_user = @{"user"}
action_legacy = @{"legacy"}
action_name = @{
action_set |
action_depend |
action_dir |
action_file |
action_license |
action_hardlink |
action_link |
action_driver |
action_group |
action_user |
action_legacy
}
quoted_string = @{
"\""
~ quoted_character*
~ "\""
}
quoted_character = {
!"\"" // if the following text is not three apostrophes
~ ANY // then consume one character
}
payload_character = {
!" " // if the following text is not three apostrophes
~ ANY // then consume one character
}
comment_string = @{
"#"
~ comment_character*
~ NEWLINE
}
comment_character = {
!NEWLINE // if the following text is not three apostrophes
~ ANY // then consume one character
}
transform_character = {
!">" // if the following text is not three apostrophes
~ ANY // then consume one character
}
transform_action = @{ transform_character*}
transform = {"<transform " ~ action_name ~ property+ ~ " "? ~ "->" ~ " "? ~ transform_action ~ ">" }
property_name = @{ ( ASCII_ALPHANUMERIC | "." | "_" )+ }
property_value = @{ ( ASCII_ALPHANUMERIC | "/" | "," | "." | "_" | "-" | "%" | "*" | "@" | "(" | ")" | "$" | ":" | "+" )+ | quoted_string }
payload = @{ payload_character* }
property = { " "? ~ property_name ~ "=" ~ property_value }
action = { action_name ~ " " ~ payload? ~ property+ ~ " "? ~ (NEWLINE | EOI) }
manifest = { SOI ~ ( NEWLINE | comment_string | transform | action )+ ~ EOI }

View file

@ -6,7 +6,7 @@
// Source https://docs.oracle.com/cd/E23824_01/html/E21796/pkg-5.html
use regex::{RegexSet, Regex};
use std::collections::HashSet;
use std::collections::{HashMap};
use std::fs::File as OsFile;
use std::io::BufRead;
use std::io::BufReader;
@ -15,7 +15,10 @@ use crate::payload::Payload;
use std::clone::Clone;
use crate::digest::Digest;
use std::str::FromStr;
use std::path::{Path, PathBuf};
use std::path::{Path};
use std::fmt;
use pest::Parser;
use crate::errors::Result;
pub trait FacetedAction {
// Add a facet to the action if the facet is already present the function returns false.
@ -30,7 +33,7 @@ pub struct Action {
kind: ActionKind,
payload: Payload,
properties: Vec<Property>,
facets: HashSet<Facet>,
facets: HashMap<String, Facet>,
}
impl Action {
@ -39,22 +42,22 @@ impl Action {
kind,
payload: Payload::default(),
properties: Vec::new(),
facets: HashSet::new(),
facets: HashMap::new(),
}
}
}
impl FacetedAction for Action {
fn add_facet(&mut self, facet: Facet) -> bool {
return self.facets.insert(facet)
return self.facets.insert(facet.name.clone(), facet.clone()) == None
}
fn remove_facet(&mut self, facet: Facet) -> bool {
return self.facets.remove(&facet)
return self.facets.remove(&facet.name) == Some(facet)
}
}
#[derive(Debug, Default)]
#[derive(Debug, Default, PartialEq)]
pub struct Dir {
pub path: String,
pub group: String,
@ -62,22 +65,22 @@ pub struct Dir {
pub mode: String, //TODO implement as bitmask
pub revert_tag: String,
pub salvage_from: String,
pub facets: HashSet<Facet>,
pub facets: HashMap<String, Facet>,
}
impl FacetedAction for Dir {
fn add_facet(&mut self, facet: Facet) -> bool {
return self.facets.insert(facet)
return self.facets.insert(facet.name.clone(), facet.clone()) == None
}
fn remove_facet(&mut self, facet: Facet) -> bool {
return self.facets.remove(&facet)
return self.facets.remove(&facet.name) == Some(facet)
}
}
#[derive(Debug, Default)]
#[derive(Debug, Default, PartialEq)]
pub struct File {
pub payload: Payload,
pub payload: Option<Payload>,
pub path: String,
pub group: String,
pub owner: String,
@ -88,15 +91,17 @@ pub struct File {
pub revert_tag: String,
pub sys_attr: String,
pub properties: Vec<Property>,
pub facets: HashSet<Facet>,
pub facets: HashMap<String, Facet>,
}
impl File {
pub fn read_from_path(p: &Path) -> Result<File, Error> {
pub fn read_from_path(p: &Path) -> Result<File> {
let mut f = File::default();
f.payload = Payload::compute_payload(p)?;
match p.to_str() {
Some(str) => f.path = str.to_string(),
Some(str) => {
f.path = str.to_string();
f.payload = Some(Payload::compute_payload(p)?);
},
None => return Err(FileError::FilePathIsNoStringError)?,
}
@ -108,11 +113,11 @@ impl File {
impl FacetedAction for File {
fn add_facet(&mut self, facet: Facet) -> bool {
return self.facets.insert(facet)
return self.facets.insert(facet.name.clone(), facet.clone()) == None
}
fn remove_facet(&mut self, facet: Facet) -> bool {
return self.facets.remove(&facet)
return self.facets.remove(&facet.name) == Some(facet)
}
}
@ -123,37 +128,37 @@ pub enum FileError {
}
//TODO implement multiple FMRI for require-any
#[derive(Debug, Default)]
#[derive(Debug, Default, PartialEq)]
pub struct Dependency {
pub fmri: String, //TODO make FMRI
pub dependency_type: String, //TODO make enum
pub predicate: String, //TODO make FMRI
pub root_image: String, //TODO make boolean
pub optional: Vec<Property>,
pub facets: HashSet<Facet>,
pub facets: HashMap<String, Facet>,
}
impl FacetedAction for Dependency {
fn add_facet(&mut self, facet: Facet) -> bool {
return self.facets.insert(facet)
return self.facets.insert(facet.name.clone(), facet.clone()) == None
}
fn remove_facet(&mut self, facet: Facet) -> bool {
return self.facets.remove(&facet)
return self.facets.remove(&facet.name) == Some(facet)
}
}
#[derive(Hash, Eq, PartialEq, Debug, Default)]
#[derive(Hash, Eq, PartialEq, Debug, Default, Clone)]
pub struct Facet {
pub name: String,
pub value: String,
}
#[derive(Debug, Default)]
#[derive(Debug, Default, PartialEq)]
pub struct Attr {
pub key: String,
pub values: Vec<String>,
pub properties: HashSet<Property>,
pub properties: HashMap<String, Property>,
}
#[derive(Hash, Eq, PartialEq, Debug, Default)]
@ -162,7 +167,7 @@ pub struct Property {
pub value: String,
}
#[derive(Debug, Default)]
#[derive(Debug, Default, PartialEq)]
pub struct Manifest {
pub attributes: Vec<Attr>,
pub directories: Vec<Dir>,
@ -183,6 +188,10 @@ impl Manifest {
pub fn add_file(&mut self, f: File) {
self.files.push(f);
}
pub fn parse_file(&mut self, f: Path) -> Result<Manifest> {
}
}
#[derive(Debug)]
@ -198,6 +207,7 @@ pub enum ActionKind {
Link,
Legacy,
Unknown{action: String},
Transform,
}
impl Default for ActionKind {
@ -220,20 +230,27 @@ pub enum ManifestError {
},
}
pub fn parse_manifest_file(filename: String) -> Result<Manifest, Error> {
#[derive(Parser)]
#[grammar = "manifest.pest"]
struct ManifestParser;
pub fn parse_manifest_file(filename: String) -> Result<Manifest> {
let mut m = Manifest::new();
let f = OsFile::open(filename)?;
let file = BufReader::new(&f);
for (line_nr, line_read) in file.lines().enumerate() {
handle_manifest_line(&mut m, line_read?.trim_start(), line_nr)?;
let line = line_read?;
if !line.starts_with("#") {
handle_manifest_line(&mut m, line.trim_start(), line_nr)?;
}
}
return Ok(m);
}
pub fn parse_manifest_string(manifest: String) -> Result<Manifest, Error> {
pub fn parse_manifest_string(manifest: String) -> Result<Manifest> {
let mut m = Manifest::new();
for (line_nr, line) in manifest.lines().enumerate() {
handle_manifest_line(&mut m, line.trim_start(), line_nr)?;
@ -241,7 +258,7 @@ pub fn parse_manifest_string(manifest: String) -> Result<Manifest, Error> {
return Ok(m);
}
fn handle_manifest_line(manifest: &mut Manifest, line: &str, line_nr: usize) -> Result<(), Error> {
fn handle_manifest_line(manifest: &mut Manifest, line: &str, line_nr: usize) -> Result<()> {
match determine_action_kind(&line) {
ActionKind::Attr => {
manifest.attributes.push(parse_attr_action(String::from(line))?);
@ -272,15 +289,20 @@ fn handle_manifest_line(manifest: &mut Manifest, line: &str, line_nr: usize) ->
}
ActionKind::Legacy => {
}
ActionKind::Transform => {
}
ActionKind::Unknown{action} => {
Err(ManifestError::UnknownAction {action, line: line_nr})?;
if !action.is_empty() {
Err(ManifestError::UnknownAction {action, line: line_nr})?;
}
}
}
Ok(())
}
fn add_facet_to_action<T: FacetedAction>(action: &mut T, facet_string: String, line: String, line_nr: usize) -> Result<(), ManifestError> {
fn add_facet_to_action<T: FacetedAction>(action: &mut T, facet_string: String, line: String, line_nr: usize) -> Result<()> {
let mut facet_key = match facet_string.find(".") {
Some(idx) => {
facet_string.clone().split_off(idx+1)
@ -325,6 +347,7 @@ fn determine_action_kind(line: &str) -> ActionKind {
"group" => ActionKind::Group,
"user" => ActionKind::User,
"legacy" => ActionKind::Legacy,
"<transform" => ActionKind::Transform,
_ => ActionKind::Unknown{action: act},
}
}
@ -333,17 +356,17 @@ fn clean_string_value(orig: &str) -> String {
return String::from(orig).trim_end().replace(&['"', '\\'][..], "")
}
fn string_to_bool(orig: &str) -> Result<bool, String> {
fn string_to_bool(orig: &str) -> Result<bool> {
match &String::from(orig).trim().to_lowercase()[..] {
"true" => Ok(true),
"false" => Ok(false),
"t" => Ok(true),
"f" => Ok(false),
_ => Err(String::from("not a boolean like value"))
_ => Err(failure::err_msg("not a boolean like value"))
}
}
fn parse_depend_action(line: String, line_nr: usize) -> Result<Dependency, Error> {
fn parse_depend_action(line: String, line_nr: usize) -> Result<Dependency> {
let mut act = Dependency::default();
let regex_set = RegexSet::new(&[
r#"([^ ]+)=([^"][^ ]+[^"])"#,
@ -380,7 +403,7 @@ fn parse_depend_action(line: String, line_nr: usize) -> Result<Dependency, Error
Ok(act)
}
fn parse_file_action(line: String, line_nr: usize) -> Result<File, Error> {
fn parse_file_action(line: String, line_nr: usize) -> Result<File> {
let mut act = File::default();
let regex_set = RegexSet::new(&[
r"file ([a-zA-Z0-9]+) ",
@ -411,11 +434,11 @@ fn parse_file_action(line: String, line_nr: usize) -> Result<File, Error> {
"sysattr" => act.sys_attr = clean_string_value(&cap[val_cap_idx]),
"overlay" => act.overlay = match string_to_bool(&cap[val_cap_idx]) {
Ok(b) => b,
Err(e) => return Err(ManifestError::InvalidAction {action: line, line: line_nr, message: e})?
},
Err(e) => return Err(ManifestError::InvalidAction {action: line, line: line_nr, message: e?})?
},/
"preserve" => act.preserve = match string_to_bool(&cap[val_cap_idx]) {
Ok(b) => b,
Err(e) => return Err(ManifestError::InvalidAction {action: line, line: line_nr, message: e})?
Err(e) => return Err(ManifestError::InvalidAction {action: line, line: line_nr, message: e?})?
},
"chash" | "pkg.content-hash" => act.payload.additional_identifiers.push(match Digest::from_str(clean_string_value(&cap[val_cap_idx]).as_str()) {
Ok(d) => d,
@ -440,7 +463,7 @@ fn parse_file_action(line: String, line_nr: usize) -> Result<File, Error> {
Ok(act)
}
fn parse_dir_action(line: String, line_nr: usize) -> Result<Dir, Error> {
fn parse_dir_action(line: String, line_nr: usize) -> Result<Dir> {
let mut act = Dir::default();
let regex_set = RegexSet::new(&[
r#"([^ ]+)=([^"][^ ]+[^"])"#,
@ -480,7 +503,7 @@ fn parse_dir_action(line: String, line_nr: usize) -> Result<Dir, Error> {
Ok(act)
}
fn parse_attr_action(line: String) -> Result<Attr, Error> {
fn parse_attr_action(line: String) -> Result<Attr> {
// Do a full line match to see if we can fast path this.
// This also catches values with spaces, that have not been properly escaped.
// Note: values with spaces must be properly escaped or the rest here will fail. Strings with
@ -534,7 +557,7 @@ fn parse_attr_action(line: String) -> Result<Attr, Error> {
let value_space_regex = Regex::new(r#"value=([^"][^ ]+[^"])"#)?;
let mut properties = HashSet::new();
let mut properties = HashMap::new();
let optionals_regex_no_quotes = Regex::new(r#"([^ ]+)=([^"][^ ]+[^"])"#)?;
let optionals_regex_quotes = Regex::new(r#"([^ ]+)=([^"][^ ]+[^"])"#)?;
@ -552,7 +575,7 @@ fn parse_attr_action(line: String) -> Result<Attr, Error> {
continue;
}
properties.insert(Property {
properties.insert(String::from(cap[1].trim()), Property {
key: String::from(cap[1].trim()),
value: String::from(cap[2].trim()),
});
@ -563,7 +586,7 @@ fn parse_attr_action(line: String) -> Result<Attr, Error> {
continue;
}
properties.insert(Property {
properties.insert(String::from(cap[1].trim()), Property {
key: String::from(cap[1].trim()),
value: String::from(cap[2].trim()),
});

View file

@ -9,7 +9,7 @@ use sha3::{Digest as Sha3Digest};
static DEFAULT_ALGORITHM: DigestAlgorithm = DigestAlgorithm::SHA512;
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Clone)]
pub enum DigestAlgorithm {
SHA1, //Default, sadly
SHA256, //sha256t
@ -24,7 +24,7 @@ impl Default for DigestAlgorithm {
fn default() -> Self { DigestAlgorithm::SHA1 }
}
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Clone)]
pub enum DigestSource {
GzipCompressed,
GNUElf,
@ -38,7 +38,7 @@ impl Default for DigestSource {
fn default() -> Self { DigestSource::PrimaryPayloadHash }
}
#[derive(Debug, Default)]
#[derive(Debug, Default, PartialEq, Clone)]
pub struct Digest {
pub hash: String,
pub algorithm: DigestAlgorithm,
@ -116,6 +116,24 @@ impl Digest {
hash,
})
}
pub fn to_string(&self) -> String {
format!("{}:{}:{}", match self.source {
DigestSource::UncompressedFile => "file",
DigestSource::GzipCompressed => "gzip",
DigestSource::GNUElf => "gelf",
DigestSource::GNUElfUnsigned => "gelf.unsigned",
DigestSource::Unknown | _ => "unknown",
}, match self.algorithm {
DigestAlgorithm::SHA1 => "sha1",
DigestAlgorithm::SHA256 => "sha256t",
DigestAlgorithm::SHA512Half => "sha512t_256",
DigestAlgorithm::SHA512 => "sha512t",
DigestAlgorithm::SHA3256 => "sha3256t",
DigestAlgorithm::SHA3512Half => "sha3512t_256",
DigestAlgorithm::SHA3512 => "sha3512t",
}, self.hash)
}
}
#[derive(Debug, Fail)]

View file

@ -7,8 +7,18 @@ pub mod actions;
pub mod digest;
pub mod payload;
#[macro_use] extern crate failure;
#[macro_use] extern crate maplit;
mod errors {
use failure::Error;
use std::result::Result as StdResult;
pub type Result<T> = StdResult<T, Error>;
}
use errors::Result;
#[macro_use]
extern crate failure;
extern crate maplit;
#[cfg(test)]
mod tests {

View file

@ -8,7 +8,7 @@ use failure::Error;
use object::Object;
use std::path::Path;
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Clone)]
pub enum PayloadCompressionAlgorithm {
Gzip,
LZ4
@ -18,7 +18,7 @@ impl Default for PayloadCompressionAlgorithm {
fn default() -> Self { PayloadCompressionAlgorithm::LZ4 }
}
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Clone)]
pub enum PayloadBits {
Independent,
Bits32,
@ -29,7 +29,7 @@ impl Default for PayloadBits {
fn default() -> Self { PayloadBits::Independent }
}
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Clone)]
pub enum PayloadArchitecture {
NOARCH,
I386,
@ -42,7 +42,7 @@ impl Default for PayloadArchitecture {
fn default() -> Self { PayloadArchitecture::NOARCH }
}
#[derive(Debug, Default)]
#[derive(Debug, Default, PartialEq, Clone)]
pub struct Payload {
pub primary_identifier: Digest,
pub additional_identifiers: Vec<Digest>,

View file

@ -12,3 +12,7 @@ keywords = ["packaging", "illumos"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
libips = {path = "../libips"}
failure = "0.1.8"
failure_derive = "0.1.8"
clap = "~3.0.0-beta.2"

View file

@ -1,3 +1,52 @@
fn main() {
println!("Hello, world!");
#[macro_use]
extern crate failure_derive;
use clap::app_from_crate;
use clap::{Arg, App};
use libips::actions::{parse_manifest_file, File};
mod errors {
use failure::Error;
use std::result::Result as StdResult;
pub type Result<T> = StdResult<T, Error>;
}
use errors::Result;
fn main() {
let opts = app_from_crate!().arg(Arg::new("proto_dir")
.short('p')
.long("proto-dir")
.value_name("PROTO_DIR")
.about("The Prototype directory where files are located after build")
.takes_value(true)//.required(true)
.default_value("../sample_data/pkgs/cups/build/prototype/i386")
).subcommand(App::new("diff-manifests")
.about("shows differences between two manifests")
.arg(Arg::new("manifests")
.value_name("MANIFESTS")
.multiple(true)
.number_of_values(2)
)
).get_matches();
let proto_dir = opts.value_of("proto_dir").expect("proto_dir is a mandatory variable. clap::Arg::required must be true");
//let manifests: Vec<_> = opts.values_of("manifests").unwrap().collect();
//let files = find_removed_files(String::from(&manifests[0]), String::from(&manifests[1])).unwrap();
let _ = find_removed_files(String::from("../sample_data/pkgs/cups/cups.p5m"), String::from("../sample_data/pkgs/cups/manifests/sample-manifest.p5m")).unwrap();
}
fn find_removed_files(manifest_file: String, other_manifest_file: String) -> Result<Vec<File>> {
let manifest = parse_manifest_file(manifest_file)?;
let other_manifest = parse_manifest_file(other_manifest_file)?;
println!("{:#?}", manifest);
println!("{:#?}", other_manifest);
Ok(vec![File::default()])
}