Skip to content

Commit bb7d88f

Browse files
pks-tgitster
authored andcommitted
builtin/history: split handling of ref updates into two phases
The function `handle_reference_updates()` is used by git-history(1) to update all references that refer to commits that have been rewritten. As such, it performs two steps: - It gathers the references that need to be updated in the first place. - It prepares and commits the reference transaction. In a subsequent commit we'll want to handle those two steps separately. Prepare for this by splitting up the function into two. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 262a216 commit bb7d88f

1 file changed

Lines changed: 64 additions & 38 deletions

File tree

builtin/history.c

Lines changed: 64 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -333,21 +333,17 @@ static int handle_ref_update(struct ref_transaction *transaction,
333333
NULL, NULL, 0, reflog_msg, err);
334334
}
335335

336-
static int handle_reference_updates(struct rev_info *revs,
337-
enum ref_action action,
338-
struct commit *original,
339-
struct commit *rewritten,
340-
const char *reflog_msg,
341-
int dry_run,
342-
enum replay_empty_commit_action empty)
336+
static int compute_pending_ref_updates(struct rev_info *revs,
337+
enum ref_action action,
338+
struct commit *original,
339+
struct commit *rewritten,
340+
enum replay_empty_commit_action empty,
341+
struct replay_result *result)
343342
{
344343
const struct name_decoration *decoration;
345344
struct replay_revisions_options opts = {
346345
.empty = empty,
347346
};
348-
struct replay_result result = { 0 };
349-
struct ref_transaction *transaction = NULL;
350-
struct strbuf err = STRBUF_INIT;
351347
char hex[GIT_MAX_HEXSZ + 1];
352348
bool detached_head;
353349
int head_flags = 0;
@@ -359,34 +355,13 @@ static int handle_reference_updates(struct rev_info *revs,
359355

360356
opts.onto = oid_to_hex_r(hex, &rewritten->object.oid);
361357

362-
ret = replay_revisions(revs, &opts, &result);
358+
ret = replay_revisions(revs, &opts, result);
363359
if (ret)
364-
goto out;
360+
return ret;
365361

366362
if (action != REF_ACTION_BRANCHES && action != REF_ACTION_HEAD)
367363
BUG("unsupported ref action %d", action);
368364

369-
if (!dry_run) {
370-
transaction = ref_store_transaction_begin(get_main_ref_store(revs->repo), 0, &err);
371-
if (!transaction) {
372-
ret = error(_("failed to begin ref transaction: %s"), err.buf);
373-
goto out;
374-
}
375-
}
376-
377-
for (size_t i = 0; i < result.updates_nr; i++) {
378-
ret = handle_ref_update(transaction,
379-
result.updates[i].refname,
380-
&result.updates[i].new_oid,
381-
&result.updates[i].old_oid,
382-
reflog_msg, &err);
383-
if (ret) {
384-
ret = error(_("failed to update ref '%s': %s"),
385-
result.updates[i].refname, err.buf);
386-
goto out;
387-
}
388-
}
389-
390365
/*
391366
* `replay_revisions()` only updates references that are
392367
* ancestors of `rewritten`, so we need to manually
@@ -414,14 +389,43 @@ static int handle_reference_updates(struct rev_info *revs,
414389
!detached_head)
415390
continue;
416391

392+
ALLOC_GROW(result->updates, result->updates_nr + 1, result->updates_alloc);
393+
result->updates[result->updates_nr].refname = xstrdup(decoration->name);
394+
result->updates[result->updates_nr].old_oid = original->object.oid;
395+
result->updates[result->updates_nr].new_oid = rewritten->object.oid;
396+
result->updates_nr++;
397+
}
398+
399+
return 0;
400+
}
401+
402+
static int apply_pending_ref_updates(struct repository *repo,
403+
const struct replay_result *result,
404+
const char *reflog_msg,
405+
int dry_run)
406+
{
407+
struct ref_transaction *transaction = NULL;
408+
struct strbuf err = STRBUF_INIT;
409+
int ret;
410+
411+
if (!dry_run) {
412+
transaction = ref_store_transaction_begin(get_main_ref_store(repo),
413+
0, &err);
414+
if (!transaction) {
415+
ret = error(_("failed to begin ref transaction: %s"), err.buf);
416+
goto out;
417+
}
418+
}
419+
420+
for (size_t i = 0; i < result->updates_nr; i++) {
417421
ret = handle_ref_update(transaction,
418-
decoration->name,
419-
&rewritten->object.oid,
420-
&original->object.oid,
422+
result->updates[i].refname,
423+
&result->updates[i].new_oid,
424+
&result->updates[i].old_oid,
421425
reflog_msg, &err);
422426
if (ret) {
423427
ret = error(_("failed to update ref '%s': %s"),
424-
decoration->name, err.buf);
428+
result->updates[i].refname, err.buf);
425429
goto out;
426430
}
427431
}
@@ -435,11 +439,33 @@ static int handle_reference_updates(struct rev_info *revs,
435439

436440
out:
437441
ref_transaction_free(transaction);
438-
replay_result_release(&result);
439442
strbuf_release(&err);
440443
return ret;
441444
}
442445

446+
static int handle_reference_updates(struct rev_info *revs,
447+
enum ref_action action,
448+
struct commit *original,
449+
struct commit *rewritten,
450+
const char *reflog_msg,
451+
int dry_run,
452+
enum replay_empty_commit_action empty)
453+
{
454+
struct replay_result result = { 0 };
455+
int ret;
456+
457+
ret = compute_pending_ref_updates(revs, action, original, rewritten,
458+
empty, &result);
459+
if (ret)
460+
goto out;
461+
462+
ret = apply_pending_ref_updates(revs->repo, &result, reflog_msg, dry_run);
463+
464+
out:
465+
replay_result_release(&result);
466+
return ret;
467+
}
468+
443469
static int commit_became_empty(struct repository *repo,
444470
struct commit *original,
445471
struct tree *result)

0 commit comments

Comments
 (0)