mirror of
https://codeberg.org/Toasterson/ips.git
synced 2026-04-10 13:20:42 +00:00
WIP: pest parser
This commit is contained in:
parent
bae6f32d88
commit
40f18ef38f
11 changed files with 430 additions and 57 deletions
0
.idea/libips.iml → .idea/ips.iml
generated
0
.idea/libips.iml → .idea/ips.iml
generated
2
.idea/modules.xml
generated
2
.idea/modules.xml
generated
|
|
@ -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
198
Cargo.lock
generated
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -22,3 +22,5 @@ maplit = "0.1.6"
|
|||
object = "0.23.0"
|
||||
sha2 = "0.9.3"
|
||||
sha3 = "0.9.1"
|
||||
pest = "2.1.3"
|
||||
pest_derive = "2.1.0"
|
||||
69
libips/src/actions/manifest.pest
Normal file
69
libips/src/actions/manifest.pest
Normal 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 }
|
||||
|
|
@ -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()),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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>,
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -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()])
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue