diff --git a/refs.c b/refs.c index 662a9e6f9e..0648df2b6c 100644 --- a/refs.c +++ b/refs.c @@ -1307,6 +1307,7 @@ struct ref_update *ref_transaction_add_update( const char *refname, unsigned int flags, const struct object_id *new_oid, const struct object_id *old_oid, + const struct object_id *peeled, const char *new_target, const char *old_target, const char *committer_info, const char *msg) @@ -1339,6 +1340,8 @@ struct ref_update *ref_transaction_add_update( update->committer_info = xstrdup_or_null(committer_info); update->msg = normalize_reflog_message(msg); } + if (flags & REF_HAVE_PEELED) + oidcpy(&update->peeled, peeled); /* * This list is generally used by the backends to avoid duplicates. @@ -1392,6 +1395,8 @@ enum ref_transaction_error ref_transaction_update(struct ref_transaction *transa unsigned int flags, const char *msg, struct strbuf *err) { + struct object_id peeled; + assert(err); if ((flags & REF_FORCE_CREATE_REFLOG) && @@ -1432,10 +1437,16 @@ enum ref_transaction_error ref_transaction_update(struct ref_transaction *transa oid_to_hex(new_oid), refname); return REF_TRANSACTION_ERROR_INVALID_NEW_VALUE; } + + if (o->type == OBJ_TAG) { + if (!peel_object(transaction->ref_store->repo, new_oid, &peeled, + PEEL_OBJECT_VERIFY_TAGGED_OBJECT_TYPE)) + flags |= REF_HAVE_PEELED; + } } ref_transaction_add_update(transaction, refname, flags, - new_oid, old_oid, new_target, + new_oid, old_oid, &peeled, new_target, old_target, NULL, msg); return 0; @@ -1462,7 +1473,7 @@ int ref_transaction_update_reflog(struct ref_transaction *transaction, return -1; update = ref_transaction_add_update(transaction, refname, flags, - new_oid, old_oid, NULL, NULL, + new_oid, old_oid, NULL, NULL, NULL, committer_info, msg); update->index = index; diff --git a/refs/files-backend.c b/refs/files-backend.c index f20f580fbc..d0896d0e37 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -1325,7 +1325,8 @@ static void prune_ref(struct files_ref_store *refs, struct ref_to_prune *r) ref_transaction_add_update( transaction, r->name, REF_NO_DEREF | REF_HAVE_NEW | REF_HAVE_OLD | REF_IS_PRUNING, - null_oid(the_hash_algo), &r->oid, NULL, NULL, NULL, NULL); + null_oid(the_hash_algo), &r->oid, NULL, NULL, NULL, + NULL, NULL); if (ref_transaction_commit(transaction, &err)) goto cleanup; @@ -2468,7 +2469,7 @@ static enum ref_transaction_error split_head_update(struct ref_update *update, new_update = ref_transaction_add_update( transaction, "HEAD", update->flags | REF_LOG_ONLY | REF_NO_DEREF | REF_LOG_VIA_SPLIT, - &update->new_oid, &update->old_oid, + &update->new_oid, &update->old_oid, &update->peeled, NULL, NULL, update->committer_info, update->msg); new_update->parent_update = update; @@ -2530,8 +2531,8 @@ static enum ref_transaction_error split_symref_update(struct ref_update *update, transaction, referent, new_flags, update->new_target ? NULL : &update->new_oid, update->old_target ? NULL : &update->old_oid, - update->new_target, update->old_target, NULL, - update->msg); + &update->peeled, update->new_target, update->old_target, + NULL, update->msg); new_update->parent_update = update; @@ -2994,7 +2995,7 @@ static int files_transaction_prepare(struct ref_store *ref_store, ref_transaction_add_update( packed_transaction, update->refname, REF_HAVE_NEW | REF_NO_DEREF, - &update->new_oid, NULL, + &update->new_oid, NULL, NULL, NULL, NULL, NULL, NULL); } } @@ -3200,19 +3201,22 @@ static int files_transaction_finish_initial(struct files_ref_store *refs, if (update->flags & REF_LOG_ONLY) ref_transaction_add_update(loose_transaction, update->refname, update->flags, &update->new_oid, - &update->old_oid, NULL, NULL, + &update->old_oid, &update->peeled, + NULL, NULL, update->committer_info, update->msg); else ref_transaction_add_update(loose_transaction, update->refname, update->flags & ~REF_HAVE_OLD, update->new_target ? NULL : &update->new_oid, NULL, - update->new_target, NULL, update->committer_info, + &update->peeled, update->new_target, + NULL, update->committer_info, NULL); } else { ref_transaction_add_update(packed_transaction, update->refname, update->flags & ~REF_HAVE_OLD, &update->new_oid, &update->old_oid, - NULL, NULL, update->committer_info, NULL); + &update->peeled, NULL, NULL, + update->committer_info, NULL); } } diff --git a/refs/refs-internal.h b/refs/refs-internal.h index d103387ebf..307dcb277b 100644 --- a/refs/refs-internal.h +++ b/refs/refs-internal.h @@ -39,6 +39,13 @@ struct ref_transaction; */ #define REF_LOG_ONLY (1 << 7) +/* + * The reference contains a peeled object ID. This is used when the + * new_oid is pointing to a tag object and the reference backend + * wants to also store the peeled value for optimized retrieval. + */ +#define REF_HAVE_PEELED (1 << 15) + /* * Return the length of time to retry acquiring a loose reference lock * before giving up, in milliseconds: @@ -92,6 +99,12 @@ struct ref_update { */ struct object_id old_oid; + /* + * If the new_oid points to a tag object, set this to the peeled + * object ID for optimized retrieval without needed to hit the odb. + */ + struct object_id peeled; + /* * If set, point the reference to this value. This can also be * used to convert regular references to become symbolic refs. @@ -169,6 +182,7 @@ struct ref_update *ref_transaction_add_update( const char *refname, unsigned int flags, const struct object_id *new_oid, const struct object_id *old_oid, + const struct object_id *peeled, const char *new_target, const char *old_target, const char *committer_info, const char *msg); diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c index 444b0c24e5..b0c010387d 100644 --- a/refs/reftable-backend.c +++ b/refs/reftable-backend.c @@ -1107,8 +1107,8 @@ static enum ref_transaction_error prepare_single_update(struct reftable_ref_stor ref_transaction_add_update( transaction, "HEAD", u->flags | REF_LOG_ONLY | REF_NO_DEREF, - &u->new_oid, &u->old_oid, NULL, NULL, NULL, - u->msg); + &u->new_oid, &u->old_oid, &u->peeled, NULL, NULL, + NULL, u->msg); } ret = reftable_backend_read_ref(be, rewritten_ref, @@ -1194,7 +1194,7 @@ static enum ref_transaction_error prepare_single_update(struct reftable_ref_stor transaction, referent->buf, new_flags, u->new_target ? NULL : &u->new_oid, u->old_target ? NULL : &u->old_oid, - u->new_target, u->old_target, + &u->peeled, u->new_target, u->old_target, u->committer_info, u->msg); new_update->parent_update = u;