Add total_units, complete_units to progress report

This commit is contained in:
Luke Street 2024-09-30 21:41:57 -06:00
parent 8acaaf528c
commit 08cd768260
6 changed files with 63 additions and 14 deletions

6
Cargo.lock generated
View File

@ -2861,7 +2861,7 @@ dependencies = [
[[package]] [[package]]
name = "objdiff-cli" name = "objdiff-cli"
version = "2.2.0" version = "2.2.1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"argp", "argp",
@ -2883,7 +2883,7 @@ dependencies = [
[[package]] [[package]]
name = "objdiff-core" name = "objdiff-core"
version = "2.2.0" version = "2.2.1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"arm-attr", "arm-attr",
@ -2922,7 +2922,7 @@ dependencies = [
[[package]] [[package]]
name = "objdiff-gui" name = "objdiff-gui"
version = "2.2.0" version = "2.2.1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bytes", "bytes",

View File

@ -13,7 +13,7 @@ strip = "debuginfo"
codegen-units = 1 codegen-units = 1
[workspace.package] [workspace.package]
version = "2.2.0" version = "2.2.1"
authors = ["Luke Street <luke@street.dev>"] authors = ["Luke Street <luke@street.dev>"]
edition = "2021" edition = "2021"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"

View File

@ -199,7 +199,7 @@ fn report_object(
.unwrap_or_default(), .unwrap_or_default(),
auto_generated: object.metadata.as_ref().and_then(|m| m.auto_generated), auto_generated: object.metadata.as_ref().and_then(|m| m.auto_generated),
}; };
let mut measures = Measures::default(); let mut measures = Measures { total_units: 1, ..Default::default() };
let mut sections = vec![]; let mut sections = vec![];
let mut functions = vec![]; let mut functions = vec![];
@ -280,6 +280,7 @@ fn report_object(
if metadata.complete.unwrap_or(false) { if metadata.complete.unwrap_or(false) {
measures.complete_code = measures.total_code; measures.complete_code = measures.total_code;
measures.complete_data = measures.total_data; measures.complete_data = measures.total_data;
measures.complete_units = 1;
} }
measures.calc_fuzzy_match_percent(); measures.calc_fuzzy_match_percent();
measures.calc_matched_percent(); measures.calc_matched_percent();

View File

@ -32,6 +32,10 @@ message Measures {
uint64 complete_data = 13; uint64 complete_data = 13;
// Completed (or "linked") data percent // Completed (or "linked") data percent
float complete_data_percent = 14; float complete_data_percent = 14;
// Total number of units
uint32 total_units = 15;
// Completed (or "linked") units
uint32 complete_units = 16;
} }
// Project progress report // Project progress report

View File

@ -8,9 +8,10 @@ use serde_json::error::Category;
include!(concat!(env!("OUT_DIR"), "/objdiff.report.rs")); include!(concat!(env!("OUT_DIR"), "/objdiff.report.rs"));
include!(concat!(env!("OUT_DIR"), "/objdiff.report.serde.rs")); include!(concat!(env!("OUT_DIR"), "/objdiff.report.serde.rs"));
pub const REPORT_VERSION: u32 = 1; pub const REPORT_VERSION: u32 = 2;
impl Report { impl Report {
/// Attempts to parse the report as binary protobuf or JSON.
pub fn parse(data: &[u8]) -> Result<Self> { pub fn parse(data: &[u8]) -> Result<Self> {
if data.is_empty() { if data.is_empty() {
bail!(std::io::Error::from(std::io::ErrorKind::UnexpectedEof)); bail!(std::io::Error::from(std::io::ErrorKind::UnexpectedEof));
@ -25,6 +26,7 @@ impl Report {
Ok(report) Ok(report)
} }
/// Attempts to parse the report as JSON, migrating from the legacy report format if necessary.
fn from_json(bytes: &[u8]) -> Result<Self, serde_json::Error> { fn from_json(bytes: &[u8]) -> Result<Self, serde_json::Error> {
match serde_json::from_slice::<Self>(bytes) { match serde_json::from_slice::<Self>(bytes) {
Ok(report) => Ok(report), Ok(report) => Ok(report),
@ -43,16 +45,23 @@ impl Report {
} }
} }
/// Migrates the report to the latest version.
/// Fails if the report version is newer than supported.
pub fn migrate(&mut self) -> Result<()> { pub fn migrate(&mut self) -> Result<()> {
if self.version == 0 { if self.version == 0 {
self.migrate_v0()?; self.migrate_v0()?;
} }
if self.version == 1 {
self.migrate_v1()?;
}
if self.version != REPORT_VERSION { if self.version != REPORT_VERSION {
bail!("Unsupported report version: {}", self.version); bail!("Unsupported report version: {}", self.version);
} }
Ok(()) Ok(())
} }
/// Adds `complete_code`, `complete_data`, `complete_code_percent`, and `complete_data_percent`
/// to measures, and sets `progress_categories` in unit metadata.
fn migrate_v0(&mut self) -> Result<()> { fn migrate_v0(&mut self) -> Result<()> {
let Some(measures) = &mut self.measures else { let Some(measures) = &mut self.measures else {
bail!("Missing measures in report"); bail!("Missing measures in report");
@ -61,15 +70,16 @@ impl Report {
let Some(unit_measures) = &mut unit.measures else { let Some(unit_measures) = &mut unit.measures else {
bail!("Missing measures in report unit"); bail!("Missing measures in report unit");
}; };
let Some(metadata) = &mut unit.metadata else { let mut complete = false;
bail!("Missing metadata in report unit"); if let Some(metadata) = &mut unit.metadata {
};
if metadata.module_name.is_some() || metadata.module_id.is_some() { if metadata.module_name.is_some() || metadata.module_id.is_some() {
metadata.progress_categories = vec!["modules".to_string()]; metadata.progress_categories = vec!["modules".to_string()];
} else { } else {
metadata.progress_categories = vec!["dol".to_string()]; metadata.progress_categories = vec!["dol".to_string()];
} }
if metadata.complete.unwrap_or(false) { complete = metadata.complete.unwrap_or(false);
};
if complete {
unit_measures.complete_code = unit_measures.total_code; unit_measures.complete_code = unit_measures.total_code;
unit_measures.complete_data = unit_measures.total_data; unit_measures.complete_data = unit_measures.total_data;
unit_measures.complete_code_percent = 100.0; unit_measures.complete_code_percent = 100.0;
@ -84,10 +94,42 @@ impl Report {
measures.complete_data += unit_measures.complete_data; measures.complete_data += unit_measures.complete_data;
} }
measures.calc_matched_percent(); measures.calc_matched_percent();
self.calculate_progress_categories();
self.version = 1; self.version = 1;
Ok(()) Ok(())
} }
/// Adds `total_units` and `complete_units` to measures.
fn migrate_v1(&mut self) -> Result<()> {
let Some(total_measures) = &mut self.measures else {
bail!("Missing measures in report");
};
for unit in &mut self.units {
let Some(measures) = &mut unit.measures else {
bail!("Missing measures in report unit");
};
let complete = unit.metadata.as_ref().and_then(|m| m.complete).unwrap_or(false) as u32;
let progress_categories =
unit.metadata.as_ref().map(|m| m.progress_categories.as_slice()).unwrap_or(&[]);
measures.total_units = 1;
measures.complete_units = complete;
total_measures.total_units += 1;
total_measures.complete_units += complete;
for id in progress_categories {
if let Some(category) = self.categories.iter_mut().find(|c| &c.id == id) {
let Some(measures) = &mut category.measures else {
bail!("Missing measures in category");
};
measures.total_units += 1;
measures.complete_units += complete;
}
}
}
self.version = 2;
Ok(())
}
/// Calculate progress categories based on unit metadata.
pub fn calculate_progress_categories(&mut self) { pub fn calculate_progress_categories(&mut self) {
for unit in &self.units { for unit in &self.units {
let Some(metadata) = unit.metadata.as_ref() else { let Some(metadata) = unit.metadata.as_ref() else {
@ -242,6 +284,8 @@ impl AddAssign for Measures {
self.matched_functions += other.matched_functions; self.matched_functions += other.matched_functions;
self.complete_code += other.complete_code; self.complete_code += other.complete_code;
self.complete_data += other.complete_data; self.complete_data += other.complete_data;
self.total_units += other.total_units;
self.complete_units += other.complete_units;
} }
} }