@matheusbsbs / matheus-bagliano / commits / 4868b2ea17
Fork 0

Subject: setup: officially support --work-tree without --git-dir

The original intention of --work-tree was to allow people to work in a subdirectory of their working tree that does not have an embedded .git directory. Because their working tree, which their $cwd was in, did not have an embedded .git, they needed to use $GIT_DIR to specify where it is, and because this meant there was no way to discover where the root level of the working tree was, so we needed to add $GIT_WORK_TREE to tell git where it was. However, this facility has long been (mis)used by people's scripts to start git from a working tree _with_ an embedded .git directory, let git find .git directory, and then pretend as if an unrelated directory were the associated working tree of the .git directory found by the discovery process. It happens to work in simple cases, and is not worth causing "regression" to these scripts. Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jonathan Nieder committed Jan 19, 2011 at 06:42 UTC 4868b2ea17b7a5e8171cb109423a25a269bfefe5
2 files changed +134 -95
setup.c
+19
@@ -411,6 +411,15 @@ static const char *setup_discovered_git_dir(const char *gitdir,
411 if (check_repository_format_gently(gitdir, nongit_ok))
412 return NULL;
413
414 + /* --work-tree is set without --git-dir; use discovered one */
415 + if (getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) {
416 + if (offset != len && !is_absolute_path(gitdir))
417 + gitdir = xstrdup(make_absolute_path(gitdir));
418 + if (chdir(cwd))
419 + die_errno("Could not come back to cwd");
420 + return setup_explicit_git_dir(gitdir, cwd, len, nongit_ok);
421 + }
422 +
423 /* #16.2, #17.2, #20.2, #21.2, #24, #25, #28, #29 (see t1510) */
424 if (is_bare_repository_cfg > 0) {
425 set_git_dir(offset == len ? gitdir : make_absolute_path(gitdir));
@@ -443,6 +452,16 @@ static const char *setup_bare_git_dir(char *cwd, int offset, int len, int *nongi
452 if (check_repository_format_gently(".", nongit_ok))
453 return NULL;
454
455 + /* --work-tree is set without --git-dir; use discovered one */
456 + if (getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) {
457 + const char *gitdir;
458 +
459 + gitdir = offset == len ? "." : xmemdupz(cwd, offset);
460 + if (chdir(cwd))
461 + die_errno("Could not come back to cwd");
462 + return setup_explicit_git_dir(gitdir, cwd, len, nongit_ok);
463 + }
464 +
465 inside_git_dir = 1;
466 inside_work_tree = 0;
467 if (offset != len) {
t/t1510-repo-setup.sh
+115 -95
@@ -16,8 +16,12 @@ A few rules for repo setup:
16 4. GIT_WORK_TREE is relative to user's cwd. --work-tree is
17 equivalent to GIT_WORK_TREE.
18
19 -5. GIT_WORK_TREE/core.worktree is only effective if GIT_DIR is set
20 - Uneffective worktree settings should be warned.
19 +5. GIT_WORK_TREE/core.worktree was originally meant to work only if
20 + GIT_DIR is set, but earlier git didn't enforce it, and some scripts
21 + depend on the implementation that happened to first discover .git by
22 + going up from the users $cwd and then using the specified working tree
23 + that may or may not have any relation to where .git was found in. This
24 + historical behaviour must be kept.
25
26 6. Effective GIT_WORK_TREE overrides core.worktree and core.bare
27
@@ -224,13 +228,16 @@ try_repo () {
228 test_expect_success '#0: nonbare repo, no explicit configuration' '
229 try_repo 0 unset unset unset "" unset \
230 .git "$here/0" "$here/0" "(null)" \
227 - .git "$here/0" "$here/0" sub/
231 + .git "$here/0" "$here/0" sub/ 2>message &&
232 + ! test -s message
233 '
234
230 -test_expect_success '#1: GIT_WORK_TREE without explicit GIT_DIR is ignored' '
231 - try_repo 1 non-existent unset unset "" unset \
232 - .git "$here/1" "$here/1" "(null)" \
233 - .git "$here/1" "$here/1" sub/
235 +test_expect_success '#1: GIT_WORK_TREE without explicit GIT_DIR is accepted' '
236 + mkdir -p wt &&
237 + try_repo 1 "$here" unset unset "" unset \
238 + "$here/1/.git" "$here" "$here" 1/ \
239 + "$here/1/.git" "$here" "$here" 1/sub/ 2>message &&
240 + ! test -s message
241 '
242
243 test_expect_success '#2: worktree defaults to cwd with explicit GIT_DIR' '
@@ -251,17 +258,24 @@ test_expect_success '#3: setup' '
258 '
259 run_wt_tests 3
260
254 -test_expect_success '#4: core.worktree without GIT_DIR set is ignored' '
255 - try_repo 4 unset unset non-existent "" unset \
256 - .git "$here/4" "$here/4" "(null)" \
257 - .git "$here/4" "$here/4" sub/
261 +test_expect_success '#4: core.worktree without GIT_DIR set is accepted' '
262 + setup_repo 4 ../sub "" unset &&
263 + mkdir -p 4/sub sub &&
264 + try_case 4 unset unset \
265 + .git "$here/4/sub" "$here/4" "(null)" \
266 + "$here/4/.git" "$here/4/sub" "$here/4/sub" "(null)" 2>message &&
267 + ! test -s message
268 '
269
260 -test_expect_success '#5: core.worktree + GIT_WORK_TREE is still ignored' '
270 +test_expect_success '#5: core.worktree + GIT_WORK_TREE is accepted' '
271 # or: you cannot intimidate away the lack of GIT_DIR setting
262 - try_repo 5 non-existent-too unset non-existent "" unset \
263 - .git "$here/5" "$here/5" "(null)" \
264 - .git "$here/5" "$here/5" sub/
272 + try_repo 5 "$here" unset "$here/5" "" unset \
273 + "$here/5/.git" "$here" "$here" 5/ \
274 + "$here/5/.git" "$here" "$here" 5/sub/ 2>message &&
275 + try_repo 5a .. unset "$here/5a" "" unset \
276 + "$here/5a/.git" "$here" "$here" 5a/ \
277 + "$here/5a/.git" "$here/5a" "$here/5a" sub/ &&
278 + ! test -s message
279 '
280
281 test_expect_success '#6: setting GIT_DIR brings core.worktree to life' '
@@ -353,10 +367,12 @@ test_expect_success '#8: gitfile, easy case' '
367 "$here/8.git" "$here/8" "$here/8" sub/
368 '
369
356 -test_expect_success '#9: GIT_WORK_TREE ignored even with gitfile' '
357 - try_repo 9 non-existent unset unset gitfile unset \
358 - "$here/9.git" "$here/9" "$here/9" "(null)" \
359 - "$here/9.git" "$here/9" "$here/9" sub/
370 +test_expect_success '#9: GIT_WORK_TREE accepted with gitfile' '
371 + mkdir -p 9/wt &&
372 + try_repo 9 wt unset unset gitfile unset \
373 + "$here/9.git" "$here/9/wt" "$here/9" "(null)" \
374 + "$here/9.git" "$here/9/sub/wt" "$here/9/sub" "(null)" 2>message &&
375 + ! test -s message
376 '
377
378 test_expect_success '#10: GIT_DIR can point to gitfile' '
@@ -378,17 +394,19 @@ test_expect_success '#11: setup' '
394 '
395 run_wt_tests 11 gitfile
396
381 -test_expect_success '#12: core.worktree with gitfile is still ignored' '
382 - try_repo 12 unset unset non-existent gitfile unset \
397 +test_expect_success '#12: core.worktree with gitfile is accepted' '
398 + try_repo 12 unset unset "$here/12" gitfile unset \
399 "$here/12.git" "$here/12" "$here/12" "(null)" \
384 - "$here/12.git" "$here/12" "$here/12" sub/
400 + "$here/12.git" "$here/12" "$here/12" sub/ 2>message &&
401 + ! test -s message
402 '
403
387 -test_expect_success '#13: core.worktree+GIT_WORK_TREE ignored (with gitfile)' '
404 +test_expect_success '#13: core.worktree+GIT_WORK_TREE accepted (with gitfile)' '
405 # or: you cannot intimidate away the lack of GIT_DIR setting
406 try_repo 13 non-existent-too unset non-existent gitfile unset \
390 - "$here/13.git" "$here/13" "$here/13" "(null)" \
391 - "$here/13.git" "$here/13" "$here/13" sub/
407 + "$here/13.git" "$here/13/non-existent-too" "$here/13" "(null)" \
408 + "$here/13.git" "$here/13/sub/non-existent-too" "$here/13/sub" "(null)" 2>message &&
409 + ! test -s message
410 '
411
412 # case #14.
@@ -499,30 +517,32 @@ test_expect_success '#16c: bare .git has no worktree' '
517 "$here/16c/.git" "(null)" "$here/16c/sub" "(null)"
518 '
519
502 -test_expect_success '#17: GIT_WORK_TREE without explicit GIT_DIR is ignored (bare case)' '
520 +test_expect_success '#17: GIT_WORK_TREE without explicit GIT_DIR is accepted (bare case)' '
521 # Just like #16.
522 setup_repo 17a unset "" true &&
523 setup_repo 17b unset "" true &&
524 mkdir -p 17a/.git/wt/sub &&
525 mkdir -p 17b/.git/wt/sub &&
526
509 - try_case 17a/.git non-existent unset \
510 - . "(null)" "$here/17a/.git" "(null)" &&
511 - try_case 17a/.git/wt non-existent unset \
512 - "$here/17a/.git" "(null)" "$here/17a/.git/wt" "(null)" &&
513 - try_case 17a/.git/wt/sub non-existent unset \
514 - "$here/17a/.git" "(null)" "$here/17a/.git/wt/sub" "(null)" &&
527 + try_case 17a/.git "$here/17a" unset \
528 + "$here/17a/.git" "$here/17a" "$here/17a" .git/ \
529 + 2>message &&
530 + try_case 17a/.git/wt "$here/17a" unset \
531 + "$here/17a/.git" "$here/17a" "$here/17a" .git/wt/ &&
532 + try_case 17a/.git/wt/sub "$here/17a" unset \
533 + "$here/17a/.git" "$here/17a" "$here/17a" .git/wt/sub/ &&
534
516 - try_case 17b/.git non-existent unset \
517 - . "(null)" "$here/17b/.git" "(null)" &&
518 - try_case 17b/.git/wt non-existent unset \
519 - "$here/17b/.git" "(null)" "$here/17b/.git/wt" "(null)" &&
520 - try_case 17b/.git/wt/sub non-existent unset \
521 - "$here/17b/.git" "(null)" "$here/17b/.git/wt/sub" "(null)" &&
535 + try_case 17b/.git "$here/17b" unset \
536 + "$here/17b/.git" "$here/17b" "$here/17b" .git/ &&
537 + try_case 17b/.git/wt "$here/17b" unset \
538 + "$here/17b/.git" "$here/17b" "$here/17b" .git/wt/ &&
539 + try_case 17b/.git/wt/sub "$here/17b" unset \
540 + "$here/17b/.git" "$here/17b" "$here/17b" .git/wt/sub/ &&
541
523 - try_repo 17c non-existent unset unset "" true \
524 - .git "(null)" "$here/17c" "(null)" \
525 - "$here/17c/.git" "(null)" "$here/17c/sub" "(null)"
542 + try_repo 17c "$here/17c" unset unset "" true \
543 + .git "$here/17c" "$here/17c" "(null)" \
544 + "$here/17c/.git" "$here/17c" "$here/17c" sub/ 2>message &&
545 + ! test -s message
546 '
547
548 test_expect_success '#18: bare .git named by GIT_DIR has no worktree' '
@@ -541,56 +561,43 @@ test_expect_success '#19: setup' '
561 '
562 run_wt_tests 19
563
544 -test_expect_success '#20a: core.worktree without GIT_DIR ignored (inside .git)' '
545 - # Just like case #16a.
546 - setup_repo 20a non-existent "" unset &&
564 +test_expect_success '#20a: core.worktree without GIT_DIR accepted (inside .git)' '
565 + # Unlike case #16a.
566 + setup_repo 20a "$here/20a" "" unset &&
567 mkdir -p 20a/.git/wt/sub &&
568 try_case 20a/.git unset unset \
549 - . "(null)" "$here/20a/.git" "(null)" &&
569 + "$here/20a/.git" "$here/20a" "$here/20a" .git/ 2>message &&
570 try_case 20a/.git/wt unset unset \
551 - "$here/20a/.git" "(null)" "$here/20a/.git/wt" "(null)" &&
571 + "$here/20a/.git" "$here/20a" "$here/20a" .git/wt/ &&
572 try_case 20a/.git/wt/sub unset unset \
553 - "$here/20a/.git" "(null)" "$here/20a/.git/wt/sub" "(null)"
573 + "$here/20a/.git" "$here/20a" "$here/20a" .git/wt/sub/ &&
574 + ! test -s message
575 '
576
556 -test_expect_success '#20b/c: core.worktree without GIT_DIR ignored (bare repository)' '
557 - # Just like case #16b/c.
577 +test_expect_success '#20b/c: core.worktree and core.bare conflict' '
578 setup_repo 20b non-existent "" true &&
579 mkdir -p 20b/.git/wt/sub &&
560 - try_case 20b/.git unset unset \
561 - . "(null)" "$here/20b/.git" "(null)" &&
562 - try_case 20b/.git/wt unset unset \
563 - "$here/20b/.git" "(null)" "$here/20b/.git/wt" "(null)" &&
564 - try_case 20b/.git/wt/sub unset unset \
565 - "$here/20b/.git" "(null)" "$here/20b/.git/wt/sub" "(null)" &&
566 - try_repo 20c unset unset non-existent "" true \
567 - .git "(null)" "$here/20c" "(null)" \
568 - "$here/20c/.git" "(null)" "$here/20c/sub" "(null)"
569 -'
570 -
571 -test_expect_success '#21: core.worktree+GIT_WORK_TREE without GIT_DIR ignored (bare cases)' '
572 - setup_repo 21a non-existent "" unset &&
573 - mkdir -p 21a/.git/wt/sub &&
574 - try_case 21a/.git non-existent-too unset \
575 - . "(null)" "$here/21a/.git" "(null)" &&
576 - try_case 21a/.git/wt non-existent-too unset \
577 - "$here/21a/.git" "(null)" "$here/21a/.git/wt" "(null)" &&
578 - try_case 21a/.git/wt/sub non-existent-too unset \
579 - "$here/21a/.git" "(null)" "$here/21a/.git/wt/sub" "(null)" &&
580 -
581 - setup_repo 21b non-existent "" true &&
582 - mkdir -p 21b/.git/wt/sub &&
583 - try_case 21b/.git non-existent-too unset \
584 - . "(null)" "$here/21b/.git" "(null)" &&
585 - try_case 21b/.git/wt non-existent-too unset \
586 - "$here/21b/.git" "(null)" "$here/21b/.git/wt" "(null)" &&
587 - try_case 21b/.git/wt/sub non-existent-too unset \
588 - "$here/21b/.git" "(null)" "$here/21b/.git/wt/sub" "(null)" &&
589 -
590 - try_repo 21c non-existent-too unset non-existent "" true \
591 - .git "(null)" "$here/21c" "(null)" \
592 - "$here/21c/.git" "(null)" "$here/21c/sub" "(null)"
580 + (
581 + cd 20b/.git &&
582 + test_must_fail git symbolic-ref HEAD >/dev/null
583 + ) 2>message &&
584 + grep "core.bare and core.worktree" message
585 +'
586 +
587 +# Case #21: core.worktree/GIT_WORK_TREE overrides core.bare' '
588 +test_expect_success '#21: setup, core.worktree warns before overriding core.bare' '
589 + setup_repo 21 non-existent "" unset &&
590 + mkdir -p 21/.git/wt/sub &&
591 + (
592 + cd 21/.git &&
593 + GIT_WORK_TREE="$here/21" &&
594 + export GIT_WORK_TREE &&
595 + git symbolic-ref HEAD >/dev/null
596 + ) 2>message &&
597 + ! test -s message
598 +
599 '
600 +run_wt_tests 21
601
602 test_expect_success '#22a: core.worktree = GIT_DIR = .git dir' '
603 # like case #6.
@@ -699,10 +706,11 @@ test_expect_success '#24: bare repo has no worktree (gitfile case)' '
706 "$here/24.git" "(null)" "$here/24/sub" "(null)"
707 '
708
702 -test_expect_success '#25: GIT_WORK_TREE ignored if GIT_DIR unset (bare gitfile case)' '
703 - try_repo 25 non-existent unset unset gitfile true \
704 - "$here/25.git" "(null)" "$here/25" "(null)" \
705 - "$here/25.git" "(null)" "$here/25/sub" "(null)"
709 +test_expect_success '#25: GIT_WORK_TREE accepted if GIT_DIR unset (bare gitfile case)' '
710 + try_repo 25 "$here/25" unset unset gitfile true \
711 + "$here/25.git" "$here/25" "$here/25" "(null)" \
712 + "$here/25.git" "$here/25" "$here/25" "sub/" 2>message &&
713 + ! test -s message
714 '
715
716 test_expect_success '#26: bare repo has no worktree (GIT_DIR -> gitfile case)' '
@@ -721,17 +729,29 @@ test_expect_success '#27: setup' '
729 '
730 run_wt_tests 27 gitfile
731
724 -test_expect_success '#28: core.worktree ignored if GIT_DIR unset (bare gitfile case)' '
725 - try_repo 28 unset unset non-existent gitfile true \
726 - "$here/28.git" "(null)" "$here/28" "(null)" \
727 - "$here/28.git" "(null)" "$here/28/sub" "(null)"
732 +test_expect_success '#28: core.worktree and core.bare conflict (gitfile case)' '
733 + setup_repo 28 "$here/28" gitfile true &&
734 + (
735 + cd 28 &&
736 + test_must_fail git symbolic-ref HEAD
737 + ) 2>message &&
738 + ! grep "^warning:" message &&
739 + grep "core.bare and core.worktree" message
740 '
741
730 -test_expect_success '#29: GIT_WORK_TREE+core.worktree ignored if GIT_DIR unset (bare gitfile case)' '
731 - try_repo 29 non-existent-too unset non-existent gitfile true \
732 - "$here/29.git" "(null)" "$here/29" "(null)" \
733 - "$here/29.git" "(null)" "$here/29/sub" "(null)"
734 -'
742 +# Case #29: GIT_WORK_TREE(+core.worktree) overries core.bare (gitfile case).
743 +test_expect_success '#29: setup' '
744 + setup_repo 29 non-existent gitfile true &&
745 + mkdir -p 29/sub/sub 29/wt/sub
746 + (
747 + cd 29 &&
748 + GIT_WORK_TREE="$here/29" &&
749 + export GIT_WORK_TREE &&
750 + git symbolic-ref HEAD >/dev/null
751 + ) 2>message &&
752 + ! test -s message
753 +'
754 +run_wt_tests 29 gitfile
755
756 test_expect_success '#30: core.worktree and core.bare conflict (gitfile version)' '
757 # Just like case #22.