示例#1
0
        private void UpdateFromPackage(PackageIndex index, string packagePath, bool filter = false)
        {
            string                id;
            NuGetVersion          version;
            IEnumerable <Version> assemblyVersions;

            using (var reader = new PackageArchiveReader(packagePath))
            {
                var identity = reader.GetIdentity();
                id      = identity.Id;
                version = identity.Version;

                if (filter && !ShouldInclude(id))
                {
                    return;
                }

                var refFiles = reader.GetFiles("ref").Where(r => !NuGetAssetResolver.IsPlaceholder(r));

                if (!refFiles.Any())
                {
                    refFiles = reader.GetFiles("lib");
                }

                assemblyVersions = refFiles.Select(refFile =>
                {
                    using (var refStream = reader.GetStream(refFile))
                        using (var memStream = new MemoryStream())
                        {
                            refStream.CopyTo(memStream);
                            memStream.Seek(0, SeekOrigin.Begin);
                            return(VersionUtility.GetAssemblyVersion(memStream));
                        }
                }).ToArray();
            }

            UpdateFromValues(index, id, version, assemblyVersions);
        }
示例#2
0
        private void UpdateFromPackage(PackageIndex index, string packagePath, bool filter = false)
        {
            string                id;
            NuGetVersion          version;
            IEnumerable <Version> assemblyVersions;
            IEnumerable <string>  dllNames;

            using (var reader = new PackageArchiveReader(packagePath))
            {
                var identity = reader.GetIdentity();
                id      = identity.Id;
                version = identity.Version;

                if (filter && !ShouldInclude(id))
                {
                    return;
                }

                var dlls = reader.GetFiles().Where(f => Path.GetExtension(f).Equals(".dll", StringComparison.OrdinalIgnoreCase));

                assemblyVersions = dlls.Select(refFile =>
                {
                    using (var refStream = reader.GetStream(refFile))
                        using (var memStream = new MemoryStream())
                        {
                            refStream.CopyTo(memStream);
                            memStream.Seek(0, SeekOrigin.Begin);
                            return(VersionUtility.GetAssemblyVersion(memStream));
                        }
                }).ToArray();

                dllNames = dlls.Select(f => Path.GetFileNameWithoutExtension(f)).Distinct().ToArray();
            }

            UpdateFromValues(index, id, version, assemblyVersions, dllNames);
        }
示例#3
0
        private void HarvestSupportedFrameworks()
        {
            List <ITaskItem> supportedFrameworks = new List <ITaskItem>();

            AggregateNuGetAssetResolver resolver = new AggregateNuGetAssetResolver(RuntimeFile);
            string packagePath = Path.Combine(PackagesFolder, PackageId, PackageVersion);

            // add the primary package
            resolver.AddPackageItems(PackageId, GetPackageItems(packagePath));

            if (RuntimePackages != null)
            {
                // add any split runtime packages
                foreach (var runtimePackage in RuntimePackages)
                {
                    var runtimePackageId      = runtimePackage.ItemSpec;
                    var runtimePackageVersion = runtimePackage.GetMetadata("Version");

                    resolver.AddPackageItems(runtimePackageId, GetPackageItems(PackagesFolder, runtimePackageId, runtimePackageVersion));
                }
            }

            // create a resolver that can be used to determine the API version for inbox assemblies
            // since inbox assemblies are represented with placeholders we can remove the placeholders
            // and use the netstandard reference assembly to determine the API version
            var filesWithoutPlaceholders = GetPackageItems(packagePath)
                                           .Where(f => !NuGetAssetResolver.IsPlaceholder(f));
            NuGetAssetResolver resolverWithoutPlaceholders = new NuGetAssetResolver(RuntimeFile, filesWithoutPlaceholders);

            string package = $"{PackageId}/{PackageVersion}";

            foreach (var framework in Frameworks)
            {
                var runtimeIds = framework.GetMetadata("RuntimeIDs")?.Split(';');

                NuGetFramework fx;
                try
                {
                    fx = FrameworkUtilities.ParseNormalized(framework.ItemSpec);
                }
                catch (Exception ex)
                {
                    Log.LogError($"Could not parse Framework {framework.ItemSpec}. {ex}");
                    continue;
                }

                if (fx.Equals(NuGetFramework.UnsupportedFramework))
                {
                    Log.LogError($"Did not recognize {framework.ItemSpec} as valid Framework.");
                    continue;
                }

                var compileAssets = resolver.ResolveCompileAssets(fx, PackageId);

                bool hasCompileAsset, hasCompilePlaceHolder;
                NuGetAssetResolver.ExamineAssets(Log, "Compile", package, fx.ToString(), compileAssets, out hasCompileAsset, out hasCompilePlaceHolder);

                // start by making sure it has some asset available for compile
                var isSupported = hasCompileAsset || hasCompilePlaceHolder;

                if (!isSupported)
                {
                    Log.LogMessage(LogImportance.Low, $"Skipping {fx} because it is not supported.");
                    continue;
                }

                foreach (var runtimeId in runtimeIds)
                {
                    string target = String.IsNullOrEmpty(runtimeId) ? fx.ToString() : $"{fx}/{runtimeId}";

                    var runtimeAssets = resolver.ResolveRuntimeAssets(fx, runtimeId);

                    bool hasRuntimeAsset, hasRuntimePlaceHolder;
                    NuGetAssetResolver.ExamineAssets(Log, "Runtime", package, target, runtimeAssets, out hasRuntimeAsset, out hasRuntimePlaceHolder);

                    isSupported &= hasCompileAsset == hasRuntimeAsset;
                    isSupported &= hasCompilePlaceHolder == hasRuntimePlaceHolder;

                    if (!isSupported)
                    {
                        Log.LogMessage(LogImportance.Low, $"Skipping {fx} because it is not supported on {target}.");
                        break;
                    }
                }

                if (isSupported)
                {
                    var supportedFramework = new TaskItem(framework.ItemSpec);
                    supportedFramework.SetMetadata("HarvestedFromPackage", package);

                    // set version

                    // first try the resolved compile asset for this package
                    var refAssm = compileAssets.FirstOrDefault(r => !NuGetAssetResolver.IsPlaceholder(r))?.Substring(PackageId.Length + 1);

                    if (refAssm == null)
                    {
                        // if we didn't have a compile asset it means this framework is supported inbox with a placeholder
                        // resolve the assets without placeholders to pick up the netstandard reference assembly.
                        compileAssets = resolverWithoutPlaceholders.ResolveCompileAssets(fx);
                        refAssm       = compileAssets.FirstOrDefault(r => !NuGetAssetResolver.IsPlaceholder(r));
                    }

                    string version = "unknown";
                    if (refAssm != null)
                    {
                        version = VersionUtility.GetAssemblyVersion(Path.Combine(packagePath, refAssm))?.ToString() ?? version;
                    }

                    supportedFramework.SetMetadata("Version", version);

                    Log.LogMessage($"Validating version {version} for {supportedFramework.ItemSpec} because it was supported by {PackageId}/{PackageVersion}.");

                    supportedFrameworks.Add(supportedFramework);
                }
            }

            SupportedFrameworks = supportedFrameworks.ToArray();
        }
