Skip to content

[RFC] rebase -m: partial support for copying extra commit headers #1902

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
25 changes: 18 additions & 7 deletions sequencer.c
Original file line number Diff line number Diff line change
Expand Up @@ -1527,6 +1527,9 @@ static int parse_head(struct repository *r, struct commit **head)
return 0;
}

/* Headers to exclude when copying extra commit headers */
static const char *exclude_gpgsig[] = { "gpgsig", "gpgsig-sha256", NULL };

/*
* Try to commit without forking 'git commit'. In some cases we need
* to run 'git commit' to display an error message
Expand All @@ -1538,14 +1541,15 @@ static int parse_head(struct repository *r, struct commit **head)
*/
static int try_to_commit(struct repository *r,
struct strbuf *msg, const char *author,
struct commit_extra_header *extra_header,
struct replay_opts *opts, unsigned int flags,
struct object_id *oid)
{
struct replay_ctx *ctx = opts->ctx;
struct object_id tree;
struct commit *current_head = NULL;
struct commit_list *parents = NULL;
struct commit_extra_header *extra = NULL;
struct commit_extra_header *extra = extra_header;
struct strbuf err = STRBUF_INIT;
struct strbuf commit_msg = STRBUF_INIT;
char *amend_author = NULL;
Expand All @@ -1561,7 +1565,6 @@ static int try_to_commit(struct repository *r,
return -1;

if (flags & AMEND_MSG) {
const char *exclude_gpgsig[] = { "gpgsig", "gpgsig-sha256", NULL };
const char *out_enc = get_commit_output_encoding();
const char *message = repo_logmsg_reencode(r, current_head,
NULL, out_enc);
Expand Down Expand Up @@ -1714,7 +1717,8 @@ static int try_to_commit(struct repository *r,
commit_post_rewrite(r, current_head, oid);

out:
free_commit_extra_headers(extra);
if (extra != extra_header)
free_commit_extra_headers(extra);
free_commit_list(parents);
strbuf_release(&err);
strbuf_release(&commit_msg);
Expand All @@ -1734,6 +1738,7 @@ static int write_rebase_head(struct object_id *oid)

static int do_commit(struct repository *r,
const char *msg_file, const char *author,
struct commit_extra_header *extra_header,
struct replay_opts *opts, unsigned int flags,
struct object_id *oid)
{
Expand All @@ -1749,7 +1754,7 @@ static int do_commit(struct repository *r,
msg_file);

res = try_to_commit(r, msg_file ? &sb : NULL,
author, opts, flags, &oid);
author, extra_header, opts, flags, &oid);
strbuf_release(&sb);
if (!res) {
refs_delete_ref(get_main_ref_store(r), "",
Expand Down Expand Up @@ -2251,6 +2256,7 @@ static int do_pick_commit(struct repository *r,
int res, unborn = 0, reword = 0, allow, drop_commit;
enum todo_command command = item->command;
struct commit *commit = item->commit;
struct commit_extra_header *extra_header = NULL;

if (opts->no_commit) {
/*
Expand Down Expand Up @@ -2391,8 +2397,12 @@ static int do_pick_commit(struct repository *r,
strbuf_addstr(&ctx->message, oid_to_hex(&commit->object.oid));
strbuf_addstr(&ctx->message, ")\n");
}
if (!is_fixup(command))
if (!is_fixup(command)) {
author = get_author(msg.message);
if (is_rebase_i(opts))
extra_header = read_commit_extra_headers(commit,
exclude_gpgsig);
}
}
ctx->have_message = 1;

Expand Down Expand Up @@ -2503,8 +2513,8 @@ static int do_pick_commit(struct repository *r,
} /* else allow == 0 and there's nothing special to do */
if (!opts->no_commit && !drop_commit) {
if (author || command == TODO_REVERT || (flags & AMEND_MSG))
res = do_commit(r, msg_file, author, opts, flags,
commit? &commit->object.oid : NULL);
res = do_commit(r, msg_file, author, extra_header, opts,
flags, commit? &commit->object.oid : NULL);
else
res = error(_("unable to parse commit author"));
*check_todo = !!(flags & EDIT_MSG);
Expand Down Expand Up @@ -2535,6 +2545,7 @@ static int do_pick_commit(struct repository *r,
leave:
free_message(commit, &msg);
free(author);
free_commit_extra_headers(extra_header);
update_abort_safety_file();

return res;
Expand Down
48 changes: 48 additions & 0 deletions t/t3404-rebase-interactive.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2297,6 +2297,54 @@ test_expect_success 'non-merge commands reject merge commits' '
test_cmp expect actual
'

test_expect_success 'unconflicted pick copies extra commit headers' '
tree="$(git rev-parse C^{tree})" &&
parent="$(git rev-parse C^{commit})" &&
for i in 1 2 3 4 5 6 7
do
cat >commit <<-EOF &&
tree $tree
parent $parent
author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> $GIT_AUTHOR_DATE
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
x-extra-header value $i

An empty commit with an extra header $i
EOF

parent="$(git hash-object -t commit -w commit)" &&
eval "oid$i=\$parent" &&
test_tick || return 1
done &&

cat >todo <<-EOF &&
pick $oid1
pick $oid2
fixup $oid3
reword $oid4
edit $oid5
pick $oid6
squash $oid7
EOF

(
set_replace_editor todo &&
FAKE_COMMIT_AMEND=EDITED git rebase -i --onto A $oid1^ $oid5
) &&
echo changed >file2 &&
git add file2 &&
FAKE_COMMIT_AMEND=EDITED git rebase --continue &&
j=4 &&
for i in 1 2 4 5 6
do
git cat-file commit HEAD~$j >actual &&
sed -n -e /^\$/q -e /^x-extra/p actual >actual.extra-header &&
echo "x-extra-header value $i" >expect &&
test_cmp expect actual.extra-header &&
j=$((j-1)) || return 1
done
'

# This must be the last test in this file
test_expect_success '$EDITOR and friends are unchanged' '
test_editor_unchanged
Expand Down
Loading