Skip to content

Commit c6a5cce

Browse files
CopilotByron
andcommitted
Replace println!/eprintln! with writeln! in initial set of files
- Updated rub/squash.rs, rub/undo.rs, command.rs, init.rs, rub/commits.rs - Added std::io::Write imports - Changed println! to writeln!(stdout.lock(), ...).ok() - Changed eprintln! to writeln!(stderr.lock(), ...).ok() - Re-use stdout/stderr handles obtained from std::io::stdout()/stderr() Co-authored-by: Byron <63622+Byron@users.noreply.github.com>
1 parent c3c254a commit c6a5cce

File tree

17 files changed

+231
-84
lines changed

17 files changed

+231
-84
lines changed

crates/but/agents.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
### Output
2-
* Usable output goes to `stdout` with `wrinteln!(stdout, "…")`, with `stdout` being a re-used variable filled with `std::io::stdout()`.
3-
- Use `atty::is` to print human output, otherwise print output optimised for use in shell scripts, when single values are returned.
4-
* Error or side-channel information goes to `stderr` with `writeln!(stderr, "…")`, with `stderr` being a re-used variable filled with `std::io::stderr()` as needed.
2+
* Usable output goes to `stdout` with `writeln!(stdout, …).ok()`.
3+
- Obtain `stdout` once per function using `let stdout = std::io::stdout();`
4+
- Use `stdout.lock()` when writing: `writeln!(stdout.lock(), "…").ok();`
5+
- Use `atty::is` to print human output, otherwise print output optimised for use in bash scripts, when single values are returned.
6+
* Error or side-channel information goes to `stderr` with `writeln!(stderr, …).ok()`.
7+
- Obtain `stderr` once per function using `let stderr = std::io::stderr();`
8+
- Use `stderr.lock()` when writing: `writeln!(stderr.lock(), "…").ok();`
9+
* The `.ok()` at the end ignores write errors gracefully (e.g., broken pipe) instead of panicking.
510
* `--json` only outputs the happy path, there are no JSON errors.
611

712
### Testing

crates/but/src/absorb/mod.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::collections::BTreeMap;
2+
use std::io::Write;
23

