@@ -574,12 +574,14 @@ int other_head_refs(each_ref_fn fn, void *cb_data)
574574 * pointing at <repo>/worktrees/<id>.
575575 */
576576static void repair_gitfile (struct worktree * wt ,
577- worktree_repair_fn fn , void * cb_data )
577+ worktree_repair_fn fn ,
578+ void * cb_data ,
579+ int use_relative_paths )
578580{
579581 struct strbuf dotgit = STRBUF_INIT ;
582+ struct strbuf gitdir = STRBUF_INIT ;
580583 struct strbuf repo = STRBUF_INIT ;
581584 struct strbuf backlink = STRBUF_INIT ;
582- struct strbuf tmp = STRBUF_INIT ;
583585 char * dotgit_contents = NULL ;
584586 const char * repair = NULL ;
585587 int err ;
@@ -595,6 +597,7 @@ static void repair_gitfile(struct worktree *wt,
595597
596598 strbuf_realpath (& repo , git_common_path ("worktrees/%s" , wt -> id ), 1 );
597599 strbuf_addf (& dotgit , "%s/.git" , wt -> path );
600+ strbuf_addf (& gitdir , "%s/gitdir" , repo .buf );
598601 dotgit_contents = xstrdup_or_null (read_gitfile_gently (dotgit .buf , & err ));
599602
600603 if (dotgit_contents ) {
@@ -612,18 +615,20 @@ static void repair_gitfile(struct worktree *wt,
612615 repair = _ (".git file broken" );
613616 else if (fspathcmp (backlink .buf , repo .buf ))
614617 repair = _ (".git file incorrect" );
618+ else if (use_relative_paths == is_absolute_path (dotgit_contents ))
619+ repair = _ (".git file absolute/relative path mismatch" );
615620
616621 if (repair ) {
617622 fn (0 , wt -> path , repair , cb_data );
618- write_file (dotgit . buf , " gitdir: %s" , relative_path ( repo . buf , wt -> path , & tmp ) );
623+ write_worktree_linking_files (dotgit , gitdir , use_relative_paths );
619624 }
620625
621626done :
622627 free (dotgit_contents );
623628 strbuf_release (& repo );
624629 strbuf_release (& dotgit );
630+ strbuf_release (& gitdir );
625631 strbuf_release (& backlink );
626- strbuf_release (& tmp );
627632}
628633
629634static void repair_noop (int iserr UNUSED ,
@@ -634,15 +639,15 @@ static void repair_noop(int iserr UNUSED,
634639 /* nothing */
635640}
636641
637- void repair_worktrees (worktree_repair_fn fn , void * cb_data )
642+ void repair_worktrees (worktree_repair_fn fn , void * cb_data , int use_relative_paths )
638643{
639644 struct worktree * * worktrees = get_worktrees_internal (1 );
640645 struct worktree * * wt = worktrees + 1 ; /* +1 skips main worktree */
641646
642647 if (!fn )
643648 fn = repair_noop ;
644649 for (; * wt ; wt ++ )
645- repair_gitfile (* wt , fn , cb_data );
650+ repair_gitfile (* wt , fn , cb_data , use_relative_paths );
646651 free_worktrees (worktrees );
647652}
648653
@@ -758,16 +763,15 @@ static ssize_t infer_backlink(const char *gitfile, struct strbuf *inferred)
758763 * the worktree's path.
759764 */
760765void repair_worktree_at_path (const char * path ,
761- worktree_repair_fn fn , void * cb_data )
766+ worktree_repair_fn fn ,
767+ void * cb_data ,
768+ int use_relative_paths )
762769{
763770 struct strbuf dotgit = STRBUF_INIT ;
764- struct strbuf realdotgit = STRBUF_INIT ;
765771 struct strbuf backlink = STRBUF_INIT ;
766772 struct strbuf inferred_backlink = STRBUF_INIT ;
767773 struct strbuf gitdir = STRBUF_INIT ;
768774 struct strbuf olddotgit = STRBUF_INIT ;
769- struct strbuf realolddotgit = STRBUF_INIT ;
770- struct strbuf tmp = STRBUF_INIT ;
771775 char * dotgit_contents = NULL ;
772776 const char * repair = NULL ;
773777 int err ;
@@ -779,25 +783,25 @@ void repair_worktree_at_path(const char *path,
779783 goto done ;
780784
781785 strbuf_addf (& dotgit , "%s/.git" , path );
782- if (!strbuf_realpath (& realdotgit , dotgit .buf , 0 )) {
786+ if (!strbuf_realpath (& dotgit , dotgit .buf , 0 )) {
783787 fn (1 , path , _ ("not a valid path" ), cb_data );
784788 goto done ;
785789 }
786790
787- infer_backlink (realdotgit .buf , & inferred_backlink );
791+ infer_backlink (dotgit .buf , & inferred_backlink );
788792 strbuf_realpath_forgiving (& inferred_backlink , inferred_backlink .buf , 0 );
789- dotgit_contents = xstrdup_or_null (read_gitfile_gently (realdotgit .buf , & err ));
793+ dotgit_contents = xstrdup_or_null (read_gitfile_gently (dotgit .buf , & err ));
790794 if (dotgit_contents ) {
791795 if (is_absolute_path (dotgit_contents )) {
792796 strbuf_addstr (& backlink , dotgit_contents );
793797 } else {
794- strbuf_addbuf (& backlink , & realdotgit );
798+ strbuf_addbuf (& backlink , & dotgit );
795799 strbuf_strip_suffix (& backlink , ".git" );
796800 strbuf_addstr (& backlink , dotgit_contents );
797801 strbuf_realpath_forgiving (& backlink , backlink .buf , 0 );
798802 }
799803 } else if (err == READ_GITFILE_ERR_NOT_A_FILE ) {
800- fn (1 , realdotgit .buf , _ ("unable to locate repository; .git is not a file" ), cb_data );
804+ fn (1 , dotgit .buf , _ ("unable to locate repository; .git is not a file" ), cb_data );
801805 goto done ;
802806 } else if (err == READ_GITFILE_ERR_NOT_A_REPO ) {
803807 if (inferred_backlink .len ) {
@@ -810,11 +814,11 @@ void repair_worktree_at_path(const char *path,
810814 */
811815 strbuf_swap (& backlink , & inferred_backlink );
812816 } else {
813- fn (1 , realdotgit .buf , _ ("unable to locate repository; .git file does not reference a repository" ), cb_data );
817+ fn (1 , dotgit .buf , _ ("unable to locate repository; .git file does not reference a repository" ), cb_data );
814818 goto done ;
815819 }
816820 } else {
817- fn (1 , realdotgit .buf , _ ("unable to locate repository; .git file broken" ), cb_data );
821+ fn (1 , dotgit .buf , _ ("unable to locate repository; .git file broken" ), cb_data );
818822 goto done ;
819823 }
820824
@@ -836,39 +840,35 @@ void repair_worktree_at_path(const char *path,
836840 * in the "copy" repository. In this case, point the "copy" worktree's
837841 * .git file at the "copy" repository.
838842 */
839- if (inferred_backlink .len && fspathcmp (backlink .buf , inferred_backlink .buf )) {
843+ if (inferred_backlink .len && fspathcmp (backlink .buf , inferred_backlink .buf ))
840844 strbuf_swap (& backlink , & inferred_backlink );
841- }
842845
843846 strbuf_addf (& gitdir , "%s/gitdir" , backlink .buf );
844847 if (strbuf_read_file (& olddotgit , gitdir .buf , 0 ) < 0 )
845848 repair = _ ("gitdir unreadable" );
849+ else if (use_relative_paths == is_absolute_path (olddotgit .buf ))
850+ repair = _ ("gitdir absolute/relative path mismatch" );
846851 else {
847852 strbuf_rtrim (& olddotgit );
848- if (is_absolute_path (olddotgit .buf )) {
849- strbuf_addbuf (& realolddotgit , & olddotgit );
850- } else {
851- strbuf_addf (& realolddotgit , "%s/%s" , backlink .buf , olddotgit .buf );
852- strbuf_realpath_forgiving (& realolddotgit , realolddotgit .buf , 0 );
853+ if (!is_absolute_path (olddotgit .buf )) {
854+ strbuf_insertf (& olddotgit , 0 , "%s/" , backlink .buf );
855+ strbuf_realpath_forgiving (& olddotgit , olddotgit .buf , 0 );
853856 }
854- if (fspathcmp (realolddotgit .buf , realdotgit .buf ))
857+ if (fspathcmp (olddotgit .buf , dotgit .buf ))
855858 repair = _ ("gitdir incorrect" );
856859 }
857860
858861 if (repair ) {
859862 fn (0 , gitdir .buf , repair , cb_data );
860- write_file ( gitdir . buf , "%s" , relative_path ( realdotgit . buf , backlink . buf , & tmp ) );
863+ write_worktree_linking_files ( dotgit , gitdir , use_relative_paths );
861864 }
862865done :
863866 free (dotgit_contents );
864867 strbuf_release (& olddotgit );
865- strbuf_release (& realolddotgit );
866868 strbuf_release (& backlink );
867869 strbuf_release (& inferred_backlink );
868870 strbuf_release (& gitdir );
869- strbuf_release (& realdotgit );
870871 strbuf_release (& dotgit );
871- strbuf_release (& tmp );
872872}
873873
874874int should_prune_worktree (const char * id , struct strbuf * reason , char * * wtpath , timestamp_t expire )
0 commit comments