示例#1
0
        private void ValidateHarvestVersionForReport(string packageReportPath)
        {
            PackageReport packageReport = GetPackageReportFromPath(packageReportPath);
            bool          isHarvestingAssetsFromPackage = TryGetHarvestVersionFromReport(packageReport, out string harvestVersion, out int harvestMajor, out int harvestMinor);

            if (isHarvestingAssetsFromPackage)
            {
                if (packageReport.Version.StartsWith($"{harvestMajor}.{harvestMinor}."))
                {
                    Log.LogError($"Validation Failed: {packageReport.Id} is harvesting package version {harvestVersion} which belongs to the current package release: {packageReport.Version}");
                    return;
                }

                string latestPatchVersion = GetLatestStableVersionForPackageRelease(packageReport.Id, harvestMajor, harvestMinor);
                if (latestPatchVersion.CompareTo(harvestVersion) != 0)
                {
                    Log.LogError($"Validation Failed: {packageReport.Id} is harvesting assets from package version {harvestVersion} which is not the latest for that package release. Latest package version from that release is {latestPatchVersion}. In order to fix this, run `dotnet msbuild {packageReport.Id}.pkgproj /t:UpdateHarvestVersionOnPackageIndex /p:UpdateStablePackageInfo=true`");
                }
                else
                {
                    Log.LogMessage(LogImportance.Normal, $"Validation Succeeded: {packageReport.Id} is harvesting assets from package version {harvestVersion} which is the latest for that package erreleasea.");
                }
            }
            else
            {
                Log.LogMessage(LogImportance.Normal, $"Validation Succeeded: {packageReport.Id} is not harvesting any assets.");
            }
        }
        private bool TryGetHarvestVersionFromReport(PackageReport report, out string harvestVersion, out int harvestEraMajor, out int harvestEraMinor)
        {
            harvestVersion  = string.Empty;
            harvestEraMajor = harvestEraMinor = 0;

            foreach (KeyValuePair <string, Target> packageTarget in report.Targets.NullAsEmpty())
            {
                foreach (PackageAsset compileAsset in packageTarget.Value.CompileAssets.NullAsEmpty())
                {
                    if (!string.IsNullOrEmpty(compileAsset.HarvestedFrom))
                    {
                        return(GetHarvestVersionFromString(compileAsset.HarvestedFrom, report.Id, out harvestVersion, out harvestEraMajor, out harvestEraMinor));
                    }
                }

                foreach (PackageAsset runtimeAsset in packageTarget.Value.RuntimeAssets.NullAsEmpty())
                {
                    if (!string.IsNullOrEmpty(runtimeAsset.HarvestedFrom))
                    {
                        return(GetHarvestVersionFromString(runtimeAsset.HarvestedFrom, report.Id, out harvestVersion, out harvestEraMajor, out harvestEraMinor));
                    }
                }

                foreach (PackageAsset nativeAsset in packageTarget.Value.NativeAssets.NullAsEmpty())
                {
                    if (!string.IsNullOrEmpty(nativeAsset.HarvestedFrom))
                    {
                        return(GetHarvestVersionFromString(nativeAsset.HarvestedFrom, report.Id, out harvestVersion, out harvestEraMajor, out harvestEraMinor));
                    }
                }
            }

            return(false);
        }
        /// <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);
        }
        public override bool Execute()
        {
            PackageReport packageReport = GetPackageReportFromPath();
            bool          isHarvestingAssetsFromPackage = TryGetHarvestVersionFromReport(packageReport, out string harvestVersion, out int harvestEraMajor, out int harvestEraMinor);

            if (isHarvestingAssetsFromPackage)
            {
                if (packageReport.Version.StartsWith($"{harvestEraMajor}.{harvestEraMinor}."))
                {
                    Log.LogError($"Validation Failed: {packageReport.Id} is harvesting package version {harvestVersion} which belongs to the current package era: {packageReport.Version}");
                    return(false);
                }

                // If no package versions endpoints were provided, then default to use NuGet.org version endpoint.
                if (NugetPackageVersionsEndpoints == null || NugetPackageVersionsEndpoints.Length == 0)
                {
                    NugetPackageVersionsEndpoints = new TaskItem[]
                    {
                        new TaskItem(NuGetDotOrgVersionEndpoint)
                    };
                }

                string latestPatchVersion = GetLatestStableVersionForEraAsync(packageReport.Id, harvestEraMajor, harvestEraMinor).GetAwaiter().GetResult();
                if (latestPatchVersion.CompareTo(harvestVersion) != 0)
                {
                    Log.LogError($"Validation Failed: {packageReport.Id} is harvesting assets from package version {harvestVersion} which is not the latest for that package era. Latest package version from that era is {latestPatchVersion}.");
                }
                else
                {
                    Log.LogMessage(LogImportance.Normal, $"Validation Succeeded: {packageReport.Id} is harvesting assets from package version {harvestVersion} which is the latest for that package era.");
                }
            }
            else
            {
                Log.LogMessage(LogImportance.Normal, $"Validation Succeeded: {packageReport.Id} is not harvesting any assets.");
            }

            return(!Log.HasLoggedErrors);
        }
        public override bool Execute()
        {
            var supportedPackages = new List <ITaskItem>();

            foreach (var packageReport in PackageReports.NullAsEmpty())
            {
                var report         = PackageReport.Load(packageReport);
                var packageId      = report.Id;
                var packageVersion = report.Version;

                var supportedTargets = report.Targets.Values.Where(target => report.SupportedFrameworks.ContainsKey(target.Framework));
                var fxRIDGroupings   = supportedTargets.GroupBy(target => target.Framework, target => target.RuntimeID);

                foreach (var fxRIDGrouping in fxRIDGroupings)
                {
                    var fx      = fxRIDGrouping.Key;
                    var rids    = fxRIDGrouping.ToArray();
                    var nugetFx = NuGetFramework.Parse(fx);

                    var supportedPackage = new TaskItem(packageId);
                    supportedPackage.SetMetadata("Version", packageVersion);
                    supportedPackage.SetMetadata("TargetFramework", fx);
                    supportedPackage.SetMetadata("TargetFrameworkShort", nugetFx.GetShortFolderName());

                    var ridList = string.Join(";", rids);

                    if (!String.IsNullOrEmpty(ridList))
                    {
                        supportedPackage.SetMetadata("RuntimeIdentifiers", ridList);
                    }

                    supportedPackages.Add(supportedPackage);
                }
            }

            SupportedPackages = supportedPackages.ToArray();

            return(!Log.HasLoggedErrors);
        }
 private void LoadReport()
 {
     _report = PackageReport.Load(ReportFile);
 }
