Skip to content

Commit b309a97

Browse files
Denton-Lgitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent f213f06 commit b309a97

File tree

4 files changed

+162
-138
lines changed

4 files changed

+162
-138
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -970,6 +970,7 @@ LIB_OBJS += replace-object.o
970970
LIB_OBJS += repo-settings.o
971971
LIB_OBJS += repository.o
972972
LIB_OBJS += rerere.o
973+
LIB_OBJS += reset.o
973974
LIB_OBJS += resolve-undo.o
974975
LIB_OBJS += revision.o
975976
LIB_OBJS += run-command.o

builtin/rebase.c

Lines changed: 1 addition & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "branch.h"
2828
#include "sequencer.h"
2929
#include "rebase-interactive.h"
30+
#include "reset.h"
3031

3132
#define DEFAULT_REFLOG_ACTION "rebase"
3233

@@ -766,144 +767,6 @@ static void add_var(struct strbuf *buf, const char *name, const char *value)
766767
}
767768
}
768769

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-
907770
static int move_to_original_branch(struct rebase_options *opts)
908771
{
909772
struct strbuf orig_head_reflog = STRBUF_INIT, head_reflog = STRBUF_INIT;

reset.c

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

0 commit comments

Comments
 (0)