{"thread":{"id":"55352","subject":"[PATCH 0/3] [GSOC] commit: add own-identity option","startedAt":"2021-03-19T12:07:41Z","lastAt":"2021-03-19T12:07:42Z","messageCount":4,"participants":["ZheNing Hu via GitGitGadget"],"isPatch":true,"patchVersion":1,"patchTotal":3},"messages":[{"id":"419695","messageId":"pull.909.git.1616155599.gitgitgadget@gmail.com","threadId":"55352","inReplyTo":null,"subject":"[PATCH 0/3] [GSOC] commit: add own-identity option","fromName":"ZheNing Hu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2021-03-19T12:06:36Z","receivedAt":"2021-03-19T12:07:41Z","isPatch":true,"sender":{"key":"adlternative@gmail.com","avatar":"https://avatars.githubusercontent.com/u/58138461?v=4"},"body":"This patch series is the basis for commit --trailer in #901 and provides\n--own-identity option for --trailer.\n\nJunio's suggestion is that we can provide --trailer=\"@SomeOne\" in the later\nstages to support filling multiple identities which obtain from git log.\n\nZheNing Hu (3):\n  [GSOC] commit: add --trailer option\n  [GSOC] interpret-trailers: add own-identity option\n  [GSOC] commit: add own-identity option\n\n Documentation/git-commit.txt             |  24 ++\n Documentation/git-interpret-trailers.txt |  13 +\n builtin/commit.c                         |  30 ++\n builtin/interpret-trailers.c             |   6 +-\n t/t7501-commit-basic-functionality.sh    |  91 ++++++\n t/t7502-commit-porcelain.sh              | 355 +++++++++++++++++++++++\n t/t7513-interpret-trailers.sh            |  12 +\n trailer.c                                |  18 +-\n trailer.h                                |   3 +-\n 9 files changed, 547 insertions(+), 5 deletions(-)\n\n\nbase-commit: 13d7ab6b5d7929825b626f050b62a11241ea4945\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-909%2Fadlternative%2Ftrailer_own_identity_option-v1\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-909/adlternative/trailer_own_identity_option-v1\nPull-Request: https://github.com/gitgitgadget/git/pull/909\n-- \ngitgitgadget\n"},{"id":"419696","messageId":"0db1210ffd6d1888760b0f74345b67337ed195be.1616155599.git.gitgitgadget@gmail.com","threadId":"55352","inReplyTo":"pull.909.git.1616155599.gitgitgadget@gmail.com","subject":"[PATCH 1/3] [GSOC] commit: add --trailer option","fromName":"ZheNing Hu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2021-03-19T12:06:37Z","receivedAt":"2021-03-19T12:07:42Z","isPatch":true,"sender":{"key":"adlternative@gmail.com","avatar":"https://avatars.githubusercontent.com/u/58138461?v=4"},"body":"From: ZheNing Hu <adlternative@gmail.com>\n\nHistorically, Git has supported the 'Signed-off-by' commit trailer\nusing the '--signoff' and the '-s' option from the command line.\nBut users may need to provide other trailer information from the\ncommand line such as \"Helped-by\", \"Reported-by\", \"Mentored-by\",\n\nNow implement a new `--trailer <token>[(=|:)<value>]` option to pass\nother trailers to `interpret-trailers` and insert them into commit\nmessages.\n\nSigned-off-by: ZheNing Hu <adlternative@gmail.com>\n---\n Documentation/git-commit.txt |  11 +-\n builtin/commit.c             |  22 +++\n t/t7502-commit-porcelain.sh  | 335 +++++++++++++++++++++++++++++++++++\n 3 files changed, 367 insertions(+), 1 deletion(-)\n\ndiff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt\nindex 17150fa7eabe..2ba2fe0dd10e 100644\n--- a/Documentation/git-commit.txt\n+++ b/Documentation/git-commit.txt\n@@ -14,7 +14,8 @@ SYNOPSIS\n \t   [--allow-empty-message] [--no-verify] [-e] [--author=<author>]\n \t   [--date=<date>] [--cleanup=<mode>] [--[no-]status]\n \t   [-i | -o] [--pathspec-from-file=<file> [--pathspec-file-nul]]\n-\t   [-S[<keyid>]] [--] [<pathspec>...]\n+\t   [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n+\t   [--] [<pathspec>...]\n \n DESCRIPTION\n -----------\n@@ -166,6 +167,14 @@ The `-m` option is mutually exclusive with `-c`, `-C`, and `-F`.\n \n include::signoff-option.txt[]\n \n+--trailer <token>[(=|:)<value>]::\n+\tSpecify a (<token>, <value>) pair that should be applied as a\n+\ttrailer. (e.g. `git commit --trailer \"Signed-off-by:C O Mitter \\\n+\t<committer@example.com>\" --trailer \"Helped-by:C O Mitter \\\n+\t<committer@example.com>\"` will add the \"Signed-off-by\" trailer\n+\tand the \"Helped-by\" trailer in the commit message.)\n+\tUse `git -c trailer.* commit --trailer` to make the appropriate\n+\tconfiguration. See linkgit:git-interpret-trailers[1] for details.\n -n::\n --no-verify::\n \tThis option bypasses the pre-commit and commit-msg hooks.\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex 739110c5a7f6..4b06672bd07d 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -113,6 +113,7 @@ static int config_commit_verbose = -1; /* unspecified */\n static int no_post_rewrite, allow_empty_message, pathspec_file_nul;\n static char *untracked_files_arg, *force_date, *ignore_submodule_arg, *ignored_arg;\n static char *sign_commit, *pathspec_from_file;\n+static struct strvec trailer_args = STRVEC_INIT;\n \n /*\n  * The default commit message cleanup mode will remove the lines\n@@ -131,6 +132,14 @@ static struct strbuf message = STRBUF_INIT;\n \n static enum wt_status_format status_format = STATUS_FORMAT_UNSPECIFIED;\n \n+static int opt_pass_trailer(const struct option *opt, const char *arg, int unset)\n+{\n+\tBUG_ON_OPT_NEG(unset);\n+\n+\tstrvec_pushl(&trailer_args, \"--trailer\", arg, NULL);\n+\treturn 0;\n+}\n+\n static int opt_parse_porcelain(const struct option *opt, const char *arg, int unset)\n {\n \tenum wt_status_format *value = (enum wt_status_format *)opt->value;\n@@ -958,6 +967,18 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n \n \tfclose(s->fp);\n \n+\tif (trailer_args.nr) {\n+\t\tstruct child_process run_trailer = CHILD_PROCESS_INIT;\n+\n+\t\tstrvec_pushl(&run_trailer.args, \"interpret-trailers\",\n+\t\t\t     \"--in-place\", git_path_commit_editmsg(), NULL);\n+\t\tstrvec_pushv(&run_trailer.args, trailer_args.v);\n+\t\trun_trailer.git_cmd = 1;\n+\t\tif (run_command(&run_trailer))\n+\t\t\tdie(_(\"unable to pass trailers to --trailers\"));\n+\t\tstrvec_clear(&trailer_args);\n+\t}\n+\n \t/*\n \t * Reject an attempt to record a non-merge empty commit without\n \t * explicit --allow-empty. In the cherry-pick case, it may be\n@@ -1507,6 +1528,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)\n \t\tOPT_STRING(0, \"fixup\", &fixup_message, N_(\"commit\"), N_(\"use autosquash formatted message to fixup specified commit\")),\n \t\tOPT_STRING(0, \"squash\", &squash_message, N_(\"commit\"), N_(\"use autosquash formatted message to squash specified commit\")),\n \t\tOPT_BOOL(0, \"reset-author\", &renew_authorship, N_(\"the commit is authored by me now (used with -C/-c/--amend)\")),\n+\t\tOPT_CALLBACK_F(0, \"trailer\", NULL, N_(\"trailer\"), N_(\"add custom trailer(s)\"), PARSE_OPT_NONEG, opt_pass_trailer),\n \t\tOPT_BOOL('s', \"signoff\", &signoff, N_(\"add a Signed-off-by trailer\")),\n \t\tOPT_FILENAME('t', \"template\", &template_file, N_(\"use specified template file\")),\n \t\tOPT_BOOL('e', \"edit\", &edit_flag, N_(\"force edit of commit\")),\ndiff --git a/t/t7502-commit-porcelain.sh b/t/t7502-commit-porcelain.sh\nindex 6396897cc818..024cf3c81b18 100755\n--- a/t/t7502-commit-porcelain.sh\n+++ b/t/t7502-commit-porcelain.sh\n@@ -154,6 +154,341 @@ test_expect_success 'sign off' '\n \n '\n \n+test_expect_success 'commit --trailer without -c' '\n+\techo \"fun\" >>file &&\n+\tgit add file &&\n+\tcat >expected <<-\\EOF &&\n+\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tSigned-off-by: C1 E1\n+\tHelped-by: C2 E2\n+\tReported-by: C3 E3\n+\tMentored-by: C4 E4\n+\tEOF\n+\tgit commit -s --trailer \"Signed-off-by:C1 E1 \" \\\n+\t\t--trailer \"Helped-by:C2 E2 \" \\\n+\t\t--trailer \"Reported-by:C3 E3\" \\\n+\t\t--trailer \"Mentored-by:C4 E4\" \\\n+\t\t-m \"hello\" &&\n+\tgit cat-file commit HEAD >commit.msg &&\n+\tsed -e \"1,6d\" commit.msg >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'commit --trailer with -c and \"replace\" as ifexists' '\n+\techo \"fun\" >>file1 &&\n+\tgit add file1 &&\n+\tcat >expected <<-\\EOF &&\n+\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tSigned-off-by: C1 E1\n+\tReported-by: C3 E3\n+\tMentored-by: C4 E4\n+\tHelped-by: C3 E3\n+\tEOF\n+\tgit -c trailer.ifexists=\"replace\" \\\n+\t\tcommit --trailer \"Mentored-by: C4 E4\" \\\n+\t\t --trailer \"Helped-by: C3 E3\" \\\n+\t\t--amend &&\n+\tgit cat-file commit HEAD >commit.msg &&\n+\tsed -e \"1,6d\" commit.msg >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'commit --trailer with -c and \"add\" as ifexists' '\n+\techo \"fun\" >>file1 &&\n+\tgit add file1 &&\n+\tcat >expected <<-\\EOF &&\n+\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tSigned-off-by: C1 E1\n+\tReported-by: C3 E3\n+\tMentored-by: C4 E4\n+\tHelped-by: C3 E3\n+\tHelped-by: C3 E3\n+\tHelped-by: C3 E3\n+\tEOF\n+\tgit -c trailer.ifexists=\"add\" \\\n+\t\tcommit --trailer \"Helped-by: C3 E3\" \\\n+\t\t--trailer \"Helped-by: C3 E3\" \\\n+\t\t--amend &&\n+\tgit cat-file commit HEAD >commit.msg &&\n+\tsed -e \"1,6d\" commit.msg >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'commit --trailer with -c and \"donothing\" as ifexists' '\n+\techo \"fun\" >>file1 &&\n+\tgit add file1 &&\n+\tcat >expected <<-\\EOF &&\n+\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tSigned-off-by: C1 E1\n+\tReported-by: C3 E3\n+\tMentored-by: C4 E4\n+\tHelped-by: C3 E3\n+\tHelped-by: C3 E3\n+\tHelped-by: C3 E3\n+\tReviewed-by: C6 E6\n+\tEOF\n+\tgit -c trailer.ifexists=\"donothing\" \\\n+\t\tcommit --trailer \"Mentored-by: C5 E5\" \\\n+\t\t--trailer \"Reviewed-by: C6 E6\" \\\n+\t\t--amend &&\n+\tgit cat-file commit HEAD >commit.msg &&\n+\tsed -e \"1,6d\" commit.msg >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'commit --trailer with -c and \"addIfDifferent\" as ifexists' '\n+\techo \"fun\" >>file1 &&\n+\tgit add file1 &&\n+\tcat >expected <<-\\EOF &&\n+\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tSigned-off-by: C1 E1\n+\tReported-by: C3 E3\n+\tMentored-by: C4 E4\n+\tHelped-by: C3 E3\n+\tHelped-by: C3 E3\n+\tHelped-by: C3 E3\n+\tReviewed-by: C6 E6\n+\tReported-by: C5 E5\n+\tEOF\n+\tgit -c trailer.ifexists=\"addIfDifferent\" \\\n+\t\tcommit --trailer \"Reviewed-by: C6 E6\" \\\n+\t\t--trailer \"Reported-by: C5 E5\" \\\n+\t\t--amend &&\n+\tgit cat-file commit HEAD >commit.msg &&\n+\tsed -e \"1,6d\" commit.msg >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'commit --trailer with -c and \"addIfDifferentNeighbor\" as ifexists' '\n+\techo \"fun\" >>file1 &&\n+\tgit add file1 &&\n+\tcat >expected <<-\\EOF &&\n+\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tSigned-off-by: C1 E1\n+\tReported-by: C3 E3\n+\tMentored-by: C4 E4\n+\tHelped-by: C3 E3\n+\tHelped-by: C3 E3\n+\tHelped-by: C3 E3\n+\tReviewed-by: C6 E6\n+\tReported-by: C5 E5\n+\tEOF\n+\tgit -c trailer.ifexists=\"addIfDifferent\" \\\n+\t\tcommit --trailer \"Reported-by: C5 E5\" \\\n+\t\t--trailer \"Reviewed-by: C6 E6\" \\\n+\t\t--amend &&\n+\tgit cat-file commit HEAD >commit.msg &&\n+\tsed -e \"1,6d\" commit.msg >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'commit --trailer with -c and \"end\" as where' '\n+\techo \"fun\" >>file1 &&\n+\tgit add file1 &&\n+\tcat >expected <<-\\EOF &&\n+\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tSigned-off-by: C1 E1\n+\tReported-by: C3 E3\n+\tMentored-by: C4 E4\n+\tHelped-by: C3 E3\n+\tHelped-by: C3 E3\n+\tHelped-by: C3 E3\n+\tReviewed-by: C6 E6\n+\tReported-by: C5 E5\n+\tReported-by: C7 E7\n+\tEOF\n+\tgit -c trailer.where=\"end\" \\\n+\t\tcommit --trailer \"Reported-by: C5 E5\" \\\n+\t\t--trailer \"Reported-by: C7 E7\" \\\n+\t\t--amend &&\n+\tgit cat-file commit HEAD >commit.msg &&\n+\tsed -e \"1,6d\" commit.msg >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'commit --trailer with -c and \"start\" as where' '\n+\techo \"fun\" >>file1 &&\n+\tgit add file1 &&\n+\tcat >expected <<-\\EOF &&\n+\n+\tSigned-off-by: C8 E8\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tSigned-off-by: C1 E1\n+\tReported-by: C3 E3\n+\tMentored-by: C4 E4\n+\tHelped-by: C3 E3\n+\tHelped-by: C3 E3\n+\tHelped-by: C3 E3\n+\tReviewed-by: C6 E6\n+\tReported-by: C5 E5\n+\tReported-by: C7 E7\n+\tEOF\n+\tgit -c trailer.where=\"start\" \\\n+\t\tcommit --trailer \"Signed-off-by: C8 E8\" \\\n+\t\t--trailer \"Signed-off-by: C8 E8\" \\\n+\t\t--amend &&\n+\tgit cat-file commit HEAD >commit.msg &&\n+\tsed -e \"1,6d\" commit.msg >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'commit --trailer with -c and \"after\" as where' '\n+\techo \"fun\" >>file1 &&\n+\tgit add file1 &&\n+\tcat >expected <<-\\EOF &&\n+\n+\tSigned-off-by: C8 E8\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tSigned-off-by: C1 E1\n+\tReported-by: C3 E3\n+\tMentored-by: C4 E4\n+\tMentored-by: C9 E9\n+\tHelped-by: C3 E3\n+\tHelped-by: C3 E3\n+\tHelped-by: C3 E3\n+\tReviewed-by: C6 E6\n+\tReported-by: C5 E5\n+\tReported-by: C7 E7\n+\tReported-by: C10 E10\n+\tEOF\n+\tgit -c trailer.where=\"after\" \\\n+\t\tcommit --trailer \"Mentored-by: C9 E9\" \\\n+\t\t--trailer \"Reported-by: C10 E10\" \\\n+\t\t--amend &&\n+\tgit cat-file commit HEAD >commit.msg &&\n+\tsed -e \"1,6d\" commit.msg >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'commit --trailer with -c and \"before\" as where' '\n+\techo \"fun\" >>file1 &&\n+\tgit add file1 &&\n+\tcat >expected <<-\\EOF &&\n+\n+\tSigned-off-by: C8 E8\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tSigned-off-by: C1 E1\n+\tReported-by: C11 E11\n+\tReported-by: C3 E3\n+\tMentored-by: C4 E4\n+\tMentored-by: C9 E9\n+\tHelped-by: C12 E12\n+\tHelped-by: C3 E3\n+\tHelped-by: C3 E3\n+\tHelped-by: C3 E3\n+\tReviewed-by: C6 E6\n+\tReported-by: C5 E5\n+\tReported-by: C7 E7\n+\tReported-by: C10 E10\n+\tEOF\n+\tgit -c trailer.where=\"before\" \\\n+\t\tcommit --trailer \"Helped-by: C12 E12\" \\\n+\t\t--trailer \"Reported-by: C11 E11\" \\\n+\t\t--amend &&\n+\tgit cat-file commit HEAD >commit.msg &&\n+\tsed -e \"1,6d\" commit.msg >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'commit --trailer with -c and \"donothing\" as ifmissing' '\n+\techo \"fun\" >>file1 &&\n+\tgit add file1 &&\n+\tcat >expected <<-\\EOF &&\n+\n+\tSigned-off-by: C8 E8\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tSigned-off-by: C1 E1\n+\tReported-by: C11 E11\n+\tReported-by: C3 E3\n+\tMentored-by: C4 E4\n+\tMentored-by: C9 E9\n+\tHelped-by: C12 E12\n+\tHelped-by: C3 E3\n+\tHelped-by: C3 E3\n+\tHelped-by: C3 E3\n+\tReviewed-by: C6 E6\n+\tReported-by: C5 E5\n+\tReported-by: C7 E7\n+\tReported-by: C10 E10\n+\tHelped-by: C12 E12\n+\tEOF\n+\tgit -c trailer.ifmissing=\"donothing\" \\\n+\t\tcommit --trailer \"Helped-by: C12 E12\" \\\n+\t\t--trailer \"Based-by: C13 E13\" \\\n+\t\t--amend &&\n+\tgit cat-file commit HEAD >commit.msg &&\n+\tsed -e \"1,6d\" commit.msg >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'commit --trailer with -c and \"add\" as ifmissing' '\n+\techo \"fun\" >>file1 &&\n+\tgit add file1 &&\n+\tcat >expected <<-\\EOF &&\n+\n+\tSigned-off-by: C8 E8\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tSigned-off-by: C1 E1\n+\tReported-by: C11 E11\n+\tReported-by: C3 E3\n+\tMentored-by: C4 E4\n+\tMentored-by: C9 E9\n+\tHelped-by: C12 E12\n+\tHelped-by: C3 E3\n+\tHelped-by: C3 E3\n+\tHelped-by: C3 E3\n+\tReviewed-by: C6 E6\n+\tReported-by: C5 E5\n+\tReported-by: C7 E7\n+\tReported-by: C10 E10\n+\tHelped-by: C12 E12\n+\tBased-by: C13 E13\n+\tEOF\n+\tgit -c trailer.ifmissing=\"add\" \\\n+\t\tcommit --trailer \"Helped-by: C12 E12\" \\\n+\t\t--trailer \"Based-by: C13 E13\" \\\n+\t\t--amend &&\n+\tgit cat-file commit HEAD >commit.msg &&\n+\tsed -e \"1,6d\" commit.msg >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'commit --trailer with \"=\" ' '\n+\techo \"fun\" >>file1 &&\n+\tgit add file1 &&\n+\tcat >expected <<-\\EOF &&\n+\n+\t\tAcked-by: Peff\n+\tEOF\n+\tgit -c trailer.ack.key=\"Acked-by\" \\\n+\t\tcommit --trailer \"ack = Peff\" -m \"hello\" &&\n+\tgit cat-file commit HEAD >commit.msg &&\n+\tsed -e \"1,6d\" commit.msg >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'commit --trailer with -c and \":=#\" as separators' '\n+\techo \"fun\" >>file1 &&\n+\tgit add file1 &&\n+\tcat >expected <<-\\EOF &&\n+\n+\t\tBug #42\n+\tEOF\n+\tgit -c trailer.separators=\":=#\" \\\n+\t\t-c trailer.bug.key=\"Bug #\" \\\n+\t\tcommit --trailer \"bug = 42\" -m \"I hate bug\" &&\n+\tgit cat-file commit HEAD >commit.msg &&\n+\tsed -e \"1,6d\" commit.msg >actual &&\n+\ttest_cmp expected actual\n+'\n+\n test_expect_success 'multiple -m' '\n \n \t>negative &&\n-- \ngitgitgadget\n\n"},{"id":"419697","messageId":"4406b8dc1d90e7524d6b9133647785c58510c3cf.1616155599.git.gitgitgadget@gmail.com","threadId":"55352","inReplyTo":"pull.909.git.1616155599.gitgitgadget@gmail.com","subject":"[PATCH 2/3] [GSOC] interpret-trailers: add own-identity option","fromName":"ZheNing Hu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2021-03-19T12:06:38Z","receivedAt":"2021-03-19T12:07:42Z","isPatch":true,"sender":{"key":"adlternative@gmail.com","avatar":"https://avatars.githubusercontent.com/u/58138461?v=4"},"body":"From: ZheNing Hu <adlternative@gmail.com>\n\n`git commit --trailer=\"Signed-off-by: \\\n$(git config user.name) <$(git config user.email)>\"`\nis difficult for users to add their own identities,\nso teach interpret-trailers a new option `--own-identity`\nwhich allow if we're optionalise <value> in `--trailer`,\nby substitute user's identity if missing. This will help\nthe use of `commit --trailer` as easy as `commit --signoff`.\n\nSigned-off-by: ZheNing Hu <adlternative@gmail.com>\n---\n Documentation/git-interpret-trailers.txt | 13 +++++++++++++\n builtin/interpret-trailers.c             |  6 ++++--\n t/t7513-interpret-trailers.sh            | 12 ++++++++++++\n trailer.c                                | 18 ++++++++++++++++--\n trailer.h                                |  3 ++-\n 5 files changed, 47 insertions(+), 5 deletions(-)\n\ndiff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt\nindex 96ec6499f001..25f6732d9e6d 100644\n--- a/Documentation/git-interpret-trailers.txt\n+++ b/Documentation/git-interpret-trailers.txt\n@@ -84,6 +84,19 @@ OPTIONS\n \ttrailer to the input messages. See the description of this\n \tcommand.\n \n+--own-identity::\n+\tUsed with `--trailer`. Those trailers without value with the\n+\t`--own-identity` option all will add the user's own identity.\n+\tFor example,` git interpret-trailers --trailer \"A:B\" --trailer \\\n+\t\"Signed-off-by\" --trailer \"Helped-by\" --own-identity --inplace a.txt`\n+\twill output:\n+\t\"\n+\tA:B\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tHelped-by: C O Mitter <committer@example.com>\n+\t\"\n+\tin `a.txt`.\n+\n --where <placement>::\n --no-where::\n \tSpecify where all new trailers will be added.  A setting\ndiff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c\nindex 84748eafc01b..be7f502a58d7 100644\n--- a/builtin/interpret-trailers.c\n+++ b/builtin/interpret-trailers.c\n@@ -47,6 +47,7 @@ static void new_trailers_clear(struct list_head *trailers)\n \tlist_for_each_safe(pos, tmp, trailers) {\n \t\titem = list_entry(pos, struct new_trailer_item, list);\n \t\tlist_del(pos);\n+\t\tfree(item->text);\n \t\tfree(item);\n \t}\n }\n@@ -66,7 +67,7 @@ static int option_parse_trailer(const struct option *opt,\n \t\treturn -1;\n \n \titem = xmalloc(sizeof(*item));\n-\titem->text = arg;\n+\titem->text = xstrdup(arg);\n \titem->where = where;\n \titem->if_exists = if_exists;\n \titem->if_missing = if_missing;\n@@ -94,7 +95,8 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)\n \tstruct option options[] = {\n \t\tOPT_BOOL(0, \"in-place\", &opts.in_place, N_(\"edit files in place\")),\n \t\tOPT_BOOL(0, \"trim-empty\", &opts.trim_empty, N_(\"trim empty trailers\")),\n-\n+\t\tOPT_BOOL(0, \"own-identity\", &opts.own_identity,\n+\t\t\t     N_(\"specify the user's own identity for omitted trailers value\")),\n \t\tOPT_CALLBACK(0, \"where\", NULL, N_(\"action\"),\n \t\t\t     N_(\"where to place the new trailer\"), option_parse_where),\n \t\tOPT_CALLBACK(0, \"if-exists\", NULL, N_(\"action\"),\ndiff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh\nindex 6602790b5f4c..f82cee93bfb2 100755\n--- a/t/t7513-interpret-trailers.sh\n+++ b/t/t7513-interpret-trailers.sh\n@@ -63,6 +63,18 @@ test_expect_success 'without config' '\n \ttest_cmp expected actual\n '\n \n+test_expect_success 'without config with --own-identity' '\n+\tcat >expected <<-\\EOF &&\n+\n+\tAcked-by: A B <C>\n+\tHelped-by: C O Mitter <committer@example.com>\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tEOF\n+\tgit interpret-trailers --trailer \"Acked-by: A B <C>\" --trailer \"Helped-by\" \\\n+\t--trailer \"Signed-off-by\" --own-identity empty >actual &&\n+\ttest_cmp expected actual\n+'\n+\n test_expect_success 'without config in another order' '\n \tsed -e \"s/ Z\\$/ /\" >expected <<-\\EOF &&\n \ndiff --git a/trailer.c b/trailer.c\nindex 249ed618ed8e..cd4f85e71c9a 100644\n--- a/trailer.c\n+++ b/trailer.c\n@@ -690,8 +690,18 @@ static void add_arg_item(struct list_head *arg_head, char *tok, char *val,\n \tlist_add_tail(&new_item->list, arg_head);\n }\n \n+static void add_user_own_identity(struct new_trailer_item *item)\n+{\n+\tstruct strbuf buf = STRBUF_INIT;\n+\tstrbuf_addstr(&buf, item->text);\n+\tstrbuf_add(&buf, \"=\", 1);\n+\tstrbuf_addstr(&buf, fmt_name(WANT_COMMITTER_IDENT));\n+\tfree(item->text);\n+\titem->text = buf.buf;\n+}\n+\n static void process_command_line_args(struct list_head *arg_head,\n-\t\t\t\t      struct list_head *new_trailer_head)\n+\t\t\t\t      struct list_head *new_trailer_head, int own_identity)\n {\n \tstruct arg_item *item;\n \tstruct strbuf tok = STRBUF_INIT;\n@@ -728,6 +738,10 @@ static void process_command_line_args(struct list_head *arg_head,\n \t\t\terror(_(\"empty trailer token in trailer '%.*s'\"),\n \t\t\t      (int) sb.len, sb.buf);\n \t\t\tstrbuf_release(&sb);\n+\t\t} else if (separator_pos == -1 && own_identity) {\n+\t\t\t\tadd_user_own_identity(tr);\n+\t\t\t\tpos = pos->prev;\n+\t\t\t\tcontinue;\n \t\t} else {\n \t\t\tparse_trailer(&tok, &val, &conf, tr->text,\n \t\t\t\t      separator_pos);\n@@ -1048,7 +1062,7 @@ void process_trailers(const char *file,\n \n \tif (!opts->only_input) {\n \t\tLIST_HEAD(arg_head);\n-\t\tprocess_command_line_args(&arg_head, new_trailer_head);\n+\t\tprocess_command_line_args(&arg_head, new_trailer_head ,opts->own_identity);\n \t\tprocess_trailers_lists(&head, &arg_head);\n \t}\n \ndiff --git a/trailer.h b/trailer.h\nindex 795d2fccfd95..235dfdfa1978 100644\n--- a/trailer.h\n+++ b/trailer.h\n@@ -57,7 +57,7 @@ struct trailer_info {\n struct new_trailer_item {\n \tstruct list_head list;\n \n-\tconst char *text;\n+\tchar *text;\n \n \tenum trailer_where where;\n \tenum trailer_if_exists if_exists;\n@@ -73,6 +73,7 @@ struct process_trailer_options {\n \tint no_divider;\n \tint key_only;\n \tint value_only;\n+\tint own_identity;\n \tconst struct strbuf *separator;\n \tconst struct strbuf *key_value_separator;\n \tint (*filter)(const struct strbuf *, void *);\n-- \ngitgitgadget\n\n"},{"id":"419698","messageId":"a89f6d0717eed9ffadb58cbed15d8c2005c3d898.1616155599.git.gitgitgadget@gmail.com","threadId":"55352","inReplyTo":"pull.909.git.1616155599.gitgitgadget@gmail.com","subject":"[PATCH 3/3] [GSOC] commit: add own-identity option","fromName":"ZheNing Hu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2021-03-19T12:06:39Z","receivedAt":"2021-03-19T12:07:42Z","isPatch":true,"sender":{"key":"adlternative@gmail.com","avatar":"https://avatars.githubusercontent.com/u/58138461?v=4"},"body":"From: ZheNing Hu <adlternative@gmail.com>\n\nUse the newly added option `--own-identity` in\n`interpret-trailers`, implement new commit option\n`--own-identity` to allow user optionalise <value>\nin `--trailer`, by substitute user's identity if\nmissing. Using the `--own-identity` option, users\ncan directly use `--trailer=\"Signed-off-by\"` to\ngenerate a signoff trailer with their own identities\nin commit messages,\n\nThe effect is basically the same as the `--signoff`\noption. However, users can add more useful options at\nthe same time. e.g. `--trailer=\"Helped-by\" --own-identity`\ncan general `Helped-by: C O Mitter <committer@example.com>`,\nor through appropriate configuration:\n`git -c trailer.signoff.key=\"Signed-off-by\" commit \\\n--trailer=\"signoff\" --own-identity`\ncan also general their needs trailers with their favorite\nkeys and their own identities.\n\nSigned-off-by: ZheNing Hu <adlternative@gmail.com>\n---\n Documentation/git-commit.txt          | 19 +++++-\n builtin/commit.c                      |  8 +++\n t/t7501-commit-basic-functionality.sh | 91 +++++++++++++++++++++++++++\n t/t7502-commit-porcelain.sh           | 20 ++++++\n 4 files changed, 136 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt\nindex 2ba2fe0dd10e..69b3e694eb20 100644\n--- a/Documentation/git-commit.txt\n+++ b/Documentation/git-commit.txt\n@@ -14,8 +14,8 @@ SYNOPSIS\n \t   [--allow-empty-message] [--no-verify] [-e] [--author=<author>]\n \t   [--date=<date>] [--cleanup=<mode>] [--[no-]status]\n \t   [-i | -o] [--pathspec-from-file=<file> [--pathspec-file-nul]]\n-\t   [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n-\t   [--] [<pathspec>...]\n+\t   [(--trailer <token>[(=|:)<value>])... [--own-identity]]\n+\t   [-S[<keyid>]] [--] [<pathspec>...]\n \n DESCRIPTION\n -----------\n@@ -175,6 +175,21 @@ include::signoff-option.txt[]\n \tand the \"Helped-by\" trailer in the commit message.)\n \tUse `git -c trailer.* commit --trailer` to make the appropriate\n \tconfiguration. See linkgit:git-interpret-trailers[1] for details.\n+\n+--own-identity::\n+\tUsed with `--trailer`. Those trailers without value with the\n+\t`--own-identity` option all will add the user's own identity.\n+\tFor example, `git commit --trailer \\\n+\t\"A:B\" --trailer\t\"Signed-off-by\" --trailer \"Helped-by\" --own-identity`,\n+\twill output:\n+\t\"\n+\tA:B\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tHelped-by: C O Mitter <committer@example.com>\n+\t\"\n+\tin commit messages.\n+\tSee linkgit:git-interpret-trailers[1]for details.\n+\n -n::\n --no-verify::\n \tThis option bypasses the pre-commit and commit-msg hooks.\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex 4b06672bd07d..dc2fc0dc46ff 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -114,6 +114,7 @@ static int no_post_rewrite, allow_empty_message, pathspec_file_nul;\n static char *untracked_files_arg, *force_date, *ignore_submodule_arg, *ignored_arg;\n static char *sign_commit, *pathspec_from_file;\n static struct strvec trailer_args = STRVEC_INIT;\n+static int own_identity;\n \n /*\n  * The default commit message cleanup mode will remove the lines\n@@ -972,6 +973,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n \n \t\tstrvec_pushl(&run_trailer.args, \"interpret-trailers\",\n \t\t\t     \"--in-place\", git_path_commit_editmsg(), NULL);\n+\t\tif (own_identity)\n+\t\t\tstrvec_push(&run_trailer.args, \"--own-identity\");\n \t\tstrvec_pushv(&run_trailer.args, trailer_args.v);\n \t\trun_trailer.git_cmd = 1;\n \t\tif (run_command(&run_trailer))\n@@ -1529,6 +1532,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)\n \t\tOPT_STRING(0, \"squash\", &squash_message, N_(\"commit\"), N_(\"use autosquash formatted message to squash specified commit\")),\n \t\tOPT_BOOL(0, \"reset-author\", &renew_authorship, N_(\"the commit is authored by me now (used with -C/-c/--amend)\")),\n \t\tOPT_CALLBACK_F(0, \"trailer\", NULL, N_(\"trailer\"), N_(\"add custom trailer(s)\"), PARSE_OPT_NONEG, opt_pass_trailer),\n+\t\tOPT_BOOL(0, \"own-identity\", &own_identity,\n+\t\t\t     N_(\"specify the user's own identity for omitted trailers value\")),\n \t\tOPT_BOOL('s', \"signoff\", &signoff, N_(\"add a Signed-off-by trailer\")),\n \t\tOPT_FILENAME('t', \"template\", &template_file, N_(\"use specified template file\")),\n \t\tOPT_BOOL('e', \"edit\", &edit_flag, N_(\"force edit of commit\")),\n@@ -1605,6 +1610,9 @@ int cmd_commit(int argc, const char **argv, const char *prefix)\n \tif (verbose == -1)\n \t\tverbose = (config_commit_verbose < 0) ? 0 : config_commit_verbose;\n \n+\tif (own_identity && !trailer_args.nr)\n+\t\tdie(_(\"--own_identity requires --trailer\"));\n+\n \tif (dry_run)\n \t\treturn dry_run_commit(argv, prefix, current_head, &s);\n \tindex_file = prepare_index(argv, prefix, current_head, 0);\ndiff --git a/t/t7501-commit-basic-functionality.sh b/t/t7501-commit-basic-functionality.sh\nindex 512ae2781fe2..7ff74cf81e75 100755\n--- a/t/t7501-commit-basic-functionality.sh\n+++ b/t/t7501-commit-basic-functionality.sh\n@@ -423,6 +423,25 @@ test_expect_success 'sign off (1)' '\n \n '\n \n+test_expect_success '--trailer=\"signoff\" (1)' '\n+\n+\techo 1 >>positive &&\n+\tgit add positive &&\n+\tgit -c trailer.signoff.key=\"Signed-off-by\" \\\n+\t\tcommit --trailer=\"signoff\" --own-identity \\\n+\t\t-m \"thank you\" &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n+\t(\n+\t\techo thank you &&\n+\t\techo &&\n+\t\tgit var GIT_COMMITTER_IDENT >ident &&\n+\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\" ident\n+\t) >expected &&\n+\ttest_cmp expected actual\n+\n+'\n+\n test_expect_success 'sign off (2)' '\n \n \techo 2 >positive &&\n@@ -444,6 +463,30 @@ $existing\" &&\n \n '\n \n+test_expect_success '--trailer=\"signoff\" (2)' '\n+\n+\techo 2 >>positive &&\n+\tgit add positive &&\n+\texisting=\"Signed-off-by: Watch This <watchthis@example.com>\" &&\n+\tgit -c trailer.signoff.key=\"Signed-off-by\" \\\n+\t\tcommit --trailer=\"signoff\" --own-identity \\\n+\t\t-m \"thank you\n+\n+$existing\" &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n+\t(\n+\t\techo thank you &&\n+\t\techo &&\n+\t\techo $existing &&\n+\t\tgit var GIT_COMMITTER_IDENT >ident &&\n+\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\" ident\n+\t) >expected &&\n+\ttest_cmp expected actual\n+\n+'\n+\n+\n test_expect_success 'signoff gap' '\n \n \techo 3 >positive &&\n@@ -464,6 +507,29 @@ $alt\" &&\n \ttest_cmp expected actual\n '\n \n+test_expect_success '--trailer=\"signoff\" gap' '\n+\n+\techo 3 >>positive &&\n+\tgit add positive &&\n+\talt=\"Alt-RFC-822-Header: Value\" &&\n+\tgit -c trailer.signoff.key=\"Signed-off-by\" \\\n+\t\tcommit --trailer=\"signoff\" --own-identity \\\n+\t\t-m \"welcome\n+\n+$alt\" &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n+\t(\n+\t\techo welcome &&\n+\t\techo &&\n+\t\techo $alt &&\n+\t\tgit var GIT_COMMITTER_IDENT >ident &&\n+\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\" ident\n+\t) >expected &&\n+\ttest_cmp expected actual\n+'\n+\n+\n test_expect_success 'signoff gap 2' '\n \n \techo 4 >positive &&\n@@ -487,6 +553,31 @@ $alt\" &&\n \ttest_cmp expected actual\n '\n \n+test_expect_success '--trailer=\"signoff\" gap 2' '\n+\n+\techo 4 >>positive &&\n+\tgit add positive &&\n+\talt=\"fixed: 34\" &&\n+\tgit -c trailer.signoff.key=\"Signed-off-by\" \\\n+\t\tcommit --trailer=\"signoff\" --own-identity \\\n+\t\t-m \"welcome\n+\n+We have now\n+$alt\" &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n+\t(\n+\t\techo welcome &&\n+\t\techo &&\n+\t\techo We have now &&\n+\t\techo $alt &&\n+\t\techo &&\n+\t\tgit var GIT_COMMITTER_IDENT >ident &&\n+\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\" ident\n+\t) >expected &&\n+\ttest_cmp expected actual\n+'\n+\n test_expect_success 'signoff respects trailer config' '\n \n \techo 5 >positive &&\ndiff --git a/t/t7502-commit-porcelain.sh b/t/t7502-commit-porcelain.sh\nindex 024cf3c81b18..6c1387c943ff 100755\n--- a/t/t7502-commit-porcelain.sh\n+++ b/t/t7502-commit-porcelain.sh\n@@ -489,6 +489,26 @@ test_expect_success 'commit --trailer with -c and \":=#\" as separators' '\n \ttest_cmp expected actual\n '\n \n+test_expect_success 'commit --trailer with -c and --own-identity' '\n+\techo \"fun\" >>file1 &&\n+\tgit add file1 &&\n+\tcat >expected <<-\\EOF &&\n+\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tEOF\n+\tgit -c trailer.signoff.key=\"Signed-off-by: \" \\\n+\t\tcommit --trailer \"signoff\" --own-identity -m \"abc\" &&\n+\tgit cat-file commit HEAD >commit.msg &&\n+\tsed -e \"1,6d\" commit.msg >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'commit --own-identity without --trailer' '\n+\techo \"fun\" >>file1 &&\n+\tgit add file1 &&\n+\ttest_must_fail git -c commit --own-identity -m \"abc\"\n+'\n+\n test_expect_success 'multiple -m' '\n \n \t>negative &&\n-- \ngitgitgadget\n"}]}