From 40f18ef38f9b7212a6b1264748456ef7ee00f13a Mon Sep 17 00:00:00 2001 From: Till Wegmueller Date: Mon, 19 Apr 2021 09:35:05 -0300 Subject: [PATCH] WIP: pest parser --- .idea/{libips.iml => ips.iml} | 0 .idea/modules.xml | 2 +- Cargo.lock | 198 +++++++++++++++++++++++++++++++ libips/Cargo.toml | 4 +- libips/src/actions/manifest.pest | 69 +++++++++++ libips/src/actions/mod.rs | 111 ++++++++++------- libips/src/digest/mod.rs | 24 +++- libips/src/lib.rs | 14 ++- libips/src/payload/mod.rs | 8 +- pkg6dev/Cargo.toml | 4 + pkg6dev/src/main.rs | 53 ++++++++- 11 files changed, 430 insertions(+), 57 deletions(-) rename .idea/{libips.iml => ips.iml} (100%) create mode 100644 libips/src/actions/manifest.pest diff --git a/.idea/libips.iml b/.idea/ips.iml similarity index 100% rename from .idea/libips.iml rename to .idea/ips.iml diff --git a/.idea/modules.xml b/.idea/modules.xml index c73cd4f..e425c83 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,7 +2,7 @@ - + \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 0d8dcc3..829a0be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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" diff --git a/libips/Cargo.toml b/libips/Cargo.toml index 6d64750..9c14e2e 100644 --- a/libips/Cargo.toml +++ b/libips/Cargo.toml @@ -21,4 +21,6 @@ failure = "0.1.8" maplit = "0.1.6" object = "0.23.0" sha2 = "0.9.3" -sha3 = "0.9.1" \ No newline at end of file +sha3 = "0.9.1" +pest = "2.1.3" +pest_derive = "2.1.0" \ No newline at end of file diff --git a/libips/src/actions/manifest.pest b/libips/src/actions/manifest.pest new file mode 100644 index 0000000..0d1ea6c --- /dev/null +++ b/libips/src/actions/manifest.pest @@ -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 ~ ">" } + +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 } diff --git a/libips/src/actions/mod.rs b/libips/src/actions/mod.rs index fc78623..df66d5b 100644 --- a/libips/src/actions/mod.rs +++ b/libips/src/actions/mod.rs @@ -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, - facets: HashSet, + facets: HashMap, } 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, + pub facets: HashMap, } 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, 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, - pub facets: HashSet, + pub facets: HashMap, } impl File { - pub fn read_from_path(p: &Path) -> Result { + pub fn read_from_path(p: &Path) -> Result { 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, - pub facets: HashSet, + pub facets: HashMap, } 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, - pub properties: HashSet, + pub properties: HashMap, } #[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, pub directories: Vec, @@ -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 { + + } } #[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 { +#[derive(Parser)] +#[grammar = "manifest.pest"] +struct ManifestParser; + +pub fn parse_manifest_file(filename: String) -> Result { 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 { +pub fn parse_manifest_string(manifest: String) -> Result { 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 { 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(action: &mut T, facet_string: String, line: String, line_nr: usize) -> Result<(), ManifestError> { +fn add_facet_to_action(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, + " 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 { +fn string_to_bool(orig: &str) -> Result { 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 { +fn parse_depend_action(line: String, line_nr: usize) -> Result { 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 Result { +fn parse_file_action(line: String, line_nr: usize) -> Result { 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 { "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 { Ok(act) } -fn parse_dir_action(line: String, line_nr: usize) -> Result { +fn parse_dir_action(line: String, line_nr: usize) -> Result { 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 { Ok(act) } -fn parse_attr_action(line: String) -> Result { +fn parse_attr_action(line: String) -> Result { // 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 { 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 { 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 { continue; } - properties.insert(Property { + properties.insert(String::from(cap[1].trim()), Property { key: String::from(cap[1].trim()), value: String::from(cap[2].trim()), }); diff --git a/libips/src/digest/mod.rs b/libips/src/digest/mod.rs index 92b3327..3de2d59 100644 --- a/libips/src/digest/mod.rs +++ b/libips/src/digest/mod.rs @@ -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)] diff --git a/libips/src/lib.rs b/libips/src/lib.rs index e5ec93e..ee57bc1 100644 --- a/libips/src/lib.rs +++ b/libips/src/lib.rs @@ -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 = StdResult; +} + +use errors::Result; + +#[macro_use] +extern crate failure; +extern crate maplit; #[cfg(test)] mod tests { diff --git a/libips/src/payload/mod.rs b/libips/src/payload/mod.rs index 77ab258..1eaa8db 100644 --- a/libips/src/payload/mod.rs +++ b/libips/src/payload/mod.rs @@ -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, diff --git a/pkg6dev/Cargo.toml b/pkg6dev/Cargo.toml index 7500933..da362a2 100644 --- a/pkg6dev/Cargo.toml +++ b/pkg6dev/Cargo.toml @@ -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" \ No newline at end of file diff --git a/pkg6dev/src/main.rs b/pkg6dev/src/main.rs index e7a11a9..f9a5c67 100644 --- a/pkg6dev/src/main.rs +++ b/pkg6dev/src/main.rs @@ -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 = StdResult; +} + +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> { + 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()]) }