From db2338388fda09b23a00f39094c60f6ba5d63461 Mon Sep 17 00:00:00 2001 From: Qihang Cai Date: Fri, 24 May 2024 15:26:45 +0800 Subject: [PATCH 1/4] fix: add `\n` before `message` in `Command/commit` not `object/commit` Signed-off-by: Qihang Cai --- libra/src/command/commit.rs | 5 +++-- libra/src/command/mod.rs | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/libra/src/command/commit.rs b/libra/src/command/commit.rs index 8caa16f98..faf46c34d 100644 --- a/libra/src/command/commit.rs +++ b/libra/src/command/commit.rs @@ -13,7 +13,7 @@ use mercury::internal::object::commit::Commit; use mercury::internal::object::tree::{Tree, TreeItem, TreeItemMode}; use mercury::internal::object::ObjectTrait; -use super::save_object; +use super::{format_commit_msg, save_object}; #[derive(Parser, Debug)] pub struct CommitArgs { @@ -38,7 +38,8 @@ pub async fn execute(args: CommitArgs) { /* Create & save commit objects */ let parents_commit_ids = get_parents_ids().await; - let commit = Commit::from_tree_id(tree.id, parents_commit_ids, args.message.as_str()); + // There must be a `blank line`(\n) before `message`, or remote unpack failed + let commit = Commit::from_tree_id(tree.id, parents_commit_ids, &format_commit_msg(&args.message, None)); // TODO default signature created in `from_tree_id`, wait `git config` to set correct user info diff --git a/libra/src/command/mod.rs b/libra/src/command/mod.rs index 2b3378dcc..d2d5bad3a 100644 --- a/libra/src/command/mod.rs +++ b/libra/src/command/mod.rs @@ -65,6 +65,21 @@ pub fn ask_basic_auth() -> BasicAuth { BasicAuth { username, password } } +/// Format commit message with GPG signature
+/// There must be a `blank line`(\n) before `message`, or remote unpack failed.
+/// If there is `GPG signature`, +/// `blank line` should be placed between `signature` and `message` +pub fn format_commit_msg(msg: &str, gpg_sig: Option<&str>) -> String { + match gpg_sig { + None => { + format!("\n{}", msg) + } + Some(gpg) => { + format!("{}\n\n{}", gpg, msg) + } + } +} + #[cfg(test)] mod test { use mercury::internal::object::commit::Commit; From 977e68fa8d12d608f930a6c0af99bed77a420207 Mon Sep 17 00:00:00 2001 From: Hou Xiaoxuan Date: Fri, 24 May 2024 16:37:39 +0800 Subject: [PATCH 2/4] log ignore gpg message Signed-off-by: Hou Xiaoxuan --- libra/src/command/log.rs | 5 ++++- libra/src/command/mod.rs | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/libra/src/command/log.rs b/libra/src/command/log.rs index cdc1c89df..264446495 100644 --- a/libra/src/command/log.rs +++ b/libra/src/command/log.rs @@ -15,6 +15,8 @@ use std::collections::VecDeque; use std::str::FromStr; use mercury::hash::SHA1; use mercury::internal::object::commit::Commit; + +use super::parse_commit_msg; #[derive(Parser, Debug)] pub struct LogArgs { /// Limit the number of output @@ -103,7 +105,8 @@ pub async fn execute(args: LogArgs) { message }; message.push_str(&format!("\nAuthor: {}", commit.author)); - message.push_str(&format!("\n{}\n", commit.message)); + let (msg, _) = parse_commit_msg(&commit.message); + message.push_str(&format!("\n{}\n", msg)); #[cfg(unix)] { diff --git a/libra/src/command/mod.rs b/libra/src/command/mod.rs index d2d5bad3a..fa7500a38 100644 --- a/libra/src/command/mod.rs +++ b/libra/src/command/mod.rs @@ -9,11 +9,11 @@ pub mod log; pub mod merge; pub mod pull; pub mod push; +pub mod remote; pub mod remove; pub mod restore; pub mod status; pub mod switch; -pub mod remote; use crate::internal::protocol::https_client::BasicAuth; use crate::utils::util; @@ -79,6 +79,23 @@ pub fn format_commit_msg(msg: &str, gpg_sig: Option<&str>) -> String { } } } +/// parse commit message +pub fn parse_commit_msg(msg_gpg: &str) -> (String, Option) { + let parse_pos = msg_gpg.find("\n\n").unwrap_or(msg_gpg.len()); + if parse_pos < msg_gpg.len() { + let gpg_sig = msg_gpg[..parse_pos].trim().to_string(); + // TODO: support ssh signature + if gpg_sig.starts_with("gpgsig -----BEGIN PGP SIGNATURE-----") + && gpg_sig.ends_with("-----END PGP SIGNATURE-----") + { + (msg_gpg[parse_pos + 2..].to_string(), Some(gpg_sig)) + } else { + (msg_gpg[1..].to_string(), None) + } + } else { + (msg_gpg[1..].to_string(), None) + } +} #[cfg(test)] mod test { @@ -93,4 +110,19 @@ mod test { save_object(&object, &object.id).unwrap(); let _ = load_object::(&object.id).unwrap(); } + + #[test] + fn test_format_and_parse_commit_msg() { + let msg = "commit message"; + let gpg_sig = "gpgsig -----BEGIN PGP SIGNATURE-----\ncontent\n-----END PGP SIGNATURE-----"; + let msg_gpg = format_commit_msg(msg, Some(gpg_sig)); + let (msg_, gpg_sig_) = parse_commit_msg(&msg_gpg); + assert_eq!(msg, msg_); + assert_eq!(gpg_sig, gpg_sig_.unwrap()); + + let msg_gpg = format_commit_msg(msg, None); + let (msg_, gpg_sig_) = parse_commit_msg(&msg_gpg); + assert_eq!(msg, msg_); + assert_eq!(None, gpg_sig_); + } } From 087c2f1c93516b6bcf826e4acd3ffb4445c6fc96 Mon Sep 17 00:00:00 2001 From: Hou Xiaoxuan Date: Fri, 24 May 2024 16:50:39 +0800 Subject: [PATCH 3/4] optimize `parse_commit_msg` Signed-off-by: Hou Xiaoxuan --- libra/src/command/mod.rs | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/libra/src/command/mod.rs b/libra/src/command/mod.rs index fa7500a38..5b323bb78 100644 --- a/libra/src/command/mod.rs +++ b/libra/src/command/mod.rs @@ -81,19 +81,24 @@ pub fn format_commit_msg(msg: &str, gpg_sig: Option<&str>) -> String { } /// parse commit message pub fn parse_commit_msg(msg_gpg: &str) -> (String, Option) { - let parse_pos = msg_gpg.find("\n\n").unwrap_or(msg_gpg.len()); - if parse_pos < msg_gpg.len() { - let gpg_sig = msg_gpg[..parse_pos].trim().to_string(); - // TODO: support ssh signature - if gpg_sig.starts_with("gpgsig -----BEGIN PGP SIGNATURE-----") - && gpg_sig.ends_with("-----END PGP SIGNATURE-----") - { - (msg_gpg[parse_pos + 2..].to_string(), Some(gpg_sig)) - } else { + let parse_pos = msg_gpg.find("\n\n"); + match parse_pos { + // if parse_pos < msg_gpg.len() { + Some(parse_pos) => { + let gpg_sig = msg_gpg[..parse_pos].trim().to_string(); + // TODO: support ssh signature + if gpg_sig.starts_with("gpgsig -----BEGIN PGP SIGNATURE-----") + && gpg_sig.ends_with("-----END PGP SIGNATURE-----") + { + (msg_gpg[parse_pos + 2..].to_string(), Some(gpg_sig)) + } else { + (msg_gpg[1..].to_string(), None) + } + } + None => { + assert!(msg_gpg.starts_with('\n'), "commit message format error"); (msg_gpg[1..].to_string(), None) } - } else { - (msg_gpg[1..].to_string(), None) } } From 7eba0ab7984a14cb138ba03b1450d16312fea0ba Mon Sep 17 00:00:00 2001 From: Qihang Cai Date: Fri, 24 May 2024 17:31:48 +0800 Subject: [PATCH 4/4] optimize `parse_commit_msg` logic Signed-off-by: Qihang Cai --- libra/src/command/mod.rs | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/libra/src/command/mod.rs b/libra/src/command/mod.rs index 5b323bb78..9116810e1 100644 --- a/libra/src/command/mod.rs +++ b/libra/src/command/mod.rs @@ -81,23 +81,32 @@ pub fn format_commit_msg(msg: &str, gpg_sig: Option<&str>) -> String { } /// parse commit message pub fn parse_commit_msg(msg_gpg: &str) -> (String, Option) { - let parse_pos = msg_gpg.find("\n\n"); - match parse_pos { - // if parse_pos < msg_gpg.len() { - Some(parse_pos) => { - let gpg_sig = msg_gpg[..parse_pos].trim().to_string(); - // TODO: support ssh signature - if gpg_sig.starts_with("gpgsig -----BEGIN PGP SIGNATURE-----") - && gpg_sig.ends_with("-----END PGP SIGNATURE-----") - { - (msg_gpg[parse_pos + 2..].to_string(), Some(gpg_sig)) + const GPG_SIG_START: &str = "gpgsig -----BEGIN PGP SIGNATURE-----"; + const GPG_SIG_END: &str = "-----END PGP SIGNATURE-----"; + let gpg_start = msg_gpg.find(GPG_SIG_START); + let gpg_end = msg_gpg.find(GPG_SIG_END).map(|end| end + GPG_SIG_END.len()); + let gpg_sig = match (gpg_start, gpg_end) { + (Some(start), Some(end)) => { + if start < end { + Some(msg_gpg[start..end].to_string()) } else { - (msg_gpg[1..].to_string(), None) + None } } + _ => None, + }; + match gpg_sig { + Some(gpg) => { + // skip the leading '\n\n' (blank line) + let msg = msg_gpg[gpg_end.unwrap()..].to_string(); + assert!(msg.starts_with("\n\n"), "commit message format error"); + let msg = msg[2..].to_string(); + (msg, Some(gpg)) + } None => { assert!(msg_gpg.starts_with('\n'), "commit message format error"); - (msg_gpg[1..].to_string(), None) + let msg = msg_gpg[1..].to_string(); // skip the leading '\n' (blank line) + (msg, None) } } }