Skip to content

Commit b072a25

Browse files
committed
receive: denyCurrentBranch=updateinstead should not blindly update
The handling of receive.denyCurrentBranch=updateInstead was added to a switch statement that handles other values of the variable, but all the other case arms only checked a condition to reject the attempted push, or let later logic in the same function to still intervene, so that a push that does not fast-forward (which is checked after the switch statement in question) is still rejected. But the handling of updateInstead incorrectly took immediate effect, without giving other checks a chance to intervene. Instead of calling update_worktree() that causes the side effect immediately, just note the fact that we will need to call the function later, and first give other checks a chance to reject the request. After the update-hook gets a chance to reject the push (which happens as the last step in a series of checks), call update_worktree() when we earlier detected the need to. Reported-by: Rajesh Madamanchi Signed-off-by: Junio C Hamano <[email protected]>
1 parent 268fbcd commit b072a25

File tree

2 files changed

+16
-4
lines changed

2 files changed

+16
-4
lines changed

builtin/receive-pack.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,6 +1037,7 @@ static const char *update(struct command *cmd, struct shallow_info *si)
10371037
const char *ret;
10381038
struct object_id *old_oid = &cmd->old_oid;
10391039
struct object_id *new_oid = &cmd->new_oid;
1040+
int do_update_worktree = 0;
10401041

10411042
/* only refs/... are allowed */
10421043
if (!starts_with(name, "refs/") || check_refname_format(name + 5, 0)) {
@@ -1062,9 +1063,8 @@ static const char *update(struct command *cmd, struct shallow_info *si)
10621063
refuse_unconfigured_deny();
10631064
return "branch is currently checked out";
10641065
case DENY_UPDATE_INSTEAD:
1065-
ret = update_worktree(new_oid->hash);
1066-
if (ret)
1067-
return ret;
1066+
/* pass -- let other checks intervene first */
1067+
do_update_worktree = 1;
10681068
break;
10691069
}
10701070
}
@@ -1129,6 +1129,12 @@ static const char *update(struct command *cmd, struct shallow_info *si)
11291129
return "hook declined";
11301130
}
11311131

1132+
if (do_update_worktree) {
1133+
ret = update_worktree(new_oid->hash);
1134+
if (ret)
1135+
return ret;
1136+
}
1137+
11321138
if (is_null_oid(new_oid)) {
11331139
struct strbuf err = STRBUF_INIT;
11341140
if (!parse_object(old_oid)) {

t/t5516-fetch-push.sh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1527,7 +1527,13 @@ test_expect_success 'receive.denyCurrentBranch = updateInstead' '
15271527
test $(git -C .. rev-parse master) = $(git rev-parse HEAD) &&
15281528
git diff --quiet &&
15291529
git diff --cached --quiet
1530-
)
1530+
) &&
1531+
1532+
# (6) updateInstead intervened by fast-forward check
1533+
test_must_fail git push void master^:master &&
1534+
test $(git -C void rev-parse HEAD) = $(git rev-parse master) &&
1535+
git -C void diff --quiet &&
1536+
git -C void diff --cached --quiet
15311537
'
15321538

15331539
test_expect_success 'updateInstead with push-to-checkout hook' '

0 commit comments

Comments
 (0)