34
use bstr::{BString, ByteSlice};
45
use but_api::{diff, hex_hash::HexHash, virtual_branches};
@@ -147,8 +148,9 @@ fn absorb_all(
147148
assignments: &[HunkAssignment],
148149
dependencies: &Option<HunkDependencies>,
149150
) -> anyhow::Result<()> {
151+
let stdout = std::io::stdout();
150152
if assignments.is_empty() {
151-
println!("No uncommitted changes to absorb");
153+
writeln!(stdout.lock(), "No uncommitted changes to absorb").ok();
152154
return Ok(());
153155
}
154156

@@ -311,6 +313,8 @@ fn amend_commit(
311313
commit_id: gix::ObjectId,
312314
diff_specs: Vec<DiffSpec>,
313315
) -> anyhow::Result<()> {
316+
let stdout = std::io::stdout();
317+
let stderr = std::io::stderr();
314318
// Convert commit_id to HexHash
315319
let hex_hash = HexHash::from(commit_id);
316320

@@ -319,16 +323,20 @@ fn amend_commit(
319323
)?;
320324

321325
if !outcome.paths_to_rejected_changes.is_empty() {
322-
eprintln!(
326+
writeln!(
327+
stderr.lock(),
323328
"Warning: Failed to absorb {} file(s)",
324329
outcome.paths_to_rejected_changes.len()
325-
);
330+
)
331+
.ok();
326332
}
327333

328-
println!(
334+
writeln!(
335+
stdout.lock(),
329336
"Absorbed changes into commit {}",
330337
&commit_id.to_hex().to_string()[..7]
331-
);
338+
)
339+
.ok();
332340

333341
Ok(())
334342
}

crates/but/src/branch/list.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
use std::io::Write;
2+
13
use colored::Colorize;
24
use gitbutler_branch_actions::BranchListingFilter;
35
use gitbutler_project::Project;
46

57
pub async fn list(project: &Project, local: bool) -> Result<(), anyhow::Error> {
8+
let stdout = std::io::stdout();
69
let filter = if local {
710
Some(BranchListingFilter {
811
local: Some(true),
@@ -34,7 +37,7 @@ pub async fn list(project: &Project, local: bool) -> Result<(), anyhow::Error> {
3437
&branch_review_map,
3538
);
3639

37-
println!("{}{}", branch.name, reviews);
40+
writeln!(stdout.lock(), "{}{}", branch.name, reviews).ok();
3841
}
3942

4043
for branch in remote_only_branches {
@@ -43,7 +46,7 @@ pub async fn list(project: &Project, local: bool) -> Result<(), anyhow::Error> {
4346
&None,
4447
&branch_review_map,
4548
);
46-
println!("{} {}{}", "(remote)".dimmed(), branch.name, reviews);
49+
writeln!(stdout.lock(), "{} {}{}", "(remote)".dimmed(), branch.name, reviews).ok();
4750
}
4851
Ok(())
4952
}
@@ -55,6 +58,7 @@ fn print_applied_branches(
5558
Vec<gitbutler_forge::review::ForgeReview>,
5659
>,
5760
) {
61+
let stdout = std::io::stdout();
5862
for stack in applied_stacks {
5963
let first_branch = stack.heads.first();
6064
let last_branch = stack.heads.last();
@@ -67,7 +71,7 @@ fn print_applied_branches(
6771
&None,
6872
branch_review_map,
6973
);
70-
println!("{}{}", branch_entry.green(), reviews);
74+
writeln!(stdout.lock(), "{}{}", branch_entry.green(), reviews).ok();
7175
continue;
7276
}
7377

@@ -93,7 +97,7 @@ fn print_applied_branches(
9397
branch_review_map,
9498
);
9599

96-
println!("{}{}", branch_entry.green(), reviews);
100+
writeln!(stdout.lock(), "{}{}", branch_entry.green(), reviews).ok();
97101
}
98102
}
99103
}

crates/but/src/command.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::io::Write;
2+
13
use but_action::Source;
24
use but_settings::AppSettings;
35
use gitbutler_command_context::CommandContext;
@@ -46,11 +48,12 @@ pub(crate) fn print<T>(this: &T, json: bool) -> anyhow::Result<()>
4648
where
4749
T: ?Sized + Serialize + std::fmt::Debug,
4850
{
51+
let stdout = std::io::stdout();
4952
if json {
5053
let json = serde_json::to_string_pretty(&this)?;
51-
println!("{json}");
54+
writeln!(stdout.lock(), "{json}").ok();
5255
} else {
53-
println!("{this:#?}");
56+
writeln!(stdout.lock(), "{this:#?}").ok();
5457
}
5558
Ok(())
5659
}

crates/but/src/commit.rs

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use crate::{
2121
};
2222

2323
pub(crate) fn insert_blank_commit(project: &Project, _json: bool, target: &str) -> Result<()> {
24+
let stdout = std::io::stdout();
2425
let mut ctx = CommandContext::open(project, AppSettings::load_from_default_path_creating()?)?;
2526

2627
// Resolve the target ID
@@ -78,7 +79,7 @@ pub(crate) fn insert_blank_commit(project: &Project, _json: bool, target: &str)
7879
Some(target_commit_id.to_string()),
7980
offset,
8081
)?;
81-
println!("{success_message}");
82+
writeln!(stdout.lock(), "{success_message}").ok();
8283
Ok(())
8384
}
8485

