private void AddRuntimeGroup(RuntimeGroup runtimeGroup)
        {
            List <RuntimeGroup> baseRuntimeGroups;

            if (!runtimeGroupsByBaseRID.TryGetValue(runtimeGroup.BaseRID, out baseRuntimeGroups))
            {
                runtimeGroupsByBaseRID[runtimeGroup.BaseRID] = baseRuntimeGroups = new List <RuntimeGroup>();
            }

            baseRuntimeGroups.Add(runtimeGroup);
            allRuntimeGroups.Add(runtimeGroup);
        }
Esempio n. 2
0
        private RuntimeGraph SafeMerge(RuntimeGraph existingGraph, RuntimeGroup runtimeGroup)
        {
            var runtimeGraph = runtimeGroup.GetRuntimeGraph();

            foreach (var existingRuntimeDescription in existingGraph.Runtimes.Values)
            {
                RuntimeDescription newRuntimeDescription;

                if (runtimeGraph.Runtimes.TryGetValue(existingRuntimeDescription.RuntimeIdentifier, out newRuntimeDescription))
                {
                    // overlapping RID, ensure that the imports match (same ordering and content)
                    if (!existingRuntimeDescription.InheritedRuntimes.SequenceEqual(newRuntimeDescription.InheritedRuntimes))
                    {
                        Log.LogError($"RuntimeGroup {runtimeGroup.BaseRID} defines RID {newRuntimeDescription.RuntimeIdentifier} with imports {string.Join(";", newRuntimeDescription.InheritedRuntimes)} which differ from existing imports {string.Join(";", existingRuntimeDescription.InheritedRuntimes)}.  You may avoid this by specifying {nameof(RuntimeGroup.OmitRIDDefinitions)} metadata with {newRuntimeDescription.RuntimeIdentifier}.");
                    }
                }
            }

            return(RuntimeGraph.Merge(existingGraph, runtimeGraph));
        }
        public void AddRuntimeIdentifier(RID rid, string parent)
        {
            // Do nothing if we already know about the RID
            if (knownRIDs.Contains(rid))
            {
                return;
            }

            RuntimeGroup runtimeGroup = null;

            if (runtimeGroupsByBaseRID.TryGetValue(rid.BaseRID, out var candidateRuntimeGroups))
            {
                RuntimeVersion closestVersion = null;

                foreach (var candidate in candidateRuntimeGroups)
                {
                    if (rid.HasVersion)
                    {
                        // Find the closest previous version
                        foreach (var version in candidate.Versions)
                        {
                            // a previous version
                            if (version <= rid.Version)
                            {
                                // haven't yet found a match or this is a closer match
                                if (closestVersion == null || version > closestVersion)
                                {
                                    closestVersion = version;
                                    runtimeGroup   = candidate;
                                }
                                else if (version == closestVersion)
                                {
                                    // found a tie in version, examine other fields
                                    considerCandidate();
                                }
                            }
                        }
                    }

                    // if we don't have a version, or if we couldn't find any match, consider other fields
                    if (!rid.HasVersion)
                    {
                        considerCandidate();
                    }

                    // if we don't have a match yet, take this as it matches on baseRID
                    runtimeGroup ??= candidate;

                    void considerCandidate()
                    {
                        // is this a better match?
                        if (!rid.HasArchitecture || candidate.Architectures.Contains(rid.Architecture))
                        {
                            if (!rid.HasQualifier || candidate.AdditionalQualifiers.Contains(rid.Qualifier))
                            {
                                // matched on arch and qualifier.
                                runtimeGroup = candidate;
                            }
                            else if (rid.HasArchitecture && !runtimeGroup.Architectures.Contains(rid.Architecture))
                            {
                                // matched only on arch and existing match doesn't match arch
                                runtimeGroup = candidate;
                            }
                        }
                    }
                }

                Debug.Assert(runtimeGroup != null, "Empty candidates?");
            }
            else
            {
                // This is an unknown base RID, we'll need to add a new group.
                if (string.IsNullOrEmpty(parent))
                {
                    throw new InvalidOperationException($"AdditionalRuntimeIdentifier {rid} was specified, which could not be found in any existing {nameof(RuntimeGroup)}, and no {nameof(parent)} was specified.");
                }

                runtimeGroup = new RuntimeGroup(rid.BaseRID, parent);

                AddRuntimeGroup(runtimeGroup);
            }

            runtimeGroup.ApplyRid(rid);

            // Compute the portion of the RID graph produced from this modified RuntimeGroup
            var ridMappings = runtimeGroup.GetRIDMappings();

            // Record any newly defined RIDs in our set of known RIDs
            foreach (RID definedRID in ridMappings.Select(mapping => mapping.RuntimeIdentifier))
            {
                knownRIDs.Add(definedRID);
            }

            // Make sure that any RID imported is added as well.  This allows users to specify
            // a single new RID and we'll add any new RIDs up the parent chain that might be needed.
            foreach (RID importedRID in ridMappings.SelectMany(mapping => mapping.Imports))
            {
                // This should not introduce any new RuntimeGroups, so we specify parent as null
                AddRuntimeIdentifier(importedRID, null);
            }
        }