private static string GetNameString(NuGetFramework framework, string runtime) { string frameworkString; // We already shipped net5.0 being listed as .NETCoreApp,Version=5.0, so it would be a breaking change // to change it. Similarly for all earlier framework identifiers. // Since net5.0-windows didn't work properly, we can use the "friendly" (folder name) for net5 with a platform. // For net6 and higher, always use friendly folder format, since this is the preferred customer-facing // format (from dotnet/design's net5 spec). // Packages lock files are checked into source control, hence customers will see it in their diffs. if (string.Equals(framework.Framework, FrameworkConstants.FrameworkIdentifiers.NetCoreApp, StringComparison.OrdinalIgnoreCase) && ( (framework.Version.Major >= 6) || (framework.Version.Major == 5 && framework.HasPlatform) ) ) { frameworkString = framework.ToString(); } else { frameworkString = framework.DotNetFrameworkName; } if (!string.IsNullOrEmpty(runtime)) { return($"{frameworkString}/{runtime}"); } return(frameworkString); }
private static bool IsKnownUnsupportedPlatform(NuGetFramework target) { var platforms = new[] { ".NETCore,Version=v5.0", ".NETFramework,Version=v4.6.3", ".NETPlatform,Version=v5.0", ".NETPlatform,Version=v5.4", ".NETPortable,Version=v0.0,Profile=aspnetcore50+net45+win8+wp8+wpa81", ".NETPortable,Version=v0.0,Profile=net40+sl4+win8", ".NETPortable,Version=v0.0,Profile=net40+sl4+win8+wp71+wpa81", ".NETPortable,Version=v0.0,Profile=net40+sl4+win8+wp8+wpa81", ".NETPortable,Version=v0.0,Profile=net40+win8+wp8+wpa81", ".NETPortable,Version=v0.0,Profile=net45+netcore45+wp8+wp81+wpa81", ".NETPortable,Version=v0.0,Profile=net45+wp8+wpa81", ".NETPortable,Version=v0.0,Profile=net451+win8+wp8+wpa81", ".NETPortable,Version=v0.0,Profile=win8+wp8+wpa81", ".NETPortable,Version=v0.0,Profile=win8+wpa81", "Any,Version=v0.0", "ASP.NETCore,Version=v5.0", "DNX,Version=v4.5.1", "DNXCore,Version=v5.0", "native,Version=v0.0", "Silverlight,Version=v4.0", "Silverlight,Version=v4.0,Profile=WindowsPhone71", "Silverlight,Version=v5.0", "WindowsPhone,Version=v8.0", "WindowsPhoneApp,Version=v8.1", }; var targetString = target.ToString(); return(platforms.Any(p => string.Equals(p, targetString, StringComparison.OrdinalIgnoreCase))); }
private void EnsureToolJsonDepsFileExists( LibraryRange toolLibrary, LockFile toolLockFile, string depsPath) { if (!File.Exists(depsPath)) { var projectContext = new ProjectContextBuilder() .WithLockFile(toolLockFile) .WithTargetFramework(s_toolPackageFramework.ToString()) .Build(); var exporter = projectContext.CreateExporter(Constants.DefaultConfiguration); var dependencyContext = new DependencyContextBuilder() .Build(null, null, exporter.GetAllExports(), true, s_toolPackageFramework, string.Empty); using (var fileStream = File.Create(depsPath)) { var dependencyContextWriter = new DependencyContextWriter(); dependencyContextWriter.Write(dependencyContext, fileStream); } } }
/// <summary> /// Get project's target frameworks /// </summary> /// <param name="project"></param> /// <returns></returns> public static IEnumerable <string> GetProjectTargetFrameworks(NuGetProject project) { List <string> frameworks = new List <string>(); NuGetFramework nugetFramework = project.GetMetadata <NuGetFramework>(NuGetProjectMetadataKeys.TargetFramework); if (nugetFramework != null) { string framework = nugetFramework.ToString(); frameworks.Add(framework); } return(frameworks); }
private IEnumerable <PackageAsset> GetTestAssets(NuGetFramework fx, string runtimeId) { var targetKey = string.IsNullOrEmpty(runtimeId) ? fx.ToString() : $"{fx}/{runtimeId}"; Target target = null; if (!_report.Targets.TryGetValue(targetKey, out target)) { Log.LogError($"Could not find target {targetKey} in {ReportFile}."); return(Enumerable.Empty <PackageAsset>()); } return(string.IsNullOrEmpty(Runtime) ? target.CompileAssets : target.RuntimeAssets); }
// Need to unit test this, so public public void GenerateDepsJsonFile( LockFile toolLockFile, string depsPath) { Reporter.Verbose.WriteLine($"Generating deps.json at: {depsPath}"); var projectContext = new ProjectContextBuilder() .WithLockFile(toolLockFile) .WithTargetFramework(s_toolPackageFramework.ToString()) .Build(); var exporter = projectContext.CreateExporter(Constants.DefaultConfiguration); var dependencyContext = new DependencyContextBuilder() .Build(null, null, exporter.GetAllExports(), true, s_toolPackageFramework, string.Empty); var tempDepsFile = Path.GetTempFileName(); using (var fileStream = File.Open(tempDepsFile, FileMode.Open, FileAccess.Write)) { var dependencyContextWriter = new DependencyContextWriter(); dependencyContextWriter.Write(dependencyContext, fileStream); } try { File.Copy(tempDepsFile, depsPath); } catch (Exception e) { Reporter.Verbose.WriteLine($"unable to generate deps.json, it may have been already generated: {e.Message}"); } finally { try { File.Delete(tempDepsFile); } catch (Exception e2) { Reporter.Verbose.WriteLine($"unable to delete temporary deps.json file: {e2.Message}"); } } }
public CentralTransitiveDependencyGroup(NuGetFramework framework, IEnumerable <LibraryDependency> transitiveDependencies) { if (framework == null) { throw new ArgumentNullException(nameof(framework)); } if (transitiveDependencies == null) { throw new ArgumentNullException(nameof(transitiveDependencies)); } FrameworkName = framework.ToString(); TransitiveDependencies = transitiveDependencies; }
/// <summary> /// Generates a table in markdown that lists the API version supported by /// various packages at all levels of NETStandard. /// </summary> /// <returns></returns> public override bool Execute() { if (PackageReports == null || PackageReports.Length == 0) { Log.LogError("PackageReports argument must be specified"); return(false); } if (TargetMoniker == null || TargetMoniker.Length == 0) { Log.LogError("TargetMoniker argument must be specified"); return(false); } NuGetFramework fx = NuGetFramework.Parse(TargetMoniker); string targetString = String.IsNullOrEmpty(TargetRuntime) ? fx.ToString() : $"{fx}/{TargetRuntime}"; var compileAssets = new List <ITaskItem>(); var runtimeAssets = new List <ITaskItem>(); var nativeAssets = new List <ITaskItem>(); var buildProjects = new List <BuildProject>(); foreach (var reportPath in PackageReports) { var report = PackageReport.Load(reportPath); Target target = null; if (report.Targets.TryGetValue(targetString, out target)) { compileAssets.AddRange(target.CompileAssets.Select(c => ItemFromApplicableAsset(c, report.Id, report.Version))); buildProjects.AddRange(target.CompileAssets.Select(c => c.SourceProject).Where(bp => bp != null)); runtimeAssets.AddRange(target.RuntimeAssets.Select(r => ItemFromApplicableAsset(r, report.Id, report.Version))); buildProjects.AddRange(target.RuntimeAssets.Select(r => r.SourceProject).Where(bp => bp != null)); nativeAssets.AddRange(target.NativeAssets.Select(r => ItemFromApplicableAsset(r, report.Id, report.Version))); buildProjects.AddRange(target.NativeAssets.Select(r => r.SourceProject).Where(bp => bp != null)); } else { Log.LogMessage($"No assets found for '{report.Id}' applicable to '{targetString}'."); } } CompileAssets = compileAssets.ToArray(); RuntimeAssets = runtimeAssets.ToArray(); NativeAssets = nativeAssets.ToArray(); BuildProjects = buildProjects.Distinct().Select(bp => bp.ToItem()).ToArray(); return(!Log.HasLoggedErrors); }
/// <summary> /// Takes a NuGet framework folder name and returns the .NET FrameworkName /// </summary> public static FrameworkName GetFrameworkName(string nugetFramework) { // TODO: Call a non-portable version of Frameworks to do this work instead. FrameworkName framework = null; NuGetFramework nf = NuGetFramework.Parse(nugetFramework); if (nf.IsSpecificFramework) { framework = new FrameworkName(nf.ToString()); } return(framework); }
private async Task <SourcePackageDependencyInfo> CacheResolvePackage(NuGetFactory factory, PackageIdentity package, NuGetFramework fx) { string key = String.Format(@"{0}-{1}", package.ToString(), fx.ToString()); if (base.IsInCache <SourcePackageDependencyInfo>("CacheResolvePackage", key)) { return(Get <SourcePackageDependencyInfo>("CacheResolvePackage", key)); } else { var depResource = await factory.GetDependency(); var output = await depResource.ResolvePackage(package, fx, CancellationToken.None); return(Get <SourcePackageDependencyInfo>("CacheResolvePackage", key, () => { return output; })); } }
private static string SynthesizeFrameworkFriendlyName(NuGetFramework targetFramework) { // Names are not present in the RedistList.xml file for older frameworks or on Mono // We do some custom version string rendering to match how net40 is rendered (.NET Framework 4) if (targetFramework.Framework.Equals(FrameworkConstants.FrameworkIdentifiers.Net)) { string versionString = targetFramework.Version.Minor == 0 ? targetFramework.Version.Major.ToString() : GetDisplayVersion(targetFramework).ToString(); string profileString = string.IsNullOrEmpty(targetFramework.Profile) ? string.Empty : $" {targetFramework.Profile} Profile"; return(".NET Framework " + versionString + profileString); } return(targetFramework.ToString()); }
private bool ValidateTools(PackageSpec spec) { // Skip this check if there are no tools at all. if (ProjectFileToolGroups.Count == 0 && spec.Tools.Count == 0) { return(true); } // The lock file should only contain tools for a single framework if (ProjectFileToolGroups.Count != 1) { return(false); } var group = ProjectFileToolGroups.First(); if (!StringComparer.OrdinalIgnoreCase.Equals( group.FrameworkName, ToolFramework.ToString())) { return(false); } var lockDependencies = group .Dependencies .OrderBy(x => x, StringComparer.Ordinal); var specDependencies = spec.Tools .Select(x => x.LibraryRange.ToLockFileDependencyGroupString()) .OrderBy(x => x, StringComparer.Ordinal); if (!specDependencies.SequenceEqual(lockDependencies)) { return(false); } return(true); }
public string GetFriendlyNuGetFramework(NuGetFramework targetFramework) { // We don't have a friendly name for this anywhere on the machine so hard code it string friendlyName = targetFramework.Framework; if (Equals(targetFramework.Framework, FrameworkConstants.CommonFrameworks.DnxCore)) { return("DNX Core " + targetFramework.Version.ToString()); } else if (Equals(targetFramework.Framework, FrameworkConstants.CommonFrameworks.Dnx)) { return("DNX " + targetFramework.Version.ToString()); } var information = _cache.GetOrAdd(targetFramework, GetFrameworkInformation); if (information == null) { return(targetFramework.ToString()); } return(information.Name); }
/// <summary> /// Validates the latest nuget package doesnot drop any target framework/rid and does not introduce any breaking changes. /// </summary> /// <param name="package">Nuget Package that needs to be validated.</param> public void Validate(Package package) { if (_runApiCompat) { _apiCompatRunner.InitializePaths(_baselinePackage.PackagePath, package.PackagePath); } foreach (ContentItem baselineCompileTimeAsset in _baselinePackage.RefAssets) { NuGetFramework baselineTargetFramework = (NuGetFramework)baselineCompileTimeAsset.Properties["tfm"]; ContentItem latestCompileTimeAsset = package.FindBestCompileAssetForFramework(baselineTargetFramework); if (latestCompileTimeAsset == null) { _log.LogError( new Suppression { DiagnosticId = DiagnosticIds.TargetFrameworkDropped, Target = baselineTargetFramework.ToString() }, DiagnosticIds.TargetFrameworkDropped, Resources.MissingTargetFramework, baselineTargetFramework.ToString()); } else if (_runApiCompat) { string header = string.Format(Resources.ApiCompatibilityBaselineHeader, baselineCompileTimeAsset.Path, latestCompileTimeAsset.Path, _baselinePackage.Version, package.Version); _apiCompatRunner.QueueApiCompatFromContentItem(package.PackageId, baselineCompileTimeAsset, latestCompileTimeAsset, header, isBaseline: true); } } foreach (ContentItem baselineRuntimeAsset in _baselinePackage.RuntimeAssets) { NuGetFramework baselineTargetFramework = (NuGetFramework)baselineRuntimeAsset.Properties["tfm"]; ContentItem latestRuntimeAsset = package.FindBestRuntimeAssetForFramework(baselineTargetFramework); if (latestRuntimeAsset == null) { _log.LogError( new Suppression { DiagnosticId = DiagnosticIds.TargetFrameworkDropped, Target = baselineTargetFramework.ToString() }, DiagnosticIds.TargetFrameworkDropped, Resources.MissingTargetFramework, baselineTargetFramework.ToString()); } else { if (_runApiCompat) { string header = string.Format(Resources.ApiCompatibilityBaselineHeader, baselineRuntimeAsset.Path, latestRuntimeAsset.Path, _baselinePackage.Version, package.Version); _apiCompatRunner.QueueApiCompatFromContentItem(package.PackageId, baselineRuntimeAsset, latestRuntimeAsset, header, isBaseline: true); } } } foreach (ContentItem baselineRuntimeSpecificAsset in _baselinePackage.RuntimeSpecificAssets) { NuGetFramework baselineTargetFramework = (NuGetFramework)baselineRuntimeSpecificAsset.Properties["tfm"]; string baselineRid = (string)baselineRuntimeSpecificAsset.Properties["rid"]; ContentItem latestRuntimeSpecificAsset = package.FindBestRuntimeAssetForFrameworkAndRuntime(baselineTargetFramework, baselineRid); if (latestRuntimeSpecificAsset == null) { _log.LogError( new Suppression { DiagnosticId = DiagnosticIds.TargetFrameworkAndRidPairDropped, Target = baselineTargetFramework.ToString() + "-" + baselineRid }, DiagnosticIds.TargetFrameworkAndRidPairDropped, Resources.MissingTargetFrameworkAndRid, baselineTargetFramework.ToString(), baselineRid); } else { if (_runApiCompat) { string header = string.Format(Resources.ApiCompatibilityBaselineHeader, baselineRuntimeSpecificAsset.Path, latestRuntimeSpecificAsset.Path, _baselinePackage.Version, package.Version); _apiCompatRunner.QueueApiCompatFromContentItem(package.PackageId, baselineRuntimeSpecificAsset, latestRuntimeSpecificAsset, header, isBaseline: true); } } } _apiCompatRunner.RunApiCompat(); }
public static string ToFriendlyName(this NuGetFramework frameworkName, bool allowRecurseProfile = true) { if (frameworkName == null) { throw new ArgumentNullException(nameof(frameworkName)); } // Defer to the NuGet client logic for displaying .NET 5 frameworks. This aligns with Visual Studio package // management UI. var isNet5Era = frameworkName.Version.Major >= 5 && StringComparer.OrdinalIgnoreCase.Equals(FrameworkConstants.FrameworkIdentifiers.NetCoreApp, frameworkName.Framework); if (isNet5Era) { return(frameworkName.ToString()); } var sb = new StringBuilder(); if (String.Equals(frameworkName.Framework, ".NETPortable", StringComparison.OrdinalIgnoreCase)) { sb.Append("Portable Class Library"); // Recursively parse the profile if (allowRecurseProfile) { sb.Append(" ("); var profiles = frameworkName.GetShortFolderName() .Replace("portable-", string.Empty) .Replace("portable40-", string.Empty) .Replace("portable45-", string.Empty) .Split('+'); sb.Append(String.Join(", ", profiles.Select(s => NuGetFramework.Parse(s).ToFriendlyName(allowRecurseProfile: false)))); sb.Append(")"); } } else { string version = null; if (frameworkName.Version.Build == 0) { version = frameworkName.Version.ToString(2); } else if (frameworkName.Version.Revision == 0) { version = frameworkName.Version.ToString(3); } else { version = frameworkName.Version.ToString(); } sb.AppendFormat("{0} {1}", frameworkName.Framework, version); if (!String.IsNullOrEmpty(frameworkName.Profile)) { sb.AppendFormat(" {0}", frameworkName.Profile); } } return(sb.ToString()); }
/// <summary> /// Target framework versions returned from ResolvePackageDependenciesDesignTime use four part version numbers /// so we cannot use TargetFrameworkMoniker as the dictionary key since this will not always match the /// project's target framework. Instead generate a NuGetFramework and use that as the key since it will /// normalize the version numbers. /// </summary> static string GetMappingKey(TargetFrameworkMoniker framework) { NuGetFramework nugetFramework = NuGetFramework.ParseFrameworkName(framework.ToString(), DefaultFrameworkNameProvider.Instance); return(nugetFramework.ToString()); }
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); } }
private static JToken WriteFrameworkName(NuGetFramework item) { return(item != null ? new JValue(item.ToString()) : JValue.CreateNull()); }
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); } }
/// <summary> /// Validates the latest nuget package doesnot drop any target framework/rid and does not introduce any breaking changes. /// </summary> /// <param name="package">Nuget Package that needs to be validated.</param> public void Validate(PackageValidatorOption option) { if (option.BaselinePackage is null) { throw new ArgumentNullException(nameof(option.BaselinePackage)); } ApiCompatRunner apiCompatRunner = new(_log, option.EnableStrictMode, option.FrameworkReferences, option.BaselinePackage.PackagePath, option.Package.PackagePath); // Iterate over all available baseline assets foreach (ContentItem baselineCompileTimeAsset in option.BaselinePackage.RefAssets) { // Search for a compatible compile time asset in the latest package NuGetFramework baselineTargetFramework = (NuGetFramework)baselineCompileTimeAsset.Properties["tfm"]; ContentItem? latestCompileTimeAsset = option.Package.FindBestCompileAssetForFramework(baselineTargetFramework); if (latestCompileTimeAsset == null) { _log.LogError( new Suppression(DiagnosticIds.TargetFrameworkDropped) { Target = baselineTargetFramework.ToString() }, DiagnosticIds.TargetFrameworkDropped, Resources.MissingTargetFramework, baselineTargetFramework.ToString()); } else if (option.RunApiCompat) { string header = string.Format(Resources.ApiCompatibilityBaselineHeader, baselineCompileTimeAsset.Path, latestCompileTimeAsset.Path, option.BaselinePackage.Version, option.Package.Version); apiCompatRunner.QueueApiCompatFromContentItem(option.Package.PackageId, baselineCompileTimeAsset, latestCompileTimeAsset, header, isBaseline: true); } } // Iterates over both runtime and runtime specific baseline assets and searches for a compatible non runtime // specific asset in the latest package. foreach (ContentItem baselineRuntimeAsset in option.BaselinePackage.RuntimeAssets) { // Search for a compatible runtime asset in the latest package NuGetFramework baselineTargetFramework = (NuGetFramework)baselineRuntimeAsset.Properties["tfm"]; ContentItem? latestRuntimeAsset = option.Package.FindBestRuntimeAssetForFramework(baselineTargetFramework); if (latestRuntimeAsset == null) { _log.LogError( new Suppression(DiagnosticIds.TargetFrameworkDropped) { Target = baselineTargetFramework.ToString() }, DiagnosticIds.TargetFrameworkDropped, Resources.MissingTargetFramework, baselineTargetFramework.ToString()); } else if (option.RunApiCompat) { string header = string.Format(Resources.ApiCompatibilityBaselineHeader, baselineRuntimeAsset.Path, latestRuntimeAsset.Path, option.BaselinePackage.Version, option.Package.Version); apiCompatRunner.QueueApiCompatFromContentItem(option.Package.PackageId, baselineRuntimeAsset, latestRuntimeAsset, header, isBaseline: true); } } // Compares runtime specific baseline assets against runtime specific latest assets. foreach (ContentItem baselineRuntimeSpecificAsset in option.BaselinePackage.RuntimeSpecificAssets) { NuGetFramework baselineTargetFramework = (NuGetFramework)baselineRuntimeSpecificAsset.Properties["tfm"]; string baselineRid = (string)baselineRuntimeSpecificAsset.Properties["rid"]; ContentItem? latestRuntimeSpecificAsset = option.Package.FindBestRuntimeAssetForFrameworkAndRuntime(baselineTargetFramework, baselineRid); if (latestRuntimeSpecificAsset == null) { _log.LogError( new Suppression(DiagnosticIds.TargetFrameworkAndRidPairDropped) { Target = baselineTargetFramework.ToString() + "-" + baselineRid }, DiagnosticIds.TargetFrameworkAndRidPairDropped, Resources.MissingTargetFrameworkAndRid, baselineTargetFramework.ToString(), baselineRid); } else if (option.RunApiCompat) { string header = string.Format(Resources.ApiCompatibilityBaselineHeader, baselineRuntimeSpecificAsset.Path, latestRuntimeSpecificAsset.Path, option.BaselinePackage.Version, option.Package.Version); apiCompatRunner.QueueApiCompatFromContentItem(option.Package.PackageId, baselineRuntimeSpecificAsset, latestRuntimeSpecificAsset, header, isBaseline: true); } } if (option.RunApiCompat) { apiCompatRunner.RunApiCompat(); } }
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(); }
public static Task <PackagesLock> FetchModules(NuGetFramework framework, IRestClient client) { return(CreateRequest().AddQueryParam("framework", framework.ToString()).Execute(client).Return <PackagesLock>()); }