[PATCH v7 05/11] reset: introduce dry-run mode
From: Patrick Steinhardt <hidden>
Date: 2026-06-29 07:34:47
Subsystem:
the rest · Maintainer:
Linus Torvalds
In a subsequent commit we'll add another caller to `reset_working_tree()` 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 4ca7f23a25..99f2c1b012 100644
--- a/reset.c
+++ b/reset.c@@ -93,11 +93,14 @@ int reset_working_tree(struct repository *r, unsigned reset_hard = opts->flags & RESET_WORKING_TREE_HARD; unsigned refs_only = opts->flags & RESET_WORKING_TREE_REFS_ONLY; unsigned update_orig_head = opts->flags & RESET_WORKING_TREE_UPDATE_ORIG_HEAD; + unsigned dry_run = opts->flags & RESET_WORKING_TREE_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;
@@ -110,7 +113,7 @@ int reset_working_tree(struct repository *r, 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; }
@@ -125,16 +128,36 @@ int reset_working_tree(struct repository *r, 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;
@@ -142,11 +165,6 @@ int reset_working_tree(struct repository *r, 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));
@@ -163,6 +181,9 @@ int reset_working_tree(struct repository *r, 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));
@@ -182,6 +203,7 @@ int reset_working_tree(struct repository *r, 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 2e5826de99..898e4a1e95 100644
--- a/reset.h
+++ b/reset.h@@ -21,6 +21,12 @@ enum reset_working_tree_flags { /* Update ORIG_HEAD as well as HEAD */ RESET_WORKING_TREE_UPDATE_ORIG_HEAD = (1 << 4), + + /* + * Perform a dry-run by performing the operation without updating + * any user-visible state. + */ + RESET_WORKING_TREE_DRY_RUN = (1 << 5), }; struct reset_working_tree_options {
--
2.55.0.rc2.803.g1fd1e6609c.dirty