private XElement FindMatchingPackageNode(PackageReference entry, XElement packagesNode) { XElement matchingIdNode; bool hasMatchingNode = PackagesConfig.HasAttributeValue(packagesNode, PackagesConfig.IdAttributeName, entry.PackageIdentity.Id, out matchingIdNode); if (matchingIdNode != null) { string version; PackagesConfig.TryGetAttribute(matchingIdNode, PackagesConfig.VersionAttributeName, out version); if (!string.IsNullOrEmpty(version)) { NuGetVersion nuGetVersion; bool isNuGetVersion = NuGetVersion.TryParse(version, out nuGetVersion); if (isNuGetVersion && nuGetVersion != null && nuGetVersion.Equals(entry.PackageIdentity.Version)) { return(matchingIdNode); } } } return(null); }
/// <summary> /// Adds a package entry to the file /// </summary> /// <param name="entry">Package reference entry</param> public void AddPackageEntry(PackageReference entry) { if (entry == null) { throw new ArgumentNullException(nameof(entry)); } if (_disposed) { throw new PackagesConfigWriterException(string.Format(CultureInfo.CurrentCulture, Strings.UnableToAddEntry)); } var packagesNode = EnsurePackagesNode(); XElement package; if (PackagesConfig.HasAttributeValue(packagesNode, PackagesConfig.IdAttributeName, entry.PackageIdentity.Id, out package)) { throw new PackagesConfigWriterException(String.Format(CultureInfo.CurrentCulture, Strings.PackageEntryAlreadyExist, entry.PackageIdentity.Id)); } else { // Append the entry to existing package nodes var node = CreateXElementForPackageEntry(entry); packagesNode.Add(node); // Sort the entries by package Id SortPackageNodes(packagesNode); } }
private XElement ReplacePackageAttributes(XElement existingNode, PackageReference newEntry) { var newEntryNode = CreateXElementForPackageEntry(newEntry); var newAttributeNames = newEntryNode.Attributes().Select(a => a.Name); var existingAttributeNames = existingNode.Attributes().Select(a => a.Name); var addableAttributeNames = newAttributeNames.Except(existingAttributeNames); foreach (XName name in existingAttributeNames) { // Clear newValue string newValue = null; // Try to get newValue correlated to the attribute on the existing node. PackagesConfig.TryGetAttribute(newEntryNode, name.LocalName, out newValue); // When the attribute is not specified a value in the new node if (string.IsNullOrEmpty(newValue)) { if (name.Equals(XName.Get(PackagesConfig.RequireInstallAttributeName))) { // Remove the requirementReinstallation attribute. existingNode.SetAttributeValue(name, value: null); } else { // no-op. Keep the allowedVersion attribute and all other attributes as-is. } } else { // Replace existing attributes with new values existingNode.SetAttributeValue(name, newValue); } } // Add new attributes that was not in the old package reference entry, if any foreach (XName name in addableAttributeNames) { var attribute = new XAttribute(name, newEntryNode.Attribute(name).Value); existingNode.Add(attribute); } return(existingNode); }
/// <summary> /// Get a boolean attribute value, or false if it does not exist /// </summary> public static bool BoolAttribute(XElement node, string name, bool defaultValue = false) { string value = null; if (PackagesConfig.TryGetAttribute(node, name, out value)) { if (StringComparer.OrdinalIgnoreCase.Equals(value, "true")) { return(true); } else { return(false); } } return(defaultValue); }
/// <summary> /// Update a package entry using the original entry as a base if it exists. /// </summary> public void UpdateOrAddPackageEntry(XDocument originalConfig, PackageReference newEntry) { if (originalConfig == null) { throw new ArgumentNullException(nameof(originalConfig)); } if (newEntry == null) { throw new ArgumentNullException(nameof(newEntry)); } if (_disposed) { throw new PackagesConfigWriterException(string.Format(CultureInfo.CurrentCulture, Strings.UnableToAddEntry)); } var originalPackagesNode = originalConfig.Element(XName.Get(PackagesConfig.PackagesNodeName)); XElement matchingIdNode; if (PackagesConfig.HasAttributeValue( originalPackagesNode, PackagesConfig.IdAttributeName, newEntry.PackageIdentity.Id, out matchingIdNode)) { // Find the old entry and update it based on the new entry var packagesNode = _xDocument.Element(XName.Get(PackagesConfig.PackagesNodeName)); var newPackageNode = ReplacePackageAttributes(matchingIdNode, newEntry); packagesNode.Add(newPackageNode); SortPackageNodes(packagesNode); } else { // There was no existing entry, add a new one AddPackageEntry(newEntry); } }
/// <summary> /// Reads all package node entries in the config. /// </summary> /// <param name="allowDuplicatePackageIds">If True validation will be performed to ensure that /// only one entry exists for each unique package id.</param> public IEnumerable <PackageReference> GetPackages(bool allowDuplicatePackageIds) { var packages = new List <PackageReference>(); foreach (var package in _doc.Root.Elements(XName.Get(PackagesConfig.PackageNodeName))) { string id = null; if (!PackagesConfig.TryGetAttribute(package, "id", out id) || String.IsNullOrEmpty(id)) { throw new PackagesConfigReaderException(string.Format( CultureInfo.CurrentCulture, Strings.ErrorNullOrEmptyPackageId)); } string version = null; if (!PackagesConfig.TryGetAttribute(package, PackagesConfig.VersionAttributeName, out version) || String.IsNullOrEmpty(version)) { throw new PackagesConfigReaderException(string.Format( CultureInfo.CurrentCulture, Strings.ErrorInvalidPackageVersion, id, version)); } NuGetVersion semver = null; if (!NuGetVersion.TryParse(version, out semver)) { throw new PackagesConfigReaderException(string.Format( CultureInfo.CurrentCulture, Strings.ErrorInvalidPackageVersion, id, version)); } string attributeValue = null; VersionRange allowedVersions = null; if (PackagesConfig.TryGetAttribute(package, PackagesConfig.allowedVersionsAttributeName, out attributeValue)) { if (!VersionRange.TryParse(attributeValue, out allowedVersions)) { throw new PackagesConfigReaderException(string.Format( CultureInfo.CurrentCulture, Strings.ErrorInvalidAllowedVersions, id, attributeValue)); } } var targetFramework = NuGetFramework.UnsupportedFramework; if (PackagesConfig.TryGetAttribute(package, PackagesConfig.TargetFrameworkAttributeName, out attributeValue)) { targetFramework = NuGetFramework.Parse(attributeValue, _frameworkMappings); } var developmentDependency = PackagesConfig.BoolAttribute(package, PackagesConfig.developmentDependencyAttributeName); var requireReinstallation = PackagesConfig.BoolAttribute(package, PackagesConfig.RequireInstallAttributeName); var userInstalled = PackagesConfig.BoolAttribute(package, PackagesConfig.UserInstalledAttributeName, true); var entry = new PackageReference(new PackageIdentity(id, semver), targetFramework, userInstalled, developmentDependency, requireReinstallation, allowedVersions); packages.Add(entry); } // check if there are duplicate entries var duplicates = new HashSet <string>(StringComparer.OrdinalIgnoreCase); PackageIdentity lastIdentity = null; var comparer = PackageIdentity.Comparer; // Sort the list of packages and check for duplicates foreach (var package in packages.OrderBy(p => p.PackageIdentity, comparer)) { if (lastIdentity != null) { if (allowDuplicatePackageIds) { // Full compare if (comparer.Equals(package.PackageIdentity, lastIdentity)) { duplicates.Add(lastIdentity.ToString()); } } else if (string.Equals( package.PackageIdentity.Id, lastIdentity.Id, StringComparison.OrdinalIgnoreCase)) { // Id only compare duplicates.Add(lastIdentity.Id); } } lastIdentity = package.PackageIdentity; } if (duplicates.Count > 0) { throw new PackagesConfigReaderException(string.Format( CultureInfo.CurrentCulture, Strings.ErrorDuplicatePackages, string.Join(", ", duplicates))); } return(packages); }