diff --git a/src/Tools/RepoUtil/ConflictingPackagesException.cs b/src/Tools/RepoUtil/ConflictingPackagesException.cs new file mode 100644 index 0000000000000000000000000000000000000000..35f66a54810a80b6a186e1656bb73061b6bc83c3 --- /dev/null +++ b/src/Tools/RepoUtil/ConflictingPackagesException.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; + +namespace RepoUtil +{ + internal class ConflictingPackagesException : Exception + { + public ConflictingPackagesException(List conflictingPackages) : + base("Creation failed because of conflicting package versions.") + { + ConflictingPackages = conflictingPackages.ToImmutableArray(); + } + + public ImmutableArray ConflictingPackages { get; } + } +} diff --git a/src/Tools/RepoUtil/ConsumesCommand.cs b/src/Tools/RepoUtil/ConsumesCommand.cs index 4582c93ff544f9dea546ae190b40aa5cc69d9426..0cb77e4fbe88398b837575f20cca0db4a20af79f 100644 --- a/src/Tools/RepoUtil/ConsumesCommand.cs +++ b/src/Tools/RepoUtil/ConsumesCommand.cs @@ -31,12 +31,23 @@ public bool Run(TextWriter writer, string[] args) private JObject GoCore() { var obj = new JObject(); + obj.Add(GetNuGetFeeds()); obj.Add(GetFixedPackages()); obj.Add(GetBuildPackages()); obj.Add(GetToolsetPackages()); return obj; } + private JProperty GetNuGetFeeds() + { + var obj = new JObject(); + foreach (var nugetFeed in _repoData.NuGetFeeds) + { + obj.Add(GetProperty(nugetFeed)); + } + return new JProperty("nugetFeeds", obj); + } + private JProperty GetFixedPackages() { var obj = new JObject(); @@ -68,6 +79,11 @@ private JProperty GetFloatingPackages(string name, IEnumerable pac return new JProperty(name, obj); } + private static JProperty GetProperty(NuGetFeed feed) + { + return new JProperty(feed.Name, feed.Url); + } + private static JProperty GetProperty(NuGetPackage package) { return new JProperty(package.Name, package.Version); diff --git a/src/Tools/RepoUtil/NuGetConfigUtil.cs b/src/Tools/RepoUtil/NuGetConfigUtil.cs new file mode 100644 index 0000000000000000000000000000000000000000..f1e8575f0bee543aff7e554c7747033c3b92ddc7 --- /dev/null +++ b/src/Tools/RepoUtil/NuGetConfigUtil.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.IO; +using System.Xml.Linq; + +namespace RepoUtil +{ + internal static class NuGetConfigUtil + { + internal static List GetNuGetFeeds(string nugetConfigFile) + { + var nugetConfig = XElement.Load(nugetConfigFile); + var nugetFeeds = + from el in nugetConfig.Descendants("packageSources").Descendants("add") + select new NuGetFeed(el.Attribute("key").Value, new Uri(el.Attribute("value").Value)); + + return nugetFeeds.ToList(); + } + + internal static IEnumerable GetNuGetConfigFiles(string sourcesPath) + { + return Directory.EnumerateFiles(sourcesPath, "nuget*config", SearchOption.AllDirectories); + } + } +} diff --git a/src/Tools/RepoUtil/NuGetFeed.cs b/src/Tools/RepoUtil/NuGetFeed.cs new file mode 100644 index 0000000000000000000000000000000000000000..a194f65514ebe3ae6255dc3ebe2565ed929104bf --- /dev/null +++ b/src/Tools/RepoUtil/NuGetFeed.cs @@ -0,0 +1,25 @@ +using System; + +namespace RepoUtil +{ + internal struct NuGetFeed : IEquatable + { + internal string Name { get; } + internal Uri Url { get; } + + internal NuGetFeed(string name, Uri url) + { + Name = name; + Url = url; + } + + public static bool operator ==(NuGetFeed left, NuGetFeed right) => + StringComparer.OrdinalIgnoreCase.Equals(left.Name, right.Name) && + left.Url == right.Url; + public static bool operator !=(NuGetFeed left, NuGetFeed right) => !(left == right); + public override bool Equals(object obj) => obj is NuGetFeed && Equals((NuGetFeed)obj); + public override int GetHashCode() => Name?.GetHashCode() ?? 0; + public override string ToString() => $"{Name}-{Url}"; + public bool Equals(NuGetFeed other) => this == other; + } +} diff --git a/src/Tools/RepoUtil/Program.cs b/src/Tools/RepoUtil/Program.cs index 700485f67f90e49c17966bf58fbb3a91d4a685ca..1d9dc6c0439d8d1216f1d8809b2a9e527fd5b136 100644 --- a/src/Tools/RepoUtil/Program.cs +++ b/src/Tools/RepoUtil/Program.cs @@ -21,7 +21,29 @@ private sealed class ParsedArgs internal static int Main(string[] args) { - return Run(args) ? 0 : 1; + int result = 1; + try + { + if (Run(args)) + result = 0; + } + catch (ConflictingPackagesException ex) + { + Console.WriteLine(ex.Message); + foreach (var package in ex.ConflictingPackages) + { + Console.WriteLine(package.PackageName); + Console.WriteLine($"\t{package.Conflict.NuGetPackage.Version} - {package.Conflict.FileName}"); + Console.WriteLine($"\t{package.Original.NuGetPackage.Version} - {package.Original.FileName}"); + } + } + catch (Exception ex) + { + Console.WriteLine("Something unexpected happened."); + Console.WriteLine(ex.ToString()); + } + + return result; } private static bool Run(string[] args) diff --git a/src/Tools/RepoUtil/RepoConfig.cs b/src/Tools/RepoUtil/RepoConfig.cs index dbfe7168c5bfb0c251fea30ab3a9fca2b9c5dc2f..c9ea19fe61ec9ee2ecf4054d2a89958d5972a6f0 100644 --- a/src/Tools/RepoUtil/RepoConfig.cs +++ b/src/Tools/RepoUtil/RepoConfig.cs @@ -41,18 +41,21 @@ internal class RepoConfig internal ImmutableArray FixedPackages { get; } internal ImmutableArray ToolsetPackages { get; } internal ImmutableArray NuSpecExcludes { get; } + internal ImmutableArray ProjectJsonExcludes { get; } internal GenerateData? MSBuildGenerateData { get; } internal RepoConfig( IEnumerable fixedPackages, IEnumerable toolsetPackages, IEnumerable nuspecExcludes, + IEnumerable projectJsonExcludes, GenerateData? msbuildGenerateData) { Debug.Assert(toolsetPackages.Distinct().Count() == toolsetPackages.Count()); MSBuildGenerateData = msbuildGenerateData; FixedPackages = fixedPackages.OrderBy(x => x.Name).ToImmutableArray(); NuSpecExcludes = nuspecExcludes.ToImmutableArray(); + ProjectJsonExcludes = projectJsonExcludes.ToImmutableArray(); ToolsetPackages = toolsetPackages.OrderBy(x => x).ToImmutableArray(); var map = new Dictionary>(); @@ -110,10 +113,18 @@ internal static RepoConfig ReadFrom(string jsonFilePath) nuspecExcludes.AddRange(((JArray)nuspecExcludesProp.Value).Values().Select(x => new Regex(x))); } + var projectJsonExcludes = new List(); + var projectJsonExcludesProp = obj.Property("projectJsonExcludes"); + if (projectJsonExcludesProp != null) + { + projectJsonExcludes.AddRange(((JArray)projectJsonExcludesProp.Value).Values().Select(x => new Regex(x))); + } + return new RepoConfig( fixedPackagesList, toolsetPackages, nuspecExcludes, + projectJsonExcludes, msbuildGenerateData); } diff --git a/src/Tools/RepoUtil/RepoData.cs b/src/Tools/RepoUtil/RepoData.cs index dc169ae9c421a3a79d7316b9450f721231d383e9..1a5a4a018dc03a00e5448f317548040d3977862f 100644 --- a/src/Tools/RepoUtil/RepoData.cs +++ b/src/Tools/RepoUtil/RepoData.cs @@ -14,16 +14,18 @@ internal sealed class RepoData { internal string SourcesPath { get; } internal RepoConfig RepoConfig { get; } + internal ImmutableArray NuGetFeeds { get; } internal ImmutableArray FloatingBuildPackages { get; } internal ImmutableArray FloatingToolsetPackages { get; } internal ImmutableArray FloatingPackages { get; } internal ImmutableArray FixedPackages => RepoConfig.FixedPackages; internal ImmutableArray AllPackages { get; } - private RepoData(RepoConfig config, string sourcesPath, IEnumerable floatingPackages) + private RepoData(RepoConfig config, string sourcesPath, IEnumerable nugetFeeds, IEnumerable floatingPackages) { SourcesPath = sourcesPath; RepoConfig = config; + NuGetFeeds = nugetFeeds.ToImmutableArray(); FloatingToolsetPackages = floatingPackages .Where(x => RepoConfig.ToolsetPackages.Contains(x.Name, Constants.NugetPackageNameComparer)) .OrderBy(x => x.Name) @@ -57,7 +59,7 @@ internal static RepoData Create(RepoConfig config, string sourcesPath) var repoData = Create(config, sourcesPath, out conflicts); if (conflicts?.Count > 0) { - throw new Exception("Creation failed because of conflicting packages"); + throw new ConflictingPackagesException(conflicts); } return repoData; @@ -65,12 +67,24 @@ internal static RepoData Create(RepoConfig config, string sourcesPath) internal static RepoData Create(RepoConfig config, string sourcesPath, out List conflicts) { + var nugetFeeds = new List(); + foreach (var nugetConfig in NuGetConfigUtil.GetNuGetConfigFiles(sourcesPath)) + { + var nugetFeed = NuGetConfigUtil.GetNuGetFeeds(nugetConfig); + nugetFeeds.AddRange(nugetFeed); + } + conflicts = null; var fixedPackageSet = new HashSet(config.FixedPackages); var floatingPackageMap = new Dictionary(Constants.NugetPackageNameComparer); foreach (var filePath in ProjectJsonUtil.GetProjectJsonFiles(sourcesPath)) { + if (config.ProjectJsonExcludes.Any(x => x.IsMatch(filePath))) + { + continue; + } + var fileName = FileName.FromFullPath(sourcesPath, filePath); foreach (var package in ProjectJsonUtil.GetDependencies(filePath)) { @@ -99,7 +113,7 @@ internal static RepoData Create(RepoConfig config, string sourcesPath, out List< } } - return new RepoData(config, sourcesPath, floatingPackageMap.Values.Select(x => x.NuGetPackage)); + return new RepoData(config, sourcesPath, nugetFeeds, floatingPackageMap.Values.Select(x => x.NuGetPackage)); } } } diff --git a/src/Tools/RepoUtil/RepoUtil.csproj b/src/Tools/RepoUtil/RepoUtil.csproj index 76f914f97e2f2140ac73070979d4e43add35e3df..7d0f53baf162286cfcee94506def596213f7ba5c 100644 --- a/src/Tools/RepoUtil/RepoUtil.csproj +++ b/src/Tools/RepoUtil/RepoUtil.csproj @@ -41,6 +41,7 @@ + @@ -48,6 +49,8 @@ + +