Skip to content

Commit cb1f217

Browse files
committed
feat: use git commit --verbose template in external editor
1 parent 6d0a2ec commit cb1f217

File tree

6 files changed

+54
-69
lines changed

6 files changed

+54
-69
lines changed

asyncgit/src/sync/commit.rs

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -182,18 +182,26 @@ pub fn tag_commit(
182182
}
183183

184184
/// Loads the comment prefix from config & uses it to prettify commit messages
185+
///
186+
/// Also removes any lines after the scissors line.
185187
pub fn commit_message_prettify(
186188
repo_path: &RepoPath,
187-
message: String,
189+
message: &str,
188190
) -> Result<String> {
189191
let comment_char = repo(repo_path)?
190192
.config()?
191193
.get_string("core.commentChar")
192194
.ok()
193195
.and_then(|char_string| char_string.chars().next())
194-
.unwrap_or('#') as u8;
195-
196-
Ok(message_prettify(message, Some(comment_char))?)
196+
.unwrap_or('#');
197+
let scissors_line = format!("{comment_char} ------------------------ >8 ------------------------");
198+
let message = message
199+
.lines()
200+
.take_while(|line| line != &scissors_line)
201+
.collect::<Vec<_>>()
202+
.join("\n");
203+
204+
Ok(message_prettify(message, Some(comment_char as u8))?)
197205
}
198206

