assert(err);
- flags = REF_HAVE_OLD | REF_HAVE_NEW | REF_LOG_ONLY | REF_FORCE_CREATE_REFLOG | REF_NO_DEREF;
+ flags = REF_HAVE_OLD | REF_HAVE_NEW | REF_LOG_ONLY | REF_FORCE_CREATE_REFLOG | REF_NO_DEREF |
+ REF_LOG_USE_PROVIDED_OIDS;
if (!transaction_refname_valid(refname, new_oid, flags, err))
return -1;
*/
#define REF_SKIP_CREATE_REFLOG (1 << 12)
+/*
+ * When writing a REF_LOG_ONLY record, use the old and new object IDs provided
+ * in the update instead of resolving the old object ID. The caller must also
+ * set both REF_HAVE_OLD and REF_HAVE_NEW.
+ */
+#define REF_LOG_USE_PROVIDED_OIDS (1 << 13)
+
/*
* Bitmask of all of the flags that are allowed to be passed in to
* ref_transaction_update() and friends:
*/
#define REF_TRANSACTION_UPDATE_ALLOWED_FLAGS \
(REF_NO_DEREF | REF_FORCE_CREATE_REFLOG | REF_SKIP_OID_VERIFICATION | \
- REF_SKIP_REFNAME_VERIFICATION | REF_SKIP_CREATE_REFLOG)
+ REF_SKIP_REFNAME_VERIFICATION | REF_SKIP_CREATE_REFLOG | REF_LOG_USE_PROVIDED_OIDS)
/*
* Add a reference update to transaction. `new_oid` is the value that
struct ref_lock *lock,
struct strbuf *err)
{
+ struct object_id *old_oid = &lock->old_oid;
+
+ if (update->flags & REF_LOG_USE_PROVIDED_OIDS) {
+ if (!(update->flags & REF_HAVE_OLD) ||
+ !(update->flags & REF_HAVE_NEW) ||
+ !(update->flags & REF_LOG_ONLY)) {
+ strbuf_addf(err, _("trying to write reflog for '%s'"
+ "with incomplete values"), update->refname);
+ return REF_TRANSACTION_ERROR_GENERIC;
+ }
+
+ old_oid = &update->old_oid;
+ }
+
if (update->new_target) {
/*
* We want to get the resolved OID for the target, to ensure
}
}
- if (files_log_ref_write(refs, lock->ref_name, &lock->old_oid,
+ if (files_log_ref_write(refs, lock->ref_name, old_oid,
&update->new_oid, update->committer_info,
update->msg, update->flags, err)) {
char *old_msg = strbuf_detach(err, NULL);
if (ret)
return REF_TRANSACTION_ERROR_GENERIC;
+ if (u->flags & REF_LOG_USE_PROVIDED_OIDS) {
+ if (!(u->flags & REF_HAVE_OLD) ||
+ !(u->flags & REF_HAVE_NEW) ||
+ !(u->flags & REF_LOG_ONLY)) {
+ strbuf_addf(err, _("trying to write reflog for '%s'"
+ "with incomplete values"), u->refname);
+ return REF_TRANSACTION_ERROR_GENERIC;
+ }
+
+ if (queue_transaction_update(refs, tx_data, u, &u->old_oid, err))
+ return REF_TRANSACTION_ERROR_GENERIC;
+ return 0;
+ }
+
/* Verify that the new object ID is valid. */
if ((u->flags & REF_HAVE_NEW) && !is_null_oid(&u->new_oid) &&
!(u->flags & REF_SKIP_OID_VERIFICATION) &&
EOF
git reflog write refs/heads/something $COMMIT_OID $COMMIT_OID second &&
- # Note: the old object ID of the second reflog entry is broken.
- # This will be fixed in subsequent commits.
test_reflog_matches . refs/heads/something <<-EOF
$ZERO_OID $COMMIT_OID $SIGNATURE first
- $ZERO_OID $COMMIT_OID $SIGNATURE second
+ $COMMIT_OID $COMMIT_OID $SIGNATURE second
EOF
)
'
. ./test-lib.sh
+print_all_reflog_entries () {
+ repo=$1 &&
+ test-tool -C "$repo" ref-store main for-each-reflog >reflogs &&
+ while read reflog
+ do
+ echo "REFLOG: $reflog" &&
+ test-tool -C "$repo" ref-store main for-each-reflog-ent "$reflog" ||
+ return 1
+ done <reflogs
+}
+
# Migrate the provided repository from one format to the other and
# verify that the references and logs are migrated over correctly.
# Usage: test_migration <repo> <format> [<skip_reflog_verify> [<options...>]]
--format='%(refname) %(objectname) %(symref)' >expect &&
if ! $skip_reflog_verify
then
- git -C "$repo" reflog --all >expect_logs &&
- git -C "$repo" reflog list >expect_log_list
+ print_all_reflog_entries "$repo" >expect_logs
fi &&
git -C "$repo" refs migrate --ref-format="$format" "$@" &&
test_cmp expect actual &&
if ! $skip_reflog_verify
then
- git -C "$repo" reflog --all >actual_logs &&
- git -C "$repo" reflog list >actual_log_list &&
- test_cmp expect_logs actual_logs &&
- test_cmp expect_log_list actual_log_list
+ print_all_reflog_entries "$repo" >actual_logs &&
+ test_cmp expect_logs actual_logs
fi &&
git -C "$repo" rev-parse --show-ref-format >actual &&
test_commit -C repo second &&
printf "update refs/heads/ref-%d HEAD\n" $(test_seq 3000) >stdin &&
git -C repo update-ref --stdin <stdin &&
- test_migration repo reftable
+ test_migration repo reftable true
'
test_expect_success 'migrating from files format deletes backend files' '