| File: Settings\SettingFactory.cs | Web Access |
| Project: src\nuget-client\src\NuGet.Core\NuGet.Configuration\NuGet.Configuration.csproj (NuGet.Configuration) |
// Copyright(c) .NET Foundation.All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Xml.Linq; namespace NuGet.Configuration { internal static class SettingFactory { internal static SettingBase Parse(XNode node, SettingsFile origin) { if (node == null) { throw new ArgumentNullException(nameof(node)); } if (node is XText textNode) { return new SettingText(textNode, origin); } if (node is XElement element) { var elementType = SettingElementType.Unknown; Enum.TryParse(element.Name.LocalName, ignoreCase: true, result: out elementType); var parentType = SettingElementType.Unknown; if (element.Parent != null) { Enum.TryParse(element.Parent?.Name.LocalName, ignoreCase: true, result: out parentType); } switch (parentType) { case SettingElementType.Configuration: return new ParsedSettingSection(element.Name.LocalName, element, origin); case SettingElementType.PackageSourceCredentials: return new CredentialsItem(element, origin); case SettingElementType.PackageSources: case SettingElementType.AuditSources: if (elementType == SettingElementType.Add) { return new SourceItem(element, origin); } break; case SettingElementType.PackageSourceMapping: if (elementType == SettingElementType.PackageSource) { return new PackageSourceMappingSourceItem(element, origin); } break; case SettingElementType.PackageSource: if (elementType == SettingElementType.Package) { return new PackagePatternItem(element, origin); } break; } switch (elementType) { case SettingElementType.Add: return new AddItem(element, origin); case SettingElementType.Author: return new AuthorItem(element, origin); case SettingElementType.Certificate: return new CertificateItem(element, origin); case SettingElementType.Clear: return new ClearItem(element, origin); case SettingElementType.Owners: return new OwnersItem(element, origin); case SettingElementType.Repository: return new RepositoryItem(element, origin); case SettingElementType.FileCert: return new FileClientCertItem(element, origin); case SettingElementType.StoreCert: return new StoreClientCertItem(element, origin); } return new UnknownItem(element, origin); } throw new InvalidOperationException("An invalid code path was taken. This should only happen when a new settings type is not implemented correctly."); } private class SettingElementKeyComparer : IComparer<SettingElement>, IEqualityComparer<SettingElement> { public int Compare(SettingElement? x, SettingElement? y) { if (ReferenceEquals(x, y)) { return 0; } if (ReferenceEquals(x, null)) { return -1; } if (ReferenceEquals(y, null)) { return 1; } return StringComparer.OrdinalIgnoreCase.Compare( x.ElementName + string.Join("", x.Attributes.Select(a => a.Value)), y.ElementName + string.Join("", y.Attributes.Select(a => a.Value))); } public bool Equals(SettingElement? x, SettingElement? y) { if (ReferenceEquals(x, y)) { return true; } if (ReferenceEquals(x, null) || ReferenceEquals(y, null)) { return false; } return StringComparer.OrdinalIgnoreCase.Equals( x.ElementName + string.Join("", x.Attributes.Select(a => a.Value)), y.ElementName + string.Join("", y.Attributes.Select(a => a.Value))); } public int GetHashCode(SettingElement obj) { if (ReferenceEquals(obj, null)) { return 0; } return StringComparer.OrdinalIgnoreCase.GetHashCode(obj.ElementName + string.Join("", obj.Attributes.Select(a => a.Value))); } } internal static IEnumerable<T> ParseChildren<T>(XElement xElement, SettingsFile origin, bool canBeCleared) where T : SettingElement { var children = new List<T>(); IEnumerable<T> descendants = xElement.Elements().Select(d => Parse(d, origin)).OfType<T>(); SettingElementKeyComparer comparer = new SettingElementKeyComparer(); HashSet<T> distinctDescendants = new HashSet<T>(comparer); List<T>? duplicatedDescendants = null; foreach (var item in descendants) { if (!distinctDescendants.Add(item)) { if (duplicatedDescendants == null) { duplicatedDescendants = new List<T>(); } duplicatedDescendants.Add(item); } } if (xElement.Name.LocalName.Equals(ConfigurationConstants.PackageSourceMapping, StringComparison.OrdinalIgnoreCase) && duplicatedDescendants != null) { var duplicatedKey = string.Join(", ", duplicatedDescendants.Select(d => d.Attributes["key"])); var source = duplicatedDescendants.Select(d => d.Origin?.ConfigFilePath).First(d => d is not null); throw new NuGetConfigurationException(string.Format(CultureInfo.CurrentCulture, Resources.Error_DuplicatePackageSource, duplicatedKey, source)); } foreach (var descendant in distinctDescendants) { if (canBeCleared && descendant is ClearItem) { children.Clear(); } children.Add(descendant); } return children; } } }