199207
#[cfg(test)]
@@ -468,7 +476,7 @@ mod tests {
468476

469477
let message = commit_message_prettify(
470478
repo_path,
471-
"#This is a test message\nTest".to_owned(),
479+
"#This is a test message\nTest",
472480
)?;
473481

474482
assert_eq!(message, "Test\n");
@@ -487,7 +495,27 @@ mod tests {
487495

488496
let message = commit_message_prettify(
489497
repo_path,
490-
";This is a test message\nTest".to_owned(),
498+
";This is a test message\nTest",
499+
)?;
500+
501+
assert_eq!(message, "Test\n");
502+
503+
Ok(())
504+
}
505+
506+
#[test]
507+
fn test_scissors_line() -> Result<()> {
508+
let (_td, repo) = repo_init_empty().unwrap();
509+
510+
let root = repo.path().parent().unwrap();
511+
let repo_path: &RepoPath =
512+
&root.as_os_str().to_str().unwrap().into();
513+
514+
repo.config()?.set_str("core.commentChar", ";")?;
515+
516+
let message = commit_message_prettify(
517+
repo_path,
518+
";This is a test message\nTest\n; ------------------------ >8 ------------------------\nTest2\nTest3\nTest4",
491519
)?;
492520

493521
assert_eq!(message, "Test\n");

asyncgit/src/sync/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ pub use tags::{
105105
pub use tree::{tree_file_content, tree_files, TreeFile};
106106
pub use utils::{
107107
get_head, get_head_tuple, repo_dir, repo_open_error,
108-
stage_add_all, stage_add_file, stage_addremoved, Head,
108+
repo_work_dir, stage_add_all, stage_add_file, stage_addremoved,
109+
Head,
109110
};
110111

111112
pub use git2::ResetType;

src/app.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -359,9 +359,7 @@ impl App {
359359
Path::new(&path),
360360
)
361361
} else {
362-
let changes =
363-
self.status_tab.get_files_changes()?;
364-
self.commit_popup.show_editor(changes)
362+
self.commit_popup.show_editor()
365363
};
366364

367365
if let Err(e) = result {

src/popups/commit.rs

Lines changed: 16 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ use asyncgit::{
1818
self, get_config_string, CommitId, HookResult,
1919
PrepareCommitMsgSource, RepoPathRef, RepoState,
2020
},
21-
StatusItem, StatusItemType,
2221
};
2322
use crossterm::event::Event;
2423
use easy_cast::Cast;
@@ -28,10 +27,11 @@ use ratatui::{
2827
Frame,
2928
};
3029

30+
use std::process::Command;
3131
use std::{
3232
fmt::Write as _,
3333
fs::{read_to_string, File},
34-
io::{Read, Write},
34+
io::Read,
3535
path::PathBuf,
3636
str::FromStr,
3737
};
@@ -144,47 +144,18 @@ impl CommitPopup {
144144
}
145145
}
146146

147-
const fn item_status_char(
148-
item_type: StatusItemType,
149-
) -> &'static str {
150-
match item_type {
151-
StatusItemType::Modified => "modified",
152-
StatusItemType::New => "new file",
153-
StatusItemType::Deleted => "deleted",
154-
StatusItemType::Renamed => "renamed",
155-
StatusItemType::Typechange => " ",
156-
StatusItemType::Conflicted => "conflicted",
157-
}
158-
}
159-
160-
pub fn show_editor(
161-
&mut self,
162-
changes: Vec<StatusItem>,
163-
) -> Result<()> {
164-
let file_path = sync::repo_dir(&self.repo.borrow())?
165-
.join("COMMIT_EDITMSG");
147+
pub fn show_editor(&mut self) -> Result<()> {
148+
let git_dir = sync::repo_dir(&self.repo.borrow())?;
149+
let work_dir = sync::repo_work_dir(&self.repo.borrow())?;
150+
let file_path = git_dir.join("COMMIT_EDITMSG");
166151

167-
{
168-
let mut file = File::create(&file_path)?;
169-
file.write_fmt(format_args!(
170-
"{}\n",
171-
self.input.get_text()
172-
))?;
173-
file.write_all(
174-
strings::commit_editor_msg(&self.key_config)
175-
.as_bytes(),
176-
)?;
177-
178-
file.write_all(b"\n#\n# Changes to be committed:")?;
179-
180-
for change in changes {
181-
let status_char =
182-
Self::item_status_char(change.status);
183-
let message =
184-
format!("\n#\t{status_char}: {}", change.path);
185-
file.write_all(message.as_bytes())?;
186-
}
187-
}
152+
Command::new("git")
153+
.arg("commit")
154+
.arg("--verbose")
155+
.env("EDITOR", "false")
156+
.env("GIT_DIR", git_dir)
157+
.env("GIT_WORK_TREE", work_dir)
158+
.output()?;
188159

189160
ExternalEditorPopup::open_file_in_editor(
190161
&self.repo.borrow(),
@@ -199,7 +170,7 @@ impl CommitPopup {
199170
std::fs::remove_file(&file_path)?;
200171

201172
message =
202-
commit_message_prettify(&self.repo.borrow(), message)?;
173+
commit_message_prettify(&self.repo.borrow(), &message)?;
203174
self.input.set_text(message);
204175
self.input.show()?;
205176

@@ -210,7 +181,7 @@ impl CommitPopup {
210181
let msg = self.input.get_text().to_string();
211182

212183
if matches!(
213-
self.commit_with_msg(msg)?,
184+
self.commit_with_msg(&msg)?,
214185
CommitResult::CommitDone
215186
) {
216187
self.options
@@ -227,10 +198,7 @@ impl CommitPopup {
227198
Ok(())
228199
}
229200

230-
fn commit_with_msg(
231-
&mut self,
232-
msg: String,
233-
) -> Result<CommitResult> {
201+
fn commit_with_msg(&mut self, msg: &str) -> Result<CommitResult> {
234202
// on exit verify should always be on
235203
let verify = self.verify;
236204
self.verify = true;

src/strings.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -131,12 +131,6 @@ pub fn commit_first_line_warning(count: usize) -> String {
131131
pub const fn branch_name_invalid() -> &'static str {
132132
"[invalid name]"
133133
}
134-
pub fn commit_editor_msg(_key_config: &SharedKeyConfig) -> String {
135-
r"
136-
# Edit your commit message
137-
# Lines starting with '#' will be ignored"
138-
.to_string()
139-
}
140134
pub fn stash_popup_title(_key_config: &SharedKeyConfig) -> String {
141135
"Stash".to_string()
142136
}

src/tabs/status.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use asyncgit::{
2121
},
2222
sync::{BranchCompare, CommitId},
2323
AsyncDiff, AsyncGitNotification, AsyncStatus, DiffParams,
24-
DiffType, PushType, StatusItem, StatusParams,
24+
DiffType, PushType, StatusParams,
2525
};
2626
use crossterm::event::Event;
2727
use itertools::Itertools;
@@ -451,10 +451,6 @@ impl Status {
451451
Ok(())
452452
}
453453

454-
pub fn get_files_changes(&self) -> Result<Vec<StatusItem>> {
455-
Ok(self.git_status_stage.last()?.items)
456-
}
457-
458454
fn update_status(&mut self) -> Result<()> {
459455
let stage_status = self.git_status_stage.last()?;
460456
self.index.set_items(&stage_status.items)?;

0 commit comments

Comments
 (0)