diff --git a/aria/contents/docs/libra/command/commit/index.mdx b/aria/contents/docs/libra/command/commit/index.mdx index 0b993dd7d..f48154049 100644 --- a/aria/contents/docs/libra/command/commit/index.mdx +++ b/aria/contents/docs/libra/command/commit/index.mdx @@ -25,6 +25,7 @@ If the `--allow-empty` option is not given, the commit will be aborted if the in - `--conventional` Check if the commit message is conventional format, if not, the commit will be aborted. - `-h`, `--help` Print help +- `-s`,`--signoff` Add sign-off-by trailer by the committer at the end of the commit message. The commit message should align with Git’s behavior as closely as possible, excpet the `--conventional` option, which is not supported in Git. Refs https://git-scm.com/docs/git-commit for more information. diff --git a/libra/src/command/commit.rs b/libra/src/command/commit.rs index d4934fa61..35e5b4981 100644 --- a/libra/src/command/commit.rs +++ b/libra/src/command/commit.rs @@ -3,6 +3,7 @@ use std::{collections::HashSet, path::PathBuf}; use crate::command::load_object; use crate::internal::branch::Branch; +use crate::internal::config::Config as UserConfig; use crate::internal::head::Head; use crate::utils::client_storage::ClientStorage; use crate::utils::path; @@ -17,7 +18,7 @@ use mercury::internal::object::ObjectTrait; use super::save_object; -#[derive(Parser, Debug)] +#[derive(Parser, Debug, Default)] pub struct CommitArgs { #[arg(short, long)] pub message: String, @@ -33,6 +34,10 @@ pub struct CommitArgs { /// amend the last commit #[arg(long)] pub amend: bool, + + /// add signed-off-by line at the end of the commit message + #[arg(short = 's', long)] + pub signoff: bool, } pub async fn execute(args: CommitArgs) { @@ -43,7 +48,26 @@ pub async fn execute(args: CommitArgs) { if tracked_entries.is_empty() && !args.allow_empty { panic!("fatal: no changes added to commit, use --allow-empty to override"); } - if args.conventional && !check_conventional_commits_message(&args.message) { + + //Prepare commit message + let commit_message = if args.signoff { + // get user + let user_name = UserConfig::get("user", None, "name") + .await + .unwrap_or_else(|| "unknown".to_string()); + let user_email = UserConfig::get("user", None, "email") + .await + .unwrap_or_else(|| "unknown".to_string()); + + // get sign line + let signoff_line = format!("Signed-off-by: {user_name} <{user_email}>"); + format!("{}\n\n{signoff_line}", args.message) + } else { + args.message.clone() + }; + + // check format(if needed) + if args.conventional && !check_conventional_commits_message(&commit_message) { panic!("fatal: commit message does not follow conventional commits"); } @@ -208,6 +232,7 @@ mod test { use crate::utils::test::*; use super::*; + #[test] ///Testing basic parameter parsing functionality. fn test_parse_args() { @@ -231,10 +256,25 @@ mod test { let args = CommitArgs::try_parse_from(["commit", "-m", "init", "--allow-empty", "--amend"]); assert!(args.is_ok()); + + let args = CommitArgs::try_parse_from(["commit", "-m", "init", "-s"]); + assert!(args.is_ok()); + assert!(args.unwrap().signoff); + + let args = CommitArgs::try_parse_from(["commit", "-m", "init", "--signoff"]); + assert!(args.is_ok()); + assert!(args.unwrap().signoff); + + let args = CommitArgs::try_parse_from(["commit", "-m", "init", "--amend", "--signoff"]); + assert!(args.is_ok()); + let args = args.unwrap(); + assert!(args.amend); + assert!(args.signoff); + } #[tokio::test] - #[serial] + #[serial] /// Tests the recursive tree creation from index entries. /// Verifies that tree objects are correctly created, saved to storage, and properly organized in a hierarchical structure. async fn test_create_tree() { diff --git a/libra/tests/command/branch_test.rs b/libra/tests/command/branch_test.rs index 69f85c013..bff55ac10 100644 --- a/libra/tests/command/branch_test.rs +++ b/libra/tests/command/branch_test.rs @@ -16,6 +16,7 @@ async fn test_branch() { allow_empty: true, conventional: false, amend: false, + signoff: false, }; commit::execute(commit_args).await; let first_commit_id = Branch::find_branch("master", None).await.unwrap().commit; @@ -25,6 +26,7 @@ async fn test_branch() { allow_empty: true, conventional: false, amend: false, + signoff: false, }; commit::execute(commit_args).await; let second_commit_id = Branch::find_branch("master", None).await.unwrap().commit; @@ -109,6 +111,7 @@ async fn test_create_branch_from_remote() { allow_empty: true, conventional: false, amend: false, + signoff: false, }; commit::execute(args).await; let hash = Head::current_commit().await.unwrap(); @@ -146,6 +149,7 @@ async fn test_invalid_branch_name() { allow_empty: true, conventional: false, amend: false, + signoff: false, }; commit::execute(args).await; diff --git a/libra/tests/command/checkout_test.rs b/libra/tests/command/checkout_test.rs index 61160ce5d..a1a5a918d 100644 --- a/libra/tests/command/checkout_test.rs +++ b/libra/tests/command/checkout_test.rs @@ -76,6 +76,7 @@ async fn test_checkout_module_functions() { allow_empty: true, conventional: false, amend: false, + signoff: false, }; commit::execute(commit_args).await; diff --git a/libra/tests/command/commit_test.rs b/libra/tests/command/commit_test.rs index b65e6d6e3..9ad795042 100644 --- a/libra/tests/command/commit_test.rs +++ b/libra/tests/command/commit_test.rs @@ -18,6 +18,7 @@ async fn test_execute_commit_with_empty_index_fail() { allow_empty: false, conventional: false, amend: false, + signoff: false, }; commit::execute(args).await; } @@ -39,6 +40,7 @@ async fn test_execute_commit() { allow_empty: true, conventional: false, amend: false, + signoff: false, }; commit::execute(args).await; @@ -63,6 +65,7 @@ async fn test_execute_commit() { allow_empty: true, conventional: false, amend: true, + signoff: false, }; commit::execute(args).await; @@ -103,6 +106,7 @@ async fn test_execute_commit() { allow_empty: false, conventional: false, amend: false, + signoff: false, }; commit::execute(args).await; @@ -130,6 +134,7 @@ async fn test_execute_commit() { allow_empty: true, conventional: false, amend: true, + signoff: false, }; commit::execute(args).await; diff --git a/libra/tests/command/switch_test.rs b/libra/tests/command/switch_test.rs index 26b868dd2..55c0bb696 100644 --- a/libra/tests/command/switch_test.rs +++ b/libra/tests/command/switch_test.rs @@ -41,6 +41,7 @@ async fn test_switch_function() { allow_empty: true, conventional: false, amend: false, + signoff: false, }; commit::execute(args).await; } @@ -82,6 +83,7 @@ async fn test_switch_function() { allow_empty: true, conventional: false, amend: false, + signoff: false, }; commit::execute(args).await; @@ -157,6 +159,7 @@ async fn test_detach_head_basic() { allow_empty: true, conventional: false, amend: false, + signoff: false, }; commit::execute(args).await; } @@ -195,6 +198,7 @@ async fn test_detach_head_basic() { allow_empty: true, conventional: false, amend: false, + signoff: false, }; commit::execute(args).await; }