示例#7
0
        public override bool Execute()
        {
            LoadFiles();
            LoadFrameworks();

            var report = new PackageReport()
            {
                Id                  = PackageId,
                Version             = PackageVersion,
                SupportedFrameworks = new Dictionary <string, string>()
            };

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

            foreach (var framework in _frameworks.OrderBy(f => f.Key.ToString()))
            {
                var fx         = framework.Key;
                var runtimeIds = framework.Value;

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

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

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

                if (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 = compileAssets.Select(c => GetPackageAssetFromTargetPath(c)).ToArray()
                    };
                    report.Targets.Add(fx.ToString(), reportTarget);
                }

                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);
                    MarkUsed(runtimeAssets);

                    if (!FrameworkUtilities.IsGenerationMoniker(fx) && !fx.IsPCL)
                    {
                        // only look at runtime assets for runnable frameworks.
                        isSupported &= (hasCompileAsset && hasRuntimeAsset) ||           // matching assets
                                       (hasCompilePlaceHolder && hasRuntimeAsset) ||     // private runtime
                                       (hasCompilePlaceHolder && hasRuntimePlaceHolder); // placeholders
                    }

                    var nativeAssets = _resolver.ResolveNativeAssets(fx, runtimeId);
                    MarkUsed(nativeAssets);

                    var reportTarget = new Target()
                    {
                        Framework     = fx.ToString(),
                        RuntimeID     = runtimeId,
                        CompileAssets = compileAssets.Select(c => GetPackageAssetFromTargetPath(c)).ToArray(),
                        RuntimeAssets = runtimeAssets.Select(r => GetPackageAssetFromTargetPath(r)).ToArray(),
                        NativeAssets  = nativeAssets.Select(n => GetPackageAssetFromTargetPath(n)).ToArray()
                    };
                    report.Targets[target] = reportTarget;
                }

                if (isSupported)
                {
                    // Find 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));
                    }

                    var version = "unknown";
                    if (refAssm != null)
                    {
                        version = _targetPathToPackageItem[AggregateNuGetAssetResolver.AsPackageSpecificTargetPath(PackageId, refAssm)].Version?.ToString() ?? version;
                    }

                    report.SupportedFrameworks.Add(fx.ToString(), version);
                }
            }

            report.UnusedAssets = _unusedTargetPaths.Select(tp => GetPackageAssetFromTargetPath(tp)).ToArray();

            report.Save(ReportFile);

            return(!Log.HasLoggedErrors);
        }
        /// <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 (Reports == null || Reports.Length == 0)
            {
                Log.LogError("Reports argument must be specified");
                return(false);
            }

            if (String.IsNullOrEmpty(DocFilePath))
            {
                Log.LogError("DocFilePath argument must be specified");
                return(false);
            }

            string docDir = Path.GetDirectoryName(DocFilePath);

            if (!Directory.Exists(docDir))
            {
                Directory.CreateDirectory(docDir);
            }

            SortedSet <Version> knownNetStandardVersions = new SortedSet <Version>();
            List <SupportRow>   rows = new List <SupportRow>(Reports.Length);

            foreach (var reportPath in Reports.Select(r => r.GetMetadata("FullPath")))
            {
                SupportRow row = new SupportRow();
                row.Name             = Path.GetFileNameWithoutExtension(reportPath);
                row.SuportedVersions = new SortedSet <NETStandardApiVersion>();

                var report = PackageReport.Load(reportPath);

                foreach (var supportedFramework in report.SupportedFrameworks)
                {
                    var fx = NuGetFramework.Parse(supportedFramework.Key);

                    if (fx.Framework == FrameworkConstants.FrameworkIdentifiers.NetStandard)
                    {
                        row.SuportedVersions.Add(new NETStandardApiVersion(fx.Version, new Version(supportedFramework.Value.ToString())));
                        knownNetStandardVersions.Add(fx.Version);
                    }
                }
                rows.Add(row);
            }

            StringBuilder table = new StringBuilder();

            table.AppendLine($"| Contract | {String.Join(" | ", knownNetStandardVersions.Select(v => v.ToString(2)))} |");
            table.AppendLine($"| -------- | {String.Join(" | ", Enumerable.Repeat("---", knownNetStandardVersions.Count))}");

            foreach (var row in rows.OrderBy(r => r.Name))
            {
                if (row.SuportedVersions.Count == 0)
                {
                    Log.LogMessage($"Skipping {row.Name} since it has no supported NETStandard versions");
                    continue;
                }

                table.Append($"| {row.Name} |");

                foreach (var netStandardVersion in knownNetStandardVersions)
                {
                    var apiVersion = row.SuportedVersions.LastOrDefault(a => a.NETStandardVersion <= netStandardVersion);

                    table.Append(" ");
                    if (apiVersion != null)
                    {
                        table.Append(apiVersion.APIVersion.ToString(3));
                    }
                    table.Append(" |");
                }
                table.AppendLine();
            }

            if (!InsertIntoFile)
            {
                File.WriteAllText(DocFilePath, table.ToString());
            }
            else
            {
                if (!File.Exists(DocFilePath))
                {
                    Log.LogError($"InsertIntoFile was specified as true but {DocFilePath} did not exist.");
                    return(false);
                }

                string originalText = File.ReadAllText(DocFilePath);
                int    startIndex   = originalText.IndexOf(startMarker);

                if (startIndex < 0)
                {
                    Log.LogError($"InsertIntoFile was specified as true but could not locate insertion start text \"{startMarker}\".");
                    return(false);
                }
                startIndex += startMarker.Length;
                // skip any white-space / new line
                while (startIndex < originalText.Length && Char.IsWhiteSpace(originalText[startIndex]))
                {
                    startIndex++;
                }

                int endIndex = originalText.IndexOf(endMarker, startIndex);

                if (endIndex < 0)
                {
                    Log.LogError($"InsertIntoFile was specified as true but could not locate insertion end text \"{endMarker}\".");
                    return(false);
                }
                var docText = new StringBuilder(originalText);
                docText.Remove(startIndex, endIndex - startIndex);
                docText.Insert(startIndex, table.ToString());

                File.WriteAllText(DocFilePath, docText.ToString(), Encoding.UTF8);
            }


            return(!Log.HasLoggedErrors);
        }
        public override bool Execute()
        {
            LoadFiles();
            LoadFrameworks();

            var report = new PackageReport()
            {
                Id = PackageId,
                Version = PackageVersion,
                SupportedFrameworks = new Dictionary<string, string>()
            };

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

            foreach (var framework in _frameworks.OrderBy(f => f.Key.ToString()))
            {
                var fx = framework.Key;
                var runtimeIds = framework.Value;

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

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

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

                if (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 = compileAssets.Select(c => GetPackageAssetFromTargetPath(c)).ToArray()
                    };
                    report.Targets.Add(fx.ToString(), reportTarget);
                }

                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);
                    MarkUsed(runtimeAssets);

                    if (!FrameworkUtilities.IsGenerationMoniker(fx) && !fx.IsPCL)
                    {
                        // only look at runtime assets for runnable frameworks.
                        isSupported &= hasCompileAsset == hasRuntimeAsset;
                        isSupported &= hasCompilePlaceHolder == hasRuntimePlaceHolder;
                    }

                    var nativeAssets = _resolver.ResolveNativeAssets(fx, runtimeId);
                    MarkUsed(nativeAssets);

                    var reportTarget = new Target()
                    {
                        Framework = fx.ToString(),
                        RuntimeID = runtimeId,
                        CompileAssets = compileAssets.Select(c => GetPackageAssetFromTargetPath(c)).ToArray(),
                        RuntimeAssets = runtimeAssets.Select(r => GetPackageAssetFromTargetPath(r)).ToArray(),
                        NativeAssets = nativeAssets.Select(n => GetPackageAssetFromTargetPath(n)).ToArray()
                    };
                    report.Targets[target] = reportTarget;
                }
                
                if (isSupported)
                {
                    // Find 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));
                    }

                    var version = "unknown";
                    if (refAssm != null)
                    {
                        version = _targetPathToPackageItem[AggregateNuGetAssetResolver.AsPackageSpecificTargetPath(PackageId, refAssm)].Version?.ToString() ?? version;
                    }

                    report.SupportedFrameworks.Add(fx.ToString(), version);
                }
            }

            report.UnusedAssets = _unusedTargetPaths.Select(tp => GetPackageAssetFromTargetPath(tp)).ToArray();

            report.Save(ReportFile);

            return !Log.HasLoggedErrors;
        }