示例#4
0
        private void LoadSupport()
        {
            _frameworks = new Dictionary <NuGetFramework, ValidationFramework>();

            // determine which TxM:RIDs should be considered for support based on Frameworks item
            foreach (var framework in Frameworks)
            {
                NuGetFramework fx;
                try
                {
                    fx = FrameworkUtilities.ParseNormalized(framework.ItemSpec);
                }
                catch (Exception ex)
                {
                    Log.LogError($"Could not parse Framework {framework.ItemSpec}. {ex}");
                    continue;
                }

                if (fx.Equals(NuGetFramework.UnsupportedFramework))
                {
                    Log.LogError($"Did not recognize {framework.ItemSpec} as valid Framework.");
                    continue;
                }

                string runtimeIdList = framework.GetMetadata("RuntimeIDs");

                if (_frameworks.ContainsKey(fx))
                {
                    Log.LogError($"Framework {fx} has been listed in Frameworks more than once.");
                    continue;
                }

                _frameworks[fx] = new ValidationFramework(fx);

                if (!String.IsNullOrWhiteSpace(runtimeIdList))
                {
                    _frameworks[fx].RuntimeIds = runtimeIdList.Split(';');
                }
            }

            // keep a list of explicitly listed supported frameworks so that we can check for conflicts.
            HashSet <NuGetFramework> explicitlySupportedFrameworks = new HashSet <NuGetFramework>();

            // determine what version should be supported based on SupportedFramework items
            foreach (var supportedFramework in SupportedFrameworks)
            {
                NuGetFramework fx;
                string         fxString           = supportedFramework.ItemSpec;
                bool           isExclusiveVersion = fxString.Length > 1 && fxString[0] == '[' && fxString[fxString.Length - 1] == ']';
                if (isExclusiveVersion)
                {
                    fxString = fxString.Substring(1, fxString.Length - 2);
                }

                try
                {
                    fx = FrameworkUtilities.ParseNormalized(fxString);
                }
                catch (Exception ex)
                {
                    Log.LogError($"Could not parse TargetFramework {fxString} as a SupportedFramework. {ex}");
                    continue;
                }

                if (fx.Equals(NuGetFramework.UnsupportedFramework))
                {
                    Log.LogError($"Did not recognize TargetFramework {fxString} as a SupportedFramework.");
                    continue;
                }

                Version supportedVersion;
                string  version = supportedFramework.GetMetadata("Version");
                try
                {
                    supportedVersion = Version.Parse(version);
                }
                catch (Exception ex)
                {
                    Log.LogError($"Could not parse Version {version} on SupportedFramework item {supportedFramework.ItemSpec}. {ex}");
                    continue;
                }

                ValidationFramework validationFramework = null;
                if (!_frameworks.TryGetValue(fx, out validationFramework))
                {
                    Log.LogError($"SupportedFramework {fx} was specified but is not part of the Framework list to use for validation.");
                    continue;
                }


                if (explicitlySupportedFrameworks.Contains(fx))
                {
                    if (validationFramework.SupportedVersion != supportedVersion)
                    {
                        Log.LogError($"Framework {fx} has been listed in SupportedFrameworks more than once with different versions {validationFramework.SupportedVersion} and {supportedVersion}.  Framework should only be listed once with the expected API version for that platform.");
                    }
                    continue;
                }
                explicitlySupportedFrameworks.Add(fx);

                validationFramework.SupportedVersion = supportedVersion;

                if (!isExclusiveVersion)
                {
                    // find all frameworks of higher version, sorted by version ascending
                    var higherFrameworks = _frameworks.Values.Where(vf => vf.Framework.Framework == fx.Framework && vf.Framework.Version > fx.Version).OrderBy(vf => vf.Framework.Version);

                    foreach (var higherFramework in higherFrameworks)
                    {
                        if (higherFramework.SupportedVersion != null && higherFramework.SupportedVersion > supportedVersion)
                        {
                            // found an higher framework version a higher API version, stop applying this supported version
                            break;
                        }

                        higherFramework.SupportedVersion = supportedVersion;
                    }
                }
            }


            // determine which Frameworks should support inbox
            _frameworkSet = FrameworkSet.Load(FrameworkListsPath);
            foreach (IEnumerable <Framework> inboxFxGroup in _frameworkSet.Frameworks.Values)
            {
                foreach (Framework inboxFx in inboxFxGroup)
                {
                    // get currently supported version to see if we have OOB'ed it
                    Version inboxVersion = null;
                    inboxFx.Assemblies.TryGetValue(ContractName, out inboxVersion);

                    if (inboxVersion != null)
                    {
                        NuGetFramework      fx = FrameworkUtilities.ParseNormalized(inboxFx.ShortName);
                        ValidationFramework validationFramework = null;
                        if (_frameworks.TryGetValue(fx, out validationFramework))
                        {
                            Version supportedVersion = validationFramework.SupportedVersion;

                            if (supportedVersion != null &&
                                (supportedVersion.Major > inboxVersion.Major ||
                                 (supportedVersion.Major == inboxVersion.Major && supportedVersion.Minor > inboxVersion.Minor)))
                            {
                                // Higher major.minor
                                Log.LogMessage(LogImportance.Low, $"Framework {fx} supported {ContractName} as inbox but the current supported version {supportedVersion} is higher in major.minor than inbox version {inboxVersion}.  Assuming out of box.");
                                continue;
                            }
                            else if (supportedVersion != null && supportedVersion < inboxVersion)
                            {
                                // Lower version
                                Log.LogError($"Framework {fx} supports {ContractName} as inbox but the current supported version {supportedVersion} is lower than the inbox version {inboxVersion}");
                            }

                            // equal major.minor, build.revision difference is permitted, prefer the version listed by ContractSupport item
                        }

                        if (validationFramework == null)
                        {
                            // we may not be explicitly validating for this framework so add it to validate inbox assets.
                            _frameworks[fx] = validationFramework = new ValidationFramework(fx)
                            {
                                SupportedVersion = inboxVersion
                            };
                        }

                        validationFramework.IsInbox = true;
                    }
                }
            }

            // for every framework we know about, also validate it's generation to ensure it can
            // be targeted by PCL.  Even if a package only supports a single framework we still
            // want to include a portable reference assembly.  This allows 3rd parties to add
            // their own implementation via a lineup/runtime.json.

            // only consider frameworks that support the contract at a specific version
            var portableFrameworks = _frameworks.Values.Where(fx => fx.SupportedVersion != null && fx.SupportedVersion != s_maxVersion).ToArray();

            var genVersionSuppression = GetSuppressionValues(Suppression.PermitPortableVersionMismatch) ?? new HashSet <string>();
            Dictionary <NuGetFramework, ValidationFramework> generationsToValidate = new Dictionary <NuGetFramework, ValidationFramework>();

            foreach (var framework in portableFrameworks)
            {
                NuGetFramework generation = new NuGetFramework(_generationIdentifier, Generations.DetermineGenerationForFramework(framework.Framework, UseNetPlatform));
                Log.LogMessage(LogImportance.Low, $"Validating {generation} for {ContractName}, {framework.SupportedVersion} since it is supported by {framework.Framework}");

                ValidationFramework existingGeneration = null;
                if (generationsToValidate.TryGetValue(generation, out existingGeneration))
                {
                    if (!VersionUtility.IsCompatibleApiVersion(framework.SupportedVersion, existingGeneration.SupportedVersion) && !genVersionSuppression.Contains(framework.Framework.ToString()))
                    {
                        Log.LogError($"Framework {framework.Framework} supports {ContractName} at {framework.SupportedVersion} which is lower than {existingGeneration.SupportedVersion} supported by generation {generation.GetShortFolderName()}");
                    }
                }
                else
                {
                    generationsToValidate.Add(generation, new ValidationFramework(generation)
                    {
                        SupportedVersion = framework.SupportedVersion
                    });
                }
            }

            foreach (var generation in generationsToValidate)
            {
                _frameworks.Add(generation.Key, generation.Value);
            }

            // for every generation supported explcitly in implementation, ensure
            // it can be targeted by PCL.
            foreach (var packageGroup in _resolver.GetAllRuntimeItems())
            {
                var allGenerationalImplementations = packageGroup.Value
                                                     .Where(contentGroup => FrameworkUtilities.IsGenerationMoniker(contentGroup.Properties[PropertyNames.TargetFrameworkMoniker] as NuGetFramework))
                                                     .SelectMany(contentGroup => contentGroup.Items.Select(item => _targetPathToPackageItem[AggregateNuGetAssetResolver.AsPackageSpecificTargetPath(packageGroup.Key, item.Path)]));

                foreach (var generationalImplementation in allGenerationalImplementations)
                {
                    NuGetFramework generation = generationalImplementation.TargetFramework;
                    if (_frameworks.ContainsKey(generation))
                    {
                        continue;
                    }

                    Version supportedVersion = generationalImplementation.Version;

                    Log.LogMessage(LogImportance.Low, $"Validating {generation} for {ContractName}, {supportedVersion} since it is supported by {generationalImplementation.TargetPath}");

                    _frameworks.Add(generation, new ValidationFramework(generation)
                    {
                        SupportedVersion = supportedVersion
                    });
                }
            }
        }
