Skip to content

Commit 639bf3e

Browse files
committed
Use FileMappings when calculating the GoalState
1 parent 7bcab36 commit 639bf3e

File tree

3 files changed

+376
-55
lines changed

3 files changed

+376
-55
lines changed

src/LibraryManager/Json/LibraryStateToFileConverter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public ILibraryInstallationState ConvertToLibraryInstallationState(LibraryInstal
3535
ProviderId = provider,
3636
DestinationPath = destination,
3737
Files = stateOnDisk.Files,
38-
FileMappings = stateOnDisk.FileMappings.Select(f => new Contracts.FileMapping { Destination = f.Destination, Root = f.Root, Files = f.Files }).ToList(),
38+
FileMappings = stateOnDisk.FileMappings?.Select(f => new Contracts.FileMapping { Destination = f.Destination, Root = f.Root, Files = f.Files }).ToList(),
3939
};
4040

4141
(state.Name, state.Version) = LibraryIdToNameAndVersionConverter.Instance.GetLibraryNameAndVersion(stateOnDisk.LibraryId, provider);

src/LibraryManager/Providers/BaseProvider.cs

Lines changed: 72 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -247,48 +247,92 @@ public async Task<OperationResult<LibraryInstallationGoalState>> GetInstallation
247247

248248
private OperationResult<LibraryInstallationGoalState> GenerateGoalState(ILibraryInstallationState desiredState, ILibrary library)
249249
{
250+
var mappings = new List<FileMapping>(desiredState.FileMappings ?? []);
250251
List<IError> errors = null;
251-
252-
if (string.IsNullOrEmpty(desiredState.DestinationPath))
253-
{
254-
return OperationResult<LibraryInstallationGoalState>.FromError(PredefinedErrors.DestinationNotSpecified(desiredState.Name));
255-
}
256-
257-
IEnumerable<string> outFiles;
258-
if (desiredState.Files == null || desiredState.Files.Count == 0)
252+
if (desiredState.Files is { Count: > 0 })
259253
{
260-
outFiles = library.Files.Keys;
254+
mappings.Add(new FileMapping { Destination = desiredState.DestinationPath, Files = desiredState.Files });
261255
}
262-
else
256+
else if (desiredState.FileMappings is null or { Count: 0 })
263257
{
264-
outFiles = FileGlobbingUtility.ExpandFileGlobs(desiredState.Files, library.Files.Keys);
258+
// no files specified and no file mappings => include all files
259+
mappings.Add(new FileMapping { Destination = desiredState.DestinationPath });
265260
}
266261

267262
Dictionary<string, string> installFiles = new();
268-
if (library.GetInvalidFiles(outFiles.ToList()) is IReadOnlyList<string> invalidFiles
269-
&& invalidFiles.Count > 0)
270-
{
271-
errors ??= [];
272-
errors.Add(PredefinedErrors.InvalidFilesInLibrary(desiredState.Name, invalidFiles, library.Files.Keys));
273-
}
274263

275-
foreach (string outFile in outFiles)
264+
foreach (FileMapping fileMapping in mappings)
276265
{
277-
// strip the source prefix
278-
string destinationFile = Path.Combine(HostInteraction.WorkingDirectory, desiredState.DestinationPath, outFile);
279-
if (!FileHelpers.IsUnderRootDirectory(destinationFile, HostInteraction.WorkingDirectory))
266+
// if Root is not specified, assume it's the root of the library
267+
string mappingRoot = fileMapping.Root ?? string.Empty;
268+
// if Destination is not specified, inherit from the library entry
269+
string destination = fileMapping.Destination ?? desiredState.DestinationPath;
270+
271+
if (destination is null)
272+
{
273+
errors ??= [];
274+
string libraryId = LibraryNamingScheme.GetLibraryId(desiredState.Name, desiredState.Version);
275+
errors.Add(PredefinedErrors.DestinationNotSpecified(libraryId));
276+
continue;
277+
}
278+
279+
IReadOnlyList<string> fileFilters;
280+
if (fileMapping.Files is { Count: > 0 })
281+
{
282+
fileFilters = fileMapping.Files;
283+
}
284+
else
285+
{
286+
fileFilters = ["**"];
287+
}
288+
289+
if (mappingRoot.Length > 0)
290+
{
291+
// prefix mappingRoot to each fileFilter item
292+
fileFilters = fileFilters.Select(f => $"{mappingRoot}/{f}").ToList();
293+
}
294+
295+
List<string> outFiles = FileGlobbingUtility.ExpandFileGlobs(fileFilters, library.Files.Keys).ToList();
296+
297+
if (library.GetInvalidFiles(outFiles) is IReadOnlyList<string> invalidFiles
298+
&& invalidFiles.Count > 0)
280299
{
281300
errors ??= [];
282-
errors.Add(PredefinedErrors.PathOutsideWorkingDirectory());
301+
errors.Add(PredefinedErrors.InvalidFilesInLibrary(desiredState.Name, invalidFiles, library.Files.Keys));
283302
}
284-
destinationFile = FileHelpers.NormalizePath(destinationFile);
285303

286-
// don't forget to include the cache folder in the path
287-
string sourceFile = GetCachedFileLocalPath(desiredState, outFile);
288-
sourceFile = FileHelpers.NormalizePath(sourceFile);
304+
foreach (string outFile in outFiles)
305+
{
306+
// strip the source prefix
307+
string relativeOutFile = mappingRoot.Length > 0 ? outFile.Substring(mappingRoot.Length + 1) : outFile;
308+
string destinationFile = Path.Combine(HostInteraction.WorkingDirectory, destination, relativeOutFile);
309+
destinationFile = FileHelpers.NormalizePath(destinationFile);
310+
311+
if (!FileHelpers.IsUnderRootDirectory(destinationFile, HostInteraction.WorkingDirectory))
312+
{
313+
errors ??= [];
314+
errors.Add(PredefinedErrors.PathOutsideWorkingDirectory());
315+
continue;
316+
}
289317

290-
// map destination back to the library-relative file it originated from
291-
installFiles.Add(destinationFile, sourceFile);
318+
// include the cache folder in the path
319+
string sourceFile = GetCachedFileLocalPath(desiredState, outFile);
320+
sourceFile = FileHelpers.NormalizePath(sourceFile);
321+
322+
// map destination back to the library-relative file it originated from
323+
if (installFiles.ContainsKey(destinationFile))
324+
{
325+
// this file is already being installed from another mapping
326+
errors ??= [];
327+
string libraryId = LibraryNamingScheme.GetLibraryId(desiredState.Name, desiredState.Version);
328+
errors.Add(PredefinedErrors.LibraryCannotBeInstalledDueToConflicts(destinationFile, [libraryId]));
329+
continue;
330+
}
331+
else
332+
{
333+
installFiles.Add(destinationFile, sourceFile);
334+
}
335+
}
292336
}
293337

294338
if (errors is not null)

0 commit comments

Comments
 (0)