/// <summary>
        /// Returns true if this cross-targeting aggregate project context has the same set of target frameworks and active target framework as the given active and known configurations.
        /// </summary>
        public bool HasMatchingTargetFrameworks(ProjectConfiguration activeProjectConfiguration,
                                                IReadOnlyCollection <ProjectConfiguration> knownProjectConfigurations)
        {
            Assumes.True(IsCrossTargeting);
            Assumes.True(activeProjectConfiguration.IsCrossTargeting());
            Assumes.True(knownProjectConfigurations.All(c => c.IsCrossTargeting()));

            ITargetFramework activeTargetFramework = _targetFrameworkProvider.GetTargetFramework(activeProjectConfiguration.Dimensions[ConfigurationGeneral.TargetFrameworkProperty]);

            if (!ActiveTargetFramework.Equals(activeTargetFramework))
            {
                // Active target framework is different.
                return(false);
            }

            var targetFrameworkMonikers = knownProjectConfigurations
                                          .Select(c => c.Dimensions[ConfigurationGeneral.TargetFrameworkProperty])
                                          .Distinct()
                                          .ToList();

            if (targetFrameworkMonikers.Count != TargetFrameworks.Length)
            {
                // Different number of target frameworks.
                return(false);
            }

            foreach (string targetFrameworkMoniker in targetFrameworkMonikers)
            {
                ITargetFramework targetFramework = _targetFrameworkProvider.GetTargetFramework(targetFrameworkMoniker);

                if (!TargetFrameworks.Contains(targetFramework))
                {
                    // Differing TargetFramework
                    return(false);
                }
            }

            return(true);
        }
        private void ParseManagedSemantics()
        {
            var stringTable      = m_context.PathTable.StringTable;
            var magicNugetMarker = PathAtom.Create(stringTable, "_._");
            var dllExtension     = PathAtom.Create(stringTable, ".dll");

            foreach (var relativePath in PackageOnDisk.Contents.OrderBy(path => path.ToString(stringTable)))
            {
                // This is a dll. Check if it is in a lib folder or ref folder.

                // This code handles two layouts
                // Case 1: /runtimes/{targetRuntime}/[lib|ref]/{targetFramework}/{fileName}
                // Case 2: /[lib|ref]/{targetFramework}/{fileName}

                // In case 1, /runtimes/{targetRuntime} is removed and then rest of string is processed as in
                // case 2.
                // Case 2 treats files under 'lib' folder as runtime dependencies (and optionally compile-time
                // references if missing a corresponding set of compile-time references for the target framework
                // under the 'ref' folder). Files under 'ref' folder are treated strictly as compile-time only references.

                var atoms = new ReadOnlySpan <PathAtom>(relativePath.GetAtoms());
                if (atoms.Length == 5)
                {
                    var isRuntime = NugetFrameworkMonikers.RuntimesFolderName.CaseInsensitiveEquals(stringTable, atoms[0]) &&
                                    NugetFrameworkMonikers.SupportedTargetRuntimeAtoms.Contains(atoms[1].StringId);

                    if (isRuntime)
                    {
                        atoms = atoms.Slice(2);
                    }
                }

                if (atoms.Length == 3)
                {
                    var libOrRef = atoms[0];
                    var targetFrameworkFolder = atoms[1];
                    var fileName = atoms[2];

                    var isLib = NugetFrameworkMonikers.LibFolderName.CaseInsensitiveEquals(stringTable, libOrRef);
                    var isRef = NugetFrameworkMonikers.RefFolderName.CaseInsensitiveEquals(stringTable, libOrRef);

                    if (isLib || isRef)
                    {
                        if (!TryGetKnownTargetFramework(targetFrameworkFolder, out NugetTargetFramework targetFramework))
                        {
                            // We skip unknown frameworks, packages are not necessarily well constructed. We log this
                            // as a verbose message (i.e., this is not an error).
                            Logger.Log.NugetUnknownFramework(m_context.LoggingContext, PackageOnDisk.Package.Id,
                                                             targetFrameworkFolder.ToString(stringTable), relativePath.ToString(stringTable));
                            continue;
                        }

                        var isManagedEntry = false;
                        var ext            = fileName.GetExtension(stringTable);
                        if (dllExtension.CaseInsensitiveEquals(stringTable, ext))
                        {
                            isManagedEntry = true;
                            if (isRef)
                            {
                                References.Add(targetFramework, relativePath);
                            }

                            if (isLib)
                            {
                                Libraries.Add(targetFramework, relativePath);
                            }
                        }
                        else if (fileName == magicNugetMarker)
                        {
                            isManagedEntry = true;
                        }

                        if (isManagedEntry)
                        {
                            IsManagedPackage = true;

                            if (!TargetFrameworks.Contains(targetFramework.Moniker))
                            {
                                TargetFrameworks.Add(targetFramework.Moniker);
                            }

                            // The magic marker is there so the framework is declared as supported, but no actual files are listed
                            // So we don't want to add a magic marker as a real artifact that can be referenced.
                            if (fileName != magicNugetMarker)
                            {
                                AssemblyToTargetFramework.Add(fileName, targetFramework);
                            }
                        }
                    }
                }
            }

            if (TargetFrameworks.Count == 0)
            {
                var history = ForceFullFrameworkQualifiersOnly ?
                              NugetFrameworkMonikers.FullFrameworkVersionHistory :
                              NugetFrameworkMonikers.WellknownMonikers.ToList();

                foreach (var moniker in history)
                {
                    TargetFrameworks.Add(moniker);
                }
            }

            // For the refs without lib, copy them to refs.
            foreach (var kv in Libraries)
            {
                if (!References.ContainsKey(kv.Key))
                {
                    References.Add(kv.Key, kv.Value.ToArray());
                }
            }
        }
        /// <nodoc />
        private bool TryParseDependenciesFromNuSpec(XDocument nuSpec)
        {
            var dependencyNodes = nuSpec
                                  .Elements()
                                  .Where(el => string.Equals(el.Name.LocalName, "package", StringComparison.Ordinal))
                                  .Elements()
                                  .Where(el => string.Equals(el.Name.LocalName, "metadata", StringComparison.Ordinal))
                                  .Elements()
                                  .Where(el => string.Equals(el.Name.LocalName, "dependencies", StringComparison.Ordinal))
                                  .Elements();

            // Namespace independent query, nuget has about 6 different namespaces as of may 2016.
            var  skipIdLookupTable     = new HashSet <string>(DependentPackageIdsToSkip);
            var  ignoreIdLookupTable   = new HashSet <string>(DependentPackageIdsToIgnore);
            bool skipAllDependencies   = skipIdLookupTable.Contains("*");
            bool ignoreAllDependencies = ignoreIdLookupTable.Contains("*");

            foreach (var dependency in dependencyNodes.Where(el => string.Equals(el.Name.LocalName, "dependency", StringComparison.Ordinal)))
            {
                var genericDependency = ReadDependencyElement(dependency);
                if (genericDependency == null && !(ignoreAllDependencies || ignoreIdLookupTable.Contains(dependency.Attribute("id")?.Value?.Trim())))
                {
                    return(false);
                }

                if (genericDependency != null && !skipAllDependencies && !skipIdLookupTable.Contains(genericDependency.GetPackageIdentity()))
                {
                    m_dependencies.Add(genericDependency);
                }
            }

            var groups = dependencyNodes.Where(el => string.Equals(el.Name.LocalName, "group", StringComparison.Ordinal));

            foreach (var group in groups)
            {
                if (group.Attribute("targetFramework") != null && NugetFrameworkMonikers.TargetFrameworkNameToMoniker.TryGetValue(group.Attribute("targetFramework").Value, out Moniker targetFramework))
                {
                    if (group.Elements().Any())
                    {
                        // If there is at least one valid dependency for a known framework, then the package is defined as managed
                        IsManagedPackage = true;

                        // Only add the group dependency target framework if the nuget package itself also contains specific assemblies of the same version
                        if (!TargetFrameworks.Contains(targetFramework) && (References.Keys.Any(tfm => tfm.Moniker == targetFramework) || Libraries.Keys.Any(tfm => tfm.Moniker == targetFramework)))
                        {
                            TargetFrameworks.Add(targetFramework);
                        }

                        // If the package has a pinned tfm and the groups tfm does not match, skip the groups dependency resolution
                        if (!string.IsNullOrEmpty(this.Tfm) && NugetFrameworkMonikers.TargetFrameworkNameToMoniker.TryGetValue(this.Tfm, out Moniker pinnedTfm) && !PathAtom.Equals(pinnedTfm, targetFramework))
                        {
                            continue;
                        }

                        foreach (
                            var dependency in
                            group.Elements().Where(
                                el => string.Equals(el.Name.LocalName, "dependency", StringComparison.Ordinal)))
                        {
                            var grouppedDependency = ReadDependencyElement(dependency);
                            if (grouppedDependency == null && !(ignoreAllDependencies || ignoreIdLookupTable.Contains(dependency.Attribute("id")?.Value?.Trim())))
                            {
                                return(false);
                            }

                            if (grouppedDependency != null && !skipAllDependencies && !skipIdLookupTable.Contains(grouppedDependency.GetPackageIdentity()))
                            {
                                DependenciesPerFramework.Add(targetFramework, grouppedDependency);
                            }
                        }
                    }
                }
            }

            IsNetStandardPackageOnly =
                !TargetFrameworks.Any(tfm => NugetFrameworkMonikers.FullFrameworkVersionHistory.Contains(tfm)) &&
                !TargetFrameworks.Any(tfm => NugetFrameworkMonikers.NetCoreAppVersionHistory.Contains(tfm));

            return(true);
        }
