Skip to content

Commit 8bb26e8

Browse files
committed
feat: 添加 thiserror 依赖并改进错误处理
1 parent e4c7e68 commit 8bb26e8

File tree

13 files changed

+321
-185
lines changed

13 files changed

+321
-185
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.

ostool/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,5 @@ lzma-rs = "0.3"
5757
regex = "1"
5858
sha2 = "0.10"
5959
tar = "0.4"
60+
thiserror = {workspace = true}
6061
ureq = "3.0"

ostool/src/bin/cargo-osrun.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
use std::{env, path::PathBuf, process::exit};
1+
use std::{
2+
env,
3+
path::PathBuf,
4+
process::{ExitCode, exit},
5+
};
26

37
use clap::{Parser, Subcommand};
48
use log::{LevelFilter, debug};
@@ -76,7 +80,18 @@ struct CliUboot {
7680
}
7781

7882
#[tokio::main]
79-
async fn main() -> anyhow::Result<()> {
83+
async fn main() -> ExitCode {
84+
match try_main().await {
85+
Ok(()) => ExitCode::SUCCESS,
86+
Err(err) => {
87+
eprintln!("Error: {err:#}");
88+
eprintln!("\nTrace:\n{err:?}");
89+
ExitCode::FAILURE
90+
}
91+
}
92+
}
93+
94+
async fn try_main() -> anyhow::Result<()> {
8095
env_logger::builder()
8196
.format_module_path(false)
8297
.filter_level(LevelFilter::Info)
@@ -118,7 +133,7 @@ async fn main() -> anyhow::Result<()> {
118133
..Default::default()
119134
};
120135

121-
app.set_elf_path(args.elf).await;
136+
app.set_elf_path(args.elf).await?;
122137
app.objcopy_elf()?;
123138

124139
app.debug = args.debug;

ostool/src/build/cargo_builder.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,13 @@ use std::{
1111

1212
use colored::Colorize;
1313

14-
use crate::{build::config::Cargo, ctx::AppContext, utils::Command};
14+
use anyhow::Context;
15+
16+
use crate::{
17+
build::config::Cargo,
18+
ctx::AppContext,
19+
utils::{Command, PathResultExt},
20+
};
1521

1622
/// A builder for constructing and executing Cargo commands.
1723
///
@@ -237,7 +243,7 @@ impl<'a> CargoBuilder<'a> {
237243
.join(if self.ctx.debug { "debug" } else { "release" })
238244
.join(&self.config.package);
239245

240-
self.ctx.set_elf_path(elf_path).await;
246+
self.ctx.set_elf_path(elf_path).await?;
241247

242248
if self.config.to_bin && !self.skip_objcopy {
243249
self.ctx.objcopy_output_bin()?;
@@ -310,7 +316,12 @@ impl<'a> CargoBuilder<'a> {
310316
if let Some(ref config_path) = self.config_path {
311317
let combined = config_path
312318
.parent()
313-
.ok_or_else(|| anyhow::anyhow!("Invalid config path"))?
319+
.ok_or_else(|| {
320+
anyhow::anyhow!(
321+
"invalid config path without parent: {}",
322+
config_path.display()
323+
)
324+
})?
314325
.join(extra);
315326
Ok(Some(combined))
316327
} else {
@@ -397,7 +408,8 @@ impl<'a> CargoBuilder<'a> {
397408
// Write to temp file
398409
tokio::fs::write(&target_path, content)
399410
.await
400-
.map_err(|e| anyhow::anyhow!("Failed to write to temp file: {}", e))?;
411+
.with_path("failed to write downloaded cargo config", &target_path)
412+
.with_context(|| format!("while downloading cargo config from {url}"))?;
401413

402414
println!("Config downloaded to: {}", target_path.display());
403415

ostool/src/build/mod.rs

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use crate::{
2828
config::{Cargo, Custom},
2929
},
3030
ctx::AppContext,
31+
utils::PathResultExt,
3132
};
3233

3334
/// Cargo builder implementation for building projects.
@@ -150,18 +151,25 @@ impl AppContext {
150151
dir.clone()
151152
};
152153

153-
bin_path
154-
.canonicalize()
155-
.or_else(|_| {
156-
if let Some(parent) = bin_path.parent() {
157-
parent
158-
.canonicalize()
159-
.map(|p| p.join(bin_path.file_name().unwrap()))
160-
} else {
161-
Ok(bin_path.clone())
162-
}
163-
})
164-
.context("Failed to normalize path")
154+
match bin_path.canonicalize() {
155+
Ok(path) => Ok(path),
156+
Err(file_err) => {
157+
let Some(parent) = bin_path.parent() else {
158+
return Err(file_err).with_path("failed to canonicalize path", &bin_path);
159+
};
160+
let Some(file_name) = bin_path.file_name() else {
161+
return Err(file_err).with_path("failed to canonicalize path", &bin_path);
162+
};
163+
164+
parent
165+
.canonicalize()
166+
.map(|parent_dir| parent_dir.join(file_name))
167+
.with_path("failed to canonicalize parent path", parent)
168+
.with_context(|| {
169+
format!("failed to normalize path: {}", bin_path.display())
170+
})
171+
}
172+
}
165173
};
166174

167175
let build_dir = self

ostool/src/ctx.rs

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
77
use std::{path::PathBuf, sync::Arc};
88

9-
use anyhow::anyhow;
9+
use anyhow::{Context, anyhow};
1010
use cargo_metadata::Metadata;
1111
use colored::Colorize;
1212
use cursive::Cursive;
@@ -19,7 +19,7 @@ use jkconfig::{
1919
use object::{Architecture, Object};
2020
use tokio::fs;
2121

22-
use crate::build::config::BuildConfig;
22+
use crate::{build::config::BuildConfig, utils::PathResultExt};
2323

2424
/// Configuration for output directories.
2525
///
@@ -148,30 +148,28 @@ impl AppContext {
148148
let res = cargo_metadata::MetadataCommand::new()
149149
.current_dir(&self.paths.manifest)
150150
.no_deps()
151-
.exec()?;
151+
.exec()
152+
.with_context(|| {
153+
format!(
154+
"failed to load cargo metadata from {}",
155+
self.paths.manifest.display()
156+
)
157+
})?;
152158
Ok(res)
153159
}
154160

155161
/// Sets the ELF file path and detects its architecture.
156162
///
157163
/// This also reads the ELF file to detect the target CPU architecture.
158-
pub async fn set_elf_path(&mut self, path: PathBuf) {
164+
pub async fn set_elf_path(&mut self, path: PathBuf) -> anyhow::Result<()> {
159165
self.paths.artifacts.elf = Some(path.clone());
160-
let binary_data = match fs::read(path).await {
161-
Ok(data) => data,
162-
Err(e) => {
163-
println!("Failed to read ELF file: {e}");
164-
return;
165-
}
166-
};
167-
let file = match object::File::parse(binary_data.as_slice()) {
168-
Ok(f) => f,
169-
Err(e) => {
170-
println!("Failed to parse ELF file: {e}");
171-
return;
172-
}
173-
};
174-
self.arch = Some(file.architecture())
166+
let binary_data = fs::read(&path)
167+
.await
168+
.with_path("failed to read ELF file", &path)?;
169+
let file = object::File::parse(binary_data.as_slice())
170+
.with_context(|| format!("failed to parse ELF file: {}", path.display()))?;
171+
self.arch = Some(file.architecture());
172+
Ok(())
175173
}
176174

177175
/// Strips debug symbols from the ELF file.
@@ -191,13 +189,15 @@ impl AppContext {
191189
.artifacts
192190
.elf
193191
.as_ref()
194-
.ok_or(anyhow!("elf not exist"))?
195-
.canonicalize()?;
192+
.ok_or(anyhow!("elf not exist"))?;
193+
let elf_path = elf_path
194+
.canonicalize()
195+
.with_path("failed to canonicalize file", elf_path)?;
196196

197197
let stripped_elf_path = elf_path.with_file_name(
198198
elf_path
199199
.file_stem()
200-
.ok_or(anyhow!("Invalid file path"))?
200+
.ok_or_else(|| anyhow!("invalid ELF file path: {}", elf_path.display()))?
201201
.to_string_lossy()
202202
.to_string()
203203
+ ".elf",
@@ -251,12 +251,14 @@ impl AppContext {
251251
.artifacts
252252
.elf
253253
.as_ref()
254-
.ok_or(anyhow!("elf not exist"))?
255-
.canonicalize()?;
254+
.ok_or(anyhow!("elf not exist"))?;
255+
let elf_path = elf_path
256+
.canonicalize()
257+
.with_path("failed to canonicalize file", elf_path)?;
256258

257259
let bin_name = elf_path
258260
.file_stem()
259-
.ok_or(anyhow!("Invalid file path"))?
261+
.ok_or_else(|| anyhow!("invalid ELF file path: {}", elf_path.display()))?
260262
.to_string_lossy()
261263
.to_string()
262264
+ ".bin";
@@ -268,7 +270,7 @@ impl AppContext {
268270
};
269271

270272
if let Some(parent) = bin_path.parent() {
271-
std::fs::create_dir_all(parent)?;
273+
std::fs::create_dir_all(parent).with_path("failed to create directory", parent)?;
272274
}
273275

274276
println!(
@@ -326,11 +328,12 @@ impl AppContext {
326328
self.build_config_path = Some(config_path.clone());
327329

328330
let Some(c): Option<BuildConfig> = jkconfig::run(
329-
config_path,
331+
config_path.clone(),
330332
menu,
331333
&[self.ui_hock_feature_select(), self.ui_hock_pacage_select()],
332334
)
333-
.await?
335+
.await
336+
.with_context(|| format!("failed to load build config: {}", config_path.display()))?
334337
else {
335338
anyhow::bail!("No build configuration obtained");
336339
};

ostool/src/main.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
use std::{env::current_dir, path::PathBuf};
1+
use std::{env::current_dir, path::PathBuf, process::ExitCode};
22

3-
use anyhow::Result;
3+
use anyhow::{Context, Result};
44
use clap::*;
55

66
use log::info;
@@ -70,7 +70,18 @@ pub struct UbootArgs {
7070
}
7171

7272
#[tokio::main]
73-
async fn main() -> Result<()> {
73+
async fn main() -> ExitCode {
74+
match try_main().await {
75+
Ok(()) => ExitCode::SUCCESS,
76+
Err(err) => {
77+
eprintln!("Error: {err:#}");
78+
eprintln!("\nTrace:\n{err:?}");
79+
ExitCode::FAILURE
80+
}
81+
}
82+
}
83+
84+
async fn try_main() -> Result<()> {
7485
#[cfg(not(feature = "ui-log"))]
7586
{
7687
env_logger::builder()
@@ -81,7 +92,7 @@ async fn main() -> Result<()> {
8192

8293
let cli = Cli::parse();
8394

84-
let pwd = current_dir()?;
95+
let pwd = current_dir().context("failed to get current working directory")?;
8596

8697
let workspace_folder = match cli.workdir {
8798
Some(dir) => dir,
@@ -119,7 +130,7 @@ async fn main() -> Result<()> {
119130
}
120131
build::config::BuildSystem::Custom(custom_cfg) => {
121132
ctx.shell_run_cmd(&custom_cfg.build_cmd)?;
122-
ctx.set_elf_path(custom_cfg.elf_path.clone().into()).await;
133+
ctx.set_elf_path(custom_cfg.elf_path.clone().into()).await?;
123134
info!(
124135
"ELF {:?}: {}",
125136
ctx.arch,

ostool/src/menuconfig.rs

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
//! - QEMU settings (`.qemu.toml`)
99
//! - U-Boot settings (`.uboot.toml`)
1010
11+
use anyhow::Context;
1112
use anyhow::Result;
1213
use clap::ValueEnum;
1314
use log::info;
@@ -16,6 +17,7 @@ use tokio::fs;
1617
use crate::ctx::AppContext;
1718
use crate::run::qemu::QemuConfig;
1819
use crate::run::uboot::UbootConfig;
20+
use crate::utils::PathResultExt;
1921

2022
/// Menu configuration mode selector.
2123
#[derive(ValueEnum, Clone, Debug)]
@@ -76,14 +78,15 @@ impl MenuConfigHandler {
7678
println!("\n未找到 U-Boot 配置文件,将使用默认配置");
7779
}
7880

79-
let config = jkconfig::run::<QemuConfig>(config_path, true, &[]).await?;
81+
let config = jkconfig::run::<QemuConfig>(config_path.clone(), true, &[])
82+
.await
83+
.with_context(|| format!("failed to load QEMU config: {}", config_path.display()))?;
8084

8185
if let Some(c) = config {
82-
fs::write(
83-
ctx.value_replace_with_var(ctx.paths.workspace.join(".qemu.toml")),
84-
toml::to_string_pretty(&c)?,
85-
)
86-
.await?;
86+
let save_path = ctx.paths.workspace.join(".qemu.toml");
87+
fs::write(&save_path, toml::to_string_pretty(&c)?)
88+
.await
89+
.with_path("failed to write file", &save_path)?;
8790
println!("\nQEMU 配置已保存到 .qemu.toml");
8891
} else {
8992
println!("\n未更改 QEMU 配置");
@@ -105,13 +108,18 @@ impl MenuConfigHandler {
105108
} else {
106109
println!("\n未找到 U-Boot 配置文件,将使用默认配置");
107110
}
108-
let config = jkconfig::run::<UbootConfig>(uboot_config_path, true, &[]).await?;
111+
let config = jkconfig::run::<UbootConfig>(uboot_config_path.clone(), true, &[])
112+
.await
113+
.with_context(|| {
114+
format!(
115+
"failed to load U-Boot config: {}",
116+
uboot_config_path.display()
117+
)
118+
})?;
109119
if let Some(c) = config {
110-
fs::write(
111-
ctx.value_replace_with_var(ctx.paths.workspace.join(".uboot.toml")),
112-
toml::to_string_pretty(&c)?,
113-
)
114-
.await?;
120+
fs::write(&uboot_config_path, toml::to_string_pretty(&c)?)
121+
.await
122+
.with_path("failed to write file", &uboot_config_path)?;
115123
println!("\nU-Boot 配置已保存到 .uboot.toml");
116124
} else {
117125
println!("\n未更改 U-Boot 配置");

0 commit comments

Comments
 (0)