reset_head(): take struct rebase_head_opts
This function takes a confusingly large number of parameters which makes it difficult to remember which order to pass them in. The following commits will add a couple more parameters which makes the problem worse. To address this change the function to take a struct of options. Using a struct means that it is no longer necessary to remember which order to pass the parameters in and anyone reading the code can easily see which value is passed to each parameter. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Phillip Wood committed
Jan 26, 2022 at 13:05 UTC
6ae8086161d81a707ff36dfdc07f57e4f473e0fd
4 files changed
+92
-48
builtin/rebase.c
+36
-21
@@ -571,6 +571,7 @@ static int finish_rebase(struct rebase_options *opts)
571
static int move_to_original_branch(struct rebase_options *opts)
572
{
573
struct strbuf orig_head_reflog = STRBUF_INIT, head_reflog = STRBUF_INIT;
574
+ struct reset_head_opts ropts = { 0 };
575
int ret;
576
577
if (!opts->head_name)
@@ -583,9 +584,11 @@ static int move_to_original_branch(struct rebase_options *opts)
584
opts->head_name, oid_to_hex(&opts->onto->object.oid));
585
strbuf_addf(&head_reflog, "rebase finished: returning to %s",
586
opts->head_name);
586
- ret = reset_head(the_repository, NULL, opts->head_name,
587
- RESET_HEAD_REFS_ONLY,
588
- orig_head_reflog.buf, head_reflog.buf, NULL);
587
+ ropts.branch = opts->head_name;
588
+ ropts.flags = RESET_HEAD_REFS_ONLY;
589
+ ropts.orig_head_msg = orig_head_reflog.buf;
590
+ ropts.head_msg = head_reflog.buf;
591
+ ret = reset_head(the_repository, &ropts);
592
593
strbuf_release(&orig_head_reflog);
594
strbuf_release(&head_reflog);
@@ -669,13 +672,15 @@ static int run_am(struct rebase_options *opts)
672
673
status = run_command(&format_patch);
674
if (status) {
675
+ struct reset_head_opts ropts = { 0 };
676
unlink(rebased_patches);
677
free(rebased_patches);
678
strvec_clear(&am.args);
679
676
- reset_head(the_repository, &opts->orig_head,
677
- opts->head_name, 0,
678
- NULL, NULL, DEFAULT_REFLOG_ACTION);
680
+ ropts.oid = &opts->orig_head;
681
+ ropts.branch = opts->head_name;
682
+ ropts.default_reflog_action = DEFAULT_REFLOG_ACTION;
683
+ reset_head(the_repository, &ropts);
684
error(_("\ngit encountered an error while preparing the "
685
"patches to replay\n"
686
"these revisions:\n"
@@ -814,14 +819,17 @@ static int rebase_config(const char *var, const char *value, void *data)
819
static int checkout_up_to_date(struct rebase_options *options)
820
{
821
struct strbuf buf = STRBUF_INIT;
822
+ struct reset_head_opts ropts = { 0 };
823
int ret = 0;
824
825
strbuf_addf(&buf, "%s: checkout %s",
826
getenv(GIT_REFLOG_ACTION_ENVIRONMENT),
827
options->switch_to);
822
- if (reset_head(the_repository, &options->orig_head,
823
- options->head_name, RESET_HEAD_RUN_POST_CHECKOUT_HOOK,
824
- NULL, buf.buf, NULL) < 0)
828
+ ropts.oid = &options->orig_head;
829
+ ropts.branch = options->head_name;
830
+ ropts.flags = RESET_HEAD_RUN_POST_CHECKOUT_HOOK;
831
+ ropts.head_msg = buf.buf;
832
+ if (reset_head(the_repository, &ropts) < 0)
833
ret = error(_("could not switch to %s"), options->switch_to);
834
strbuf_release(&buf);
835
@@ -1033,6 +1041,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
1041
int reschedule_failed_exec = -1;
1042
int allow_preemptive_ff = 1;
1043
int preserve_merges_selected = 0;
1044
+ struct reset_head_opts ropts = { 0 };
1045
struct option builtin_rebase_options[] = {
1046
OPT_STRING(0, "onto", &options.onto_name,
1047
N_("revision"),
@@ -1270,9 +1279,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
1279
1280
rerere_clear(the_repository, &merge_rr);
1281
string_list_clear(&merge_rr, 1);
1273
-
1274
- if (reset_head(the_repository, NULL, NULL, RESET_HEAD_HARD,
1275
- NULL, NULL, NULL) < 0)
1282
+ ropts.flags = RESET_HEAD_HARD;
1283
+ if (reset_head(the_repository, &ropts) < 0)
1284
die(_("could not discard worktree changes"));
1285
remove_branch_state(the_repository, 0);
1286
if (read_basic_state(&options))
@@ -1289,9 +1297,11 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
1297
1298
if (read_basic_state(&options))
1299
exit(1);
1292
- if (reset_head(the_repository, &options.orig_head,
1293
- options.head_name, RESET_HEAD_HARD,
1294
- NULL, NULL, DEFAULT_REFLOG_ACTION) < 0)
1300
+ ropts.oid = &options.orig_head;
1301
+ ropts.branch = options.head_name;
1302
+ ropts.flags = RESET_HEAD_HARD;
1303
+ ropts.default_reflog_action = DEFAULT_REFLOG_ACTION;
1304
+ if (reset_head(the_repository, &ropts) < 0)
1305
die(_("could not move back to %s"),
1306
oid_to_hex(&options.orig_head));
1307
remove_branch_state(the_repository, 0);
@@ -1758,10 +1768,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
1768
1769
strbuf_addf(&msg, "%s: checkout %s",
1770
getenv(GIT_REFLOG_ACTION_ENVIRONMENT), options.onto_name);
1761
- if (reset_head(the_repository, &options.onto->object.oid, NULL,
1762
- RESET_HEAD_DETACH | RESET_ORIG_HEAD |
1763
- RESET_HEAD_RUN_POST_CHECKOUT_HOOK,
1764
- NULL, msg.buf, DEFAULT_REFLOG_ACTION))
1771
+ ropts.oid = &options.onto->object.oid;
1772
+ ropts.flags = RESET_HEAD_DETACH | RESET_ORIG_HEAD |
1773
+ RESET_HEAD_RUN_POST_CHECKOUT_HOOK;
1774
+ ropts.head_msg = msg.buf;
1775
+ ropts.default_reflog_action = DEFAULT_REFLOG_ACTION;
1776
+ if (reset_head(the_repository, &ropts))
1777
die(_("Could not detach HEAD"));
1778
strbuf_release(&msg);
1779
@@ -1776,8 +1788,11 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
1788
strbuf_addf(&msg, "rebase finished: %s onto %s",
1789
options.head_name ? options.head_name : "detached HEAD",
1790
oid_to_hex(&options.onto->object.oid));
1779
- reset_head(the_repository, NULL, options.head_name,
1780
- RESET_HEAD_REFS_ONLY, NULL, msg.buf, NULL);
1791
+ memset(&ropts, 0, sizeof(ropts));
1792
+ ropts.branch = options.head_name;
1793
+ ropts.flags = RESET_HEAD_REFS_ONLY;
1794
+ ropts.head_msg = msg.buf;
1795
+ reset_head(the_repository, &ropts);
1796
strbuf_release(&msg);
1797
ret = finish_rebase(&options);
1798
goto cleanup;
reset.c
+18
-20
@@ -8,14 +8,17 @@
8
#include "tree.h"
9
#include "unpack-trees.h"
10
11
-static int update_refs(const struct object_id *oid, const char *switch_to_branch,
12
- const struct object_id *head, const char *reflog_head,
13
- const char *reflog_orig_head,
14
- const char *default_reflog_action, unsigned flags)
11
+static int update_refs(const struct reset_head_opts *opts,
12
+ const struct object_id *oid,
13
+ const struct object_id *head)
14
{
16
- unsigned detach_head = flags & RESET_HEAD_DETACH;
17
- unsigned run_hook = flags & RESET_HEAD_RUN_POST_CHECKOUT_HOOK;
18
- unsigned update_orig_head = flags & RESET_ORIG_HEAD;
15
+ unsigned detach_head = opts->flags & RESET_HEAD_DETACH;
16
+ unsigned run_hook = opts->flags & RESET_HEAD_RUN_POST_CHECKOUT_HOOK;
17
+ unsigned update_orig_head = opts->flags & RESET_ORIG_HEAD;
18
+ const char *switch_to_branch = opts->branch;
19
+ const char *reflog_head = opts->head_msg;
20
+ const char *reflog_orig_head = opts->orig_head_msg;
21
+ const char *default_reflog_action = opts->default_reflog_action;
22
struct object_id *old_orig = NULL, oid_old_orig;
23
struct strbuf msg = STRBUF_INIT;
24
const char *reflog_action;
@@ -69,14 +72,13 @@ static int update_refs(const struct object_id *oid, const char *switch_to_branch
72
return ret;
73
}
74
72
-int reset_head(struct repository *r, struct object_id *oid,
73
- const char *switch_to_branch, unsigned flags,
74
- const char *reflog_orig_head, const char *reflog_head,
75
- const char *default_reflog_action)
75
+int reset_head(struct repository *r, const struct reset_head_opts *opts)
76
{
77
- unsigned reset_hard = flags & RESET_HEAD_HARD;
78
- unsigned refs_only = flags & RESET_HEAD_REFS_ONLY;
79
- unsigned update_orig_head = flags & RESET_ORIG_HEAD;
77
+ const struct object_id *oid = opts->oid;
78
+ const char *switch_to_branch = opts->branch;
79
+ unsigned reset_hard = opts->flags & RESET_HEAD_HARD;
80
+ unsigned refs_only = opts->flags & RESET_HEAD_REFS_ONLY;
81
+ unsigned update_orig_head = opts->flags & RESET_ORIG_HEAD;
82
struct object_id *head = NULL, head_oid;
83
struct tree_desc desc[2] = { { NULL }, { NULL } };
84
struct lock_file lock = LOCK_INIT;
@@ -104,9 +106,7 @@ int reset_head(struct repository *r, struct object_id *oid,
106
oid = &head_oid;
107
108
if (refs_only)
107
- return update_refs(oid, switch_to_branch, head, reflog_head,
108
- reflog_orig_head, default_reflog_action,
109
- flags);
109
+ return update_refs(opts, oid, head);
110
111
action = reset_hard ? "reset" : "checkout";
112
setup_unpack_trees_porcelain(&unpack_tree_opts, action);
@@ -151,9 +151,7 @@ int reset_head(struct repository *r, struct object_id *oid,
151
}
152
153
if (oid != &head_oid || update_orig_head || switch_to_branch)
154
- ret = update_refs(oid, switch_to_branch, head, reflog_head,
155
- reflog_orig_head, default_reflog_action,
156
- flags);
154
+ ret = update_refs(opts, oid, head);
155
156
leave_reset_head:
157
rollback_lock_file(&lock);
reset.h
+36
-4
@@ -6,15 +6,47 @@
6
7
#define GIT_REFLOG_ACTION_ENVIRONMENT "GIT_REFLOG_ACTION"
8
9
+/* Request a detached checkout */
10
#define RESET_HEAD_DETACH (1<<0)
11
+/* Request a reset rather than a checkout */
12
#define RESET_HEAD_HARD (1<<1)
13
+/* Run the post-checkout hook */
14
#define RESET_HEAD_RUN_POST_CHECKOUT_HOOK (1<<2)
15
+/* Only update refs, do not touch the worktree */
16
#define RESET_HEAD_REFS_ONLY (1<<3)
17
+/* Update ORIG_HEAD as well as HEAD */
18
#define RESET_ORIG_HEAD (1<<4)
19
15
-int reset_head(struct repository *r, struct object_id *oid,
16
- const char *switch_to_branch, unsigned flags,
17
- const char *reflog_orig_head, const char *reflog_head,
18
- const char *default_reflog_action);
20
+struct reset_head_opts {
21
+ /*
22
+ * The commit to checkout/reset to. Defaults to HEAD.
23
+ */
24
+ const struct object_id *oid;
25
+ /*
26
+ * Optional branch to switch to.
27
+ */
28
+ const char *branch;
29
+ /*
30
+ * Flags defined above.
31
+ */
32
+ unsigned flags;
33
+ /*
34
+ * Optional reflog message for HEAD, if this omitted but oid or branch
35
+ * are given then default_reflog_action must be given.
36
+ */
37
+ const char *head_msg;
38
+ /*
39
+ * Optional reflog message for ORIG_HEAD, if this omitted and flags
40
+ * contains RESET_ORIG_HEAD then default_reflog_action must be given.
41
+ */
42
+ const char *orig_head_msg;
43
+ /*
44
+ * Action to use in default reflog messages, only required if a ref is
45
+ * being updated and the reflog messages above are omitted.
46
+ */
47
+ const char *default_reflog_action;
48
+};
49
+
50
+int reset_head(struct repository *r, const struct reset_head_opts *opts);
51
52
#endif
sequencer.c
+2
-3
@@ -4115,6 +4115,7 @@ void create_autostash(struct repository *r, const char *path)
4115
if (has_unstaged_changes(r, 1) ||
4116
has_uncommitted_changes(r, 1)) {
4117
struct child_process stash = CHILD_PROCESS_INIT;
4118
+ struct reset_head_opts ropts = { .flags = RESET_HEAD_HARD };
4119
struct object_id oid;
4120
4121
strvec_pushl(&stash.args,
@@ -4136,10 +4137,8 @@ void create_autostash(struct repository *r, const char *path)
4137
path);
4138
write_file(path, "%s", oid_to_hex(&oid));
4139
printf(_("Created autostash: %s\n"), buf.buf);
4139
- if (reset_head(r, NULL, NULL, RESET_HEAD_HARD, NULL, NULL,
4140
- NULL) < 0)
4140
+ if (reset_head(r, &ropts) < 0)
4141
die(_("could not reset --hard"));
4142
-
4142
if (discard_index(r->index) < 0 ||
4143
repo_read_index(r) < 0)
4144
die(_("could not read index"));