static IEnumerable <PackageInfo> ResolveDependenciesFor_NUSPEC(IEnumerable <PackageInfo> packages) { var result = new List <PackageInfo>(packages); var queue = new Queue <PackageInfo>(packages); while (queue.Any()) { PackageInfo item = queue.Dequeue(); IEnumerable <XElement> dependencyPackages; var dependenciesSection = XElement.Parse(File.ReadAllText(item.SpecFile)) .FindDescendants("dependencies") .FirstOrDefault(); if (dependenciesSection == null) { continue; } // <dependencies> // <group targetFramework=".NETStandard2.0"> // <dependency id="Microsoft.Extensions.Logging.Abstractions" version="2.1.0" exclude="Build,Analyzers" /> var frameworks = dependenciesSection.FindDescendants("group"); if (frameworks.Any()) { IEnumerable <XElement> frameworkGroups = dependenciesSection.FindDescendants("group"); var match = GetCompatibleTargetFramework(frameworkGroups, item); dependencyPackages = match != null ? match.FindDescendants("dependency") : new XElement[0]; } else { dependencyPackages = dependenciesSection.FindDescendants("dependency"); } foreach (var element in dependencyPackages) { var newPackage = new PackageInfo { Name = element.Attribute("id").Value, Version = element.Attribute("version").Value, PreferredRuntime = item.PreferredRuntime }; newPackage.SpecFile = NuGetCache.PathJoin(newPackage.Name, newPackage.Version, newPackage.Name + ".nuspec"); if (!result.Any(x => x.Name == newPackage.Name) && File.Exists(newPackage.SpecFile)) { queue.Enqueue(newPackage); result.Add(newPackage); } } } return(result.ToArray()); }
public void InstallPackage(string packageNameMask, string version = null) { var packages = new string[0]; //index is 1-based, exactly as it is printed with ListPackages if (int.TryParse(packageNameMask, out int index)) { var all_packages = ListPackages(); if (0 < index && index <= all_packages.Count()) { packages = new string[] { all_packages[index - 1] } } ; else { Console.WriteLine("There is no package with the specified index"); } } else { // Regex is too much at this stage // string pattern = CSSUtils.ConvertSimpleExpToRegExp(); // Regex wildcard = new Regex(pattern, RegexOptions.IgnoreCase); if (packageNameMask.EndsWith("*")) { packages = ListPackages().Where(x => x.StartsWith(packageNameMask.Substring(0, packageNameMask.Length - 1))).ToArray(); } else { packages = new[] { packageNameMask } }; } // C:\Users\user\AppData\Local\Temp\csscript.core\.nuget\333 var nuget_dir = CSExecutor.GetScriptTempDir() .PathJoin(".nuget", Process.GetCurrentProcess().Id) .EnsureDir(); try { var proj_template = nuget_dir.PathJoin("build.csproj"); if (!File.Exists(proj_template)) { Utils.Run("dotnet", "new console", nuget_dir); foreach (var name in packages) { var ver = ""; if (version != null) { ver = "-v " + version; } Utils.Run("dotnet", $"add package {name} {ver}", nuget_dir, x => Console.WriteLine(x)); } // intercept and report incompatible packages (maybe) } } finally { Task.Run(() => { nuget_dir.DeleteDir(); ClearAnabdonedNugetDirs(nuget_dir.GetDirName()); }); } } void ClearAnabdonedNugetDirs(string nuget_root) { // not implemented yet foreach (var item in Directory.GetDirectories(nuget_root)) { if (int.TryParse(item.GetFileName(), out int proc_id)) { if (Process.GetProcessById(proc_id) == null) { try { item.DeleteDir(); } catch { } } } } } IEnumerable <PackageInfo> ResolveDependenciesFor(IEnumerable <PackageInfo> packages) { var result = new List <PackageInfo>(packages); var queue = new Queue <PackageInfo>(packages); while (queue.Any()) { PackageInfo item = queue.Dequeue(); IEnumerable <XElement> dependencyPackages; var dependenciesSection = XElement.Parse(File.ReadAllText(item.SpecFile)) .FindDescendants("dependencies") .FirstOrDefault(); if (dependenciesSection == null) { continue; } // <dependencies> // <group targetFramework=".NETStandard2.0"> // <dependency id="Microsoft.Extensions.Logging.Abstractions" version="2.1.0" exclude="Build,Analyzers" /> var frameworks = dependenciesSection.FindDescendants("group"); if (frameworks.Any()) { IEnumerable <XElement> frameworkGroups = dependenciesSection.FindDescendants("group"); dependencyPackages = GetCompatibleTargetFramework(frameworkGroups, item) ?.FindDescendants("dependency") ?? new XElement[0]; } else { dependencyPackages = dependenciesSection.FindDescendants("dependency"); } foreach (var element in dependencyPackages) { var newPackage = new PackageInfo { Name = element.Attribute("id").Value, Version = element.Attribute("version").Value, PreferredRuntime = item.PreferredRuntime }; newPackage.SpecFile = NuGetCache.PathJoin(newPackage.Name, newPackage.Version, newPackage.Name + ".nuspec"); if (!result.Any(x => x.Name == newPackage.Name) && File.Exists(newPackage.SpecFile)) { queue.Enqueue(newPackage); result.Add(newPackage); } } } return(result.ToArray()); } /// <summary> /// Gets the compatible target framework. Similar to `GetPackageCompatibleLib` but relies on NuGet spec file /// </summary> /// <param name="freameworks">The frameworks.</param> /// <param name="package">The package.</param> /// <returns></returns> XElement GetCompatibleTargetFramework(IEnumerable <XElement> freameworks, PackageInfo package) { // https://docs.microsoft.com/en-us/dotnet/standard/frameworks // netstandard?.? // netcoreapp?.? // net?? | net??? // "" (no framework element, meaning "any framework") // Though packages use Upper case with '.' preffix: '<group targetFramework=".NETStandard2.0">' XElement findMatch(Predicate <string> matchTest) { var items = freameworks.Select(x => new { Name = x.Attribute("targetFramework")?.Value, Element = x }) .OrderByDescending(x => x.Name) .ToArray(); var match = items.FirstOrDefault(x => matchTest(x.Name ?? ""))?.Element ?? // exact match items.FirstOrDefault(x => x.Name == null)?.Element; // universal dependency specified by not supplying targetFramework element return(match); } if (package.PreferredRuntime != null) { // by requested runtime return(findMatch(x => x.Contains(package.PreferredRuntime))); } else { if (CSharpCompiler.DefaultCompilerRuntime == DefaultCompilerRuntime.Standard) { // by configured runtime return(findMatch(x => x.Contains("netstandard", ignoreCase: true))); } else { if (Runtime.IsCore) { // by runtime of the host return(findMatch(x => x.Contains("netcore", ignoreCase: true)) ?? findMatch(x => x.Contains("netstandard", ignoreCase: true))); } else { // by .NET full as tehre is no other options return(findMatch(x => (x.StartsWith("net", ignoreCase: true) || x.StartsWith(".net", ignoreCase: true)) && !x.Contains("netcore", ignoreCase: true) && !x.Contains("netstandard", ignoreCase: true)) ?? findMatch(x => x.Contains("netstandard", ignoreCase: true))); } } } } /// <summary> /// Gets the package compatible library. Similar to `GetCompatibleTargetFramework` but relies on file structure /// </summary> /// <param name="package">The package.</param> /// <returns></returns> string GetPackageCompatibleLib(PackageInfo package) { var libDir = package.SpecFile.GetDirName().PathJoin("lib"); if (!Directory.Exists(libDir)) { return(null); } var frameworks = Directory.GetDirectories(package.SpecFile.GetDirName().PathJoin("lib")) .OrderByDescending(x => x) .Select(x => new { Runtime = x.GetFileName(), Path = x }); if (package.PreferredRuntime != null) { return(frameworks.FirstOrDefault(x => x.Runtime.EndsWith(package.PreferredRuntime))?.Path); } else { if (CSharpCompiler.DefaultCompilerRuntime == DefaultCompilerRuntime.Standard) { return(frameworks.FirstOrDefault(x => x.Runtime.StartsWith("netstandard", ignoreCase: true))?.Path); } else // host runtime { if (Runtime.IsCore) { return((frameworks.FirstOrDefault(x => x.Runtime.StartsWith("netcore", ignoreCase: true)) ?? frameworks.FirstOrDefault(x => x.Runtime.StartsWith("netstandard", ignoreCase: true)))?.Path); } else { return(frameworks.FirstOrDefault(x => x.Runtime.StartsWith("net", ignoreCase: true) && !x.Runtime.StartsWith("netcore", ignoreCase: true) && !x.Runtime.StartsWith("netstandard", ignoreCase: true))?.Path); } } } } string[] GetCompatibleAssemblies(PackageInfo package) { var lib = GetPackageCompatibleLib(package); if (lib != null) { return(Directory.GetFiles(GetPackageCompatibleLib(package), "*.dll") .Where(item => !item.EndsWith(".resources.dll", StringComparison.OrdinalIgnoreCase)) .Where(x => Utils.IsRuntimeCompatibleAsm(x)) .ToArray()); } else { return(new string[0]); } }