示例#5
0
        private void ValidateSupport()
        {
            // validate support for each TxM:RID
            foreach (var validateFramework in _frameworks.Values)
            {
                NuGetFramework fx = validateFramework.Framework;
                Version        supportedVersion = validateFramework.SupportedVersion;

                var  compileAssetPaths = _resolver.ResolveCompileAssets(fx, PackageId);
                bool hasCompileAsset, hasCompilePlaceHolder;
                ExamineAssets("Compile", ContractName, fx.ToString(), compileAssetPaths, out hasCompileAsset, out hasCompilePlaceHolder);

                // resolve/test for each RID associated with this framework.
                foreach (string runtimeId in validateFramework.RuntimeIds)
                {
                    string target            = String.IsNullOrEmpty(runtimeId) ? fx.ToString() : $"{fx}/{runtimeId}";
                    var    runtimeAssetPaths = _resolver.ResolveRuntimeAssets(fx, runtimeId);

                    bool hasRuntimeAsset, hasRuntimePlaceHolder;
                    ExamineAssets("Runtime", ContractName, target, runtimeAssetPaths, out hasRuntimeAsset, out hasRuntimePlaceHolder);

                    if (null == supportedVersion)
                    {
                        // Contract should not be supported on this platform.
                        bool permitImplementation = HasSuppression(Suppression.PermitImplementation, target);

                        if (hasCompileAsset && (hasRuntimeAsset & !permitImplementation))
                        {
                            Log.LogError($"{ContractName} should not be supported on {target} but has both compile and runtime assets.");
                        }
                        else if (hasRuntimeAsset & !permitImplementation)
                        {
                            Log.LogError($"{ContractName} should not be supported on {target} but has runtime assets.");
                        }

                        if (hasRuntimePlaceHolder && hasCompilePlaceHolder)
                        {
                            Log.LogError($"{ContractName} should not be supported on {target} but has placeholders for both compile and runtime which will permit the package to install.");
                        }
                    }
                    else
                    {
                        if (validateFramework.IsInbox)
                        {
                            if (!hasCompileAsset && !hasCompilePlaceHolder)
                            {
                                Log.LogError($"Framework {fx} should support {ContractName} inbox but was missing a placeholder for compile-time.  You may need to add <InboxOnTargetFramework Include=\"{fx.GetShortFolderName()}\" /> to your project.");
                            }
                            else if (hasCompileAsset)
                            {
                                Log.LogError($"Framework {fx} should support {ContractName} inbox but contained a reference assemblies: {String.Join(", ", compileAssetPaths)}.  You may need to add <InboxOnTargetFramework Include=\"{fx.GetShortFolderName()}\" /> to your project.");
                            }

                            if (!hasRuntimeAsset && !hasRuntimePlaceHolder)
                            {
                                Log.LogError($"Framework {fx} should support {ContractName} inbox but was missing a placeholder for run-time.  You may need to add <InboxOnTargetFramework Include=\"{fx.GetShortFolderName()}\" /> to your project.");
                            }
                            else if (hasRuntimeAsset)
                            {
                                Log.LogError($"Framework {fx} should support {ContractName} inbox but contained a implementation assemblies: {String.Join(", ", runtimeAssetPaths)}.  You may need to add <InboxOnTargetFramework Include=\"{fx.GetShortFolderName()}\" /> to your project.");
                            }
                        }
                        else
                        {
                            Version referenceAssemblyVersion = null;
                            if (!hasCompileAsset)
                            {
                                Log.LogError($"{ContractName} should be supported on {target} but has no compile assets.");
                            }
                            else
                            {
                                var referenceAssemblies = compileAssetPaths.Where(IsDll);

                                if (referenceAssemblies.Count() > 1)
                                {
                                    Log.LogError($"{ContractName} should only contain a single compile asset for {target}.");
                                }

                                foreach (var referenceAssembly in referenceAssemblies)
                                {
                                    referenceAssemblyVersion = _targetPathToPackageItem[referenceAssembly].Version;

                                    if (!VersionUtility.IsCompatibleApiVersion(supportedVersion, referenceAssemblyVersion))
                                    {
                                        Log.LogError($"{ContractName} should support API version {supportedVersion} on {target} but {referenceAssembly} was found to support {referenceAssemblyVersion?.ToString() ?? "<unknown version>"}.");
                                    }
                                }
                            }

                            if (!hasRuntimeAsset && !FrameworkUtilities.IsGenerationMoniker(validateFramework.Framework))
                            {
                                Log.LogError($"{ContractName} should be supported on {target} but has no runtime assets.");
                            }
                            else
                            {
                                var implementationAssemblies = runtimeAssetPaths.Where(IsDll);

                                Dictionary <string, string> implementationFiles = new Dictionary <string, string>();
                                foreach (var implementationAssembly in implementationAssemblies)
                                {
                                    Version implementationVersion = _targetPathToPackageItem[implementationAssembly].Version;

                                    if (!VersionUtility.IsCompatibleApiVersion(supportedVersion, implementationVersion))
                                    {
                                        Log.LogError($"{ContractName} should support API version {supportedVersion} on {target} but {implementationAssembly} was found to support {implementationVersion?.ToString() ?? "<unknown version>"}.");
                                    }

                                    if (referenceAssemblyVersion != null &&
                                        HasSuppression(Suppression.PermitHigherCompatibleImplementationVersion) ?
                                        !VersionUtility.IsCompatibleApiVersion(referenceAssemblyVersion, implementationVersion) :
                                        (implementationVersion != referenceAssemblyVersion))
                                    {
                                        Log.LogError($"{ContractName} has mismatched compile ({referenceAssemblyVersion}) and runtime ({implementationVersion}) versions on {target}.");
                                    }

                                    string fileName = Path.GetFileName(implementationAssembly);

                                    if (implementationFiles.ContainsKey(fileName))
                                    {
                                        Log.LogError($"{ContractName} includes both {implementationAssembly} and {implementationFiles[fileName]} an on {target} which have the same name and will clash when both packages are used.");
                                    }
                                    else
                                    {
                                        implementationFiles[fileName] = implementationAssembly;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // Set output items
            AllSupportedFrameworks = _frameworks.Values.Where(fx => fx.SupportedVersion != null).Select(fx => fx.ToItem()).OrderBy(i => i.ItemSpec).ToArray();

            if (!String.IsNullOrEmpty(ValidationReport))
            {
                WriteValidationReport(ValidationReport, _frameworks.Values);
            }
        }
        public void GetLastStablePackagesFromIndex()
        {
            var index = PackageIndex.Load(PackageIndexes.Select(pi => pi.GetMetadata("FullPath")));

            List <ITaskItem> lastStablePackages = new List <ITaskItem>();

            foreach (var latestPackage in LatestPackages)
            {
                var packageId = latestPackage.ItemSpec;

                var          versionString = latestPackage.GetMetadata("Version");
                NuGetVersion nuGetVersion  = null;
                if (versionString == null || !NuGetVersion.TryParse(versionString, out nuGetVersion))
                {
                    Log.LogMessage($"Could not parse version {versionString} for LatestPackage {packageId}, will use latest stable.");
                }

                var latestVersion = nuGetVersion?.Version;

                PackageInfo info;
                if (index.Packages.TryGetValue(packageId, out info))
                {
                    var candidateVersions = (latestVersion == null) ? info.StableVersions : info.StableVersions.Where(sv => VersionUtility.As4PartVersion(sv) < latestVersion);

                    if (candidateVersions.Any())
                    {
                        lastStablePackages.Add(CreateItem(latestPackage, candidateVersions.Max()));
                    }
                }
            }

            LastStablePackages = lastStablePackages.ToArray();
        }
示例#7
0
 public static Version GetLatestPatchStableVersionForRelease(this IEnumerable <Version> versions, int eraMajorVersion, int eraMinorVersion)
 {
     return(versions.Where(v => VersionUtility.As2PartVersion(v) == new Version(eraMajorVersion, eraMinorVersion))
            .OrderByDescending(v => v)
            .FirstOrDefault());
 }
示例#8
0
        public void HarvestFilesFromPackage()
        {
            string pathToPackage = Path.Combine(PackagesFolder, PackageId, PackageVersion);

            if (!Directory.Exists(pathToPackage))
            {
                Log.LogError($"Cannot harvest from package {PackageId}/{PackageVersion} because {pathToPackage} does not exist.");
                return;
            }

            var livePackageFiles = Files.NullAsEmpty()
                                   .Where(f => IsIncludedExtension(f.GetMetadata("Extension")))
                                   .Select(f => new PackageItem(f))
                                   .ToDictionary(p => p.TargetPath, StringComparer.OrdinalIgnoreCase);

            var harvestedFiles = new List <ITaskItem>();
            var removeFiles    = new List <ITaskItem>();

            // make sure we preserve refs that match desktop assemblies
            var liveDesktopDlls    = livePackageFiles.Values.Where(pi => pi.IsDll && pi.TargetFramework?.Framework == FrameworkConstants.FrameworkIdentifiers.Net);
            var desktopRefVersions = liveDesktopDlls.Where(d => d.IsRef && d.Version != null).Select(d => d.Version);
            var desktopLibVersions = liveDesktopDlls.Where(d => !d.IsRef && d.Version != null).Select(d => d.Version);

            // find destkop assemblies with no matching lib.
            var preserveRefVersion = new HashSet <Version>(desktopLibVersions);

            preserveRefVersion.ExceptWith(desktopRefVersions);

            foreach (var extension in s_includedExtensions)
            {
                foreach (var packageFile in Directory.EnumerateFiles(pathToPackage, $"*{extension}", SearchOption.AllDirectories))
                {
                    string packagePath = packageFile.Substring(pathToPackage.Length + 1).Replace('\\', '/');

                    // determine if we should include this file from the harvested package

                    // exclude if its specifically set for exclusion
                    if (ShouldExclude(packagePath))
                    {
                        Log.LogMessage(LogImportance.Low, $"Excluding package path {packagePath}.");
                        continue;
                    }

                    var assemblyVersion = extension == s_dll?VersionUtility.GetAssemblyVersion(packageFile) : null;

                    PackageItem liveFile = null;

                    // determine if the harvested file clashes with a live built file
                    // we'll prefer the harvested reference assembly so long as it's the same API
                    // version and not required to match implementation 1:1 as is the case for desktop
                    if (livePackageFiles.TryGetValue(packagePath, out liveFile))
                    {
                        // Not a dll, not a ref, or not a versioned assembly: prefer live built file.
                        if (extension != s_dll || !liveFile.IsRef || assemblyVersion == null || liveFile.Version == null)
                        {
                            Log.LogMessage(LogImportance.Low, $"Preferring live build of package path {packagePath} over the asset from last stable package.");
                            continue;
                        }

                        // preserve desktop references to ensure bindingRedirects will work.
                        if (liveFile.TargetFramework.Framework == FrameworkConstants.FrameworkIdentifiers.Net)
                        {
                            Log.LogMessage(LogImportance.Low, $"Preferring live build of package path {packagePath} over the asset from last stable package for desktop framework.");
                            continue;
                        }

                        // as above but handle the case where a netstandard ref may be used for a desktop impl.
                        if (preserveRefVersion.Contains(liveFile.Version))
                        {
                            Log.LogMessage(LogImportance.Low, $"Preferring live build of package path {packagePath} over the asset from last stable package for desktop framework.");
                            continue;
                        }

                        // preserve references with a different major.minor version
                        if (assemblyVersion.Major != liveFile.Version.Major ||
                            assemblyVersion.Minor != liveFile.Version.Minor)
                        {
                            Log.LogMessage(LogImportance.Low, $"Preferring live build of reference {packagePath} over the asset from last stable package since the live build is a different API version.");
                            continue;
                        }

                        // preserve references that specifically set the preserve metadata.
                        bool preserve = false;
                        bool.TryParse(liveFile.OriginalItem.GetMetadata("Preserve"), out preserve);
                        if (preserve)
                        {
                            Log.LogMessage(LogImportance.Low, $"Preferring live build of reference {packagePath} over the asset from last stable package since Preserve was set to true.");
                            continue;
                        }

                        // replace the live file with the harvested one, removing both the live file and PDB from the
                        // file list.
                        Log.LogMessage($"Using reference {packagePath} from last stable package {PackageId}/{PackageVersion} rather than the built reference {liveFile.SourcePath} since it is the same API version.  Set <Preserve>true</Preserve> on {liveFile.SourceProject} if you'd like to avoid this..");
                        removeFiles.Add(liveFile.OriginalItem);

                        PackageItem livePdbFile;
                        if (livePackageFiles.TryGetValue(Path.ChangeExtension(packagePath, ".pdb"), out livePdbFile))
                        {
                            removeFiles.Add(livePdbFile.OriginalItem);
                        }
                    }
                    else
                    {
                        Log.LogMessage(LogImportance.Low, $"Including {packagePath} from last stable package {PackageId}/{PackageVersion}.");
                    }

                    var item = new TaskItem(packageFile);

                    if (liveFile?.OriginalItem != null)
                    {
                        // preserve all the meta-data from the live file that was replaced.
                        liveFile.OriginalItem.CopyMetadataTo(item);
                    }
                    else
                    {
                        var targetPath = Path.GetDirectoryName(packagePath).Replace('\\', '/');
                        item.SetMetadata("TargetPath", targetPath);
                        string targetFramework = GetTargetFrameworkFromPackagePath(targetPath);
                        item.SetMetadata("TargetFramework", targetFramework);
                        // only harvest for non-portable frameworks, matches logic in packaging.targets.
                        bool harvestDependencies = !targetFramework.StartsWith("portable-");
                        item.SetMetadata("HarvestDependencies", harvestDependencies.ToString());
                        item.SetMetadata("IsReferenceAsset", IsReferencePackagePath(targetPath).ToString());
                    }

                    if (assemblyVersion != null)
                    {
                        // overwrite whatever metadata may have been copied from the live file.
                        item.SetMetadata("AssemblyVersion", assemblyVersion.ToString());
                    }

                    harvestedFiles.Add(item);
                }
            }

            HarvestedFiles = harvestedFiles.ToArray();

            if (Files != null)
            {
                UpdatedFiles = Files.Except(removeFiles).ToArray();
            }
        }
示例#9
0
        private void ValidateIndex()
        {
            if (SkipIndexCheck)
            {
                return;
            }

            if (PackageIndexes == null || PackageIndexes.Length == 0)
            {
                return;
            }

            PackageIndex.Current.Merge(PackageIndexes.Select(pi => pi.GetMetadata("FullPath")));

            PackageInfo info;

            if (!PackageIndex.Current.Packages.TryGetValue(PackageId, out info))
            {
                Log.LogError($"PackageIndex from {String.Join(", ", PackageIndexes.Select(i => i.ItemSpec))} is missing an entry for package {PackageId}.  Please run /t:UpdatePackageIndex on this project to commit an update.");
                return;
            }

            var thisPackageFiles = _validateFiles[PackageId];
            var refFiles         = thisPackageFiles.Where(f => f.TargetPath.StartsWith("ref/", StringComparison.OrdinalIgnoreCase));

            if (!refFiles.Any())
            {
                refFiles = thisPackageFiles.Where(f => f.TargetPath.StartsWith("lib/", StringComparison.OrdinalIgnoreCase));
            }

            foreach (var refFileVersion in refFiles.Where(r => r.Version != null).Select(r => VersionUtility.As4PartVersion(r.Version)).Distinct())
            {
                if (!info.AssemblyVersionInPackageVersion.ContainsKey(refFileVersion))
                {
                    Log.LogError($"PackageIndex from {String.Join(", ", PackageIndexes.Select(i => i.ItemSpec))} is missing an assembly version entry for {refFileVersion} for package {PackageId}.  Please run /t:UpdatePackageIndex on this project to commit an update.");
                }
            }
        }
示例#10
0
        private void ValidateSupport()
        {
            var runtimeFxSuppression = GetSuppressionValues(Suppression.PermitRuntimeTargetMonikerMismatch) ?? new HashSet <string>();
            ValidationReport report  = null;

            if (ValidationReport != null)
            {
                report = CreateValidationReport();
            }

            // validate support for each TxM:RID
            foreach (var validateFramework in _frameworks.Values)
            {
                NuGetFramework fx = validateFramework.Framework;
                Version        supportedVersion = validateFramework.SupportedVersion;

                var  compileAssetPaths = _resolver.ResolveCompileAssets(fx, PackageId);
                bool hasCompileAsset, hasCompilePlaceHolder;
                NuGetAssetResolver.ExamineAssets(Log, "Compile", ContractName, fx.ToString(), compileAssetPaths, out hasCompileAsset, out hasCompilePlaceHolder);

                if (report != null && validateFramework.RuntimeIds.All(rid => !String.IsNullOrEmpty(rid)))
                {
                    // Add Framework only (compile) target if all RIDs are non-empty.
                    // This acts as a compile target for a framework that requires a RID for runtime.
                    var reportTarget = new Target()
                    {
                        Framework     = fx.ToString(),
                        RuntimeID     = null,
                        CompileAssets = compileAssetPaths.Where(c => !NuGetAssetResolver.IsPlaceholder(c)).Select(c => GetPackageAssetFromTargetPath(c)).ToArray()
                    };
                    report.Targets.Add(fx.ToString(), reportTarget);
                }

                // resolve/test for each RID associated with this framework.
                foreach (string runtimeId in validateFramework.RuntimeIds)
                {
                    string target            = String.IsNullOrEmpty(runtimeId) ? fx.ToString() : $"{fx}/{runtimeId}";
                    var    runtimeAssetPaths = _resolver.ResolveRuntimeAssets(fx, runtimeId);

                    bool hasRuntimeAsset, hasRuntimePlaceHolder;
                    NuGetAssetResolver.ExamineAssets(Log, "Runtime", ContractName, target, runtimeAssetPaths, out hasRuntimeAsset, out hasRuntimePlaceHolder);

                    if (null == supportedVersion)
                    {
                        // Contract should not be supported on this platform.
                        bool permitImplementation = HasSuppression(Suppression.PermitImplementation, target);

                        if (hasCompileAsset && (hasRuntimeAsset & !permitImplementation))
                        {
                            Log.LogError($"{ContractName} should not be supported on {target} but has both compile and runtime assets.");
                        }
                        else if (hasRuntimeAsset & !permitImplementation)
                        {
                            Log.LogError($"{ContractName} should not be supported on {target} but has runtime assets.");
                        }

                        if (hasRuntimePlaceHolder && hasCompilePlaceHolder)
                        {
                            Log.LogError($"{ContractName} should not be supported on {target} but has placeholders for both compile and runtime which will permit the package to install.");
                        }
                    }
                    else
                    {
                        if (report != null)
                        {
                            var reportTarget = new Target()
                            {
                                Framework     = fx.ToString(),
                                RuntimeID     = runtimeId,
                                CompileAssets = compileAssetPaths.Where(c => !NuGetAssetResolver.IsPlaceholder(c)).Select(c => GetPackageAssetFromTargetPath(c)).ToArray(),
                                RuntimeAssets = runtimeAssetPaths.Where(r => !NuGetAssetResolver.IsPlaceholder(r)).Select(r => GetPackageAssetFromTargetPath(r)).ToArray()
                            };
                            report.Targets.Add(target, reportTarget);
                        }

                        if (validateFramework.IsInbox)
                        {
                            if (!hasCompileAsset && !hasCompilePlaceHolder)
                            {
                                Log.LogError($"Framework {fx} should support {ContractName} inbox but was missing a placeholder for compile-time.  You may need to add <InboxOnTargetFramework Include=\"{fx.GetShortFolderName()}\" /> to your project.");
                            }
                            else if (hasCompileAsset)
                            {
                                Log.LogError($"Framework {fx} should support {ContractName} inbox but contained a reference assemblies: {String.Join(", ", compileAssetPaths)}.  You may need to add <InboxOnTargetFramework Include=\"{fx.GetShortFolderName()}\" /> to your project.");
                            }

                            if (!hasRuntimeAsset && !hasRuntimePlaceHolder)
                            {
                                Log.LogError($"Framework {fx} should support {ContractName} inbox but was missing a placeholder for run-time.  You may need to add <InboxOnTargetFramework Include=\"{fx.GetShortFolderName()}\" /> to your project.");
                            }
                            else if (hasRuntimeAsset)
                            {
                                Log.LogError($"Framework {fx} should support {ContractName} inbox but contained a implementation assemblies: {String.Join(", ", runtimeAssetPaths)}.  You may need to add <InboxOnTargetFramework Include=\"{fx.GetShortFolderName()}\" /> to your project.");
                            }
                        }
                        else
                        {
                            Version referenceAssemblyVersion = null;
                            if (!hasCompileAsset)
                            {
                                Log.LogError($"{ContractName} should be supported on {target} but has no compile assets.");
                            }
                            else
                            {
                                var referenceAssemblies = compileAssetPaths.Where(IsDll);

                                if (referenceAssemblies.Count() > 1)
                                {
                                    Log.LogError($"{ContractName} should only contain a single compile asset for {target}.");
                                }

                                foreach (var referenceAssembly in referenceAssemblies)
                                {
                                    referenceAssemblyVersion = _targetPathToPackageItem[referenceAssembly].Version;

                                    if (!VersionUtility.IsCompatibleApiVersion(supportedVersion, referenceAssemblyVersion))
                                    {
                                        Log.LogError($"{ContractName} should support API version {supportedVersion} on {target} but {referenceAssembly} was found to support {referenceAssemblyVersion?.ToString() ?? "<unknown version>"}.");
                                    }
                                }
                            }

                            if (!hasRuntimeAsset && !FrameworkUtilities.IsGenerationMoniker(validateFramework.Framework))
                            {
                                Log.LogError($"{ContractName} should be supported on {target} but has no runtime assets.");
                            }
                            else
                            {
                                var implementationAssemblies = runtimeAssetPaths.Where(IsDll);

                                Dictionary <string, string> implementationFiles = new Dictionary <string, string>();
                                foreach (var implementationAssembly in implementationAssemblies)
                                {
                                    var     packageItem           = _targetPathToPackageItem[implementationAssembly];
                                    Version implementationVersion = packageItem.Version;

                                    if (!VersionUtility.IsCompatibleApiVersion(supportedVersion, implementationVersion))
                                    {
                                        Log.LogError($"{ContractName} should support API version {supportedVersion} on {target} but {implementationAssembly} was found to support {implementationVersion?.ToString() ?? "<unknown version>"}.");
                                    }

                                    // Previously we only permitted compatible mismatch if Suppression.PermitHigherCompatibleImplementationVersion was specified
                                    // this is a permitted thing on every framework but desktop (which requires exact match to ensure bindingRedirects exist)
                                    // Now make this the default, we'll check desktop, where it matters, more strictly
                                    if (referenceAssemblyVersion != null &&
                                        !VersionUtility.IsCompatibleApiVersion(referenceAssemblyVersion, implementationVersion))
                                    {
                                        Log.LogError($"{ContractName} has mismatched compile ({referenceAssemblyVersion}) and runtime ({implementationVersion}) versions on {target}.");
                                    }

                                    if (fx.Framework == FrameworkConstants.FrameworkIdentifiers.Net &&
                                        !referenceAssemblyVersion.Equals(implementationVersion))
                                    {
                                        Log.LogError($"{ContractName} has a higher runtime version ({implementationVersion}) than compile version ({referenceAssemblyVersion}) on .NET Desktop framework {target}.  This will break bindingRedirects.");
                                    }

                                    string fileName = Path.GetFileName(implementationAssembly);

                                    if (implementationFiles.ContainsKey(fileName))
                                    {
                                        Log.LogError($"{ContractName} includes both {implementationAssembly} and {implementationFiles[fileName]} an on {target} which have the same name and will clash when both packages are used.");
                                    }
                                    else
                                    {
                                        implementationFiles[fileName] = implementationAssembly;
                                    }

                                    if (packageItem.TargetFramework != fx && !runtimeFxSuppression.Contains(fx.ToString()))
                                    {
                                        // the selected asset wasn't an exact framework match, let's see if we have an exact match in any other runtime asset.
                                        var matchingFxAssets = _targetPathToPackageItem.Values.Where(i => i.TargetFramework == fx && // exact framework
                                                                                                                                     // Same file
                                                                                                     Path.GetFileName(i.TargetPath).Equals(fileName, StringComparison.OrdinalIgnoreCase) &&
                                                                                                                                     // Is implementation
                                                                                                     (i.TargetPath.StartsWith("lib") || i.TargetPath.StartsWith("runtimes")) &&
                                                                                                                                     // is not the same source file as was already selected
                                                                                                     i.SourcePath != packageItem.SourcePath);

                                        if (matchingFxAssets.Any())
                                        {
                                            Log.LogError($"When targeting {target} {ContractName} will use {implementationAssembly} which targets {packageItem.TargetFramework.GetShortFolderName()}  but {String.Join(";", matchingFxAssets.Select(i => i.TargetPath))} targets {fx.GetShortFolderName()} specifically.");
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // Set output items
            AllSupportedFrameworks = _frameworks.Values.Where(fx => fx.SupportedVersion != null).Select(fx => fx.ToItem()).OrderBy(i => i.ItemSpec).ToArray();

            if (!String.IsNullOrEmpty(ValidationReport))
            {
                report.Save(ValidationReport);
            }
        }
示例#11
0
        public void HarvestFilesFromPackage()
        {
            string pathToPackage = _packageFolders[PackageId];

            var livePackageItems = Files.NullAsEmpty()
                                   .Where(f => IsIncludedExtension(f.GetMetadata("Extension")))
                                   .Select(f => new PackageItem(f));

            var livePackageFiles = new Dictionary <string, PackageItem>(StringComparer.OrdinalIgnoreCase);

            foreach (var livePackageItem in livePackageItems)
            {
                PackageItem existingitem;

                if (livePackageFiles.TryGetValue(livePackageItem.TargetPath, out existingitem))
                {
                    Log.LogError($"Package contains two files with same targetpath: {livePackageItem.TargetPath}, items:{livePackageItem.SourcePath}, {existingitem.SourcePath}.");
                }
                else
                {
                    livePackageFiles.Add(livePackageItem.TargetPath, livePackageItem);
                }
            }

            var harvestedFiles = new List <ITaskItem>();
            var removeFiles    = new List <ITaskItem>();

            // make sure we preserve refs that match desktop assemblies
            var liveDesktopDlls    = livePackageFiles.Values.Where(pi => pi.IsDll && pi.TargetFramework?.Framework == FrameworkConstants.FrameworkIdentifiers.Net);
            var desktopRefVersions = liveDesktopDlls.Where(d => d.IsRef && d.Version != null).Select(d => d.Version);
            var desktopLibVersions = liveDesktopDlls.Where(d => !d.IsRef && d.Version != null).Select(d => d.Version);

            // find desktop assemblies with no matching lib.
            var preserveRefVersion = new HashSet <Version>(desktopLibVersions);

            preserveRefVersion.ExceptWith(desktopRefVersions);

            foreach (var extension in s_includedExtensions)
            {
                foreach (var packageFile in Directory.EnumerateFiles(pathToPackage, $"*{extension}", SearchOption.AllDirectories))
                {
                    string harvestPackagePath = packageFile.Substring(pathToPackage.Length + 1).Replace('\\', '/');

                    // determine if we should include this file from the harvested package

                    // exclude if its specifically set for exclusion
                    if (ShouldExclude(harvestPackagePath))
                    {
                        Log.LogMessage(LogImportance.Low, $"Excluding package path {harvestPackagePath} because it is specifically excluded.");
                        continue;
                    }

                    ITaskItem includeItem = null;
                    if (!IncludeAllPaths && !ShouldInclude(harvestPackagePath, out includeItem))
                    {
                        Log.LogMessage(LogImportance.Low, $"Excluding package path {harvestPackagePath} because it is not included in {nameof(PathsToInclude)}.");
                        continue;
                    }

                    // allow for the harvested item to be moved
                    var remappedTargetPath = includeItem?.GetMetadata("TargetPath");
                    if (!String.IsNullOrEmpty(remappedTargetPath))
                    {
                        harvestPackagePath = remappedTargetPath + '/' + Path.GetFileName(packageFile);
                    }

                    List <string> targetPaths = new List <string>()
                    {
                        harvestPackagePath
                    };

                    var additionalTargetPaths = includeItem?.GetMetadata("AdditionalTargetPath");
                    if (!String.IsNullOrEmpty(additionalTargetPaths))
                    {
                        foreach (var additionalTargetPath in additionalTargetPaths.Split(';'))
                        {
                            if (!String.IsNullOrEmpty(additionalTargetPath))
                            {
                                targetPaths.Add(additionalTargetPath + '/' + Path.GetFileName(packageFile));
                            }
                        }
                    }

                    var assemblyVersion = extension == s_dll?VersionUtility.GetAssemblyVersion(packageFile) : null;

                    PackageItem liveFile = null;

                    foreach (var livePackagePath in targetPaths)
                    {
                        // determine if the harvested file clashes with a live built file
                        // we'll prefer the harvested reference assembly so long as it's the same API
                        // version and not required to match implementation 1:1 as is the case for desktop
                        if (livePackageFiles.TryGetValue(livePackagePath, out liveFile))
                        {
                            // Not a dll, or not a versioned assembly: prefer live built file.
                            if (extension != s_dll || assemblyVersion == null || liveFile.Version == null)
                            {
                                // we don't consider this an error even for explicitly included files
                                Log.LogMessage(LogImportance.Low, $"Preferring live build of package path {livePackagePath} over the asset from last stable package because the file is not versioned.");
                                continue;
                            }

                            // not a ref
                            if (!liveFile.IsRef)
                            {
                                LogSkipIncludedFile(livePackagePath, " because it is a newer implementation.");
                                continue;
                            }

                            // preserve desktop references to ensure bindingRedirects will work.
                            if (liveFile.TargetFramework.Framework == FrameworkConstants.FrameworkIdentifiers.Net)
                            {
                                LogSkipIncludedFile(livePackagePath, " because it is desktop reference.");
                                continue;
                            }

                            // as above but handle the case where a netstandard ref may be used for a desktop impl.
                            if (preserveRefVersion.Contains(liveFile.Version))
                            {
                                LogSkipIncludedFile(livePackagePath, " because it will be applicable for desktop projects.");
                                continue;
                            }

                            // preserve references with a different major.minor version
                            if (assemblyVersion.Major != liveFile.Version.Major ||
                                assemblyVersion.Minor != liveFile.Version.Minor)
                            {
                                LogSkipIncludedFile(livePackagePath, $" because it is a different API version ( {liveFile.Version.Major}.{liveFile.Version.Minor} vs {assemblyVersion.Major}.{assemblyVersion.Minor}.");
                                continue;
                            }

                            // preserve references that specifically set the preserve metadata.
                            bool preserve = false;
                            bool.TryParse(liveFile.OriginalItem.GetMetadata("Preserve"), out preserve);
                            if (preserve)
                            {
                                LogSkipIncludedFile(livePackagePath, " because it set metadata Preserve=true.");
                                continue;
                            }

                            // replace the live file with the harvested one, removing both the live file and PDB from the
                            // file list.
                            Log.LogMessage($"Using reference {livePackagePath} from last stable package {PackageId}/{PackageVersion} rather than the built reference {liveFile.SourcePath} since it is the same API version.  Set <Preserve>true</Preserve> on {liveFile.SourceProject} if you'd like to avoid this..");
                            removeFiles.Add(liveFile.OriginalItem);

                            PackageItem livePdbFile;
                            if (livePackageFiles.TryGetValue(Path.ChangeExtension(livePackagePath, ".pdb"), out livePdbFile))
                            {
                                removeFiles.Add(livePdbFile.OriginalItem);
                            }
                        }
                        else
                        {
                            Log.LogMessage(LogImportance.Low, $"Including {livePackagePath} from last stable package {PackageId}/{PackageVersion}.");
                        }

                        var item = new TaskItem(packageFile);

                        if (liveFile?.OriginalItem != null)
                        {
                            // preserve all the meta-data from the live file that was replaced.
                            liveFile.OriginalItem.CopyMetadataTo(item);
                        }
                        else
                        {
                            if (includeItem != null)
                            {
                                includeItem.CopyMetadataTo(item);
                            }
                            var targetPath = Path.GetDirectoryName(livePackagePath).Replace('\\', '/');
                            item.SetMetadata("TargetPath", targetPath);
                            string targetFramework = GetTargetFrameworkFromPackagePath(targetPath);
                            item.SetMetadata("TargetFramework", targetFramework);
                            // only harvest for non-portable frameworks, matches logic in packaging.targets.
                            bool harvestDependencies = !targetFramework.StartsWith("portable-");
                            item.SetMetadata("HarvestDependencies", harvestDependencies.ToString());
                            item.SetMetadata("IsReferenceAsset", IsReferencePackagePath(targetPath).ToString());
                        }

                        if (assemblyVersion != null)
                        {
                            // overwrite whatever metadata may have been copied from the live file.
                            item.SetMetadata("AssemblyVersion", assemblyVersion.ToString());
                        }

                        item.SetMetadata("HarvestedFrom", $"{PackageId}/{PackageVersion}/{harvestPackagePath}");

                        harvestedFiles.Add(item);
                    }
                }
            }

            HarvestedFiles = harvestedFiles.ToArray();

            if (_pathsNotIncluded != null)
            {
                foreach (var pathNotIncluded in _pathsNotIncluded)
                {
                    Log.LogError($"Path '{pathNotIncluded}' was specified in {nameof(PathsToInclude)} but was not found in the package {PackageId}/{PackageVersion}.");
                }
            }

            if (Files != null)
            {
                UpdatedFiles = Files.Except(removeFiles).ToArray();
            }
        }
示例#12
0
        private void UpdateFromValues(PackageIndex index, string id, NuGetVersion version, IEnumerable <Version> assemblyVersions, IEnumerable <string> dllNames)
        {
            PackageInfo info = GetOrCreatePackageInfo(index, id);

            var packageVersion = VersionUtility.As3PartVersion(version.Version);

            // if we have a stable version, add it to the stable versions list
            if (!version.IsPrerelease)
            {
                info.StableVersions.Add(packageVersion);
            }

            var assmVersions = new HashSet <Version>(assemblyVersions.NullAsEmpty().Where(v => v != null));

            // add any new assembly versions
            info.AddAssemblyVersionsInPackage(assmVersions, packageVersion);

            // try to find an identity package to also add a mapping in the case this is a runtime package
            if (id.StartsWith("runtime."))
            {
                foreach (var dllName in dllNames)
                {
                    PackageInfo identityInfo;
                    if (index.Packages.TryGetValue(dllName, out identityInfo))
                    {
                        identityInfo.AddAssemblyVersionsInPackage(assmVersions, packageVersion);
                    }
                }
            }

            // remove any assembly mappings which claim to be in this package version, but aren't in the assemblyList
            var orphanedAssemblyVersions = info.AssemblyVersionInPackageVersion
                                           .Where(pair => pair.Value == packageVersion && !assmVersions.Contains(pair.Key))
                                           .Select(pair => pair.Key);

            if (orphanedAssemblyVersions.Any())
            {
                // make sure these aren't coming from a runtime package.
                var runtimeAssemblyVersions = index.Packages
                                              .Where(p => p.Key.StartsWith("runtime.") && p.Key.EndsWith(id))
                                              .SelectMany(p => p.Value.AssemblyVersionInPackageVersion)
                                              .Where(pair => pair.Value == packageVersion)
                                              .Select(pair => pair.Key);

                orphanedAssemblyVersions = orphanedAssemblyVersions.Except(runtimeAssemblyVersions);
            }

            foreach (var orphanedAssemblyVersion in orphanedAssemblyVersions.ToArray())
            {
                info.AssemblyVersionInPackageVersion.Remove(orphanedAssemblyVersion);
            }

            // if no assemblies are present in this package nor were ever present
            if (assmVersions.Count == 0 &&
                info.AssemblyVersionInPackageVersion.Count == 0)
            {
                // if in the native module map
                if (index.ModulesToPackages.Values.Any(p => p.Equals(id)))
                {
                    // ensure the baseline is set
                    info.BaselineVersion = packageVersion;
                }
            }
        }
示例#13
0
        public Version DetermineGenerationFromFile(string assemblyPath, ILog log, Version expectedVersion = null, IDictionary <string, string> candidateRefs = null, ICollection <string> ignoredRefs = null)
        {
            Version maxGeneration = null;

            if (_generationCache.TryGetValue(assemblyPath, out maxGeneration))
            {
                log.LogMessage(LogImportance.Low, $"Generation of {assemblyPath} is {_generationIdentifier}{maxGeneration} from cache.");
                return(maxGeneration);
            }

            string assemblyName = Path.GetFileNameWithoutExtension(assemblyPath);

            if (ignoredRefs != null && ignoredRefs.Contains(assemblyName))
            {
                return(null);
            }

            using (PEReader peReader = new PEReader(new FileStream(assemblyPath, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.Read)))
            {
                MetadataReader     reader      = peReader.GetMetadataReader();
                AssemblyDefinition assemblyDef = reader.GetAssemblyDefinition();

                assemblyName = reader.GetString(assemblyDef.Name);
                if (ignoredRefs != null && ignoredRefs.Contains(assemblyName))
                {
                    return(null);
                }

                // break a circular dependency
                int cycleIndex = _cycleStack.IndexOf(assemblyName);
                if (cycleIndex != -1)
                {
                    log.LogError($"Cycle detected {string.Join(" > ", _cycleStack.Skip(cycleIndex).ToArray())} > {assemblyName}");
                    return(null);
                }

                _cycleStack.Add(assemblyName);

                if (expectedVersion != null && !VersionUtility.IsCompatibleApiVersion(expectedVersion, assemblyDef.Version))
                {
                    log.LogError($"Expected version {expectedVersion} for referenced assembly {assemblyPath} but found {assemblyDef.Version}");
                }

                // first determine if the identity itself has a generation.
                maxGeneration = DetermineGenerationFromSeeds(assemblyName, assemblyDef.Version, log);

                foreach (var handle in reader.AssemblyReferences)
                {
                    AssemblyReference reference     = reader.GetAssemblyReference(handle);
                    string            referenceName = reader.GetString(reference.Name);

                    if (ignoredRefs != null && ignoredRefs.Contains(referenceName))
                    {
                        continue;
                    }

                    // indirect dependency: prefer the seed value if it exists since we only care about
                    // reference assembly generation for indirect dependencies
                    Version assemblyGeneration = DetermineGenerationFromSeeds(referenceName, reference.Version, log);

                    if (assemblyGeneration == null)
                    {
                        string contractPath = null;
                        if (candidateRefs != null && candidateRefs.TryGetValue(referenceName, out contractPath) &&
                            File.Exists(contractPath))
                        {
                            // traverse the indirect dependencies recursively.
                            assemblyGeneration = DetermineGenerationFromFile(contractPath, log, reference.Version, candidateRefs, ignoredRefs);
                        }
                        else
                        {
                            log.LogError($"Cannot resolve indirect dependency {referenceName}, Version={reference.Version}");
                        }
                    }

                    if (assemblyGeneration == null)
                    {
                        log.LogError($"Could not determine generation for {referenceName}, {reference.Version}.  File did not exist and isn't a known mapping.");
                    }

                    if (maxGeneration == null)
                    {
                        maxGeneration = assemblyGeneration;
                    }
                    else if (assemblyGeneration != null && assemblyGeneration > maxGeneration)
                    {
                        maxGeneration = assemblyGeneration;
                    }
                }
            }

            log.LogMessage(LogImportance.Low, $"Generation of {assemblyPath} is {_generationIdentifier}{maxGeneration}.");
            _generationCache.Add(assemblyPath, maxGeneration);
            _cycleStack.RemoveAt(_cycleStack.Count - 1);

            return(maxGeneration);
        }
示例#14
0
        private void ValidateSupport()
        {
            var runtimeFxSuppression = GetSuppressionValues(Suppression.PermitRuntimeTargetMonikerMismatch) ?? new HashSet <string>();

            // validate support for each TxM:RID
            foreach (var validateFramework in _frameworks.Values)
            {
                NuGetFramework fx = validateFramework.Framework;
                Version        supportedVersion = validateFramework.SupportedVersion;

                Target compileTarget;
                if (!_report.Targets.TryGetValue(fx.ToString(), out compileTarget))
                {
                    Log.LogError($"Missing target {fx.ToString()} from validation report {ReportFile}");
                    continue;
                }

                var  compileAssetPaths = compileTarget.CompileAssets.Select(ca => ca.PackagePath);
                bool hasCompileAsset, hasCompilePlaceHolder;
                NuGetAssetResolver.ExamineAssets(Log, "Compile", ContractName, fx.ToString(), compileAssetPaths, out hasCompileAsset, out hasCompilePlaceHolder);

                // resolve/test for each RID associated with this framework.
                foreach (string runtimeId in validateFramework.RuntimeIds)
                {
                    string target = String.IsNullOrEmpty(runtimeId) ? fx.ToString() : $"{fx}/{runtimeId}";

                    Target runtimeTarget;
                    if (!_report.Targets.TryGetValue(target, out runtimeTarget))
                    {
                        Log.LogError($"Missing target {target} from validation report {ReportFile}");
                        continue;
                    }

                    var runtimeAssetPaths = runtimeTarget.RuntimeAssets.Select(ra => ra.PackagePath);

                    bool hasRuntimeAsset, hasRuntimePlaceHolder;
                    NuGetAssetResolver.ExamineAssets(Log, "Runtime", ContractName, target, runtimeAssetPaths, out hasRuntimeAsset, out hasRuntimePlaceHolder);

                    if (null == supportedVersion)
                    {
                        // Contract should not be supported on this platform.
                        bool permitImplementation = HasSuppression(Suppression.PermitImplementation, target);

                        if (hasCompileAsset && (hasRuntimeAsset & !permitImplementation))
                        {
                            Log.LogError($"{ContractName} should not be supported on {target} but has both compile and runtime assets.");
                        }
                        else if (hasRuntimeAsset & !permitImplementation)
                        {
                            Log.LogError($"{ContractName} should not be supported on {target} but has runtime assets.");
                        }

                        if (hasRuntimePlaceHolder && hasCompilePlaceHolder)
                        {
                            Log.LogError($"{ContractName} should not be supported on {target} but has placeholders for both compile and runtime which will permit the package to install.");
                        }
                    }
                    else
                    {
                        if (validateFramework.IsInbox)
                        {
                            if (!hasCompileAsset && !hasCompilePlaceHolder)
                            {
                                Log.LogError($"Framework {fx} should support {ContractName} inbox but was missing a placeholder for compile-time.  You may need to add <InboxOnTargetFramework Include=\"{fx.GetShortFolderName()}\" /> to your project.");
                            }
                            else if (hasCompileAsset)
                            {
                                Log.LogError($"Framework {fx} should support {ContractName} inbox but contained a reference assemblies: {String.Join(", ", compileAssetPaths)}.  You may need to add <InboxOnTargetFramework Include=\"{fx.GetShortFolderName()}\" /> to your project.");
                            }

                            if (!hasRuntimeAsset && !hasRuntimePlaceHolder)
                            {
                                Log.LogError($"Framework {fx} should support {ContractName} inbox but was missing a placeholder for run-time.  You may need to add <InboxOnTargetFramework Include=\"{fx.GetShortFolderName()}\" /> to your project.");
                            }
                            else if (hasRuntimeAsset)
                            {
                                Log.LogError($"Framework {fx} should support {ContractName} inbox but contained a implementation assemblies: {String.Join(", ", runtimeAssetPaths)}.  You may need to add <InboxOnTargetFramework Include=\"{fx.GetShortFolderName()}\" /> to your project.");
                            }
                        }
                        else
                        {
                            Version referenceAssemblyVersion = null;
                            if (!hasCompileAsset)
                            {
                                Log.LogError($"{ContractName} should be supported on {target} but has no compile assets.");
                            }
                            else
                            {
                                var referenceAssemblies = compileTarget.CompileAssets.Where(ca => IsDll(ca.PackagePath));

                                if (referenceAssemblies.Count() > 1)
                                {
                                    Log.LogError($"{ContractName} should only contain a single compile asset for {target}.");
                                }

                                foreach (var referenceAssembly in referenceAssemblies)
                                {
                                    referenceAssemblyVersion = referenceAssembly.Version;

                                    if (!VersionUtility.IsCompatibleApiVersion(supportedVersion, referenceAssemblyVersion))
                                    {
                                        Log.LogError($"{ContractName} should support API version {supportedVersion} on {target} but {referenceAssembly.LocalPath} was found to support {referenceAssemblyVersion?.ToString() ?? "<unknown version>"}.");
                                    }
                                }
                            }


                            if (!hasRuntimeAsset)
                            {
                                if (HasSuppression(Suppression.PermitMissingImplementation, target))
                                {
                                    Log.LogMessage($"Suppressed: {ContractName} should be supported on {target} but has no runtime assets.");
                                }
                                else
                                {
                                    // Contract should not be supported on this platform.
                                    Log.LogError($"{ContractName} should be supported on {target} but has no runtime assets.");
                                }
                            }
                            else
                            {
                                var implementationAssemblies = runtimeTarget.RuntimeAssets.Where(ra => IsDll(ra.PackagePath));

                                Dictionary <string, PackageAsset> implementationFiles = new Dictionary <string, PackageAsset>();
                                foreach (var implementationAssembly in implementationAssemblies)
                                {
                                    Version implementationVersion = implementationAssembly.Version;

                                    if (!VersionUtility.IsCompatibleApiVersion(supportedVersion, implementationVersion))
                                    {
                                        Log.LogError($"{ContractName} should support API version {supportedVersion} on {target} but {implementationAssembly.LocalPath} was found to support {implementationVersion?.ToString() ?? "<unknown version>"}.");
                                    }

                                    // Previously we only permitted compatible mismatch if Suppression.PermitHigherCompatibleImplementationVersion was specified
                                    // this is a permitted thing on every framework but desktop (which requires exact match to ensure bindingRedirects exist)
                                    // Now make this the default, we'll check desktop, where it matters, more strictly
                                    if (referenceAssemblyVersion != null &&
                                        !VersionUtility.IsCompatibleApiVersion(referenceAssemblyVersion, implementationVersion))
                                    {
                                        Log.LogError($"{ContractName} has mismatched compile ({referenceAssemblyVersion}) and runtime ({implementationVersion}) versions on {target}.");
                                    }

                                    if (fx.Framework == FrameworkConstants.FrameworkIdentifiers.Net &&
                                        referenceAssemblyVersion != null &&
                                        !referenceAssemblyVersion.Equals(implementationVersion))
                                    {
                                        Log.LogError($"{ContractName} has a higher runtime version ({implementationVersion}) than compile version ({referenceAssemblyVersion}) on .NET Desktop framework {target}.  This will break bindingRedirects.  If the live reference was replaced with a harvested reference you may need to set <Preserve>true</Preserve> on your reference assembly ProjectReference.");
                                    }

                                    string fileName = Path.GetFileName(implementationAssembly.PackagePath);

                                    if (implementationFiles.ContainsKey(fileName))
                                    {
                                        Log.LogError($"{ContractName} includes both {implementationAssembly.LocalPath} and {implementationFiles[fileName].LocalPath} an on {target} which have the same name and will clash when both packages are used.");
                                    }
                                    else
                                    {
                                        implementationFiles[fileName] = implementationAssembly;
                                    }

                                    if (!implementationAssembly.TargetFramework.Equals(fx) && !runtimeFxSuppression.Contains(fx.ToString()))
                                    {
                                        // the selected asset wasn't an exact framework match, let's see if we have an exact match in any other runtime asset.
                                        var matchingFxAssets = _report.UnusedAssets.Where(i => i.TargetFramework != null && i.TargetFramework.Equals(fx) && // exact framework
                                                                                                                                                            // Same file
                                                                                          Path.GetFileName(i.PackagePath).Equals(fileName, StringComparison.OrdinalIgnoreCase) &&
                                                                                                                                                            // Is implementation
                                                                                          (i.PackagePath.StartsWith("lib") || i.PackagePath.StartsWith("runtimes")) &&
                                                                                                                                                            // is not the same source file as was already selected
                                                                                          i.LocalPath != implementationAssembly.LocalPath);

                                        if (matchingFxAssets.Any())
                                        {
                                            Log.LogError($"When targeting {target} {ContractName} will use {implementationAssembly.LocalPath} which targets {implementationAssembly.TargetFramework.GetShortFolderName()}  but {String.Join(";", matchingFxAssets.Select(i => i.PackagePath))} targets {fx.GetShortFolderName()} specifically.");
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // Set output items
            AllSupportedFrameworks = _frameworks.Values.Where(fx => fx.SupportedVersion != null).Select(fx => fx.ToItem()).OrderBy(i => i.ItemSpec).ToArray();
        }
示例#15
0
        private void ValidateIndex()
        {
            if (SkipIndexCheck)
            {
                return;
            }

            if (PackageIndexes == null || PackageIndexes.Length == 0)
            {
                return;
            }

            PackageIndex.Current.Merge(PackageIndexes.Select(pi => pi.GetMetadata("FullPath")));

            PackageInfo info;

            if (!PackageIndex.Current.Packages.TryGetValue(PackageId, out info))
            {
                Log.LogError($"PackageIndex from {String.Join(", ", PackageIndexes.Select(i => i.ItemSpec))} is missing an entry for package {PackageId}.  Please run /t:UpdatePackageIndex on this project to commit an update.");
                return;
            }

            var thisPackageFiles = _validateFiles[PackageId];
            var refFiles         = thisPackageFiles.Where(f => f.TargetPath.StartsWith("ref/", StringComparison.OrdinalIgnoreCase)).Where(r => !NuGetAssetResolver.IsPlaceholder(r.TargetPath));

            if (!refFiles.Any())
            {
                refFiles = thisPackageFiles.Where(f => f.TargetPath.StartsWith("lib/", StringComparison.OrdinalIgnoreCase));
            }

            var thisPackageVersion = VersionUtility.As3PartVersion(NuGetVersion.Parse(PackageVersion).Version);
            var refFileVersions    = new HashSet <Version>(refFiles.Where(r => r.Version != null).Select(r => VersionUtility.As4PartVersion(r.Version)));

            foreach (var refFileVersion in refFileVersions)
            {
                Version refPackageVersion;

                // determine if we're missing a mapping for this package
                if (!info.AssemblyVersionInPackageVersion.TryGetValue(refFileVersion, out refPackageVersion))
                {
                    Log.LogError($"PackageIndex from {String.Join(", ", PackageIndexes.Select(i => i.ItemSpec))} is missing an assembly version entry for {refFileVersion} for package {PackageId}.  Please run /t:UpdatePackageIndex on this project to commit an update.");
                }
                else
                {
                    // determine if we have a mapping for an unstable package and that unstable package is not this one
                    if (!info.StableVersions.Contains(refPackageVersion) && refPackageVersion != thisPackageVersion)
                    {
                        Log.LogError($"PackageIndex from {String.Join(", ", PackageIndexes.Select(i => i.ItemSpec))} indicates that assembly version {refFileVersion} is contained in non-stable package version {refPackageVersion} which differs from this package version {thisPackageVersion}.");
                    }
                }
            }

            var orphanedAssemblyVersions = info.AssemblyVersionInPackageVersion
                                           .Where(pair => pair.Value == thisPackageVersion && !refFileVersions.Contains(pair.Key))
                                           .Select(pair => pair.Key);

            if (orphanedAssemblyVersions.Any())
            {
                Log.LogError($"PackageIndex from {String.Join(", ", PackageIndexes.Select(i => i.ItemSpec))} is has an assembly version entry(s) for {String.Join(", ", orphanedAssemblyVersions)} which are no longer in package {PackageId}.  Please run /t:UpdatePackageIndex on this project to commit an update.");
            }
        }
示例#16
0
        private void ValidateIndex()
        {
            if (SkipIndexCheck)
            {
                return;
            }

            if (PackageIndexes == null || PackageIndexes.Length == 0)
            {
                return;
            }

            var index = PackageIndex.Load(PackageIndexes.Select(pi => pi.GetMetadata("FullPath")));

            PackageInfo info;

            if (!index.Packages.TryGetValue(PackageId, out info))
            {
                Log.LogError($"PackageIndex from {String.Join(", ", PackageIndexes.Select(i => i.ItemSpec))} is missing an entry for package {PackageId}.  Please run /t:UpdatePackageIndex on this project to commit an update.");
                return;
            }

            var allDlls          = _report.Targets.Values.SelectMany(t => t.CompileAssets.NullAsEmpty().Concat(t.RuntimeAssets.NullAsEmpty()));
            var allAssemblies    = allDlls.Where(f => f.Version != null);
            var assemblyVersions = new HashSet <Version>(allAssemblies.Select(f => VersionUtility.As4PartVersion(f.Version)));

            var thisPackageVersion = VersionUtility.As3PartVersion(NuGetVersion.Parse(PackageVersion).Version);

            foreach (var fileVersion in assemblyVersions)
            {
                Version packageVersion;

                // determine if we're missing a mapping for this package
                if (!info.AssemblyVersionInPackageVersion.TryGetValue(fileVersion, out packageVersion))
                {
                    Log.LogError($"PackageIndex from {String.Join(", ", PackageIndexes.Select(i => i.ItemSpec))} is missing an assembly version entry for {fileVersion} for package {PackageId}.  Please run /t:UpdatePackageIndex on this project to commit an update.");
                }
                else
                {
                    // determine if we have a mapping for an unstable package and that unstable package is not this one
                    if (!info.StableVersions.Contains(packageVersion) && packageVersion != thisPackageVersion)
                    {
                        Log.LogError($"PackageIndex from {String.Join(", ", PackageIndexes.Select(i => i.ItemSpec))} indicates that assembly version {fileVersion} is contained in non-stable package version {packageVersion} which differs from this package version {thisPackageVersion}.");
                    }
                }
            }

            var orphanedAssemblyVersions = info.AssemblyVersionInPackageVersion
                                           .Where(pair => pair.Value == thisPackageVersion && !assemblyVersions.Contains(pair.Key))
                                           .Select(pair => pair.Key);

            if (orphanedAssemblyVersions.Any())
            {
                Log.LogError($"PackageIndex from {String.Join(", ", PackageIndexes.Select(i => i.ItemSpec))} is has an assembly version entry(s) for {String.Join(", ", orphanedAssemblyVersions)} which are no longer in package {PackageId}.  Please run /t:UpdatePackageIndex on this project to commit an update.");
            }

            // if no assemblies are present in this package nor were ever present
            if (assemblyVersions.Count == 0 &&
                info.AssemblyVersionInPackageVersion.Count == 0)
            {
                // if in the native module map
                if (index.ModulesToPackages.Values.Any(p => p.Equals(PackageId)))
                {
                    // ensure the baseline is set
                    if (info.BaselineVersion != thisPackageVersion)
                    {
                        Log.LogError($"PackageIndex from {String.Join(", ", PackageIndexes.Select(i => i.ItemSpec))} is missing an baseline entry(s) for native module {PackageId}.  Please run /t:UpdatePackageIndex on this project to commit an update.");
                    }
                }
                else
                {
                    // not in the native module map, see if any of the modules in this package are present
                    // (with a different package, as would be the case for runtime-specific packages)
                    var moduleNames        = allDlls.Select(d => Path.GetFileNameWithoutExtension(d.LocalPath));
                    var missingModuleNames = moduleNames.Where(m => !index.ModulesToPackages.ContainsKey(m));
                    if (missingModuleNames.Any())
                    {
                        Log.LogError($"PackageIndex from {String.Join(", ", PackageIndexes.Select(i => i.ItemSpec))} is missing ModulesToPackages entry(s) for {String.Join(", ", missingModuleNames)} to package {PackageId}.  Please add a an entry for the appropriate package.");
                    }
                }
            }
        }
示例#17
0
        private void UpdateFromValues(PackageIndex index, string id, NuGetVersion version, IEnumerable <Version> assemblyVersions, IEnumerable <string> dllNames)
        {
            PackageInfo info = GetOrCreatePackageInfo(index, id);

            if (UpdateStablePackageInfo)
            {
                try
                {
                    IEnumerable <Version> allStableVersions = NuGetUtility.GetAllVersionsForPackageId(id, includePrerelease: false, includeUnlisted: false, Log, CancellationToken.None);
                    info.StableVersions.AddRange(allStableVersions);
                }
                catch (NuGetProtocolException)
                {
                    Log.LogWarning("Failed fetching stable nuget package versions from one or more of your feeds. Make sure you are connected to the internet and that all your feeds are reachable.");
                }
            }

            var packageVersion = VersionUtility.As3PartVersion(version.Version);

            // if we have a stable version, add it to the stable versions list
            if (!version.IsPrerelease)
            {
                info.StableVersions.Add(packageVersion);
            }

            var assmVersions = new HashSet <Version>(assemblyVersions.NullAsEmpty().Where(v => v != null));

            // add any new assembly versions
            info.AddAssemblyVersionsInPackage(assmVersions, packageVersion);

            // try to find an identity package to also add a mapping in the case this is a runtime package
            if (id.StartsWith("runtime."))
            {
                foreach (var dllName in dllNames)
                {
                    PackageInfo identityInfo;
                    if (index.Packages.TryGetValue(dllName, out identityInfo))
                    {
                        identityInfo.AddAssemblyVersionsInPackage(assmVersions, packageVersion);
                    }
                }
            }

            // remove any assembly mappings which claim to be in this package version, but aren't in the assemblyList
            var orphanedAssemblyVersions = info.AssemblyVersionInPackageVersion
                                           .Where(pair => pair.Value == packageVersion && !assmVersions.Contains(pair.Key))
                                           .Select(pair => pair.Key);

            if (orphanedAssemblyVersions.Any())
            {
                // make sure these aren't coming from a runtime package.
                var runtimeAssemblyVersions = index.Packages
                                              .Where(p => p.Key.StartsWith("runtime.") && p.Key.EndsWith(id))
                                              .SelectMany(p => p.Value.AssemblyVersionInPackageVersion)
                                              .Where(pair => pair.Value == packageVersion)
                                              .Select(pair => pair.Key);

                orphanedAssemblyVersions = orphanedAssemblyVersions.Except(runtimeAssemblyVersions);
            }

            foreach (var orphanedAssemblyVersion in orphanedAssemblyVersions.ToArray())
            {
                info.AssemblyVersionInPackageVersion.Remove(orphanedAssemblyVersion);
            }

            // if no assemblies are present in this package nor were ever present
            if (assmVersions.Count == 0 &&
                info.AssemblyVersionInPackageVersion.Count == 0)
            {
                // if in the native module map
                if (index.ModulesToPackages.Values.Any(p => p.Equals(id)))
                {
                    // ensure the baseline is set
                    info.BaselineVersion = packageVersion;
                }
            }
        }