@@ -381,29 +381,24 @@ int validate_worktree(const struct worktree *wt, struct strbuf *errmsg,
381381void update_worktree_location (struct worktree * wt , const char * path_ )
382382{
383383 struct strbuf path = STRBUF_INIT ;
384- struct strbuf repo = STRBUF_INIT ;
385- struct strbuf file = STRBUF_INIT ;
386- struct strbuf tmp = STRBUF_INIT ;
384+ struct strbuf dotgit = STRBUF_INIT ;
385+ struct strbuf gitdir = STRBUF_INIT ;
387386
388387 if (is_main_worktree (wt ))
389388 BUG ("can't relocate main worktree" );
390389
391- strbuf_realpath (& repo , git_common_path ("worktrees/%s" , wt -> id ), 1 );
390+ strbuf_realpath (& gitdir , git_common_path ("worktrees/%s/gitdir " , wt -> id ), 1 );
392391 strbuf_realpath (& path , path_ , 1 );
392+ strbuf_addf (& dotgit , "%s/.git" , path .buf );
393393 if (fspathcmp (wt -> path , path .buf )) {
394- strbuf_addf (& file , "%s/gitdir" , repo .buf );
395- write_file (file .buf , "%s/.git" , relative_path (path .buf , repo .buf , & tmp ));
396- strbuf_reset (& file );
397- strbuf_addf (& file , "%s/.git" , path .buf );
398- write_file (file .buf , "gitdir: %s" , relative_path (repo .buf , path .buf , & tmp ));
394+ write_worktree_linking_files (dotgit , gitdir );
399395
400396 free (wt -> path );
401397 wt -> path = strbuf_detach (& path , NULL );
402398 }
403399 strbuf_release (& path );
404- strbuf_release (& repo );
405- strbuf_release (& file );
406- strbuf_release (& tmp );
400+ strbuf_release (& dotgit );
401+ strbuf_release (& gitdir );
407402}
408403
409404int is_worktree_being_rebased (const struct worktree * wt ,
@@ -582,9 +577,9 @@ static void repair_gitfile(struct worktree *wt,
582577 worktree_repair_fn fn , void * cb_data )
583578{
584579 struct strbuf dotgit = STRBUF_INIT ;
580+ struct strbuf gitdir = STRBUF_INIT ;
585581 struct strbuf repo = STRBUF_INIT ;
586582 struct strbuf backlink = STRBUF_INIT ;
587- struct strbuf tmp = STRBUF_INIT ;
588583 char * dotgit_contents = NULL ;
589584 const char * repair = NULL ;
590585 int err ;
@@ -600,6 +595,7 @@ static void repair_gitfile(struct worktree *wt,
600595
601596 strbuf_realpath (& repo , git_common_path ("worktrees/%s" , wt -> id ), 1 );
602597 strbuf_addf (& dotgit , "%s/.git" , wt -> path );
598+ strbuf_addf (& gitdir , "%s/gitdir" , repo .buf );
603599 dotgit_contents = xstrdup_or_null (read_gitfile_gently (dotgit .buf , & err ));
604600
605601 if (dotgit_contents ) {
@@ -617,18 +613,20 @@ static void repair_gitfile(struct worktree *wt,
617613 repair = _ (".git file broken" );
618614 else if (fspathcmp (backlink .buf , repo .buf ))
619615 repair = _ (".git file incorrect" );
616+ else if (use_relative_paths == is_absolute_path (dotgit_contents ))
617+ repair = _ (".git file absolute/relative path mismatch" );
620618
621619 if (repair ) {
622620 fn (0 , wt -> path , repair , cb_data );
623- write_file (dotgit . buf , " gitdir: %s" , relative_path ( repo . buf , wt -> path , & tmp ) );
621+ write_worktree_linking_files (dotgit , gitdir );
624622 }
625623
626624done :
627625 free (dotgit_contents );
628626 strbuf_release (& repo );
629627 strbuf_release (& dotgit );
628+ strbuf_release (& gitdir );
630629 strbuf_release (& backlink );
631- strbuf_release (& tmp );
632630}
633631
634632static void repair_noop (int iserr UNUSED ,
@@ -653,45 +651,30 @@ void repair_worktrees(worktree_repair_fn fn, void *cb_data)
653651
654652void repair_worktree_after_gitdir_move (struct worktree * wt , const char * old_path )
655653{
656- struct strbuf path = STRBUF_INIT ;
657- struct strbuf repo = STRBUF_INIT ;
658654 struct strbuf gitdir = STRBUF_INIT ;
659655 struct strbuf dotgit = STRBUF_INIT ;
660- struct strbuf olddotgit = STRBUF_INIT ;
661- struct strbuf tmp = STRBUF_INIT ;
662656
663657 if (is_main_worktree (wt ))
664658 goto done ;
665659
666- strbuf_realpath (& repo , git_common_path ("worktrees/%s" , wt -> id ), 1 );
667- strbuf_addf (& gitdir , "%s/gitdir" , repo .buf );
660+ strbuf_realpath (& gitdir , git_common_path ("worktrees/%s/gitdir" , wt -> id ), 1 );
668661
669- if (strbuf_read_file (& olddotgit , gitdir .buf , 0 ) < 0 )
662+ if (strbuf_read_file (& dotgit , gitdir .buf , 0 ) < 0 )
670663 goto done ;
671664
672- strbuf_rtrim (& olddotgit );
673- if (is_absolute_path (olddotgit .buf )) {
674- strbuf_addbuf (& dotgit , & olddotgit );
675- } else {
676- strbuf_addf (& dotgit , "%s/worktrees/%s/%s" , old_path , wt -> id , olddotgit .buf );
665+ strbuf_rtrim (& dotgit );
666+ if (!is_absolute_path (dotgit .buf )) {
667+ strbuf_insertf (& dotgit , 0 , "%s/worktrees/%s/" , old_path , wt -> id );
677668 strbuf_realpath_forgiving (& dotgit , dotgit .buf , 0 );
678669 }
679670
680671 if (!file_exists (dotgit .buf ))
681672 goto done ;
682673
683- strbuf_addbuf (& path , & dotgit );
684- strbuf_strip_suffix (& path , "/.git" );
685-
686- write_file (dotgit .buf , "gitdir: %s" , relative_path (repo .buf , path .buf , & tmp ));
687- write_file (gitdir .buf , "%s" , relative_path (dotgit .buf , repo .buf , & tmp ));
674+ write_worktree_linking_files (dotgit , gitdir );
688675done :
689- strbuf_release (& path );
690- strbuf_release (& repo );
691676 strbuf_release (& gitdir );
692677 strbuf_release (& dotgit );
693- strbuf_release (& olddotgit );
694- strbuf_release (& tmp );
695678}
696679
697680void repair_worktrees_after_gitdir_move (const char * old_path )
@@ -766,13 +749,10 @@ void repair_worktree_at_path(const char *path,
766749 worktree_repair_fn fn , void * cb_data )
767750{
768751 struct strbuf dotgit = STRBUF_INIT ;
769- struct strbuf realdotgit = STRBUF_INIT ;
770752 struct strbuf backlink = STRBUF_INIT ;
771753 struct strbuf inferred_backlink = STRBUF_INIT ;
772754 struct strbuf gitdir = STRBUF_INIT ;
773755 struct strbuf olddotgit = STRBUF_INIT ;
774- struct strbuf realolddotgit = STRBUF_INIT ;
775- struct strbuf tmp = STRBUF_INIT ;
776756 char * dotgit_contents = NULL ;
777757 const char * repair = NULL ;
778758 int err ;
@@ -784,25 +764,25 @@ void repair_worktree_at_path(const char *path,
784764 goto done ;
785765
786766 strbuf_addf (& dotgit , "%s/.git" , path );
787- if (!strbuf_realpath (& realdotgit , dotgit .buf , 0 )) {
767+ if (!strbuf_realpath (& dotgit , dotgit .buf , 0 )) {
788768 fn (1 , path , _ ("not a valid path" ), cb_data );
789769 goto done ;
790770 }
791771
792- infer_backlink (realdotgit .buf , & inferred_backlink );
772+ infer_backlink (dotgit .buf , & inferred_backlink );
793773 strbuf_realpath_forgiving (& inferred_backlink , inferred_backlink .buf , 0 );
794- dotgit_contents = xstrdup_or_null (read_gitfile_gently (realdotgit .buf , & err ));
774+ dotgit_contents = xstrdup_or_null (read_gitfile_gently (dotgit .buf , & err ));
795775 if (dotgit_contents ) {
796776 if (is_absolute_path (dotgit_contents )) {
797777 strbuf_addstr (& backlink , dotgit_contents );
798778 } else {
799- strbuf_addbuf (& backlink , & realdotgit );
779+ strbuf_addbuf (& backlink , & dotgit );
800780 strbuf_strip_suffix (& backlink , ".git" );
801781 strbuf_addstr (& backlink , dotgit_contents );
802782 strbuf_realpath_forgiving (& backlink , backlink .buf , 0 );
803783 }
804784 } else if (err == READ_GITFILE_ERR_NOT_A_FILE ) {
805- fn (1 , realdotgit .buf , _ ("unable to locate repository; .git is not a file" ), cb_data );
785+ fn (1 , dotgit .buf , _ ("unable to locate repository; .git is not a file" ), cb_data );
806786 goto done ;
807787 } else if (err == READ_GITFILE_ERR_NOT_A_REPO ) {
808788 if (inferred_backlink .len ) {
@@ -815,11 +795,11 @@ void repair_worktree_at_path(const char *path,
815795 */
816796 strbuf_swap (& backlink , & inferred_backlink );
817797 } else {
818- fn (1 , realdotgit .buf , _ ("unable to locate repository; .git file does not reference a repository" ), cb_data );
798+ fn (1 , dotgit .buf , _ ("unable to locate repository; .git file does not reference a repository" ), cb_data );
819799 goto done ;
820800 }
821801 } else {
822- fn (1 , realdotgit .buf , _ ("unable to locate repository; .git file broken" ), cb_data );
802+ fn (1 , dotgit .buf , _ ("unable to locate repository; .git file broken" ), cb_data );
823803 goto done ;
824804 }
825805
@@ -841,39 +821,35 @@ void repair_worktree_at_path(const char *path,
841821 * in the "copy" repository. In this case, point the "copy" worktree's
842822 * .git file at the "copy" repository.
843823 */
844- if (inferred_backlink .len && fspathcmp (backlink .buf , inferred_backlink .buf )) {
824+ if (inferred_backlink .len && fspathcmp (backlink .buf , inferred_backlink .buf ))
845825 strbuf_swap (& backlink , & inferred_backlink );
846- }
847826
848827 strbuf_addf (& gitdir , "%s/gitdir" , backlink .buf );
849828 if (strbuf_read_file (& olddotgit , gitdir .buf , 0 ) < 0 )
850829 repair = _ ("gitdir unreadable" );
830+ else if (use_relative_paths == is_absolute_path (olddotgit .buf ))
831+ repair = _ ("gitdir absolute/relative path mismatch" );
851832 else {
852833 strbuf_rtrim (& olddotgit );
853- if (is_absolute_path (olddotgit .buf )) {
854- strbuf_addbuf (& realolddotgit , & olddotgit );
855- } else {
856- strbuf_addf (& realolddotgit , "%s/%s" , backlink .buf , olddotgit .buf );
857- strbuf_realpath_forgiving (& realolddotgit , realolddotgit .buf , 0 );
834+ if (!is_absolute_path (olddotgit .buf )) {
835+ strbuf_insertf (& olddotgit , 0 , "%s/" , backlink .buf );
836+ strbuf_realpath_forgiving (& olddotgit , olddotgit .buf , 0 );
858837 }
859- if (fspathcmp (realolddotgit .buf , realdotgit .buf ))
838+ if (fspathcmp (olddotgit .buf , dotgit .buf ))
860839 repair = _ ("gitdir incorrect" );
861840 }
862841
863842 if (repair ) {
864843 fn (0 , gitdir .buf , repair , cb_data );
865- write_file ( gitdir . buf , "%s" , relative_path ( realdotgit . buf , backlink . buf , & tmp ) );
844+ write_worktree_linking_files ( dotgit , gitdir );
866845 }
867846done :
868847 free (dotgit_contents );
869848 strbuf_release (& olddotgit );
870- strbuf_release (& realolddotgit );
871849 strbuf_release (& backlink );
872850 strbuf_release (& inferred_backlink );
873851 strbuf_release (& gitdir );
874- strbuf_release (& realdotgit );
875852 strbuf_release (& dotgit );
876- strbuf_release (& tmp );
877853}
878854
879855int should_prune_worktree (const char * id , struct strbuf * reason , char * * wtpath , timestamp_t expire )
@@ -1034,3 +1010,29 @@ int init_worktree_config(struct repository *r)
10341010 free (main_worktree_file );
10351011 return res ;
10361012}
1013+
1014+ void write_worktree_linking_files (struct strbuf dotgit , struct strbuf gitdir )
1015+ {
1016+ struct strbuf path = STRBUF_INIT ;
1017+ struct strbuf repo = STRBUF_INIT ;
1018+ struct strbuf tmp = STRBUF_INIT ;
1019+
1020+ strbuf_addbuf (& path , & dotgit );
1021+ strbuf_strip_suffix (& path , "/.git" );
1022+ strbuf_realpath (& path , path .buf , 1 );
1023+ strbuf_addbuf (& repo , & gitdir );
1024+ strbuf_strip_suffix (& repo , "/gitdir" );
1025+ strbuf_realpath (& repo , repo .buf , 1 );
1026+
1027+ if (use_relative_paths ) {
1028+ write_file (gitdir .buf , "%s/.git" , relative_path (path .buf , repo .buf , & tmp ));
1029+ write_file (dotgit .buf , "gitdir: %s" , relative_path (repo .buf , path .buf , & tmp ));
1030+ } else {
1031+ write_file (gitdir .buf , "%s/.git" , path .buf );
1032+ write_file (dotgit .buf , "gitdir: %s" , repo .buf );
1033+ }
1034+
1035+ strbuf_release (& path );
1036+ strbuf_release (& repo );
1037+ strbuf_release (& tmp );
1038+ }
0 commit comments