Skip to content

Commit 0c578a6

Browse files
Address review feedback: improve error handling
- Remove unused thiserror dependency from workspace - Add from_josh_err helper function for converting josh::JoshError - Replace manual error mapping with from_josh_err + .context() - Replace all bail! macro calls with explicit return Err(...) This makes error handling clearer and avoids hidden control flow. Co-authored-by: Vlad Ivanov <vlad-ivanov-name@users.noreply.github.com>
1 parent 1ab2c00 commit 0c578a6

File tree

2 files changed

+35
-21
lines changed

2 files changed

+35
-21
lines changed

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ rs_tracing = { version = "1.1.0", features = ["rs_tracing"] }
3535
serde = { version = "1.0.228", features = ["std", "derive"] }
3636
serde_json = "1.0.145"
3737
serde_yaml = "0.9.34"
38-
thiserror = "2.0"
3938
toml = "0.9.8"
4039
tracing-subscriber = { version = "0.3.20", features = ["env-filter"] }
4140
tempfile = "3.23.0"

josh-cli/src/bin/josh.rs

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ use log::debug;
88
use std::io::IsTerminal;
99
use std::process::{Command as ProcessCommand, Stdio};
1010

11+
/// Helper function to convert josh::JoshError to anyhow::Error
12+
fn from_josh_err(err: josh::JoshError) -> anyhow::Error {
13+
anyhow::anyhow!("{}", err.0)
14+
}
15+
1116
/// Spawn a git command directly to the terminal so users can see progress
1217
/// Falls back to captured output if not in a TTY environment
1318
fn spawn_git_command(
@@ -278,7 +283,8 @@ fn apply_josh_filtering(
278283

279284
// Use josh API directly instead of calling josh-filter binary
280285
let filterobj = josh::filter::parse(filter)
281-
.map_err(|e| anyhow::anyhow!("Failed to parse filter: {}", e.0))?;
286+
.map_err(from_josh_err)
287+
.context("Failed to parse filter")?;
282288

283289
josh::cache_sled::sled_load(&repo_path.join(".git"))
284290
.context("Failed to load sled cache")?;
@@ -288,15 +294,18 @@ fn apply_josh_filtering(
288294
.with_backend(josh::cache_sled::SledCacheBackend::default())
289295
.with_backend(
290296
josh::cache_notes::NotesCacheBackend::new(repo_path)
291-
.map_err(|e| anyhow::anyhow!("Failed to create NotesCacheBackend: {}", e.0))?,
297+
.map_err(from_josh_err)
298+
.context("Failed to create NotesCacheBackend")?,
292299
),
293300
);
294301

295302
// Open Josh transaction
296303
let transaction = josh::cache::TransactionContext::from_env(cache.clone())
297-
.map_err(|e| anyhow::anyhow!("Failed TransactionContext::from_env: {}", e.0))?
304+
.map_err(from_josh_err)
305+
.context("Failed TransactionContext::from_env")?
298306
.open(None)
299-
.map_err(|e| anyhow::anyhow!("Failed TransactionContext::open: {}", e.0))?;
307+
.map_err(from_josh_err)
308+
.context("Failed TransactionContext::open")?;
300309

301310
let repo = transaction.repo();
302311

@@ -356,7 +365,7 @@ fn apply_josh_filtering(
356365
)?;
357366

358367
if exit_code != 0 {
359-
anyhow::bail!("Failed to fetch filtered refs: exit code {}", exit_code);
368+
return Err(anyhow::anyhow!("Failed to fetch filtered refs: exit code {}", exit_code));
360369
}
361370

362371
Ok(())
@@ -449,11 +458,11 @@ fn handle_clone(args: &CloneArgs) -> Result<()> {
449458
)?;
450459

451460
if exit_code != 0 {
452-
anyhow::bail!(
461+
return Err(anyhow::anyhow!(
453462
"Failed to checkout branch {}: exit code {}",
454463
default_branch,
455464
exit_code
456-
);
465+
));
457466
}
458467

459468
// Set up upstream tracking for the branch
@@ -469,11 +478,11 @@ fn handle_clone(args: &CloneArgs) -> Result<()> {
469478
)?;
470479

471480
if exit_code != 0 {
472-
anyhow::bail!(
481+
return Err(anyhow::anyhow!(
473482
"Failed to set upstream for branch {}: exit code {}",
474483
default_branch,
475484
exit_code
476-
);
485+
));
477486
}
478487

479488
println!("Cloned repository to: {}", output_dir.display());
@@ -568,10 +577,10 @@ fn handle_fetch_internal(args: &FetchArgs, repo_path: &std::path::Path) -> Resul
568577
)?;
569578

570579
if exit_code != 0 {
571-
anyhow::bail!(
580+
return Err(anyhow::anyhow!(
572581
"git fetch to josh/remotes failed with exit code: {}",
573582
exit_code
574-
);
583+
));
575584
}
576585

577586
// Set up remote HEAD reference using git ls-remote
@@ -648,7 +657,8 @@ fn handle_push(args: &PushArgs) -> Result<()> {
648657

649658
// Parse the filter using Josh API
650659
let filter = josh::filter::parse(&filter_str)
651-
.map_err(|e| anyhow::anyhow!("Failed to parse filter: {}", e.0))?;
660+
.map_err(from_josh_err)
661+
.context("Failed to parse filter")?;
652662

653663
josh::cache_sled::sled_load(repo_path)
654664
.context("Failed to load sled cache")?;
@@ -657,15 +667,18 @@ fn handle_push(args: &PushArgs) -> Result<()> {
657667
.with_backend(josh::cache_sled::SledCacheBackend::default())
658668
.with_backend(
659669
josh::cache_notes::NotesCacheBackend::new(repo_path)
660-
.map_err(|e| anyhow::anyhow!("Failed to create NotesCacheBackend: {}", e.0))?,
670+
.map_err(from_josh_err)
671+
.context("Failed to create NotesCacheBackend")?,
661672
),
662673
);
663674

664675
// Open Josh transaction
665676
let transaction = josh::cache::TransactionContext::from_env(cache.clone())
666-
.map_err(|e| anyhow::anyhow!("Failed TransactionContext::from_env: {}", e.0))?
677+
.map_err(from_josh_err)
678+
.context("Failed TransactionContext::from_env")?
667679
.open(None)
668-
.map_err(|e| anyhow::anyhow!("Failed TransactionContext::open: {}", e.0))?;
680+
.map_err(from_josh_err)
681+
.context("Failed TransactionContext::open")?;
669682

670683
// Get the remote URL from josh-remote config
671684
let remote_url = config
@@ -786,7 +799,8 @@ fn handle_push(args: &PushArgs) -> Result<()> {
786799
None, // reparent_orphans
787800
&mut changes, // change_ids
788801
)
789-
.map_err(|e| format!("Failed to unapply filter: {}", e.0))?;
802+
.map_err(from_josh_err)
803+
.context("Failed to unapply filter")?;
790804

791805
// Define variables needed for build_to_push
792806
let baseref = remote_ref.clone();
@@ -805,7 +819,8 @@ fn handle_push(args: &PushArgs) -> Result<()> {
805819
oid_to_push,
806820
old,
807821
)
808-
.map_err(|e| anyhow::anyhow!("Failed to build to push: {}", e.0))?;
822+
.map_err(from_josh_err)
823+
.context("Failed to build to push")?;
809824

810825
debug!("to_push: {:?}", to_push);
811826

@@ -846,7 +861,7 @@ fn handle_push(args: &PushArgs) -> Result<()> {
846861
)?;
847862

848863
if exit_code != 0 {
849-
anyhow::bail!("git push failed for {}: exit code {}", refname, exit_code);
864+
return Err(anyhow::anyhow!("git push failed for {}: exit code {}", refname, exit_code));
850865
}
851866

852867
println!("Pushed {} to {}/{}", oid, args.remote, refname);
@@ -932,7 +947,7 @@ fn handle_remote_add_internal(args: &RemoteAddArgs, repo_path: &std::path::Path)
932947
)?;
933948

934949
if exit_code != 0 {
935-
anyhow::bail!("Failed to add git remote: exit code {}", exit_code);
950+
return Err(anyhow::anyhow!("Failed to add git remote: exit code {}", exit_code));
936951
}
937952

938953
// Set up namespace configuration for the remote
@@ -950,7 +965,7 @@ fn handle_remote_add_internal(args: &RemoteAddArgs, repo_path: &std::path::Path)
950965
)?;
951966

952967
if exit_code != 0 {
953-
anyhow::bail!("Failed to set remote uploadpack: exit code {}", exit_code);
968+
return Err(anyhow::anyhow!("Failed to set remote uploadpack: exit code {}", exit_code));
954969
}
955970

956971
println!(

0 commit comments

Comments
 (0)