[PATCH v3 4/9] reset: introduce dry-run mode
From: Patrick Steinhardt <hidden>
Date: 2026-06-08 10:23:42
Subsystem:
the rest · Maintainer:
Linus Torvalds
In a subsequent commit we'll add another caller to `reset_head()` that wants to perform a dry-run check of whether it would be possible to update the index and working tree when moving to a new commit. Introduce a new flag that lets the caller perform this operation. Signed-off-by: Patrick Steinhardt <redacted> --- reset.c | 44 +++++++++++++++++++++++++++++++++----------- reset.h | 6 ++++++ 2 files changed, 39 insertions(+), 11 deletions(-)
diff --git a/reset.c b/reset.c
index 228cad5f42..8fb39d4c51 100644
--- a/reset.c
+++ b/reset.c@@ -92,11 +92,14 @@ int reset_head(struct repository *r, const struct reset_head_opts *opts) unsigned reset_hard = opts->flags & RESET_HEAD_HARD; unsigned refs_only = opts->flags & RESET_HEAD_REFS_ONLY; unsigned update_orig_head = opts->flags & RESET_HEAD_UPDATE_ORIG_HEAD; + unsigned dry_run = opts->flags & RESET_HEAD_DRY_RUN; struct object_id *head = NULL, head_oid; struct tree_desc desc[2] = { { NULL }, { NULL } }; struct lock_file lock = LOCK_INIT; struct unpack_trees_options unpack_tree_opts = { 0 }; struct tree *tree; + struct index_state scratch_index = INDEX_STATE_INIT(r); + struct index_state *istate; const char *action; int ret = 0, nr = 0;
@@ -109,7 +112,7 @@ int reset_head(struct repository *r, const struct reset_head_opts *opts) if (opts->branch_msg && !opts->branch) BUG("branch reflog message given without a branch"); - if (!refs_only && repo_hold_locked_index(r, &lock, LOCK_REPORT_ON_ERROR) < 0) { + if (!refs_only && !dry_run && repo_hold_locked_index(r, &lock, LOCK_REPORT_ON_ERROR) < 0) { ret = -1; goto leave_reset_head; }
@@ -124,16 +127,36 @@ int reset_head(struct repository *r, const struct reset_head_opts *opts) if (!oid) oid = &head_oid; - if (refs_only) - return update_refs(r, opts, oid, head); + if (refs_only) { + if (!dry_run) + return update_refs(r, opts, oid, head); + return 0; + } + + if (dry_run) { + if (read_index_from(&scratch_index, r->index_file, r->gitdir) < 0 || + index_state_unmerged_to_stage0(&scratch_index) < 0) { + ret = error(_("could not read index")); + goto leave_reset_head; + } + + istate = &scratch_index; + } else { + if (repo_read_index_unmerged(r) < 0) { + ret = error(_("could not read index")); + goto leave_reset_head; + } + istate = r->index; + } action = reset_hard ? "reset" : "checkout"; setup_unpack_trees_porcelain(&unpack_tree_opts, action); unpack_tree_opts.head_idx = 1; - unpack_tree_opts.src_index = r->index; - unpack_tree_opts.dst_index = r->index; + unpack_tree_opts.src_index = istate; + unpack_tree_opts.dst_index = istate; unpack_tree_opts.fn = reset_hard ? oneway_merge : twoway_merge; - unpack_tree_opts.update = 1; + unpack_tree_opts.update = !dry_run; + unpack_tree_opts.dry_run = dry_run; unpack_tree_opts.merge = 1; unpack_tree_opts.preserve_ignored = 0; /* FIXME: !overwrite_ignore */ unpack_tree_opts.skip_cache_tree_update = 1;
@@ -141,11 +164,6 @@ int reset_head(struct repository *r, const struct reset_head_opts *opts) if (reset_hard) unpack_tree_opts.reset = UNPACK_RESET_PROTECT_UNTRACKED; - if (repo_read_index_unmerged(r) < 0) { - ret = error(_("could not read index")); - goto leave_reset_head; - } - if (!reset_hard && !fill_tree_descriptor(r, &desc[nr++], &head_oid)) { ret = error(_("failed to find tree of %s"), oid_to_hex(&head_oid));
@@ -162,6 +180,9 @@ int reset_head(struct repository *r, const struct reset_head_opts *opts) goto leave_reset_head; } + if (dry_run) + goto leave_reset_head; + tree = repo_parse_tree_indirect(r, oid); if (!tree) { ret = error(_("unable to read tree (%s)"), oid_to_hex(oid));
@@ -181,6 +202,7 @@ int reset_head(struct repository *r, const struct reset_head_opts *opts) leave_reset_head: rollback_lock_file(&lock); clear_unpack_trees_porcelain(&unpack_tree_opts); + release_index(&scratch_index); while (nr) free((void *)desc[--nr].buffer); return ret;
diff --git a/reset.h b/reset.h
index 0bf25c51de..cc9fd4378a 100644
--- a/reset.h
+++ b/reset.h@@ -21,6 +21,12 @@ enum reset_head_flags { /* Update ORIG_HEAD as well as HEAD */ RESET_HEAD_UPDATE_ORIG_HEAD = (1 << 4), + + /* + * Perform a dry-run by performing the operation without updating + * any user-visible state. + */ + RESET_HEAD_DRY_RUN = (1 << 5), }; struct reset_head_opts {
--
2.54.0.1136.gdb2ca164c4.dirty