| File: ToolPackage\ToolConfigurationDeserializer.cs | Web Access |
| Project: src\sdk\src\Cli\dotnet\dotnet.csproj (dotnet) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #nullable disable using System.Xml; using System.Xml.Linq; using Microsoft.DotNet.Cli.ToolPackage.ToolConfigurationDeserialization; using Microsoft.Extensions.EnvironmentAbstractions; using NuGet.Packaging.Core; namespace Microsoft.DotNet.Cli.ToolPackage; internal static class ToolConfigurationDeserializer { // The supported tool configuration schema version. // This should match the schema version in the GenerateToolsSettingsFile task from the SDK. private const int SupportedVersion = 2; public static ToolConfiguration Deserialize(string pathToXml, IFileSystem fileSystem = null) { fileSystem ??= new FileSystemWrapper(); DotNetCliTool dotNetCliTool; try { XDocument doc; using (var stream = fileSystem.File.OpenRead(pathToXml)) { doc = XDocument.Load(stream); } var root = doc.Root; dotNetCliTool = new DotNetCliTool { Version = (string)root.Attribute("Version"), Commands = root.Element("Commands")? .Elements("Command") .Select(e => new DotNetCliToolCommand { Name = (string)e.Attribute("Name"), EntryPoint = (string)e.Attribute("EntryPoint"), Runner = (string)e.Attribute("Runner"), }) .ToArray(), RuntimeIdentifierPackages = root.Element("RuntimeIdentifierPackages")? .Elements("RuntimeIdentifierPackage") .Select(e => new DotNetCliToolRuntimeIdentifierPackage { RuntimeIdentifier = (string)e.Attribute("RuntimeIdentifier"), Id = (string)e.Attribute("Id"), }) .ToArray(), }; } catch (XmlException ex) { throw new ToolConfigurationException( string.Format( CliStrings.ToolSettingsInvalidXml, ex.Message), ex); } catch (Exception ex) when (ex is IOException || ex is UnauthorizedAccessException) { throw new ToolConfigurationException( string.Format( CliStrings.FailedToRetrieveToolConfiguration, ex.Message), ex); } List<string> warnings = GenerateWarningAccordingToVersionAttribute(dotNetCliTool); if (dotNetCliTool.Commands.Length != 1) { throw new ToolConfigurationException(CliStrings.ToolSettingsMoreThanOneCommand); } var runner = dotNetCliTool.Commands[0].Runner; if (!string.IsNullOrEmpty(runner) && runner != "dotnet" && runner != "executable") { throw new ToolConfigurationException( string.Format( CliStrings.ToolSettingsUnsupportedRunner, dotNetCliTool.Commands[0].Name, dotNetCliTool.Commands[0].Runner)); } var ridSpecificPackages = dotNetCliTool.RuntimeIdentifierPackages?.ToDictionary(p => p.RuntimeIdentifier, p => new PackageIdentity(p.Id, null)) .AsReadOnly(); // Also error out if there are no RID-specific packages and the runner is empty if (string.IsNullOrEmpty(runner) && (ridSpecificPackages == null || !ridSpecificPackages.Any())) { throw new ToolConfigurationException( string.Format( CliStrings.ToolSettingsUnsupportedRunner, dotNetCliTool.Commands[0].Name, dotNetCliTool.Commands[0].Runner)); } return new ToolConfiguration( dotNetCliTool.Commands[0].Name, dotNetCliTool.Commands[0].EntryPoint, dotNetCliTool.Commands[0].Runner, ridSpecificPackages: ridSpecificPackages, warnings: warnings); } private static List<string> GenerateWarningAccordingToVersionAttribute(DotNetCliTool dotNetCliTool) { List<string> warnings = []; if (string.IsNullOrWhiteSpace(dotNetCliTool.Version)) { warnings.Add(CliStrings.FormatVersionIsMissing); } else { if (!int.TryParse(dotNetCliTool.Version, out int version)) { warnings.Add(CliStrings.FormatVersionIsMalformed); } else { if (version > SupportedVersion) { warnings.Add(CliStrings.FormatVersionIsHigher); } } } return warnings; } }