File tree Expand file tree Collapse file tree 2 files changed +26
-0
lines changed Expand file tree Collapse file tree 2 files changed +26
-0
lines changed Original file line number Diff line number Diff line change @@ -341,11 +341,14 @@ private struct IndexOutOfDateChecker {
341341
342342  private  enum  Error :  Swift . Error ,  CustomStringConvertible  { 
343343    case  fileAttributesDontHaveModificationDate
344+     case  circularSymlink( URL ) 
344345
345346    var  description :  String  { 
346347      switch  self  { 
347348      case  . fileAttributesDontHaveModificationDate: 
348349        return  " File attributes don't contain a modification date " 
350+       case  . circularSymlink( let  url) : 
351+         return  " Circular symlink at  \( url) " 
349352      } 
350353    } 
351354  } 
@@ -484,6 +487,8 @@ private struct IndexOutOfDateChecker {
484487      } 
485488      var  modificationDate  =  try Self . modificationDate ( atPath:  fileURL. filePath) 
486489
490+       var  visited :  Set < URL >  =  [ fileURL] 
491+ 
487492      // Get the maximum mtime in the symlink chain as the modification date of the URI. That way if either the symlink
488493      // is changed to point to a different file or if the underlying file is modified, the modification time is
489494      // updated.
@@ -492,6 +497,9 @@ private struct IndexOutOfDateChecker {
492497      ) , 
493498        let  symlinkDestination =  URL ( string:  relativeSymlinkDestination,  relativeTo:  fileURL) 
494499      { 
500+         if  !visited. insert ( symlinkDestination) . inserted { 
501+           throw  Error . circularSymlink ( symlinkDestination) 
502+         } 
495503        fileURL =  symlinkDestination
496504        modificationDate =  max ( modificationDate,  try Self . modificationDate ( atPath:  fileURL. filePath) ) 
497505      } 
Original file line number Diff line number Diff line change @@ -2281,6 +2281,24 @@ final class BackgroundIndexingTests: XCTestCase {
22812281    try await  project. testClient. send ( SynchronizeRequest ( index:  true ) ) 
22822282    XCTAssertEqual ( indexedFiles. value,  [ try . uri ( for:  " test.c " ) ] ) 
22832283  } 
2284+ 
2285+   func  testCircularSymlink( )  async  throws  { 
2286+     let  project  =  try await  SwiftPMTestProject ( 
2287+       files:  [ 
2288+         " Symlink.swift " :  " " 
2289+       ] , 
2290+       enableBackgroundIndexing:  true 
2291+     ) 
2292+     let  circularSymlink  =  try XCTUnwrap ( project. uri ( for:  " Symlink.swift " ) . fileURL) 
2293+     try FileManager . default. removeItem ( at:  circularSymlink) 
2294+     try FileManager . default. createSymbolicLink ( at:  circularSymlink,  withDestinationURL:  circularSymlink) 
2295+ 
2296+     project. testClient. send ( 
2297+       DidChangeWatchedFilesNotification ( changes:  [ FileEvent ( uri:  URI ( circularSymlink) ,  type:  . changed) ] ) 
2298+     ) 
2299+     // Check that we don't enter an infinite loop trying to index the circular symlink.
2300+     try await  project. testClient. send ( SynchronizeRequest ( index:  true ) ) 
2301+   } 
22842302} 
22852303
22862304extension  HoverResponseContents  { 
 
 
   
 
     
   
   
          
    
    
     
    
      
     
     
    You can’t perform that action at this time.
  
 
    
  
    
      
        
     
       
      
     
   
 
    
    
  
 
  
 
     
    
0 commit comments