From: Patrick Steinhardt Date: Wed, 3 Jun 2026 16:14:03 +0000 (+0200) Subject: reset: introduce dry-run mode X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=c39ed0f69fba50a1604cb62b368ab9ba37b4c216;p=thirdparty%2Fgit.git reset: introduce dry-run mode In a subsequent commit we'll add add another caller to `reset_head()` that wants to perform a dry-run check of whether it would be possible to udpate 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 Signed-off-by: Junio C Hamano --- diff --git a/reset.c b/reset.c index 9ff14f5ed1..a8d7eea4d6 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_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 97ced2601e..9f696382c1 100644 --- a/reset.h +++ b/reset.h @@ -21,6 +21,12 @@ enum reset_head_flags { /* Update ORIG_HEAD as well as HEAD */ RESET_HEAD_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 {