Skip to content

Commit 9ffedc3

Browse files
committed
Use BString as editor return value to not enforce encodings.
This will make it harder to call from legacy code, but will make it clear for modern code that we don't know the encoding and shouldn't lighthartedly butcher it by converting to unicode lossily. Note that all callers now state explicitly that they handle the message lossily, and we should fix this once the code is modernised. While at it, also avoid rewriting line endings in favor of reusing the ones that the user specified.
1 parent 0b8c1ae commit 9ffedc3

File tree

4 files changed

+29
-25
lines changed

4 files changed

+29
-25
lines changed

crates/but/src/command/legacy/commit.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -497,8 +497,9 @@ fn get_commit_message_from_editor(
497497
template.push_str("#\n");
498498

499499
// Read the result from the editor and strip comments
500-
let message = tui::get_text::from_editor_no_comments("commit_msg", &template)?;
501-
Ok(message)
500+
let lossy_message =
501+
tui::get_text::from_editor_no_comments("commit_msg", &template)?.to_string();
502+
Ok(lossy_message)
502503
}
503504

504505
fn get_status_char(path: &BString, changes: &[TreeChange]) -> &'static str {

crates/but/src/command/legacy/describe.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -236,13 +236,14 @@ fn get_commit_message_from_editor(
236236
template.push_str("#\n");
237237

238238
// Read the result and strip comments
239-
let message = tui::get_text::from_editor_no_comments("commit_msg", &template)?;
239+
let lossy_message =
240+
tui::get_text::from_editor_no_comments("commit_msg", &template)?.to_string();
240241

241-
if message.is_empty() {
242+
if lossy_message.is_empty() {
242243
bail!("Aborting due to empty commit message");
243244
}
244245

245-
Ok(message)
246+
Ok(lossy_message)
246247
}
247248

248249
fn get_branch_name_from_editor(current_name: &str) -> Result<String> {
@@ -255,13 +256,14 @@ fn get_branch_name_from_editor(current_name: &str) -> Result<String> {
255256
template.push_str("# with '#' will be ignored, and an empty name aborts the operation.\n");
256257
template.push_str("#\n");
257258

258-
let branch_name = tui::get_text::from_editor_no_comments("branch_name", &template)?;
259+
let branch_name_lossy =
260+
tui::get_text::from_editor_no_comments("branch_name", &template)?.to_string();
259261

260-
if branch_name.is_empty() {
262+
if branch_name_lossy.is_empty() {
261263
bail!("Aborting due to empty branch name");
262264
}
263265

264-
Ok(branch_name)
266+
Ok(branch_name_lossy)
265267
}
266268

267269
#[cfg(test)]

crates/but/src/command/legacy/forge/review.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -564,8 +564,8 @@ fn get_review_body_from_editor(
564564
template.push_str("# with '#' will be ignored, and an empty body is allowed.\n");
565565
template.push_str("#\n");
566566

567-
let body = get_text::from_editor_no_comments("review_body", &template)?;
568-
Ok(body)
567+
let lossy_body = get_text::from_editor_no_comments("review_body", &template)?.to_string();
568+
Ok(lossy_body)
569569
}
570570

571571
/// Extract the commit description (body) from the commit message, skipping the first line (title).
@@ -606,13 +606,13 @@ fn get_review_title_from_editor(
606606
template.push_str("# with '#' will be ignored, and an empty title aborts the operation.\n");
607607
template.push_str("#\n");
608608

609-
let title = get_text::from_editor_no_comments("review_title", &template)?;
609+
let lossy_title = get_text::from_editor_no_comments("review_title", &template)?.to_string();
610610

611-
if title.is_empty() {
611+
if lossy_title.is_empty() {
612612
anyhow::bail!("Aborting due to empty review title");
613613
}
614614

615-
Ok(title)
615+
Ok(lossy_title)
616616
}
617617

618618
/// Extract the commit title from the commit message (first line).

crates/but/src/tui/get_text.rs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,32 @@
11
//! Various functions that involve launching the Git editor (i.e. `GIT_EDITOR`).
2-
use anyhow::Result;
3-
use bstr::ByteSlice;
2+
use anyhow::{Result, bail};
3+
use bstr::{BStr, BString, ByteSlice};
44
use std::ffi::OsStr;
55

66
/// Launches the user's preferred text editor to edit some `initial_text`,
77
/// identified by a `filename_safe_intent` to help the user understand what's wanted of them.
88
/// Note that this string must be valid in filenames.
99
///
10-
/// Returns the edited text, with comment lines (starting with `#`) removed.
11-
pub fn from_editor_no_comments(filename_safe_intent: &str, initial_text: &str) -> Result<String> {
10+
/// Returns the edited text (*without known encoding*), with comment lines (starting with `#`) removed.
11+
pub fn from_editor_no_comments(filename_safe_intent: &str, initial_text: &str) -> Result<BString> {
1212
let content = from_editor(filename_safe_intent, initial_text)?;
1313

1414
// Strip comment lines (starting with '#')
15-
let filtered_lines: Vec<&str> = content
16-
.lines()
17-
.filter(|line| !line.trim_start().starts_with('#'))
15+
let filtered_lines: Vec<&BStr> = content
16+
.lines_with_terminator()
17+
.filter(|line| !line.trim_start().starts_with_str("#"))
18+
.map(|line| line.as_bstr())
1819
.collect();
1920

20-
Ok(filtered_lines.join("\n").trim().to_string())
21+
Ok(filtered_lines.into_iter().collect())
2122
}
2223

2324
/// Launches the user's preferred text editor to edit some `initial_text`,
2425
/// identified by a `filename_safe_intent` to help the user understand what's wanted of them.
2526
/// Note that this string must be valid in filenames.
2627
///
27-
/// Returns the edited text verbatim.
28-
pub fn from_editor(identifier: &str, initial_text: &str) -> Result<String> {
28+
/// Returns the edited text (*without known encoding*) verbatim.
29+
pub fn from_editor(identifier: &str, initial_text: &str) -> Result<BString> {
2930
let editor_cmd = get_editor_command()?;
3031

3132
// Create a temporary file with the initial text
@@ -46,9 +47,9 @@ pub fn from_editor(identifier: &str, initial_text: &str) -> Result<String> {
4647
.wait()?;
4748

4849
if !status.success() {
49-
return Err(anyhow::anyhow!("Editor exited with non-zero status"));
50+
bail!("Editor exited with non-zero status");
5051
}
51-
Ok(std::fs::read_to_string(&tempfile)?)
52+
Ok(std::fs::read(&tempfile)?.into())
5253
}
5354

5455
/// Get the user's preferred editor command.

0 commit comments

Comments
 (0)