reset: extract reset_head() from rebase
Continue the process of lib-ifying the autostash code. In a future commit, this will be used to implement `--autostash` in other builtins. This patch is best viewed with `--color-moved`. Signed-off-by: Denton Liu <liu.denton@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Denton Liu committed
Apr 7, 2020 at 10:28 UTC
b309a9710899dab2f76455526f573a90fad5d13c
4 files changed
+162
-138
Makefile
+1
@@ -970,6 +970,7 @@ LIB_OBJS += replace-object.o
970
LIB_OBJS += repo-settings.o
971
LIB_OBJS += repository.o
972
LIB_OBJS += rerere.o
973
+LIB_OBJS += reset.o
974
LIB_OBJS += resolve-undo.o
975
LIB_OBJS += revision.o
976
LIB_OBJS += run-command.o
builtin/rebase.c
+1
-138
@@ -27,6 +27,7 @@
27
#include "branch.h"
28
#include "sequencer.h"
29
#include "rebase-interactive.h"
30
+#include "reset.h"
31
32
#define DEFAULT_REFLOG_ACTION "rebase"
33
@@ -766,144 +767,6 @@ static void add_var(struct strbuf *buf, const char *name, const char *value)
767
}
768
}
769
769
-#define GIT_REFLOG_ACTION_ENVIRONMENT "GIT_REFLOG_ACTION"
770
-
771
-#define RESET_HEAD_DETACH (1<<0)
772
-#define RESET_HEAD_HARD (1<<1)
773
-#define RESET_HEAD_RUN_POST_CHECKOUT_HOOK (1<<2)
774
-#define RESET_HEAD_REFS_ONLY (1<<3)
775
-#define RESET_ORIG_HEAD (1<<4)
776
-
777
-static int reset_head(struct repository *r, struct object_id *oid, const char *action,
778
- const char *switch_to_branch, unsigned flags,
779
- const char *reflog_orig_head, const char *reflog_head,
780
- const char *default_reflog_action)
781
-{
782
- unsigned detach_head = flags & RESET_HEAD_DETACH;
783
- unsigned reset_hard = flags & RESET_HEAD_HARD;
784
- unsigned run_hook = flags & RESET_HEAD_RUN_POST_CHECKOUT_HOOK;
785
- unsigned refs_only = flags & RESET_HEAD_REFS_ONLY;
786
- unsigned update_orig_head = flags & RESET_ORIG_HEAD;
787
- struct object_id head_oid;
788
- struct tree_desc desc[2] = { { NULL }, { NULL } };
789
- struct lock_file lock = LOCK_INIT;
790
- struct unpack_trees_options unpack_tree_opts;
791
- struct tree *tree;
792
- const char *reflog_action;
793
- struct strbuf msg = STRBUF_INIT;
794
- size_t prefix_len;
795
- struct object_id *orig = NULL, oid_orig,
796
- *old_orig = NULL, oid_old_orig;
797
- int ret = 0, nr = 0;
798
-
799
- if (switch_to_branch && !starts_with(switch_to_branch, "refs/"))
800
- BUG("Not a fully qualified branch: '%s'", switch_to_branch);
801
-
802
- if (!refs_only && repo_hold_locked_index(r, &lock, LOCK_REPORT_ON_ERROR) < 0) {
803
- ret = -1;
804
- goto leave_reset_head;
805
- }
806
-
807
- if ((!oid || !reset_hard) && get_oid("HEAD", &head_oid)) {
808
- ret = error(_("could not determine HEAD revision"));
809
- goto leave_reset_head;
810
- }
811
-
812
- if (!oid)
813
- oid = &head_oid;
814
-
815
- if (refs_only)
816
- goto reset_head_refs;
817
-
818
- memset(&unpack_tree_opts, 0, sizeof(unpack_tree_opts));
819
- setup_unpack_trees_porcelain(&unpack_tree_opts, action);
820
- unpack_tree_opts.head_idx = 1;
821
- unpack_tree_opts.src_index = r->index;
822
- unpack_tree_opts.dst_index = r->index;
823
- unpack_tree_opts.fn = reset_hard ? oneway_merge : twoway_merge;
824
- unpack_tree_opts.update = 1;
825
- unpack_tree_opts.merge = 1;
826
- if (!detach_head)
827
- unpack_tree_opts.reset = 1;
828
-
829
- if (repo_read_index_unmerged(r) < 0) {
830
- ret = error(_("could not read index"));
831
- goto leave_reset_head;
832
- }
833
-
834
- if (!reset_hard && !fill_tree_descriptor(r, &desc[nr++], &head_oid)) {
835
- ret = error(_("failed to find tree of %s"),
836
- oid_to_hex(&head_oid));
837
- goto leave_reset_head;
838
- }
839
-
840
- if (!fill_tree_descriptor(r, &desc[nr++], oid)) {
841
- ret = error(_("failed to find tree of %s"), oid_to_hex(oid));
842
- goto leave_reset_head;
843
- }
844
-
845
- if (unpack_trees(nr, desc, &unpack_tree_opts)) {
846
- ret = -1;
847
- goto leave_reset_head;
848
- }
849
-
850
- tree = parse_tree_indirect(oid);
851
- prime_cache_tree(r, r->index, tree);
852
-
853
- if (write_locked_index(r->index, &lock, COMMIT_LOCK) < 0) {
854
- ret = error(_("could not write index"));
855
- goto leave_reset_head;
856
- }
857
-
858
-reset_head_refs:
859
- reflog_action = getenv(GIT_REFLOG_ACTION_ENVIRONMENT);
860
- strbuf_addf(&msg, "%s: ", reflog_action ? reflog_action : default_reflog_action);
861
- prefix_len = msg.len;
862
-
863
- if (update_orig_head) {
864
- if (!get_oid("ORIG_HEAD", &oid_old_orig))
865
- old_orig = &oid_old_orig;
866
- if (!get_oid("HEAD", &oid_orig)) {
867
- orig = &oid_orig;
868
- if (!reflog_orig_head) {
869
- strbuf_addstr(&msg, "updating ORIG_HEAD");
870
- reflog_orig_head = msg.buf;
871
- }
872
- update_ref(reflog_orig_head, "ORIG_HEAD", orig,
873
- old_orig, 0, UPDATE_REFS_MSG_ON_ERR);
874
- } else if (old_orig)
875
- delete_ref(NULL, "ORIG_HEAD", old_orig, 0);
876
- }
877
-
878
- if (!reflog_head) {
879
- strbuf_setlen(&msg, prefix_len);
880
- strbuf_addstr(&msg, "updating HEAD");
881
- reflog_head = msg.buf;
882
- }
883
- if (!switch_to_branch)
884
- ret = update_ref(reflog_head, "HEAD", oid, orig,
885
- detach_head ? REF_NO_DEREF : 0,
886
- UPDATE_REFS_MSG_ON_ERR);
887
- else {
888
- ret = update_ref(reflog_head, switch_to_branch, oid,
889
- NULL, 0, UPDATE_REFS_MSG_ON_ERR);
890
- if (!ret)
891
- ret = create_symref("HEAD", switch_to_branch,
892
- reflog_head);
893
- }
894
- if (run_hook)
895
- run_hook_le(NULL, "post-checkout",
896
- oid_to_hex(orig ? orig : &null_oid),
897
- oid_to_hex(oid), "1", NULL);
898
-
899
-leave_reset_head:
900
- strbuf_release(&msg);
901
- rollback_lock_file(&lock);
902
- while (nr)
903
- free((void *)desc[--nr].buffer);
904
- return ret;
905
-}
906
-
770
static int move_to_original_branch(struct rebase_options *opts)
771
{
772
struct strbuf orig_head_reflog = STRBUF_INIT, head_reflog = STRBUF_INIT;
reset.c
new
+140
@@ -0,0 +1,140 @@
1
+#include "git-compat-util.h"
2
+#include "cache-tree.h"
3
+#include "lockfile.h"
4
+#include "refs.h"
5
+#include "reset.h"
6
+#include "run-command.h"
7
+#include "tree-walk.h"
8
+#include "tree.h"
9
+#include "unpack-trees.h"
10
+
11
+int reset_head(struct repository *r, struct object_id *oid, const char *action,
12
+ const char *switch_to_branch, unsigned flags,
13
+ const char *reflog_orig_head, const char *reflog_head,
14
+ const char *default_reflog_action)
15
+{
16
+ unsigned detach_head = flags & RESET_HEAD_DETACH;
17
+ unsigned reset_hard = flags & RESET_HEAD_HARD;
18
+ unsigned run_hook = flags & RESET_HEAD_RUN_POST_CHECKOUT_HOOK;
19
+ unsigned refs_only = flags & RESET_HEAD_REFS_ONLY;
20
+ unsigned update_orig_head = flags & RESET_ORIG_HEAD;
21
+ struct object_id head_oid;
22
+ struct tree_desc desc[2] = { { NULL }, { NULL } };
23
+ struct lock_file lock = LOCK_INIT;
24
+ struct unpack_trees_options unpack_tree_opts;
25
+ struct tree *tree;
26
+ const char *reflog_action;
27
+ struct strbuf msg = STRBUF_INIT;
28
+ size_t prefix_len;
29
+ struct object_id *orig = NULL, oid_orig,
30
+ *old_orig = NULL, oid_old_orig;
31
+ int ret = 0, nr = 0;
32
+
33
+ if (switch_to_branch && !starts_with(switch_to_branch, "refs/"))
34
+ BUG("Not a fully qualified branch: '%s'", switch_to_branch);
35
+
36
+ if (!refs_only && repo_hold_locked_index(r, &lock, LOCK_REPORT_ON_ERROR) < 0) {
37
+ ret = -1;
38
+ goto leave_reset_head;
39
+ }
40
+
41
+ if ((!oid || !reset_hard) && get_oid("HEAD", &head_oid)) {
42
+ ret = error(_("could not determine HEAD revision"));
43
+ goto leave_reset_head;
44
+ }
45
+
46
+ if (!oid)
47
+ oid = &head_oid;
48
+
49
+ if (refs_only)
50
+ goto reset_head_refs;
51
+
52
+ memset(&unpack_tree_opts, 0, sizeof(unpack_tree_opts));
53
+ setup_unpack_trees_porcelain(&unpack_tree_opts, action);
54
+ unpack_tree_opts.head_idx = 1;
55
+ unpack_tree_opts.src_index = r->index;
56
+ unpack_tree_opts.dst_index = r->index;
57
+ unpack_tree_opts.fn = reset_hard ? oneway_merge : twoway_merge;
58
+ unpack_tree_opts.update = 1;
59
+ unpack_tree_opts.merge = 1;
60
+ if (!detach_head)
61
+ unpack_tree_opts.reset = 1;
62
+
63
+ if (repo_read_index_unmerged(r) < 0) {
64
+ ret = error(_("could not read index"));
65
+ goto leave_reset_head;
66
+ }
67
+
68
+ if (!reset_hard && !fill_tree_descriptor(r, &desc[nr++], &head_oid)) {
69
+ ret = error(_("failed to find tree of %s"),
70
+ oid_to_hex(&head_oid));
71
+ goto leave_reset_head;
72
+ }
73
+
74
+ if (!fill_tree_descriptor(r, &desc[nr++], oid)) {
75
+ ret = error(_("failed to find tree of %s"), oid_to_hex(oid));
76
+ goto leave_reset_head;
77
+ }
78
+
79
+ if (unpack_trees(nr, desc, &unpack_tree_opts)) {
80
+ ret = -1;
81
+ goto leave_reset_head;
82
+ }
83
+
84
+ tree = parse_tree_indirect(oid);
85
+ prime_cache_tree(r, r->index, tree);
86
+
87
+ if (write_locked_index(r->index, &lock, COMMIT_LOCK) < 0) {
88
+ ret = error(_("could not write index"));
89
+ goto leave_reset_head;
90
+ }
91
+
92
+reset_head_refs:
93
+ reflog_action = getenv(GIT_REFLOG_ACTION_ENVIRONMENT);
94
+ strbuf_addf(&msg, "%s: ", reflog_action ? reflog_action : default_reflog_action);
95
+ prefix_len = msg.len;
96
+
97
+ if (update_orig_head) {
98
+ if (!get_oid("ORIG_HEAD", &oid_old_orig))
99
+ old_orig = &oid_old_orig;
100
+ if (!get_oid("HEAD", &oid_orig)) {
101
+ orig = &oid_orig;
102
+ if (!reflog_orig_head) {
103
+ strbuf_addstr(&msg, "updating ORIG_HEAD");
104
+ reflog_orig_head = msg.buf;
105
+ }
106
+ update_ref(reflog_orig_head, "ORIG_HEAD", orig,
107
+ old_orig, 0, UPDATE_REFS_MSG_ON_ERR);
108
+ } else if (old_orig)
109
+ delete_ref(NULL, "ORIG_HEAD", old_orig, 0);
110
+ }
111
+
112
+ if (!reflog_head) {
113
+ strbuf_setlen(&msg, prefix_len);
114
+ strbuf_addstr(&msg, "updating HEAD");
115
+ reflog_head = msg.buf;
116
+ }
117
+ if (!switch_to_branch)
118
+ ret = update_ref(reflog_head, "HEAD", oid, orig,
119
+ detach_head ? REF_NO_DEREF : 0,
120
+ UPDATE_REFS_MSG_ON_ERR);
121
+ else {
122
+ ret = update_ref(reflog_head, switch_to_branch, oid,
123
+ NULL, 0, UPDATE_REFS_MSG_ON_ERR);
124
+ if (!ret)
125
+ ret = create_symref("HEAD", switch_to_branch,
126
+ reflog_head);
127
+ }
128
+ if (run_hook)
129
+ run_hook_le(NULL, "post-checkout",
130
+ oid_to_hex(orig ? orig : &null_oid),
131
+ oid_to_hex(oid), "1", NULL);
132
+
133
+leave_reset_head:
134
+ strbuf_release(&msg);
135
+ rollback_lock_file(&lock);
136
+ while (nr)
137
+ free((void *)desc[--nr].buffer);
138
+ return ret;
139
+
140
+}
reset.h
new
+20
@@ -0,0 +1,20 @@
1
+#ifndef RESET_H
2
+#define RESET_H
3
+
4
+#include "hash.h"
5
+#include "repository.h"
6
+
7
+#define GIT_REFLOG_ACTION_ENVIRONMENT "GIT_REFLOG_ACTION"
8
+
9
+#define RESET_HEAD_DETACH (1<<0)
10
+#define RESET_HEAD_HARD (1<<1)
11
+#define RESET_HEAD_RUN_POST_CHECKOUT_HOOK (1<<2)
12
+#define RESET_HEAD_REFS_ONLY (1<<3)
13
+#define RESET_ORIG_HEAD (1<<4)
14
+
15
+int reset_head(struct repository *r, struct object_id *oid, const char *action,
16
+ const char *switch_to_branch, unsigned flags,
17
+ const char *reflog_orig_head, const char *reflog_head,
18
+ const char *default_reflog_action);
19
+
20
+#endif