示例#10
0
 private void LoadReport()
 {
     _report = PackageReport.Load(ReportFile);
 }
 // Making this method protected virtual for tests.
 protected virtual PackageReport GetPackageReportFromPath()
 {
     return(PackageReport.Load(PackageReportPath));
 }
示例#12
0
 // Making this method protected virtual for tests.
 protected virtual PackageReport GetPackageReportFromPath(string path)
 {
     return(PackageReport.Load(path));
 }
示例#13
0
        public override bool Execute()
        {
            var frameworks = Frameworks.NullAsEmpty().ToDictionary(
                i => NuGetFramework.Parse(i.ItemSpec),
                i =>
            {
                var rids = i.GetMetadata("RuntimeIds");
                return(String.IsNullOrEmpty(rids) ? new HashSet <string>() : new HashSet <string>(rids.Split(';')));
            },
                NuGetFramework.Comparer);

            var layoutFiles = new List <ITaskItem>();

            foreach (var packageReportFile in PackageReports)
            {
                var packageReport = PackageReport.Load(packageReportFile);

                foreach (var targetInfo in packageReport.Targets)
                {
                    var targetName = targetInfo.Key;
                    var target     = targetInfo.Value;

                    var targetParts = targetName.Split('/');

                    var    fx  = NuGetFramework.Parse(targetParts[0]);
                    string rid = null;

                    if (targetParts.Length > 1)
                    {
                        rid = targetParts[1];
                    }

                    if (frameworks.Count != 0)
                    {
                        HashSet <string> rids = null;

                        if (!frameworks.TryGetValue(fx, out rids))
                        {
                            Log.LogMessage(LogImportance.Low, $"Skipping {fx} since it is not in {nameof(Frameworks)}");
                            continue;
                        }

                        if (rid != null && rids.Count > 0 && !rids.Contains(rid))
                        {
                            Log.LogMessage(LogImportance.Low, $"Skipping {fx}/{rid} since it is not in {nameof(Frameworks)}");
                            continue;
                        }
                    }

                    if (!packageReport.SupportedFrameworks.ContainsKey(fx.ToString()))
                    {
                        Log.LogMessage(LogImportance.Low, $"Skipping {fx} since it is not supported");
                        continue;
                    }

                    var fxFolder = fx.GetShortFolderName();

                    if (rid == null)
                    {
                        // only consider compile assets for RID-less target
                        layoutFiles.AddRange(CreateLayoutFiles(target.CompileAssets, $"ref\\{fxFolder}", "Compile"));
                    }

                    layoutFiles.AddRange(CreateLayoutFiles(target.RuntimeAssets, $"runtimes\\{rid}\\lib\\{fxFolder}", "Runtime"));
                    layoutFiles.AddRange(CreateLayoutFiles(target.NativeAssets, $"runtimes\\{rid}\\native", "Native"));
                }
            }

            LayoutFiles = layoutFiles.ToArray();

            return(!Log.HasLoggedErrors);
        }