| File: Settings\Items\RepositoryItem.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; using NuGet.Shared; namespace NuGet.Configuration { public sealed class RepositoryItem : TrustedSignerItem { public override string ElementName => ConfigurationConstants.Repository; public string ServiceIndex => Attributes[ConfigurationConstants.ServiceIndex]; public new string Name { get => base.Name; set => SetName(value); } private OwnersItem? _owners; public IList<string> Owners { get; private set; } protected override IReadOnlyCollection<string> RequiredAttributes { get; } = new HashSet<string>(new[] { ConfigurationConstants.NameAttribute, ConfigurationConstants.ServiceIndex }); public RepositoryItem(string name, string serviceIndex, params CertificateItem[] certificates) : this(name, serviceIndex, owners: null, certificates: certificates) { } public RepositoryItem(string name, string serviceIndex, string? owners, params CertificateItem[] certificates) : base(name, certificates) { if (string.IsNullOrEmpty(serviceIndex)) { throw new ArgumentNullException(nameof(serviceIndex)); } AddAttribute(ConfigurationConstants.ServiceIndex, serviceIndex); if (!string.IsNullOrEmpty(owners)) { _owners = new OwnersItem(owners!); Owners = _owners.Content; } else { _owners = null; Owners = new List<string>(); } } internal RepositoryItem(XElement element, SettingsFile origin) : this(element, origin, ParseDescendants(element, origin)) { } internal RepositoryItem(XElement element, SettingsFile origin, IEnumerable<SettingBase> parsedDescendants) : base(element, origin, parsedDescendants) { var parsedOwners = parsedDescendants.OfType<OwnersItem>(); if (parsedOwners != null && parsedOwners.Any()) { if (parsedOwners.Count() > 1) { throw new NuGetConfigurationException( string.Format(CultureInfo.CurrentCulture, Resources.UserSettings_UnableToParseConfigFile, string.Format(CultureInfo.CurrentCulture, Resources.RepositoryMustHaveOneOwners, Name, ServiceIndex), origin.ConfigFilePath)); } _owners = parsedOwners.FirstOrDefault(); Owners = _owners?.Content ?? new List<string>(); } else { Owners = new List<string>(); } } public override SettingBase Clone() { var newItem = new RepositoryItem( Name, ServiceIndex, string.Join(OwnersItem.OwnersListSeparator.ToString(CultureInfo.CurrentCulture), Owners), Certificates.Select(c => (CertificateItem)c.Clone()).ToArray()); if (Origin != null) { newItem.SetOrigin(Origin); } return newItem; } internal override XNode AsXNode() { if (Node is XElement) { return Node; } var element = new XElement(ElementName); foreach (var cert in Certificates) { element.Add(cert.AsXNode()); } if (_owners != null) { element.Add(_owners.AsXNode()); } foreach (var attr in Attributes) { element.SetAttributeValue(attr.Key, attr.Value); } return element; } public override bool Equals(object? other) { if (other is RepositoryItem repository) { if (ReferenceEquals(this, repository)) { return true; } return string.Equals(ServiceIndex, repository.ServiceIndex, StringComparison.Ordinal); } return false; } public override int GetHashCode() { var combiner = new HashCodeCombiner(); combiner.AddObject(Name); combiner.AddObject(ServiceIndex); return combiner.CombinedHash; } internal override void SetOrigin(SettingsFile origin) { base.SetOrigin(origin); _owners?.SetOrigin(origin); } internal override void RemoveFromSettings() { base.RemoveFromSettings(); _owners?.RemoveFromSettings(); } internal override void Update(SettingItem otherRepository) { base.Update(otherRepository); var other = (RepositoryItem)otherRepository; if (!Owners.SequenceEqual(other.Owners, StringComparer.Ordinal)) { if (_owners == null || !Owners.Any()) { _owners = new OwnersItem(string.Join(OwnersItem.OwnersListSeparator.ToString(CultureInfo.CurrentCulture), other.Owners)); Owners = _owners.Content; if (Origin != null) { _owners.SetOrigin(Origin); if (Node != null) { _owners.SetNode(_owners.AsXNode()); XElementUtility.AddIndented(Node as XElement, _owners.Node); Origin.IsDirty = true; } } } else if (!other.Owners.Any()) { XElementUtility.RemoveIndented(_owners.Node); _owners = null; Owners.Clear(); if (Origin != null) { Origin.IsDirty = true; } } else { #pragma warning disable CS8604 // Possible null reference argument. // While adding nullable annotations to the codebase, the compiler is warning about this line, but after a long time // trying to understand this code, I can't convince myself that this is safe. It's also not obvious to me how to fix it. // Since this code has existed for years, apparently without causing NullReferenceExeptions, I'm going to suppress the warning // until someone can refactor this code to make it safe. _owners.Update(other._owners); #pragma warning restore CS8604 // Possible null reference argument. Owners = _owners.Content; } } } } }