mirror of
https://github.com/loot/loot-condition-interpreter.git
synced 2026-07-27 14:16:09 -07:00
Add ability to read executable product version field
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
/target/
|
/target/
|
||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
Cargo.lock
|
Cargo.lock
|
||||||
|
/tests/7z
|
||||||
/tests/testing-plugins
|
/tests/testing-plugins
|
||||||
/tests/loot_api*
|
/tests/loot_api*
|
||||||
/ffi/include/
|
/ffi/include/
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ before_script:
|
|||||||
- 7z x loot_api-0.13.8-0-g47797cc_dev-win64.7z
|
- 7z x loot_api-0.13.8-0-g47797cc_dev-win64.7z
|
||||||
- mv loot_api-0.13.8-0-g47797cc_dev-win64 loot_api_win64
|
- mv loot_api-0.13.8-0-g47797cc_dev-win64 loot_api_win64
|
||||||
|
|
||||||
|
- wget https://7-zip.org/a/7z1805-extra.7z
|
||||||
|
- 7z x 7z1805-extra.7z -o7z
|
||||||
|
|
||||||
- cd ..
|
- cd ..
|
||||||
|
|
||||||
script:
|
script:
|
||||||
|
|||||||
@@ -31,6 +31,9 @@ install:
|
|||||||
- 7z x loot_api_win64.7z
|
- 7z x loot_api_win64.7z
|
||||||
- mv loot_api-0.13.8-0-g47797cc_dev-win64 loot_api_win64
|
- mv loot_api-0.13.8-0-g47797cc_dev-win64 loot_api_win64
|
||||||
|
|
||||||
|
- ps: (New-Object Net.WebClient).DownloadFile('https://7-zip.org/a/7z1805-extra.7z', "$PWD/7z.7z")
|
||||||
|
- ps: 7z x "$PWD/7z.7z" -o7z
|
||||||
|
|
||||||
- cd ..
|
- cd ..
|
||||||
|
|
||||||
build: false
|
build: false
|
||||||
|
|||||||
+1
-1
@@ -53,7 +53,7 @@ impl fmt::Display for Error {
|
|||||||
),
|
),
|
||||||
Error::PeParsingError(p, e) => write!(
|
Error::PeParsingError(p, e) => write!(
|
||||||
f,
|
f,
|
||||||
"An error was encountered while reading the file version field of \"{}\": {}",
|
"An error was encountered while reading the version fields of \"{}\": {}",
|
||||||
p.display(),
|
p.display(),
|
||||||
e
|
e
|
||||||
),
|
),
|
||||||
|
|||||||
+86
-11
@@ -1,6 +1,7 @@
|
|||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
use pelite::image::VS_FIXEDFILEINFO;
|
||||||
use pelite::resources::version_info::VersionInfo;
|
use pelite::resources::version_info::VersionInfo;
|
||||||
use pelite::resources::FindError;
|
use pelite::resources::FindError;
|
||||||
use pelite::FileMap;
|
use pelite::FileMap;
|
||||||
@@ -29,21 +30,40 @@ pub struct Version {
|
|||||||
|
|
||||||
impl Version {
|
impl Version {
|
||||||
pub fn read_file_version(file_path: &Path) -> Result<Self, Error> {
|
pub fn read_file_version(file_path: &Path) -> Result<Self, Error> {
|
||||||
|
Self::read_version(file_path, |f| {
|
||||||
|
format!(
|
||||||
|
"{}.{}.{}.{}",
|
||||||
|
f.dwFileVersion.Major,
|
||||||
|
f.dwFileVersion.Minor,
|
||||||
|
f.dwFileVersion.Patch,
|
||||||
|
f.dwFileVersion.Build
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_product_version(file_path: &Path) -> Result<Self, Error> {
|
||||||
|
Self::read_version(file_path, |f| {
|
||||||
|
format!(
|
||||||
|
"{}.{}.{}.{}",
|
||||||
|
f.dwProductVersion.Major,
|
||||||
|
f.dwProductVersion.Minor,
|
||||||
|
f.dwProductVersion.Patch,
|
||||||
|
f.dwProductVersion.Build
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_version<F: Fn(&VS_FIXEDFILEINFO) -> String>(
|
||||||
|
file_path: &Path,
|
||||||
|
formatter: F,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
let file_map =
|
let file_map =
|
||||||
FileMap::open(file_path).map_err(|e| Error::IoError(file_path.to_path_buf(), e))?;
|
FileMap::open(file_path).map_err(|e| Error::IoError(file_path.to_path_buf(), e))?;
|
||||||
let version_info = get_pe_version_info(file_map.as_ref())
|
let version_info = get_pe_version_info(file_map.as_ref())
|
||||||
.map_err(|e| Error::PeParsingError(file_path.to_path_buf(), e.into()))?;
|
.map_err(|e| Error::PeParsingError(file_path.to_path_buf(), e.into()))?;
|
||||||
|
|
||||||
if let Some(fixed_file_info) = version_info.fixed() {
|
if let Some(fixed_file_info) = version_info.fixed() {
|
||||||
let version = format!(
|
Ok(Version::from(formatter(fixed_file_info).as_str()))
|
||||||
"{}.{}.{}.{}",
|
|
||||||
fixed_file_info.dwFileVersion.Major,
|
|
||||||
fixed_file_info.dwFileVersion.Minor,
|
|
||||||
fixed_file_info.dwFileVersion.Patch,
|
|
||||||
fixed_file_info.dwFileVersion.Build
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(Version::from(version.as_str()))
|
|
||||||
} else {
|
} else {
|
||||||
Ok(Version::from(""))
|
Ok(Version::from(""))
|
||||||
}
|
}
|
||||||
@@ -143,7 +163,7 @@ fn pad_release_ids(ids1: &[Identifier], ids2: &[Identifier]) -> (Vec<Identifier>
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
mod empty {
|
mod constructors {
|
||||||
use super::super::*;
|
use super::super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -195,9 +215,64 @@ mod tests {
|
|||||||
fn version_read_file_version_should_error_with_path_if_the_file_is_not_an_executable() {
|
fn version_read_file_version_should_error_with_path_if_the_file_is_not_an_executable() {
|
||||||
let error = Version::read_file_version(Path::new("Cargo.toml")).unwrap_err();
|
let error = Version::read_file_version(Path::new("Cargo.toml")).unwrap_err();
|
||||||
|
|
||||||
assert_eq!("An error was encountered while reading the file version field of \"Cargo.toml\": bad magic", error.to_string());
|
assert_eq!("An error was encountered while reading the version fields of \"Cargo.toml\": bad magic", error.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn version_read_product_version_should_read_the_file_version_field_of_a_32_bit_executable()
|
||||||
|
{
|
||||||
|
let version = Version::read_product_version(Path::new("tests/7z/7za.exe")).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
version.release_ids,
|
||||||
|
vec![
|
||||||
|
Identifier::Numeric(18),
|
||||||
|
Identifier::Numeric(5),
|
||||||
|
Identifier::Numeric(0),
|
||||||
|
Identifier::Numeric(0),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
assert!(version.pre_release_ids.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn version_read_product_version_should_read_the_file_version_field_of_a_64_bit_executable()
|
||||||
|
{
|
||||||
|
let version = Version::read_product_version(Path::new("tests/7z/x64/7za.exe")).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
version.release_ids,
|
||||||
|
vec![
|
||||||
|
Identifier::Numeric(18),
|
||||||
|
Identifier::Numeric(5),
|
||||||
|
Identifier::Numeric(0),
|
||||||
|
Identifier::Numeric(0),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
assert!(version.pre_release_ids.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn version_read_product_version_should_error_with_path_if_path_does_not_exist() {
|
||||||
|
let error = Version::read_product_version(Path::new("missing")).unwrap_err();
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
error
|
||||||
|
.to_string()
|
||||||
|
.starts_with("An error was encountered while accessing the path \"missing\":")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn version_read_product_version_should_error_with_path_if_the_file_is_not_an_executable() {
|
||||||
|
let error = Version::read_product_version(Path::new("Cargo.toml")).unwrap_err();
|
||||||
|
|
||||||
|
assert_eq!("An error was encountered while reading the version fields of \"Cargo.toml\": bad magic", error.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod empty {
|
||||||
|
use super::super::*;
|
||||||
#[test]
|
#[test]
|
||||||
fn version_eq_an_empty_string_should_equal_an_empty_string() {
|
fn version_eq_an_empty_string_should_equal_an_empty_string() {
|
||||||
assert_eq!(Version::from(""), Version::from(""));
|
assert_eq!(Version::from(""), Version::from(""));
|
||||||
|
|||||||
Reference in New Issue
Block a user