1
0
mirror of https://github.com/git/git.git synced 2024-09-28 08:49:45 +02:00
git/reset.c
Phillip Wood d6a9f5ea8e reset_head(): factor out ref updates
In the next commit we will stop trying to update HEAD when we are
removing uncommitted changes from the working tree. Move the code that
updates the refs to its own function in preparation for that.

Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-01-26 12:08:53 -08:00

158 lines
4.6 KiB
C

#include "git-compat-util.h"
#include "cache-tree.h"
#include "lockfile.h"
#include "refs.h"
#include "reset.h"
#include "run-command.h"
#include "tree-walk.h"
#include "tree.h"
#include "unpack-trees.h"
static int update_refs(const struct object_id *oid, const char *switch_to_branch,
const struct object_id *head, const char *reflog_head,
const char *reflog_orig_head,
const char *default_reflog_action, unsigned flags)
{
unsigned detach_head = flags & RESET_HEAD_DETACH;
unsigned run_hook = flags & RESET_HEAD_RUN_POST_CHECKOUT_HOOK;
unsigned update_orig_head = flags & RESET_ORIG_HEAD;
struct object_id *old_orig = NULL, oid_old_orig;
struct strbuf msg = STRBUF_INIT;
const char *reflog_action;
size_t prefix_len;
int ret;
reflog_action = getenv(GIT_REFLOG_ACTION_ENVIRONMENT);
strbuf_addf(&msg, "%s: ", reflog_action ? reflog_action : default_reflog_action);
prefix_len = msg.len;
if (update_orig_head) {
if (!get_oid("ORIG_HEAD", &oid_old_orig))
old_orig = &oid_old_orig;
if (head) {
if (!reflog_orig_head) {
strbuf_addstr(&msg, "updating ORIG_HEAD");
reflog_orig_head = msg.buf;
}
update_ref(reflog_orig_head, "ORIG_HEAD", head,
old_orig, 0, UPDATE_REFS_MSG_ON_ERR);
} else if (old_orig)
delete_ref(NULL, "ORIG_HEAD", old_orig, 0);
}
if (!reflog_head) {
strbuf_setlen(&msg, prefix_len);
strbuf_addstr(&msg, "updating HEAD");
reflog_head = msg.buf;
}
if (!switch_to_branch)
ret = update_ref(reflog_head, "HEAD", oid, head,
detach_head ? REF_NO_DEREF : 0,
UPDATE_REFS_MSG_ON_ERR);
else {
ret = update_ref(reflog_head, switch_to_branch, oid,
NULL, 0, UPDATE_REFS_MSG_ON_ERR);
if (!ret)
ret = create_symref("HEAD", switch_to_branch,
reflog_head);
}
if (!ret && run_hook)
run_hook_le(NULL, "post-checkout",
oid_to_hex(head ? head : null_oid()),
oid_to_hex(oid), "1", NULL);
strbuf_release(&msg);
return ret;
}
int reset_head(struct repository *r, struct object_id *oid,
const char *switch_to_branch, unsigned flags,
const char *reflog_orig_head, const char *reflog_head,
const char *default_reflog_action)
{
unsigned reset_hard = flags & RESET_HEAD_HARD;
unsigned refs_only = flags & RESET_HEAD_REFS_ONLY;
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;
const char *action;
int ret = 0, nr = 0;
if (switch_to_branch && !starts_with(switch_to_branch, "refs/"))
BUG("Not a fully qualified branch: '%s'", switch_to_branch);
if (!refs_only && repo_hold_locked_index(r, &lock, LOCK_REPORT_ON_ERROR) < 0) {
ret = -1;
goto leave_reset_head;
}
if (!get_oid("HEAD", &head_oid)) {
head = &head_oid;
} else if (!oid || !reset_hard) {
ret = error(_("could not determine HEAD revision"));
goto leave_reset_head;
}
if (!oid)
oid = &head_oid;
if (refs_only)
return update_refs(oid, switch_to_branch, head, reflog_head,
reflog_orig_head, default_reflog_action,
flags);
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.fn = reset_hard ? oneway_merge : twoway_merge;
unpack_tree_opts.update = 1;
unpack_tree_opts.merge = 1;
unpack_tree_opts.preserve_ignored = 0; /* FIXME: !overwrite_ignore */
init_checkout_metadata(&unpack_tree_opts.meta, switch_to_branch, oid, NULL);
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));
goto leave_reset_head;
}
if (!fill_tree_descriptor(r, &desc[nr++], oid)) {
ret = error(_("failed to find tree of %s"), oid_to_hex(oid));
goto leave_reset_head;
}
if (unpack_trees(nr, desc, &unpack_tree_opts)) {
ret = -1;
goto leave_reset_head;
}
tree = parse_tree_indirect(oid);
prime_cache_tree(r, r->index, tree);
if (write_locked_index(r->index, &lock, COMMIT_LOCK) < 0) {
ret = error(_("could not write index"));
goto leave_reset_head;
}
ret = update_refs(oid, switch_to_branch, head, reflog_head,
reflog_orig_head, default_reflog_action, flags);
leave_reset_head:
rollback_lock_file(&lock);
clear_unpack_trees_porcelain(&unpack_tree_opts);
while (nr)
free((void *)desc[--nr].buffer);
return ret;
}