diff --git a/CHANGELOG.md b/CHANGELOG.md index bceb31185c..f9005d557c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added * support 'n'/'p' key to move to the next/prev hunk in diff component [[@hamflx](https://github.com/hamflx)] ([#1523](https://github.com/extrawurst/gitui/issues/1523)) * simplify theme overrides [[@cruessler](https://github.com/cruessler)] ([#1367](https://github.com/extrawurst/gitui/issues/1367)) +* support for sign-off of commits [[@domtac](https://github.com/domtac)]([#1757](https://github.com/extrawurst/gitui/issues/1757)) ### Fixes * fix commit dialog char count for multibyte characters ([#1726](https://github.com/extrawurst/gitui/issues/1726)) diff --git a/src/components/commit.rs b/src/components/commit.rs index 875d0a35e9..586dbb2569 100644 --- a/src/components/commit.rs +++ b/src/components/commit.rs @@ -255,7 +255,9 @@ impl CommitComponent { return Ok(CommitResult::Aborted); } } + let mut msg = message_prettify(msg, Some(b'#'))?; + if verify { // run commit message check hook - can reject commit if let HookResult::NotOk(e) = @@ -341,6 +343,13 @@ impl CommitComponent { Ok(()) } + fn signoff_commit(&mut self) { + let msg = self.input.get_text(); + let signed_msg = self.add_sign_off(msg); + if let std::result::Result::Ok(signed_msg) = signed_msg { + self.input.set_text(signed_msg); + } + } fn toggle_verify(&mut self) { self.verify = !self.verify; } @@ -416,6 +425,30 @@ impl CommitComponent { Ok(()) } + + fn add_sign_off(&self, msg: &str) -> Result { + const CONFIG_KEY_USER_NAME: &str = "user.name"; + const CONFIG_KEY_USER_MAIL: &str = "user.email"; + + let user = get_config_string( + &self.repo.borrow(), + CONFIG_KEY_USER_NAME, + )?; + + let mail = get_config_string( + &self.repo.borrow(), + CONFIG_KEY_USER_MAIL, + )?; + + let mut msg = msg.to_owned(); + if let (Some(user), Some(mail)) = (user, mail) { + msg.push_str(&format!( + "\n\nSigned-off-by {user} <{mail}>" + )); + } + + Ok(msg) + } } impl DrawableComponent for CommitComponent { @@ -464,6 +497,12 @@ impl Component for CommitComponent { true, )); + out.push(CommandInfo::new( + strings::commands::commit_signoff(&self.key_config), + true, + true, + )); + out.push(CommandInfo::new( strings::commands::commit_open_editor( &self.key_config, @@ -531,6 +570,11 @@ impl Component for CommitComponent { self.input.set_text(msg); self.commit_msg_history_idx += 1; } + } else if key_match( + e, + self.key_config.keys.toggle_signoff, + ) { + self.signoff_commit(); } // stop key event propagation return Ok(EventState::Consumed); diff --git a/src/keys/key_list.rs b/src/keys/key_list.rs index 134d992d87..619dde5ee1 100644 --- a/src/keys/key_list.rs +++ b/src/keys/key_list.rs @@ -88,6 +88,7 @@ pub struct KeysList { pub log_reset_comit: GituiKeyEvent, pub log_reword_comit: GituiKeyEvent, pub commit_amend: GituiKeyEvent, + pub toggle_signoff: GituiKeyEvent, pub toggle_verify: GituiKeyEvent, pub copy: GituiKeyEvent, pub create_branch: GituiKeyEvent, @@ -174,6 +175,7 @@ impl Default for KeysList { log_reset_comit: GituiKeyEvent { code: KeyCode::Char('R'), modifiers: KeyModifiers::SHIFT }, log_reword_comit: GituiKeyEvent { code: KeyCode::Char('r'), modifiers: KeyModifiers::empty() }, commit_amend: GituiKeyEvent::new(KeyCode::Char('a'), KeyModifiers::CONTROL), + toggle_signoff: GituiKeyEvent::new(KeyCode::Char('s'), KeyModifiers::CONTROL), toggle_verify: GituiKeyEvent::new(KeyCode::Char('f'), KeyModifiers::CONTROL), copy: GituiKeyEvent::new(KeyCode::Char('y'), KeyModifiers::empty()), create_branch: GituiKeyEvent::new(KeyCode::Char('c'), KeyModifiers::empty()), diff --git a/src/strings.rs b/src/strings.rs index 3e1ff80633..1f856b9c5d 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -980,6 +980,18 @@ pub mod commands { CMD_GROUP_COMMIT_POPUP, ) } + pub fn commit_signoff( + key_config: &SharedKeyConfig, + ) -> CommandText { + CommandText::new( + format!( + "Sing-off [{}]", + key_config.get_hint(key_config.keys.toggle_signoff), + ), + "sign-off commit (-s option)", + CMD_GROUP_COMMIT_POPUP, + ) + } pub fn edit_item(key_config: &SharedKeyConfig) -> CommandText { CommandText::new( format!(