Esempio n. 1
0
        internal IEnumerable <RIDMapping> GetRIDMappings()
        {
            // base =>
            //      Parent
            yield return(Parent == null ?
                         new RIDMapping(CreateRuntime(BaseRID)) :
                         new RIDMapping(CreateRuntime(BaseRID), new[] { CreateRuntime(Parent) }));

            foreach (var architecture in Architectures)
            {
                // base + arch =>
                //      base,
                //      parent + arch
                var imports = new List <RID>()
                {
                    CreateRuntime(BaseRID)
                };

                if (!IsNullOrRoot(Parent))
                {
                    imports.Add(CreateRuntime(Parent, architecture: architecture));
                }

                yield return(new RIDMapping(CreateRuntime(BaseRID, architecture: architecture), imports));
            }

            RuntimeVersion lastVersion = null;

            foreach (var version in Versions)
            {
                // base + version =>
                //      base + lastVersion,
                //      parent + version (optionally)
                var imports = new List <RID>()
                {
                    CreateRuntime(BaseRID, version: lastVersion)
                };

                if (ApplyVersionsToParent)
                {
                    imports.Add(CreateRuntime(Parent, version: version));
                }

                yield return(new RIDMapping(CreateRuntime(BaseRID, version: version), imports));

                foreach (var architecture in Architectures)
                {
                    // base + version + architecture =>
                    //      base + version,
                    //      base + lastVersion + architecture,
                    //      parent + version + architecture (optionally)
                    var archImports = new List <RID>()
                    {
                        CreateRuntime(BaseRID, version: version),
                        CreateRuntime(BaseRID, version: lastVersion, architecture: architecture)
                    };

                    if (ApplyVersionsToParent)
                    {
                        archImports.Add(CreateRuntime(Parent, version: version, architecture: architecture));
                    }

                    yield return(new RIDMapping(CreateRuntime(BaseRID, version: version, architecture: architecture), archImports));
                }

                if (TreatVersionsAsCompatible)
                {
                    lastVersion = version;
                }
            }

            foreach (var qualifier in AdditionalQualifiers)
            {
                // base + qual =>
                //      base,
                //      parent + qual
                yield return(new RIDMapping(CreateRuntime(BaseRID, qualifier: qualifier),
                                            new[]
                {
                    CreateRuntime(BaseRID),
                    IsNullOrRoot(Parent) ? CreateRuntime(qualifier) : CreateRuntime(Parent, qualifier: qualifier)
                }));

                foreach (var architecture in Architectures)
                {
                    // base + arch + qualifier =>
                    //      base + qualifier,
                    //      base + arch
                    //      parent + arch + qualifier
                    var imports = new List <RID>()
                    {
                        CreateRuntime(BaseRID, qualifier: qualifier),
                        CreateRuntime(BaseRID, architecture: architecture)
                    };

                    if (!IsNullOrRoot(Parent))
                    {
                        imports.Add(CreateRuntime(Parent, architecture: architecture, qualifier: qualifier));
                    }

                    yield return(new RIDMapping(CreateRuntime(BaseRID, architecture: architecture, qualifier: qualifier), imports));
                }

                lastVersion = null;
                foreach (var version in Versions)
                {
                    // base + version + qualifier =>
                    //      base + version,
                    //      base + lastVersion + qualifier
                    //      parent + version + qualifier (optionally)
                    var imports = new List <RID>()
                    {
                        CreateRuntime(BaseRID, version: version),
                        CreateRuntime(BaseRID, version: lastVersion, qualifier: qualifier)
                    };

                    if (ApplyVersionsToParent)
                    {
                        imports.Add(CreateRuntime(Parent, version: version, qualifier: qualifier));
                    }

                    yield return(new RIDMapping(CreateRuntime(BaseRID, version: version, qualifier: qualifier), imports));

                    foreach (var architecture in Architectures)
                    {
                        // base + version + architecture + qualifier =>
                        //      base + version + qualifier,
                        //      base + version + architecture,
                        //      base + version,
                        //      base + lastVersion + architecture + qualifier,
                        //      parent + version + architecture + qualifier (optionally)
                        var archImports = new List <RID>()
                        {
                            CreateRuntime(BaseRID, version: version, qualifier: qualifier),
                            CreateRuntime(BaseRID, version: version, architecture: architecture),
                            CreateRuntime(BaseRID, version: version),
                            CreateRuntime(BaseRID, version: lastVersion, architecture: architecture, qualifier: qualifier)
                        };

                        if (ApplyVersionsToParent)
                        {
                            imports.Add(CreateRuntime(Parent, version: version, architecture: architecture, qualifier: qualifier));
                        }

                        yield return(new RIDMapping(CreateRuntime(BaseRID, version: version, architecture: architecture, qualifier: qualifier), archImports));
                    }

                    if (TreatVersionsAsCompatible)
                    {
                        lastVersion = version;
                    }
                }
            }
        }
        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);
            }
        }