Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions libra/src/command/commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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

Expand Down
5 changes: 4 additions & 1 deletion libra/src/command/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)]
{
Expand Down
63 changes: 62 additions & 1 deletion libra/src/command/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -65,6 +65,52 @@ pub fn ask_basic_auth() -> BasicAuth {
BasicAuth { username, password }
}

/// Format commit message with GPG signature<br>
/// There must be a `blank line`(\n) before `message`, or remote unpack failed.<br>
/// 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)
}
}
}
/// parse commit message
pub fn parse_commit_msg(msg_gpg: &str) -> (String, Option<String>) {
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 {
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");
let msg = msg_gpg[1..].to_string(); // skip the leading '\n' (blank line)
(msg, None)
}
}
}

#[cfg(test)]
mod test {
use mercury::internal::object::commit::Commit;
Expand All @@ -78,4 +124,19 @@ mod test {
save_object(&object, &object.id).unwrap();
let _ = load_object::<Commit>(&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_);
}
}