wt-status: read HEAD and ORIG_HEAD via the refdb

We read both the HEAD and ORIG_HEAD references directly from the filesystem in order to figure out whether we're currently splitting a commit. If both of the following are true: - HEAD points to the same object as "rebase-merge/amend". - ORIG_HEAD points to the same object as "rebase-merge/orig-head". Then we are currently splitting commits. The current code only works by chance because we only have a single reference backend implementation. Refactor it to instead read both refs via the refdb layer so that we'll also be compatible with alternate reference backends. There are some subtleties involved here: - We pass `RESOLVE_REF_READING` so that a missing ref will cause `read_ref_full()` to return an error. - We pass `RESOLVE_REF_NO_RECURSE` so that we do not try to resolve symrefs. The old code didn't resolve symrefs either, and we only ever write object IDs into the refs in "rebase-merge/". - In the same spirit we verify that successfully-read refs are not symbolic refs. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Dec 14, 2023 at 14:36 UTC 8f61321ccbdea20945a73446f24a6c380cb2c53b
1 file changed +14 -8
wt-status.c
+14 -8
@@ -1295,26 +1295,32 @@ static char *read_line_from_git_path(const char *filename)
1295 static int split_commit_in_progress(struct wt_status *s)
1296 {
1297 int split_in_progress = 0;
1298 - char *head, *orig_head, *rebase_amend, *rebase_orig_head;
1298 + struct object_id head_oid, orig_head_oid;
1299 + char *rebase_amend, *rebase_orig_head;
1300 + int head_flags, orig_head_flags;
1301
1302 if ((!s->amend && !s->nowarn && !s->workdir_dirty) ||
1303 !s->branch || strcmp(s->branch, "HEAD"))
1304 return 0;
1305
1304 - head = read_line_from_git_path("HEAD");
1305 - orig_head = read_line_from_git_path("ORIG_HEAD");
1306 + if (read_ref_full("HEAD", RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
1307 + &head_oid, &head_flags) ||
1308 + read_ref_full("ORIG_HEAD", RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
1309 + &orig_head_oid, &orig_head_flags))
1310 + return 0;
1311 + if (head_flags & REF_ISSYMREF || orig_head_flags & REF_ISSYMREF)
1312 + return 0;
1313 +
1314 rebase_amend = read_line_from_git_path("rebase-merge/amend");
1315 rebase_orig_head = read_line_from_git_path("rebase-merge/orig-head");
1316
1309 - if (!head || !orig_head || !rebase_amend || !rebase_orig_head)
1317 + if (!rebase_amend || !rebase_orig_head)
1318 ; /* fall through, no split in progress */
1319 else if (!strcmp(rebase_amend, rebase_orig_head))
1312 - split_in_progress = !!strcmp(head, rebase_amend);
1313 - else if (strcmp(orig_head, rebase_orig_head))
1320 + split_in_progress = !!strcmp(oid_to_hex(&head_oid), rebase_amend);
1321 + else if (strcmp(oid_to_hex(&orig_head_oid), rebase_orig_head))
1322 split_in_progress = 1;
1323
1316 - free(head);
1317 - free(orig_head);
1324 free(rebase_amend);
1325 free(rebase_orig_head);
1326