When migrating reflog entries between different storage formats we must reconstruct the identity of reflog entries. This is done by passing the committer passed to the `migrate_one_reflog_entry()` callback function to `fmt_ident()`. This results in an invalid identity though: `fmt_ident()` expects the caller to provide both name and mail of the author, but we pass the full identity as mail. This leads to an identity like: pks <Patrick Steinhardt ps@xxxxxx> Fix the bug by splitting the identity line first. This allows us to extract both the name and mail so that we can pass them to `fmt_ident()` separately. This commit does not yet add any tests as there is another bug in the reflog migration that will be fixed in a subsequent commit. Once that bug is fixed we'll make the reflog verification in t1450 stricter, and that will catch both this bug here and the other bug. Note that we also add two new `name` and `mail` string buffers to the callback structures and splice them through to the callbacks. This is done so that we can avoid allocating a new buffer every time we compute the committer information. Signed-off-by: Patrick Steinhardt <ps@xxxxxx> --- refs.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/refs.c b/refs.c index 8aa9f7236a..a5f9ffaa45 100644 --- a/refs.c +++ b/refs.c @@ -2954,7 +2954,7 @@ struct migration_data { struct ref_store *old_refs; struct ref_transaction *transaction; struct strbuf *errbuf; - struct strbuf sb; + struct strbuf sb, name, mail; }; static int migrate_one_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, @@ -2993,7 +2993,7 @@ struct reflog_migration_data { struct ref_store *old_refs; struct ref_transaction *transaction; struct strbuf *errbuf; - struct strbuf *sb; + struct strbuf *sb, *name, *mail; }; static int migrate_one_reflog_entry(struct object_id *old_oid, @@ -3003,13 +3003,21 @@ static int migrate_one_reflog_entry(struct object_id *old_oid, const char *msg, void *cb_data) { struct reflog_migration_data *data = cb_data; + struct ident_split ident; const char *date; int ret; + if (split_ident_line(&ident, committer, strlen(committer)) < 0) + return -1; + + strbuf_reset(data->name); + strbuf_add(data->name, ident.name_begin, ident.name_end - ident.name_begin); + strbuf_reset(data->mail); + strbuf_add(data->mail, ident.mail_begin, ident.mail_end - ident.mail_begin); + date = show_date(timestamp, tz, DATE_MODE(NORMAL)); strbuf_reset(data->sb); - /* committer contains name and email */ - strbuf_addstr(data->sb, fmt_ident("", committer, WANT_BLANK_IDENT, date, 0)); + strbuf_addstr(data->sb, fmt_ident(data->name->buf, data->mail->buf, WANT_BLANK_IDENT, date, 0)); ret = ref_transaction_update_reflog(data->transaction, data->refname, new_oid, old_oid, data->sb->buf, @@ -3026,6 +3034,8 @@ static int migrate_one_reflog(const char *refname, void *cb_data) .transaction = migration_data->transaction, .errbuf = migration_data->errbuf, .sb = &migration_data->sb, + .name = &migration_data->name, + .mail = &migration_data->mail, }; return refs_for_each_reflog_ent(migration_data->old_refs, refname, @@ -3124,6 +3134,8 @@ int repo_migrate_ref_storage_format(struct repository *repo, struct strbuf new_gitdir = STRBUF_INIT; struct migration_data data = { .sb = STRBUF_INIT, + .name = STRBUF_INIT, + .mail = STRBUF_INIT, }; int did_migrate_refs = 0; int ret; @@ -3299,6 +3311,8 @@ int repo_migrate_ref_storage_format(struct repository *repo, ref_transaction_free(transaction); strbuf_release(&new_gitdir); strbuf_release(&data.sb); + strbuf_release(&data.name); + strbuf_release(&data.mail); return ret; } -- 2.50.1.723.g3e08bea96f.dirty