@@ -165,6 +165,13 @@ public async Task<OperationResult<LibraryInstallationGoalState>> GetInstallation
165165
166166 #endregion
167167
168+ /// <summary>
169+ /// Generates the goal state for library installation based on the desired state and library information.
170+ /// </summary>
171+ /// <param name="desiredState">Specifies the target state for the library installation, including file mappings and destination paths.</param>
172+ /// <param name="library">Represents the library from which files are being installed, containing file information and validation
173+ /// methods.</param>
174+ /// <returns>Returns an operation result containing the goal state or errors encountered during the generation process.</returns>
168175 private OperationResult < LibraryInstallationGoalState > GenerateGoalState ( ILibraryInstallationState desiredState , ILibrary library )
169176 {
170177 var mappings = new List < FileMapping > ( desiredState . FileMappings ?? [ ] ) ;
@@ -212,33 +219,26 @@ private OperationResult<LibraryInstallationGoalState> GenerateGoalState(ILibrary
212219 fileFilters = fileFilters . Select ( f => $ "{ mappingRoot } /{ f } ") . ToList ( ) ;
213220 }
214221
215- List < string > outFiles = FileGlobbingUtility . ExpandFileGlobs ( fileFilters , library . Files . Keys ) . ToList ( ) ;
222+ List < string > filteredFiles = FileGlobbingUtility . ExpandFileGlobs ( fileFilters , library . Files . Keys ) . ToList ( ) ;
216223
217- if ( library . GetInvalidFiles ( outFiles ) is IReadOnlyList < string > invalidFiles
218- && invalidFiles . Count > 0 )
224+ if ( library . GetInvalidFiles ( filteredFiles ) is IReadOnlyList < string > { Count : > 0 } invalidFiles )
219225 {
220226 errors ??= [ ] ;
221227 errors . Add ( PredefinedErrors . InvalidFilesInLibrary ( desiredState . Name , invalidFiles , library . Files . Keys ) ) ;
228+ filteredFiles . RemoveAll ( file => invalidFiles . Contains ( file ) ) ;
222229 }
223230
224- foreach ( string outFile in outFiles )
225- {
226- // strip the source prefix
227- string relativeOutFile = mappingRoot . Length > 0 ? outFile . Substring ( mappingRoot . Length + 1 ) : outFile ;
228- string destinationFile = Path . Combine ( HostInteraction . WorkingDirectory , destination , relativeOutFile ) ;
229- destinationFile = FileHelpers . NormalizePath ( destinationFile ) ;
231+ Dictionary < string , string > fileMappings = GetFileMappings ( library , filteredFiles , mappingRoot , destination , desiredState , errors ) ;
230232
233+ foreach ( ( string destinationFile , string sourceFile ) in fileMappings )
234+ {
231235 if ( ! FileHelpers . IsUnderRootDirectory ( destinationFile , HostInteraction . WorkingDirectory ) )
232236 {
233237 errors ??= [ ] ;
234238 errors . Add ( PredefinedErrors . PathOutsideWorkingDirectory ( ) ) ;
235239 continue ;
236240 }
237241
238- // include the cache folder in the path
239- string sourceFile = GetCachedFileLocalPath ( desiredState , outFile ) ;
240- sourceFile = FileHelpers . NormalizePath ( sourceFile ) ;
241-
242242 // map destination back to the library-relative file it originated from
243243 if ( installFiles . ContainsKey ( destinationFile ) )
244244 {
@@ -248,10 +248,8 @@ private OperationResult<LibraryInstallationGoalState> GenerateGoalState(ILibrary
248248 errors . Add ( PredefinedErrors . LibraryCannotBeInstalledDueToConflicts ( destinationFile , [ libraryId ] ) ) ;
249249 continue ;
250250 }
251- else
252- {
253- installFiles . Add ( destinationFile , sourceFile ) ;
254- }
251+
252+ installFiles . Add ( destinationFile , sourceFile ) ;
255253 }
256254 }
257255
@@ -264,6 +262,28 @@ private OperationResult<LibraryInstallationGoalState> GenerateGoalState(ILibrary
264262 return OperationResult < LibraryInstallationGoalState > . FromSuccess ( goalState ) ;
265263 }
266264
265+
266+ protected virtual Dictionary < string , string > GetFileMappings ( ILibrary library , IReadOnlyList < string > libraryFiles , string mappingRoot , string destination , ILibraryInstallationState desiredState , List < IError > errors )
267+ {
268+ Dictionary < string , string > installFiles = new ( StringComparer . OrdinalIgnoreCase ) ;
269+
270+ foreach ( string file in libraryFiles )
271+ {
272+ // strip the source prefix
273+ string relativeOutFile = mappingRoot . Length > 0 ? file . Substring ( mappingRoot . Length + 1 ) : file ;
274+ string destinationFile = Path . Combine ( HostInteraction . WorkingDirectory , destination , relativeOutFile ) ;
275+ destinationFile = FileHelpers . NormalizePath ( destinationFile ) ;
276+
277+ // include the cache folder in the path
278+ string sourceFile = GetCachedFileLocalPath ( desiredState , file ) ;
279+ sourceFile = FileHelpers . NormalizePath ( sourceFile ) ;
280+
281+ installFiles . Add ( destinationFile , sourceFile ) ;
282+ }
283+
284+ return installFiles ;
285+ }
286+
267287 public bool IsSourceCacheReady ( LibraryInstallationGoalState goalState )
268288 {
269289 foreach ( KeyValuePair < string , string > item in goalState . InstalledFiles )
0 commit comments