Skip to content

Commit 1a51b52

Browse files
committed
push-to-deploy: allow pushing into an unborn branch and updating it
Setting receive.denycurrentbranch to updateinstead and pushing into the current branch, when the working tree and the index is truly clean, is supposed to reset the working tree and the index to match the tree of the pushed commit. This did not work when pushing into an unborn branch. The code that drives push-to-checkout hook needs no change, as the interface is defined so that hook can decide what to do when the push is coming to an unborn branch and take an appropriate action since the beginning. Acked-by: Johannes Schindelin <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 0855331 commit 1a51b52

File tree

2 files changed

+74
-2
lines changed

2 files changed

+74
-2
lines changed

builtin/receive-pack.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,22 @@ static int update_shallow_ref(struct command *cmd, struct shallow_info *si)
733733
return 0;
734734
}
735735

736+
/*
737+
* NEEDSWORK: we should consolidate various implementions of "are we
738+
* on an unborn branch?" test into one, and make the unified one more
739+
* robust. !get_sha1() based check used here and elsewhere would not
740+
* allow us to tell an unborn branch from corrupt ref, for example.
741+
* For the purpose of fixing "deploy-to-update does not work when
742+
* pushing into an empty repository" issue, this should suffice for
743+
* now.
744+
*/
745+
static int head_has_history(void)
746+
{
747+
unsigned char sha1[20];
748+
749+
return !get_sha1("HEAD", sha1);
750+
}
751+
736752
static const char *push_to_deploy(unsigned char *sha1,
737753
struct argv_array *env,
738754
const char *work_tree)
@@ -745,7 +761,7 @@ static const char *push_to_deploy(unsigned char *sha1,
745761
};
746762
const char *diff_index[] = {
747763
"diff-index", "--quiet", "--cached", "--ignore-submodules",
748-
"HEAD", "--", NULL
764+
NULL, "--", NULL
749765
};
750766
const char *read_tree[] = {
751767
"read-tree", "-u", "-m", NULL, NULL
@@ -772,6 +788,9 @@ static const char *push_to_deploy(unsigned char *sha1,
772788
if (run_command(&child))
773789
return "Working directory has unstaged changes";
774790

791+
/* diff-index with either HEAD or an empty tree */
792+
diff_index[4] = head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX;
793+
775794
child_process_init(&child);
776795
child.argv = diff_index;
777796
child.env = env->argv;

t/t5516-fetch-push.sh

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1430,8 +1430,22 @@ test_expect_success 'receive.denyCurrentBranch = updateInstead' '
14301430
test $(git -C .. rev-parse HEAD^^) = $(git rev-parse HEAD) &&
14311431
git diff --quiet &&
14321432
test fifth = "$(cat path3)"
1433-
)
1433+
) &&
14341434
1435+
# (5) push into void
1436+
rm -fr void &&
1437+
git init void &&
1438+
(
1439+
cd void &&
1440+
git config receive.denyCurrentBranch updateInstead
1441+
) &&
1442+
git push void master &&
1443+
(
1444+
cd void &&
1445+
test $(git -C .. rev-parse master) = $(git rev-parse HEAD) &&
1446+
git diff --quiet &&
1447+
git diff --cached --quiet
1448+
)
14351449
'
14361450

14371451
test_expect_success 'updateInstead with push-to-checkout hook' '
@@ -1494,6 +1508,45 @@ test_expect_success 'updateInstead with push-to-checkout hook' '
14941508
test "$(cat path5)" = irrelevant &&
14951509
test "$(git diff --name-only --cached HEAD)" = path5 &&
14961510
test $(git -C .. rev-parse HEAD) = $(git rev-parse HEAD)
1511+
) &&
1512+
1513+
# push into void
1514+
rm -fr void &&
1515+
git init void &&
1516+
(
1517+
cd void &&
1518+
git config receive.denyCurrentBranch updateInstead &&
1519+
write_script .git/hooks/push-to-checkout <<-\EOF
1520+
if git rev-parse --quiet --verify HEAD
1521+
then
1522+
has_head=yes
1523+
echo >&2 updating from $(git rev-parse HEAD)
1524+
else
1525+
has_head=no
1526+
echo >&2 pushing into void
1527+
fi
1528+
echo >&2 updating to "$1"
1529+
1530+
git update-index -q --refresh &&
1531+
case "$has_head" in
1532+
yes)
1533+
git read-tree -u -m HEAD "$1" ;;
1534+
no)
1535+
git read-tree -u -m "$1" ;;
1536+
esac || {
1537+
status=$?
1538+
echo >&2 read-tree failed
1539+
exit $status
1540+
}
1541+
EOF
1542+
) &&
1543+
1544+
git push void master &&
1545+
(
1546+
cd void &&
1547+
git diff --quiet &&
1548+
git diff --cached --quiet &&
1549+
test $(git -C .. rev-parse HEAD) = $(git rev-parse HEAD)
14971550
)
14981551
'
14991552

0 commit comments

Comments
 (0)