@@ -573,12 +573,13 @@ int other_head_refs(each_ref_fn fn, void *cb_data)
573573 * pointing at <repo>/worktrees/<id>.
574574 */
575575static void repair_gitfile (struct worktree * wt ,
576- worktree_repair_fn fn , void * cb_data )
576+ worktree_repair_fn fn , void * cb_data ,
577+ int use_relative_paths )
577578{
578579 struct strbuf dotgit = STRBUF_INIT ;
580+ struct strbuf gitdir = STRBUF_INIT ;
579581 struct strbuf repo = STRBUF_INIT ;
580582 struct strbuf backlink = STRBUF_INIT ;
581- struct strbuf tmp = STRBUF_INIT ;
582583 char * dotgit_contents = NULL ;
583584 const char * repair = NULL ;
584585 int err ;
@@ -594,6 +595,7 @@ static void repair_gitfile(struct worktree *wt,
594595
595596 strbuf_realpath (& repo , git_common_path ("worktrees/%s" , wt -> id ), 1 );
596597 strbuf_addf (& dotgit , "%s/.git" , wt -> path );
598+ strbuf_addf (& gitdir , "%s/gitdir" , repo .buf );
597599 dotgit_contents = xstrdup_or_null (read_gitfile_gently (dotgit .buf , & err ));
598600
599601 if (dotgit_contents ) {
@@ -611,18 +613,20 @@ static void repair_gitfile(struct worktree *wt,
611613 repair = _ (".git file broken" );
612614 else if (fspathcmp (backlink .buf , repo .buf ))
613615 repair = _ (".git file incorrect" );
616+ else if (use_relative_paths == is_absolute_path (dotgit_contents ))
617+ repair = _ (".git file absolute/relative path mismatch" );
614618
615619 if (repair ) {
616620 fn (0 , wt -> path , repair , cb_data );
617- write_file (dotgit . buf , " gitdir: %s" , relative_path ( repo . buf , wt -> path , & tmp ) );
621+ write_worktree_linking_files (dotgit , gitdir , use_relative_paths );
618622 }
619623
620624done :
621625 free (dotgit_contents );
622626 strbuf_release (& repo );
623627 strbuf_release (& dotgit );
628+ strbuf_release (& gitdir );
624629 strbuf_release (& backlink );
625- strbuf_release (& tmp );
626630}
627631
628632static void repair_noop (int iserr UNUSED ,
@@ -633,15 +637,15 @@ static void repair_noop(int iserr UNUSED,
633637 /* nothing */
634638}
635639
636- void repair_worktrees (worktree_repair_fn fn , void * cb_data )
640+ void repair_worktrees (worktree_repair_fn fn , void * cb_data , int use_relative_paths )
637641{
638642 struct worktree * * worktrees = get_worktrees_internal (1 );
639643 struct worktree * * wt = worktrees + 1 ; /* +1 skips main worktree */
640644
641645 if (!fn )
642646 fn = repair_noop ;
643647 for (; * wt ; wt ++ )
644- repair_gitfile (* wt , fn , cb_data );
648+ repair_gitfile (* wt , fn , cb_data , use_relative_paths );
645649 free_worktrees (worktrees );
646650}
647651
@@ -757,16 +761,14 @@ static ssize_t infer_backlink(const char *gitfile, struct strbuf *inferred)
757761 * the worktree's path.
758762 */
759763void repair_worktree_at_path (const char * path ,
760- worktree_repair_fn fn , void * cb_data )
764+ worktree_repair_fn fn , void * cb_data ,
765+ int use_relative_paths )
761766{
762767 struct strbuf dotgit = STRBUF_INIT ;
763- struct strbuf realdotgit = STRBUF_INIT ;
764768 struct strbuf backlink = STRBUF_INIT ;
765769 struct strbuf inferred_backlink = STRBUF_INIT ;
766770 struct strbuf gitdir = STRBUF_INIT ;
767771 struct strbuf olddotgit = STRBUF_INIT ;
768- struct strbuf realolddotgit = STRBUF_INIT ;
769- struct strbuf tmp = STRBUF_INIT ;
770772 char * dotgit_contents = NULL ;
771773 const char * repair = NULL ;
772774 int err ;
@@ -778,25 +780,25 @@ void repair_worktree_at_path(const char *path,
778780 goto done ;
779781
780782 strbuf_addf (& dotgit , "%s/.git" , path );
781- if (!strbuf_realpath (& realdotgit , dotgit .buf , 0 )) {
783+ if (!strbuf_realpath (& dotgit , dotgit .buf , 0 )) {
782784 fn (1 , path , _ ("not a valid path" ), cb_data );
783785 goto done ;
784786 }
785787
786- infer_backlink (realdotgit .buf , & inferred_backlink );
788+ infer_backlink (dotgit .buf , & inferred_backlink );
787789 strbuf_realpath_forgiving (& inferred_backlink , inferred_backlink .buf , 0 );
788- dotgit_contents = xstrdup_or_null (read_gitfile_gently (realdotgit .buf , & err ));
790+ dotgit_contents = xstrdup_or_null (read_gitfile_gently (dotgit .buf , & err ));
789791 if (dotgit_contents ) {
790792 if (is_absolute_path (dotgit_contents )) {
791793 strbuf_addstr (& backlink , dotgit_contents );
792794 } else {
793- strbuf_addbuf (& backlink , & realdotgit );
795+ strbuf_addbuf (& backlink , & dotgit );
794796 strbuf_strip_suffix (& backlink , ".git" );
795797 strbuf_addstr (& backlink , dotgit_contents );
796798 strbuf_realpath_forgiving (& backlink , backlink .buf , 0 );
797799 }
798800 } else if (err == READ_GITFILE_ERR_NOT_A_FILE ) {
799- fn (1 , realdotgit .buf , _ ("unable to locate repository; .git is not a file" ), cb_data );
801+ fn (1 , dotgit .buf , _ ("unable to locate repository; .git is not a file" ), cb_data );
800802 goto done ;
801803 } else if (err == READ_GITFILE_ERR_NOT_A_REPO ) {
802804 if (inferred_backlink .len ) {
@@ -809,11 +811,11 @@ void repair_worktree_at_path(const char *path,
809811 */
810812 strbuf_swap (& backlink , & inferred_backlink );
811813 } else {
812- fn (1 , realdotgit .buf , _ ("unable to locate repository; .git file does not reference a repository" ), cb_data );
814+ fn (1 , dotgit .buf , _ ("unable to locate repository; .git file does not reference a repository" ), cb_data );
813815 goto done ;
814816 }
815817 } else {
816- fn (1 , realdotgit .buf , _ ("unable to locate repository; .git file broken" ), cb_data );
818+ fn (1 , dotgit .buf , _ ("unable to locate repository; .git file broken" ), cb_data );
817819 goto done ;
818820 }
819821
@@ -835,39 +837,35 @@ void repair_worktree_at_path(const char *path,
835837 * in the "copy" repository. In this case, point the "copy" worktree's
836838 * .git file at the "copy" repository.
837839 */
838- if (inferred_backlink .len && fspathcmp (backlink .buf , inferred_backlink .buf )) {
840+ if (inferred_backlink .len && fspathcmp (backlink .buf , inferred_backlink .buf ))
839841 strbuf_swap (& backlink , & inferred_backlink );
840- }
841842
842843 strbuf_addf (& gitdir , "%s/gitdir" , backlink .buf );
843844 if (strbuf_read_file (& olddotgit , gitdir .buf , 0 ) < 0 )
844845 repair = _ ("gitdir unreadable" );
846+ else if (use_relative_paths == is_absolute_path (olddotgit .buf ))
847+ repair = _ ("gitdir absolute/relative path mismatch" );
845848 else {
846849 strbuf_rtrim (& olddotgit );
847- if (is_absolute_path (olddotgit .buf )) {
848- strbuf_addbuf (& realolddotgit , & olddotgit );
849- } else {
850- strbuf_addf (& realolddotgit , "%s/%s" , backlink .buf , olddotgit .buf );
851- strbuf_realpath_forgiving (& realolddotgit , realolddotgit .buf , 0 );
850+ if (!is_absolute_path (olddotgit .buf )) {
851+ strbuf_insertf (& olddotgit , 0 , "%s/" , backlink .buf );
852+ strbuf_realpath_forgiving (& olddotgit , olddotgit .buf , 0 );
852853 }
853- if (fspathcmp (realolddotgit .buf , realdotgit .buf ))
854+ if (fspathcmp (olddotgit .buf , dotgit .buf ))
854855 repair = _ ("gitdir incorrect" );
855856 }
856857
857858 if (repair ) {
858859 fn (0 , gitdir .buf , repair , cb_data );
859- write_file ( gitdir . buf , "%s" , relative_path ( realdotgit . buf , backlink . buf , & tmp ) );
860+ write_worktree_linking_files ( dotgit , gitdir , use_relative_paths );
860861 }
861862done :
862863 free (dotgit_contents );
863864 strbuf_release (& olddotgit );
864- strbuf_release (& realolddotgit );
865865 strbuf_release (& backlink );
866866 strbuf_release (& inferred_backlink );
867867 strbuf_release (& gitdir );
868- strbuf_release (& realdotgit );
869868 strbuf_release (& dotgit );
870- strbuf_release (& tmp );
871869}
872870
873871int should_prune_worktree (const char * id , struct strbuf * reason , char * * wtpath , timestamp_t expire )
0 commit comments