Skip to content

Commit 8151f4f

Browse files
pabloosabaterrgitster
authored andcommitted
receive-pack: use worktree HEAD for updateInstead
When a bare repo has linked worktrees, and its HEAD points to an unborn branch, pushing to a wt branch with updateInstead fails and rejects the push, even if the wt is clean. This happens because HEAD is checked only for the bare repo context, instead of the wt. Remove head_has_history and check for worktree->head_oid which does have the correct HEAD of the wt. Update the test added by Runxi's patch to expect success. Signed-off-by: Pablo Sabater <pabloosabaterr@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent b310755 commit 8151f4f

File tree

2 files changed

+16
-29
lines changed

2 files changed

+16
-29
lines changed

builtin/receive-pack.c

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1380,32 +1380,16 @@ static int update_shallow_ref(struct command *cmd, struct shallow_info *si)
13801380
return 0;
13811381
}
13821382

1383-
/*
1384-
* NEEDSWORK: we should consolidate various implementations of "are we
1385-
* on an unborn branch?" test into one, and make the unified one more
1386-
* robust. !get_sha1() based check used here and elsewhere would not
1387-
* allow us to tell an unborn branch from corrupt ref, for example.
1388-
* For the purpose of fixing "deploy-to-update does not work when
1389-
* pushing into an empty repository" issue, this should suffice for
1390-
* now.
1391-
*/
1392-
static int head_has_history(void)
1393-
{
1394-
struct object_id oid;
1395-
1396-
return !repo_get_oid(the_repository, "HEAD", &oid);
1397-
}
1398-
13991383
static const char *push_to_deploy(unsigned char *sha1,
14001384
struct strvec *env,
1401-
const char *work_tree)
1385+
const struct worktree *worktree)
14021386
{
14031387
struct child_process child = CHILD_PROCESS_INIT;
14041388

14051389
strvec_pushl(&child.args, "update-index", "-q", "--ignore-submodules",
14061390
"--refresh", NULL);
14071391
strvec_pushv(&child.env, env->v);
1408-
child.dir = work_tree;
1392+
child.dir = worktree->path;
14091393
child.no_stdin = 1;
14101394
child.stdout_to_stderr = 1;
14111395
child.git_cmd = 1;
@@ -1417,7 +1401,7 @@ static const char *push_to_deploy(unsigned char *sha1,
14171401
strvec_pushl(&child.args, "diff-files", "--quiet",
14181402
"--ignore-submodules", "--", NULL);
14191403
strvec_pushv(&child.env, env->v);
1420-
child.dir = work_tree;
1404+
child.dir = worktree->path;
14211405
child.no_stdin = 1;
14221406
child.stdout_to_stderr = 1;
14231407
child.git_cmd = 1;
@@ -1427,9 +1411,16 @@ static const char *push_to_deploy(unsigned char *sha1,
14271411
child_process_init(&child);
14281412
strvec_pushl(&child.args, "diff-index", "--quiet", "--cached",
14291413
"--ignore-submodules",
1430-
/* diff-index with either HEAD or an empty tree */
1431-
head_has_history() ? "HEAD" : empty_tree_oid_hex(the_repository->hash_algo),
1432-
"--", NULL);
1414+
/*
1415+
* diff-index with either HEAD or an empty tree
1416+
*
1417+
* NEEDSWORK: is_null_oid() cannot know whether it's an
1418+
* unborn HEAD or a corrupt ref. It works for now because
1419+
* it's only needed to know if we are comparing HEAD or an
1420+
* empty tree.
1421+
*/
1422+
!is_null_oid(&worktree->head_oid) ? "HEAD" :
1423+
empty_tree_oid_hex(the_repository->hash_algo), "--", NULL);
14331424
strvec_pushv(&child.env, env->v);
14341425
child.no_stdin = 1;
14351426
child.no_stdout = 1;
@@ -1442,7 +1433,7 @@ static const char *push_to_deploy(unsigned char *sha1,
14421433
strvec_pushl(&child.args, "read-tree", "-u", "-m", hash_to_hex(sha1),
14431434
NULL);
14441435
strvec_pushv(&child.env, env->v);
1445-
child.dir = work_tree;
1436+
child.dir = worktree->path;
14461437
child.no_stdin = 1;
14471438
child.no_stdout = 1;
14481439
child.stdout_to_stderr = 0;
@@ -1490,7 +1481,7 @@ static const char *update_worktree(unsigned char *sha1, const struct worktree *w
14901481

14911482
retval = push_to_checkout(sha1, &invoked_hook, &env, worktree->path);
14921483
if (!invoked_hook)
1493-
retval = push_to_deploy(sha1, &env, worktree->path);
1484+
retval = push_to_deploy(sha1, &env, worktree);
14941485

14951486
strvec_clear(&env);
14961487
free(git_dir);

t/t5516-fetch-push.sh

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1817,11 +1817,7 @@ test_expect_success 'denyCurrentBranch and bare repository worktrees' '
18171817
test_must_fail git push --delete bare.git wt
18181818
'
18191819

1820-
# NEEDSWORK: updateInstead unexpectedly fails when bare HEAD points to unborn
1821-
# branch (or probably any ref that differs from the target worktree) despite
1822-
# the target worktree being clean. This seems to be because receive-pack.c
1823-
# diffs the target worktree index against the bare repository HEAD.
1824-
test_expect_failure 'updateInstead with bare repository worktree and unborn bare HEAD' '
1820+
test_expect_success 'updateInstead with bare repository worktree and unborn bare HEAD' '
18251821
test_when_finished "rm -fr bare.git cloned" &&
18261822
git clone --bare . bare.git &&
18271823
git -C bare.git worktree add wt &&

0 commit comments

Comments
 (0)