示例#4
0
        private void ParseManagedSemantics()
        {
            var stringTable      = m_context.PathTable.StringTable;
            var magicNugetMarker = PathAtom.Create(stringTable, "_._");
            var dllExtension     = PathAtom.Create(stringTable, ".dll");

            var refs = new MultiValueDictionary <NugetTargetFramework, RelativePath>();
            var libs = new MultiValueDictionary <NugetTargetFramework, RelativePath>();
            var assemblyToTargetFramework = new MultiValueDictionary <PathAtom, NugetTargetFramework>();

            foreach (var relativePath in PackageOnDisk.Contents.OrderBy(path => path.ToString(stringTable)))
            {
                // This is a dll. Check if it is in a lib folder or ref folder.
                var atoms = relativePath.GetAtoms();
                if (atoms.Length == 3)
                {
                    var libOrRef = atoms[0];
                    var targetFrameworkFolder = atoms[1];
                    var fileName = atoms[2];

                    var isLib = NugetFrameworkMonikers.LibFolderName.CaseInsensitiveEquals(stringTable, libOrRef);
                    var isRef = NugetFrameworkMonikers.RefFolderName.CaseInsensitiveEquals(stringTable, libOrRef);

                    if (isLib || isRef)
                    {
                        if (!TryGetKnownTargetFramework(targetFrameworkFolder, out NugetTargetFramework targetFramework))
                        {
                            // We skip unknown frameworks, packages are not necessarily well constructed. We log this
                            // as a verbose message (i.e., this is not an error).
                            Logger.Log.NugetUnknownFramework(m_context.LoggingContext, PackageOnDisk.Package.Id,
                                                             targetFrameworkFolder.ToString(stringTable), relativePath.ToString(stringTable));
                            continue;
                        }

                        var isManagedEntry = false;
                        var ext            = fileName.GetExtension(stringTable);
                        if (dllExtension.CaseInsensitiveEquals(stringTable, ext))
                        {
                            isManagedEntry = true;
                            if (isRef)
                            {
                                refs.Add(targetFramework, relativePath);
                            }

                            if (isLib)
                            {
                                libs.Add(targetFramework, relativePath);
                            }
                        }
                        else if (fileName == magicNugetMarker)
                        {
                            isManagedEntry = true;
                        }

                        if (isManagedEntry)
                        {
                            IsManagedPackage = true;

                            if (!TargetFrameworks.Contains(targetFramework.Moniker))
                            {
                                TargetFrameworks.Add(targetFramework.Moniker);
                            }

                            // The magic marker is there so the framework is declared as supported, but no actual files are listed
                            // So we don't want to add a magic marker as a real artifact that can be referenced.
                            if (fileName != magicNugetMarker)
                            {
                                assemblyToTargetFramework.Add(fileName, targetFramework);
                            }
                        }
                    }
                }
            }

            if (TargetFrameworks.Count == 0)
            {
                var history = ForceFullFrameworkQualifiersOnly ?
                              NugetFrameworkMonikers.FullFrameworkVersionHistory :
                              NugetFrameworkMonikers.WellknownMonikers.ToList();

                foreach (var moniker in history)
                {
                    TargetFrameworks.Add(moniker);
                }
            }

            // For the refs without lib, copy them to refs.
            foreach (var kv in libs)
            {
                if (!refs.ContainsKey(kv.Key))
                {
                    refs.Add(kv.Key, kv.Value.ToArray());
                }
            }

            References = refs;
            Libraries  = libs;
            AssemblyToTargetFramework = assemblyToTargetFramework;
        }