refs/reftable: perform explicit D/F check when writing symrefs
We already perform explicit D/F checks in all reftable callbacks which write refs, except when writing symrefs. For one this leads to an error message which isn't perfectly actionable because we only tell the user that there was a D/F conflict, but not which refs conflicted with each other. But second, once all ref updating callbacks explicitly check for D/F conflicts, we can disable the D/F checks in the reftable library itself and thus avoid some duplicated efforts. Refactor the code that writes symref tables to explicitly call into `refs_verify_refname_available()` when writing symrefs. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Patrick Steinhardt committed
Apr 8, 2024 at 14:23 UTC
455d61b6d22b41176194483f82c9caa531661bec
2 files changed
+18
-4
refs/reftable-backend.c
+17
-3
@@ -1217,6 +1217,7 @@ out:
1217
struct write_create_symref_arg {
1218
struct reftable_ref_store *refs;
1219
struct reftable_stack *stack;
1220
+ struct strbuf *err;
1221
const char *refname;
1222
const char *target;
1223
const char *logmsg;
@@ -1239,6 +1240,11 @@ static int write_create_symref_table(struct reftable_writer *writer, void *cb_da
1240
1241
reftable_writer_set_limits(writer, ts, ts);
1242
1243
+ ret = refs_verify_refname_available(&create->refs->base, create->refname,
1244
+ NULL, NULL, create->err);
1245
+ if (ret < 0)
1246
+ return ret;
1247
+
1248
ret = reftable_writer_add_ref(writer, &ref);
1249
if (ret)
1250
return ret;
@@ -1280,12 +1286,14 @@ static int reftable_be_create_symref(struct ref_store *ref_store,
1286
struct reftable_ref_store *refs =
1287
reftable_be_downcast(ref_store, REF_STORE_WRITE, "create_symref");
1288
struct reftable_stack *stack = stack_for(refs, refname, &refname);
1289
+ struct strbuf err = STRBUF_INIT;
1290
struct write_create_symref_arg arg = {
1291
.refs = refs,
1292
.stack = stack,
1293
.refname = refname,
1294
.target = target,
1295
.logmsg = logmsg,
1296
+ .err = &err,
1297
};
1298
int ret;
1299
@@ -1301,9 +1309,15 @@ static int reftable_be_create_symref(struct ref_store *ref_store,
1309
1310
done:
1311
assert(ret != REFTABLE_API_ERROR);
1304
- if (ret)
1305
- error("unable to write symref for %s: %s", refname,
1306
- reftable_error_str(ret));
1312
+ if (ret) {
1313
+ if (err.len)
1314
+ error("%s", err.buf);
1315
+ else
1316
+ error("unable to write symref for %s: %s", refname,
1317
+ reftable_error_str(ret));
1318
+ }
1319
+
1320
+ strbuf_release(&err);
1321
return ret;
1322
}
1323
t/t0610-reftable-basics.sh
+1
-1
@@ -255,7 +255,7 @@ test_expect_success 'ref transaction: creating symbolic ref fails with F/D confl
255
git init repo &&
256
test_commit -C repo A &&
257
cat >expect <<-EOF &&
258
- error: unable to write symref for refs/heads: file/directory conflict
258
+ error: ${SQ}refs/heads/main${SQ} exists; cannot create ${SQ}refs/heads${SQ}
259
EOF
260
test_must_fail git -C repo symbolic-ref refs/heads refs/heads/foo 2>err &&
261
test_cmp expect err