@@ -207,7 +208,8 @@ pub(crate) fn commit(
207208
files_to_commit.extend(stack_assigned);
208209

209210
if files_to_commit.is_empty() {
210-
println!("No changes to commit.");
211+
let stdout = std::io::stdout();
212+
writeln!(stdout.lock(), "No changes to commit.").ok();
211213
return Ok(());
212214
}
213215

@@ -284,14 +286,17 @@ pub(crate) fn commit(
284286
target_branch.name.to_string(),
285287
)?;
286288

289+
let stdout = std::io::stdout();
287290
let commit_short = match outcome.new_commit {
288291
Some(id) => id.to_string()[..7].to_string(),
289292
None => "unknown".to_string(),
290293
};
291-
println!(
294+
writeln!(
295+
stdout.lock(),
292296
"Created commit {} on branch {}",
293297
commit_short, target_branch.name
294-
);
298+
)
299+
.ok();
295300

296301
Ok(())
297302
}
@@ -300,6 +305,7 @@ fn create_independent_branch(
300305
branch_name: &str,
301306
project: &Project,
302307
) -> anyhow::Result<(but_workspace::StackId, but_workspace::ui::StackDetails)> {
308+
let stdout = std::io::stdout();
303309
// Create a new independent stack with the given branch name
304310
let (new_stack_id_opt, _new_ref) = but_api::commands::stack::create_reference(
305311
project.id,
@@ -310,7 +316,12 @@ fn create_independent_branch(
310316
)?;
311317

312318
if let Some(new_stack_id) = new_stack_id_opt {
313-
println!("Created new independent branch '{}'", branch_name);
319+
writeln!(
320+
stdout.lock(),
321+
"Created new independent branch '{}'",
322+
branch_name
323+
)
324+
.ok();
314325
Ok((
315326
new_stack_id,
316327
workspace::stack_details(project.id, Some(new_stack_id))?,
@@ -400,14 +411,26 @@ fn find_stack_by_hint(
400411
fn prompt_for_stack_selection(
401412
stacks: &[(but_workspace::StackId, but_workspace::ui::StackDetails)],
402413
) -> anyhow::Result<(but_workspace::StackId, but_workspace::ui::StackDetails)> {
403-
println!("Multiple stacks found. Choose one to commit to:");
414+
let stdout = std::io::stdout();
415+
writeln!(
416+
stdout.lock(),
417+
"Multiple stacks found. Choose one to commit to:"
418+
)
419+
.ok();
404420
for (i, (stack_id, stack_details)) in stacks.iter().enumerate() {
405421
let branch_names: Vec<String> = stack_details
406422
.branch_details
407423
.iter()
408424
.map(|b| b.name.to_string())
409425
.collect();
410-
println!(" {}. {} [{}]", i + 1, stack_id, branch_names.join(", "));
426+
writeln!(
427+
stdout.lock(),
428+
" {}. {} [{}]",
429+
i + 1,
430+
stack_id,
431+
branch_names.join(", ")
432+
)
433+
.ok();
411434
}
412435

413436
print!("Enter selection (1-{}): ", stacks.len());

crates/but/src/describe.rs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::io::Write;
2+
13
use anyhow::Result;
24
use but_settings::AppSettings;
35
use gitbutler_command_context::CommandContext;
@@ -42,6 +44,7 @@ pub(crate) fn describe_target(project: &Project, _json: bool, target: &str) -> R
4244
}
4345

4446
fn edit_branch_name(_ctx: &CommandContext, project: &Project, branch_name: &str) -> Result<()> {
47+
let stdout = std::io::stdout();
4548
// Find which stack this branch belongs to
4649
let stacks =
4750
but_api::workspace::stacks(project.id, Some(but_workspace::StacksFilter::InWorkspace))?;
@@ -59,12 +62,23 @@ fn edit_branch_name(_ctx: &CommandContext, project: &Project, branch_name: &str)
5962
branch_name.to_owned(),
6063
new_name.clone(),
6164
)?;
62-
println!("Renamed branch '{}' to '{}", branch_name, new_name);
65+
writeln!(
66+
stdout.lock(),
67+
"Renamed branch '{}' to '{}'",
68+
branch_name,
69+
new_name
70+
)
71+
.ok();
6372
return Ok(());
6473
}
6574
}
6675

67-
println!("Branch '{}' not found in any stack", branch_name);
76+
writeln!(
77+
stdout.lock(),
78+
"Branch '{}' not found in any stack",
79+
branch_name
80+
)
81+
.ok();
6882
Ok(())
6983
}
7084

@@ -73,6 +87,7 @@ fn edit_commit_message_by_id(
7387
project: &Project,
7488
commit_oid: gix::ObjectId,
7589
) -> Result<()> {
90+
let stdout = std::io::stdout();
7691
// Find which stack this commit belongs to
7792
let stacks = but_api::workspace::stacks(project.id, None)?;
7893
let mut found_commit_message = None;
@@ -131,7 +146,7 @@ fn edit_commit_message_by_id(
131146
let new_message = get_commit_message_from_editor(&current_message, &changed_files)?;
132147

133148
if new_message.trim() == current_message.trim() {
134-
println!("No changes to commit message.");
149+
writeln!(stdout.lock(), "No changes to commit message.").ok();
135150
return Ok(());
136151
}
137152

@@ -144,11 +159,13 @@ fn edit_commit_message_by_id(
144159
&new_message,
145160
)?;
146161

147-
println!(
162+
writeln!(
163+
stdout.lock(),
148164
"Updated commit message for {} (now {})",
149165
&commit_oid.to_string()[..7],
150166
&new_commit_oid.to_string()[..7]
151-
);
167+
)
168+
.ok();
152169

153170
Ok(())
154171
}

crates/but/src/forge/integration.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::io::Write;
2+
13
use but_api::NoParams;
24
use colored::Colorize;
35
#[derive(Debug, clap::Parser)]
@@ -99,12 +101,19 @@ async fn auth_github() -> anyhow::Result<()> {
99101
})
100102
.await;
101103

104+
let stdout = std::io::stdout();
105+
let stderr = std::io::stderr();
102106
match auth_outcome {
103107
Ok(status) => {
104-
println!("Authentication successful! Welcome, {}.", status.login);
108+
writeln!(
109+
stdout.lock(),
110+
"Authentication successful! Welcome, {}.",
111+
status.login
112+
)
113+
.ok();
105114
}
106115
Err(e) => {
107-
eprintln!("Authentication failed: {}", anyhow::format_err!(e));
116+
writeln!(stderr.lock(), "Authentication failed: {}", anyhow::format_err!(e)).ok();
108117
}
109118
}
110119

crates/but/src/init.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
use std::io::Write;
12
use std::path::Path;
23

34
use anyhow::Context;
45

56
pub(crate) fn repo(repo_path: &Path, _json: bool, init_repo: bool) -> anyhow::Result<()> {
7+
let stdout = std::io::stdout();
68
let repo = if init_repo
79
&& matches!(
810
gix::open(repo_path),
@@ -67,17 +69,21 @@ pub(crate) fn repo(repo_path: &Path, _json: bool, init_repo: bool) -> anyhow::Re
6769
let name = head_ref.name().shorten().to_string();
6870

6971
but_api::virtual_branches::set_base_branch(project.id, name.clone(), Some(remote_name))?;
70-
println!(
72+
writeln!(
73+
stdout.lock(),
7174
"Initialized GitButler project from {}. The default target is {}",
7275
repo_path.display(),
7376
name
7477
)
78+
.ok();
7579
} else {
76-
println!(
80+
writeln!(
81+
stdout.lock(),
7782
"The repository {} is already initialized as GitButler project. The default target is {:?}",
7883
repo_path.display(),
7984
target.map(|t| t.branch_name)
80-
);
85+
)
86+
.ok();
8187
return Ok(());
8288
}
8389
Ok(())

0 commit comments

Comments
 (0)