Skip to content

Commit 192a06b

Browse files
committed
Project configuration improvements
- Support `completed` field for objects in project config. In object tree, displays red for incomplete, green for complete. - Add support for one-sided diffs. A project can include objects without an associated source file for viewing. - Add versioning to AppConfig, supporting upgrades without losing user configuration.
1 parent 5bfa47f commit 192a06b

File tree

12 files changed

+430
-159
lines changed

12 files changed

+430
-159
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ png = "0.17.9"
4242
ppc750cl = { git = "https://github.com/terorie/ppc750cl", rev = "9ae36eef34aa6d74e00972c7671f547a2acfd0aa" }
4343
rabbitizer = "1.7.4"
4444
rfd = { version = "0.11.4" } #, default-features = false, features = ['xdg-portal']
45+
ron = "0.8.0"
4546
serde = { version = "1", features = ["derive"] }
4647
serde_json = "1.0.104"
4748
serde_yaml = "0.9.25"

src/app.rs

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@ use notify::{RecursiveMode, Watcher};
1414
use time::UtcOffset;
1515

1616
use crate::{
17+
app_config::{deserialize_config, AppConfigVersion},
1718
config::{
1819
build_globset, load_project_config, ProjectObject, ProjectObjectNode, CONFIG_FILENAMES,
1920
},
2021
jobs::{objdiff::start_build, Job, JobQueue, JobResult, JobStatus},
2122
views::{
2223
appearance::{appearance_window, Appearance},
23-
config::{config_ui, project_window, ConfigViewState},
24+
config::{config_ui, project_window, ConfigViewState, DEFAULT_WATCH_PATTERNS},
2425
data_diff::data_diff_ui,
2526
demangle::{demangle_window, DemangleViewState},
2627
function_diff::function_diff_ui,
@@ -44,16 +45,21 @@ pub struct ViewState {
4445
#[derive(Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
4546
pub struct ObjectConfig {
4647
pub name: String,
47-
pub target_path: PathBuf,
48-
pub base_path: PathBuf,
48+
pub target_path: Option<PathBuf>,
49+
pub base_path: Option<PathBuf>,
4950
pub reverse_fn_order: Option<bool>,
51+
pub complete: Option<bool>,
5052
}
5153

5254
#[inline]
5355
fn bool_true() -> bool { true }
5456

55-
#[derive(Default, Clone, serde::Deserialize, serde::Serialize)]
57+
#[derive(Clone, serde::Deserialize, serde::Serialize)]
5658
pub struct AppConfig {
59+
// TODO: https://github.com/ron-rs/ron/pull/455
60+
// #[serde(flatten)]
61+
// pub version: AppConfigVersion,
62+
pub version: u32,
5763
pub custom_make: Option<String>,
5864
pub selected_wsl_distro: Option<String>,
5965
pub project_dir: Option<PathBuf>,
@@ -82,6 +88,31 @@ pub struct AppConfig {
8288
pub project_config_loaded: bool,
8389
}
8490

91+
impl Default for AppConfig {
92+
fn default() -> Self {
93+
Self {
94+
version: AppConfigVersion::default().version,
95+
custom_make: None,
96+
selected_wsl_distro: None,
97+
project_dir: None,
98+
target_obj_dir: None,
99+
base_obj_dir: None,
100+
selected_obj: None,
101+
build_target: false,
102+
rebuild_on_changes: true,
103+
auto_update_check: true,
104+
watch_patterns: DEFAULT_WATCH_PATTERNS.iter().map(|s| Glob::new(s).unwrap()).collect(),
105+
objects: vec![],
106+
object_nodes: vec![],
107+
watcher_change: false,
108+
config_change: false,
109+
obj_change: false,
110+
queue_build: false,
111+
project_config_loaded: false,
112+
}
113+
}
114+
}
115+
85116
impl AppConfig {
86117
pub fn set_project_dir(&mut self, path: PathBuf) {
87118
self.project_dir = Some(path);
@@ -133,8 +164,8 @@ pub struct App {
133164
should_relaunch: bool,
134165
}
135166

136-
const APPEARANCE_KEY: &str = "appearance";
137-
const CONFIG_KEY: &str = "app_config";
167+
pub const APPEARANCE_KEY: &str = "appearance";
168+
pub const CONFIG_KEY: &str = "app_config";
138169

139170
impl App {
140171
/// Called once before the first frame.
@@ -153,7 +184,7 @@ impl App {
153184
if let Some(appearance) = eframe::get_value::<Appearance>(storage, APPEARANCE_KEY) {
154185
app.appearance = appearance;
155186
}
156-
if let Some(mut config) = eframe::get_value::<AppConfig>(storage, CONFIG_KEY) {
187+
if let Some(mut config) = deserialize_config(storage) {
157188
if config.project_dir.is_some() {
158189
config.config_change = true;
159190
config.watcher_change = true;

src/app_config.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
use std::path::PathBuf;
2+
3+
use eframe::Storage;
4+
use globset::Glob;
5+
6+
use crate::app::{AppConfig, ObjectConfig, CONFIG_KEY};
7+
8+
#[derive(Clone, serde::Deserialize, serde::Serialize)]
9+
pub struct AppConfigVersion {
10+
pub version: u32,
11+
}
12+
13+
impl Default for AppConfigVersion {
14+
fn default() -> Self { Self { version: 1 } }
15+
}
16+
17+
/// Deserialize the AppConfig from storage, handling upgrades from older versions.
18+
pub fn deserialize_config(storage: &dyn Storage) -> Option<AppConfig> {
19+
let str = storage.get_string(CONFIG_KEY)?;
20+
match ron::from_str::<AppConfigVersion>(&str) {
21+
Ok(version) => match version.version {
22+
1 => from_str::<AppConfig>(&str),
23+
_ => {
24+
log::warn!("Unknown config version: {}", version.version);
25+
None
26+
}
27+
},
28+
Err(e) => {
29+
log::warn!("Failed to decode config version: {e}");
30+
// Try to decode as v0
31+
from_str::<AppConfigV0>(&str).map(|c| c.into_config())
32+
}
33+
}
34+
}
35+
36+
fn from_str<T>(str: &str) -> Option<T>
37+
where T: serde::de::DeserializeOwned {
38+
match ron::from_str(str) {
39+
Ok(config) => Some(config),
40+
Err(err) => {
41+
log::warn!("Failed to decode config: {err}");
42+
None
43+
}
44+
}
45+
}
46+
47+
#[derive(serde::Deserialize, serde::Serialize)]
48+
pub struct ObjectConfigV0 {
49+
pub name: String,
50+
pub target_path: PathBuf,
51+
pub base_path: PathBuf,
52+
pub reverse_fn_order: Option<bool>,
53+
}
54+
55+
impl ObjectConfigV0 {
56+
fn into_config(self) -> ObjectConfig {
57+
ObjectConfig {
58+
name: self.name,
59+
target_path: Some(self.target_path),
60+
base_path: Some(self.base_path),
61+
reverse_fn_order: self.reverse_fn_order,
62+
complete: None,
63+
}
64+
}
65+
}
66+
67+
#[derive(serde::Deserialize, serde::Serialize)]
68+
pub struct AppConfigV0 {
69+
pub custom_make: Option<String>,
70+
pub selected_wsl_distro: Option<String>,
71+
pub project_dir: Option<PathBuf>,
72+
pub target_obj_dir: Option<PathBuf>,
73+
pub base_obj_dir: Option<PathBuf>,
74+
pub selected_obj: Option<ObjectConfigV0>,
75+
pub build_target: bool,
76+
pub auto_update_check: bool,
77+
pub watch_patterns: Vec<Glob>,
78+
}
79+
80+
impl AppConfigV0 {
81+
fn into_config(self) -> AppConfig {
82+
log::info!("Upgrading configuration from v0");
83+
AppConfig {
84+
custom_make: self.custom_make,
85+
selected_wsl_distro: self.selected_wsl_distro,
86+
project_dir: self.project_dir,
87+
target_obj_dir: self.target_obj_dir,
88+
base_obj_dir: self.base_obj_dir,
89+
selected_obj: self.selected_obj.map(|obj| obj.into_config()),
90+
build_target: self.build_target,
91+
auto_update_check: self.auto_update_check,
92+
watch_patterns: self.watch_patterns,
93+
..Default::default()
94+
}
95+
}
96+
}

src/config.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ pub struct ProjectObject {
2727
pub target_path: Option<PathBuf>,
2828
pub base_path: Option<PathBuf>,
2929
pub reverse_fn_order: Option<bool>,
30+
pub complete: Option<bool>,
3031
}
3132

3233
impl ProjectObject {

src/diff.rs

Lines changed: 76 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -372,66 +372,80 @@ fn find_section_and_symbol(obj: &ObjInfo, name: &str) -> Option<(usize, usize)>
372372
None
373373
}
374374

375-
pub fn diff_objs(left: &mut ObjInfo, right: &mut ObjInfo) -> Result<()> {
376-
for left_section in &mut left.sections {
377-
if left_section.kind == ObjSectionKind::Code {
378-
for left_symbol in &mut left_section.symbols {
379-
if let Some((right_section_idx, right_symbol_idx)) =
380-
find_section_and_symbol(right, &left_symbol.name)
381-
{
382-
let right_section = &mut right.sections[right_section_idx];
383-
let right_symbol = &mut right_section.symbols[right_symbol_idx];
384-
left_symbol.diff_symbol = Some(right_symbol.name.clone());
385-
right_symbol.diff_symbol = Some(left_symbol.name.clone());
386-
diff_code(
387-
left.architecture,
388-
&left_section.data,
389-
&right_section.data,
390-
left_symbol,
391-
right_symbol,
392-
&left_section.relocations,
393-
&right_section.relocations,
394-
&left.line_info,
395-
&right.line_info,
396-
)?;
397-
} else {
398-
no_diff_code(
399-
left.architecture,
400-
&left_section.data,
401-
left_symbol,
402-
&left_section.relocations,
403-
&left.line_info,
404-
)?;
375+
pub fn diff_objs(mut left: Option<&mut ObjInfo>, mut right: Option<&mut ObjInfo>) -> Result<()> {
376+
if let Some(left) = left.as_mut() {
377+
for left_section in &mut left.sections {
378+
if left_section.kind == ObjSectionKind::Code {
379+
for left_symbol in &mut left_section.symbols {
380+
if let Some((right, (right_section_idx, right_symbol_idx))) =
381+
right.as_mut().and_then(|obj| {
382+
find_section_and_symbol(obj, &left_symbol.name).map(|s| (obj, s))
383+
})
384+
{
385+
let right_section = &mut right.sections[right_section_idx];
386+
let right_symbol = &mut right_section.symbols[right_symbol_idx];
387+
left_symbol.diff_symbol = Some(right_symbol.name.clone());
388+
right_symbol.diff_symbol = Some(left_symbol.name.clone());
389+
diff_code(
390+
left.architecture,
391+
&left_section.data,
392+
&right_section.data,
393+
left_symbol,
394+
right_symbol,
395+
&left_section.relocations,
396+
&right_section.relocations,
397+
&left.line_info,
398+
&right.line_info,
399+
)?;
400+
} else {
401+
no_diff_code(
402+
left.architecture,
403+
&left_section.data,
404+
left_symbol,
405+
&left_section.relocations,
406+
&left.line_info,
407+
)?;
408+
}
405409
}
406-
}
407-
} else {
408-
let Some(right_section) =
409-
right.sections.iter_mut().find(|s| s.name == left_section.name)
410-
else {
411-
continue;
412-
};
413-
if left_section.kind == ObjSectionKind::Data {
414-
diff_data(left_section, right_section);
415-
// diff_data_symbols(left_section, right_section)?;
416-
} else if left_section.kind == ObjSectionKind::Bss {
417-
diff_bss_symbols(&mut left_section.symbols, &mut right_section.symbols)?;
410+
} else if let Some(right_section) = right
411+
.as_mut()
412+
.and_then(|obj| obj.sections.iter_mut().find(|s| s.name == left_section.name))
413+
{
414+
if left_section.kind == ObjSectionKind::Data {
415+
diff_data(left_section, right_section);
416+
// diff_data_symbols(left_section, right_section)?;
417+
} else if left_section.kind == ObjSectionKind::Bss {
418+
diff_bss_symbols(&mut left_section.symbols, &mut right_section.symbols)?;
419+
}
420+
} else if left_section.kind == ObjSectionKind::Data {
421+
no_diff_data(left_section);
418422
}
419423
}
420424
}
421-
for right_section in right.sections.iter_mut().filter(|s| s.kind == ObjSectionKind::Code) {
422-
for right_symbol in &mut right_section.symbols {
423-
if right_symbol.instructions.is_empty() {
424-
no_diff_code(
425-
right.architecture,
426-
&right_section.data,
427-
right_symbol,
428-
&right_section.relocations,
429-
&right.line_info,
430-
)?;
425+
if let Some(right) = right.as_mut() {
426+
for right_section in right.sections.iter_mut() {
427+
if right_section.kind == ObjSectionKind::Code {
428+
for right_symbol in &mut right_section.symbols {
429+
if right_symbol.instructions.is_empty() {
430+
no_diff_code(
431+
right.architecture,
432+
&right_section.data,
433+
right_symbol,
434+
&right_section.relocations,
435+
&right.line_info,
436+
)?;
437+
}
438+
}
439+
} else if right_section.kind == ObjSectionKind::Data
440+
&& right_section.data_diff.is_empty()
441+
{
442+
no_diff_data(right_section);
431443
}
432444
}
433445
}
434-
diff_bss_symbols(&mut left.common, &mut right.common)?;
446+
if let (Some(left), Some(right)) = (left, right) {
447+
diff_bss_symbols(&mut left.common, &mut right.common)?;
448+
}
435449
Ok(())
436450
}
437451

@@ -710,3 +724,12 @@ fn diff_data(left: &mut ObjSection, right: &mut ObjSection) {
710724
left.data_diff = left_diff;
711725
right.data_diff = right_diff;
712726
}
727+
728+
fn no_diff_data(section: &mut ObjSection) {
729+
section.data_diff = vec![ObjDataDiff {
730+
data: section.data.clone(),
731+
kind: ObjDataDiffKind::None,
732+
len: section.data.len(),
733+
symbol: String::new(),
734+
}];
735+
}

0 commit comments

Comments
 (0)