diff --git a/CHANGELOG.md b/CHANGELOG.md index b7708aa..2a25a0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,23 @@ # Changelog +## [0.2.17] - 2024-08-29 + +### Added + +- Read global config file from $HOME/.anvil/anvil.toml + +### Changed + +- Fix C header generation not using passed tag's info +- Bump expected amboso version to 2.0.7 + +## [0.2.16] - 2024-08-10 + +### Changed + +- Print warranty info after version splash +- Bump deps + ## [0.2.15] - 2024-07-03 ### Changed diff --git a/Cargo.lock b/Cargo.lock index 1ff2c5d..d5a5cf6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,10 +3,10 @@ version = 3 [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "aho-corasick" @@ -95,9 +95,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.5.14" +version = "4.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c937d4061031a6d0c8da4b9a4f98a172fc2976dfb1c19213a9cf7d0d3c837e36" +checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" dependencies = [ "clap_builder", "clap_derive", @@ -105,9 +105,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.14" +version = "4.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85379ba512b21a328adf887e85f7742d12e96eb31f3ef077df4ffc26b506ffed" +checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" dependencies = [ "anstream", "anstyle", @@ -157,6 +157,27 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -187,9 +208,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.31" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f211bbe8e69bbd0cfdea405084f128ae8b4aaa6b0b522fc8f2b009084797920" +checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" dependencies = [ "crc32fast", "miniz_oxide", @@ -204,6 +225,17 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "getrandom" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "git2" version = "0.19.0" @@ -253,9 +285,10 @@ dependencies = [ [[package]] name = "invil" -version = "0.2.16" +version = "0.2.17" dependencies = [ "clap", + "dirs", "flate2", "git2", "is_executable", @@ -311,6 +344,16 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.4.1", + "libc", +] + [[package]] name = "libssh2-sys" version = "0.3.0" @@ -357,11 +400,11 @@ checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", ] [[package]] @@ -397,6 +440,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "percent-encoding" version = "2.3.1" @@ -442,6 +491,17 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + [[package]] name = "regex" version = "1.10.6" @@ -561,6 +621,26 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "thiserror" +version = "1.0.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e3de26b0965292219b4287ff031fcba86837900fe9cd2b34ea8ad893c0953d2" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "268026685b2be38d7103e9e507c938a1fcb3d7e6eb15e87870b617bf37b6d581" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "time" version = "0.3.36" @@ -687,6 +767,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index 443f423..86e9818 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "invil" description = "A port of amboso to Rust" -version = "0.2.16" +version = "0.2.17" edition = "2021" license = "GPL-3.0-only" homepage = "https://github.com/jgabaut/invil" @@ -24,8 +24,9 @@ anvilPy = ["dep:flate2", "dep:tar", "dep:url"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -clap = { version = "4.5.14", features = ["derive"] } -flate2 = { version = "1.0.31", optional = true } +clap = { version = "4.5.16", features = ["derive"] } +dirs = "5.0.1" +flate2 = { version = "1.0.33", optional = true } git2 = "0.19.0" is_executable = "1.0.1" log = "0.4.22" diff --git a/README.md b/README.md index b79425f..1dd85ed 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,9 @@ - [x] `-a` to set compatibility level - [x] `-k` to set project type - [x] `-O` to set stego.lock dir (defaults to working directory) + - [x] Retrocompatible `stego.lock` parsing, up to `1.7.x` + - [x] Init subcommand uses passed directory's basename for flags + - [x] Read global config file from `$HOME/.anvil/anvil.toml` ## Extended amboso features diff --git a/src/core.rs b/src/core.rs index 3639ff6..ea26853 100644 --- a/src/core.rs +++ b/src/core.rs @@ -48,7 +48,7 @@ pub const ANVIL_BONEDIR_KEYNAME: &str = "testsdir"; pub const ANVIL_KULPODIR_KEYNAME: &str = "errortestsdir"; pub const ANVIL_VERSION_KEYNAME: &str = "version"; pub const ANVIL_KERN_KEYNAME: &str = "kern"; -pub const EXPECTED_AMBOSO_API_LEVEL: &str = "2.0.6"; +pub const EXPECTED_AMBOSO_API_LEVEL: &str = "2.0.7"; pub const MIN_AMBOSO_V_EXTENSIONS: &str = "2.0.1"; pub const MIN_AMBOSO_V_STEGO_NOFORCE: &str = "2.0.3"; pub const MIN_AMBOSO_V_STEGODIR: &str = "2.0.3"; @@ -58,6 +58,7 @@ pub const MIN_AMBOSO_V_PYKERN: &str = "2.1.0"; pub const MIN_AMBOSO_V_SKIPRETRYSTEGO: &str = "2.0.4"; pub const MIN_AMBOSO_V_DENY_ANVILPY: &str = "2.0.5"; pub const ANVIL_INTERPRETER_TAG_REGEX: &str = "stego.lock$"; +pub const ANVIL_DEFAULT_CONF_PATH: &str = ".anvil/anvil.toml"; pub const RULELINE_MARK_CHAR: char = '\t'; pub const RULE_REGEX: &str = "^([[:graph:]^:]+:){1,1}([[:space:]]*[[:graph:]]*)*$"; pub const RULEWARN_REGEX: &str = "^ +"; @@ -348,6 +349,14 @@ pub struct AmbosoEnv { pub anvilpy_env: Option, } +pub struct AmbosoConf { + /// Anvil kern + pub anvil_kern: AnvilKern, + + /// Anvil version we run as + pub anvil_version: String, +} + #[derive(Subcommand, Debug, Clone)] pub enum Commands { /// does testing things @@ -954,6 +963,124 @@ pub fn check_amboso_dir(dir: &PathBuf, args: &Args) -> Result } } +pub fn parse_invil_toml(invil_path: &PathBuf) -> Result { + let start_time = Instant::now(); + debug!("Checking global config file at {}", invil_path.display()); + let invil = fs::read_to_string(invil_path).expect("Could not read anvil_conf.toml contents"); + return parse_invil_tomlvalue(&invil, start_time); +} + +fn parse_invil_tomlvalue(invil_str: &str, start_time: Instant) -> Result { + let toml_value = invil_str.parse::(); + match toml_value { + Ok(y) => { + let mut anvil_conf: AmbosoConf = AmbosoConf { + anvil_version: EXPECTED_AMBOSO_API_LEVEL.to_string(), + anvil_kern: AnvilKern::AmbosoC, + }; + if let Some(anvil_table) = y.get("anvil").and_then(|v| v.as_table()) { + if let Some(anvil_version) = anvil_table.get(ANVIL_VERSION_KEYNAME) { + let anvil_v_str = anvil_version.as_str().expect("toml conversion failed"); + if is_semver(anvil_v_str) { + if anvil_v_str.starts_with("2.0") { + match anvil_v_str { + "2.0.0" => { + info!("Running as 2.0, turning off extensions"); + anvil_conf.anvil_kern = AnvilKern::AmbosoC; + } + "2.0.1" | "2.0.2" | "2.0.3" => { + info!("Running as <2.0.4"); + anvil_conf.anvil_kern = AnvilKern::AmbosoC; + } + "2.0.4" | "2.0.5" | "2.0.6" | "2.0.7" => { + info!("Running as {{{}}}", anvil_v_str); + anvil_conf.anvil_kern = AnvilKern::AmbosoC; + } + _ => { + error!("Invalid anvil_version: {{{anvil_version}}}"); + return Err("Invalid anvil_version".to_string()); + } + } + trace!("ANVIL_VERSION: {{{anvil_version}}}"); + anvil_conf.anvil_version = format!("{}", anvil_v_str); + } else if anvil_v_str.starts_with("2.1") { + trace!("Accepting preview version from stego.lock"); + match anvil_v_str { + "2.1.0" => { + info!("Running as 2.1 preview"); + } + _ => { + error!("Invalid anvil_version: {{{anvil_version}}}"); + return Err("Invalid anvil_version".to_string()); + } + } + trace!("ANVIL_VERSION: {{{anvil_version}}}"); + anvil_conf.anvil_version = format!("{}", anvil_v_str); + } else { + error!("Invalid anvil_version: {{{anvil_version}}}"); + return Err("Invalid anvil_version".to_string()); + } + } else { + error!("Invalid anvil_version: {{{}}}", anvil_v_str); + return Err("Invalid anvil_version".to_string()); + } + } else { + debug!("Missing ANVIL_VERSION definition."); + } + + match semver_compare(&anvil_conf.anvil_version, MIN_AMBOSO_V_KERN) { + Ordering::Less => {}, + Ordering::Equal | Ordering::Greater => { + if let Some(anvil_kern) = anvil_table.get(ANVIL_KERN_KEYNAME) { + match anvil_kern.as_str().expect("toml conversion failed") { + "amboso-C" => { + anvil_conf.anvil_kern = AnvilKern::AmbosoC; + } + "anvilPy" => { + match semver_compare(&anvil_conf.anvil_version, MIN_AMBOSO_V_PYKERN) { + Ordering::Less => { + error!("Unsupported AnvilKern value: {{{anvil_kern}}}"); + warn!("Try running as >={MIN_AMBOSO_V_PYKERN}"); + warn!("Current anvil_version: {{{}}}", anvil_conf.anvil_version); + return Err("Unsupported anvil_kern".to_string()); + }, + Ordering::Equal | Ordering::Greater => { + match semver_compare(&anvil_conf.anvil_version, MIN_AMBOSO_V_DENY_ANVILPY) { + Ordering::Less => { + return Err("Unsupported anvil_kern".to_string()); + } + Ordering::Equal | Ordering::Greater => { + warn!("The AnvilPy kern is experimental. Be careful."); + anvil_conf.anvil_kern = AnvilKern::AnvilPy; + } + } + } + } + } + _ => { + error!("Invalid AnvilKern value: {{{anvil_kern}}}"); + return Err("Invalid anvil_kern".to_string()); + } + } + } else { + debug!("Missing ANVIL_KERN definition."); + } + } + } + } else { + debug!("Missing ANVIL section."); + } + return Ok(anvil_conf); + } + Err(e) => { + let elapsed = start_time.elapsed(); + debug!("Done parsing anvil.toml. Elapsed: {:.2?}", elapsed); + error!("Failed parsing {{{}}} as TOML. Err: [{e}]", invil_str); + return Err("Failed parsing TOML".to_string()); + } + } +} + pub fn parse_stego_toml(stego_path: &PathBuf, builds_path: &PathBuf) -> Result { let start_time = Instant::now(); let stego = fs::read_to_string(stego_path).expect("Could not read {stego_path} contents"); @@ -1024,7 +1151,7 @@ fn parse_stego_tomlvalue(stego_str: &str, builds_path: &PathBuf, stego_dir: Path info!("Running as <2.0.4"); anvil_env.anvil_kern = AnvilKern::AmbosoC; } - "2.0.4" | "2.0.5" | "2.0.6" => { + "2.0.4" | "2.0.5" | "2.0.6" | "2.0.7" => { info!("Running as {{{}}}", anvil_v_str); anvil_env.anvil_kern = AnvilKern::AmbosoC; } @@ -1609,7 +1736,7 @@ pub fn check_passed_args(args: &mut Args) -> Result { info!("Running as {}", x.as_str()); args.anvil_kern = Some(AnvilKern::AmbosoC.to_string()); } - "2.0.4" | "2.0.5" | "2.0.6" => { + "2.0.4" | "2.0.5" | "2.0.6" | "2.0.7" => { info!("Running as {}", x.as_str()); } _ => { @@ -1714,6 +1841,38 @@ pub fn check_passed_args(args: &mut Args) -> Result { } } + //Get AmbosoConf + // + if !args.strict { + let user_home_dir = dirs::home_dir(); + match user_home_dir { + Some(_) => {}, + None => { + error!("Could not retrieve user's home directory"); + return Err("Could not find $HOME".to_string()); + } + } + let mut invil_conf_path = PathBuf::from(user_home_dir.expect("Failed getting user's home directory")); + invil_conf_path.push(ANVIL_DEFAULT_CONF_PATH); + let res = parse_invil_toml(&invil_conf_path); + match res { + Ok(c) => { + match args.anvil_version { + Some(_) => {}, + None => { args.anvil_version = Some(c.anvil_version);}, + } + match args.anvil_kern { + Some(_) => {}, + None => { args.anvil_kern = Some(c.anvil_kern.to_string()); }, + } + } + Err(e) => { + error!("Failed parsing anvil config file."); + return Err(e.to_string()); + } + } + } + //Check amboso_dir arg match args.amboso_dir { Some(ref x) => { @@ -1726,6 +1885,12 @@ pub fn check_passed_args(args: &mut Args) -> Result { if override_stego_anvil_version { a.anvil_version = anvil_env.anvil_version; } + match a.stego_dir { + Some(ref p) => { + debug!("{}", format!("stego_dir: {}", p.display())); + } + None => {}, + } anvil_env = a; } Err(e) => { diff --git a/src/ops.rs b/src/ops.rs index 100c2a8..fd09a61 100644 --- a/src/ops.rs +++ b/src/ops.rs @@ -857,41 +857,47 @@ pub fn gen_c_header(target_path: &PathBuf, target_tag: &String, bin_name: &Strin } match repo { Ok(r) => { - let head = r.head(); - match head { - Ok(head) => { - let commit = head.peel_to_commit(); - match commit { - Ok(commit) => { - if let Some(msg) = commit.message() { - info!("Commit message: {{{}}}", msg); - commit_message = msg.escape_default().to_string(); - } - id = commit.id().to_string(); - info!("Commit id: {{{}}}", id); - let author = commit.author(); - let name = author.name(); - match name { - Some(name) => { - head_author_name = name.to_string(); - info!("Commit author: {{{}}}", head_author_name); - } - None => { - warn!("Commit author is empty: {}", head_author_name); - } - } - commit_time = commit.time().seconds(); - info!("Commit time: {{{}}}", commit_time); - } - Err(e) => { - error!("Failed peel to head commit for {{{}}}. Err: {e}", target_path.display()); - return Err("Failed peel to head commit for repo".to_string()); + let lookup_name = format!("refs/tags/{}", target_tag); + let reference = r.find_reference(&lookup_name); + match reference { + Ok(refr) => { + if !refr.is_tag() { + error!("{target_tag} is not a reference"); + return Err("ERROR".to_string()); + } else { + let commit = refr.peel_to_commit(); + match commit { + Ok(commit) => { + if let Some(msg) = commit.message() { + info!("Commit message: {{{}}}", msg); + commit_message = msg.escape_default().to_string(); } + id = commit.id().to_string(); + info!("Commit id: {{{}}}", id); + let author = commit.author(); + let name = author.name(); + match name { + Some(name) => { + head_author_name = name.to_string(); + info!("Commit author: {{{}}}", head_author_name); + } + None => { + warn!("Commit author is empty: {}", head_author_name); + } + } + commit_time = commit.time().seconds(); + info!("Commit time: {{{}}}", commit_time); + } + Err(e) => { + error!("Failed peel to head commit for {{{}}}. Err: {e}", target_path.display()); + return Err("Failed peel to head commit for repo".to_string()); } + } + } } - Err(e) => { - error!("Failed getting head for {{{}}}. Err: {e}", target_path.display()); - return Err("Failed getting head for repo".to_string()); + Err(_) => { + error!("{}", format!("Failed getting {target_tag}")); + return Err(format!("Failed getting tag {{{target_tag}}}")); } } }