diff --git a/src/UniGetUI.Core.Data/Licenses.cs b/src/UniGetUI.Core.Data/Licenses.cs index babd89a84f..616f2b2936 100644 --- a/src/UniGetUI.Core.Data/Licenses.cs +++ b/src/UniGetUI.Core.Data/Licenses.cs @@ -25,7 +25,6 @@ public static class LicenseData {"parse_pip_search", "MIT"}, {"PowerShell Gallery", "Unknown"}, {".NET SDK", "MIT"}, - {"dotnet-tools-outdated", "MIT"}, {"Cargo", "MIT"}, {"cargo-binstall", "GPL-3.0-only"}, {"cargo-update", "MIT"}, @@ -59,7 +58,6 @@ public static class LicenseData {"Pip", new Uri("https://github.com/pypa/pip/blob/main/LICENSE.txt")}, {"parse_pip_search", new Uri("https://github.com/marticliment/parseable_pip_search/blob/master/LICENSE.md")}, {".NET SDK", new Uri("https://github.com/dotnet/sdk/blob/main/LICENSE.TXT")}, - {"dotnet-tools-outdated", new Uri("https://github.com/rychlym/dotnet-tools-outdated/blob/master/LICENSE")}, {"PowerShell Gallery", new Uri("https://www.powershellgallery.com/")}, {"Cargo", new Uri("https://github.com/rust-lang/cargo/blob/master/LICENSE-MIT")}, {"cargo-binstall", new Uri("https://spdx.org/licenses/GPL-3.0-only.html")}, @@ -94,7 +92,6 @@ public static class LicenseData {"Pip", new Uri("https://github.com/pypa/pip/")}, {"parse_pip_search", new Uri("https://github.com/marticliment/parseable_pip_search/")}, {".NET SDK", new Uri("https://dotnet.microsoft.com/")}, - {"dotnet-tools-outdated", new Uri("https://github.com/rychlym/dotnet-tools-outdated/")}, {"PowerShell Gallery", new Uri("https://www.powershellgallery.com/")}, {"Cargo", new Uri("https://github.com/rust-lang/cargo")}, {"cargo-binstall", new Uri("https://github.com/cargo-bins/cargo-binstall")}, diff --git a/src/UniGetUI.PackageEngine.Managers.Chocolatey/Chocolatey.cs b/src/UniGetUI.PackageEngine.Managers.Chocolatey/Chocolatey.cs index 69d11818aa..a7a1bbd2b8 100644 --- a/src/UniGetUI.PackageEngine.Managers.Chocolatey/Chocolatey.cs +++ b/src/UniGetUI.PackageEngine.Managers.Chocolatey/Chocolatey.cs @@ -117,7 +117,7 @@ protected override IReadOnlyList GetAvailableUpdates_UnSafe() return Packages; } - protected override IReadOnlyList GetInstalledPackages_UnSafe() + protected override IReadOnlyList _getInstalledPackages_UnSafe() { Process p = new() { diff --git a/src/UniGetUI.PackageEngine.Managers.Dotnet/DotNet.cs b/src/UniGetUI.PackageEngine.Managers.Dotnet/DotNet.cs index 86b5924fe6..b47d174374 100644 --- a/src/UniGetUI.PackageEngine.Managers.Dotnet/DotNet.cs +++ b/src/UniGetUI.PackageEngine.Managers.Dotnet/DotNet.cs @@ -25,15 +25,6 @@ public class DotNet : BaseNuGet public DotNet() { - Dependencies = [ - new ManagerDependency( - ".NET Tools Outdated", - Path.Join(Environment.SystemDirectory, "windowspowershell\\v1.0\\powershell.exe"), - "-ExecutionPolicy Bypass -NoLogo -NoProfile -Command \"& {dotnet tool install --global dotnet-tools-outdated --add-source https://api.nuget.org/v3/index.json; if ($error.count -ne 0){pause}}\"", - "dotnet tool install --global dotnet-tools-outdated --add-source https://api.nuget.org/v3/index.json", - async () => (await CoreTools.WhichAsync("dotnet-tools-outdated.exe")).Item1) - ]; - Capabilities = new ManagerCapabilities { CanRunAsAdmin = true, @@ -66,96 +57,7 @@ public DotNet() OperationHelper = new DotNetPkgOperationHelper(this); } - protected override IReadOnlyList GetAvailableUpdates_UnSafe() - { - var (found, path) = CoreTools.Which("dotnet-tools-outdated.exe"); - if (!found) - { - Process proc = new() - { - StartInfo = new ProcessStartInfo - { - FileName = Status.ExecutablePath, - Arguments = Properties.ExecutableCallArgs + " install --global dotnet-tools-outdated", - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - CreateNoWindow = true, - } - }; - - IProcessTaskLogger aux_logger = TaskLogger.CreateNew(LoggableTaskType.InstallManagerDependency, proc); - proc.Start(); - - aux_logger.AddToStdOut(proc.StandardOutput.ReadToEnd()); - aux_logger.AddToStdErr(proc.StandardError.ReadToEnd()); - proc.WaitForExit(); - aux_logger.Close(proc.ExitCode); - - path = "dotnet-tools-outdated.exe"; - } - - Process p = new() - { - StartInfo = new ProcessStartInfo - { - FileName = path, - Arguments = "--format json --utf8", - RedirectStandardOutput = true, - RedirectStandardError = true, - UseShellExecute = false, - CreateNoWindow = true, - StandardOutputEncoding = System.Text.Encoding.UTF8 - } - }; - - p.StartInfo = CoreTools.UpdateEnvironmentVariables(p.StartInfo); - IProcessTaskLogger logger = TaskLogger.CreateNew(LoggableTaskType.ListUpdates, p); - p.Start(); - - List Packages = []; - string output = p.StandardOutput.ReadToEnd(); - logger.AddToStdOut(output); - logger.AddToStdErr(p.StandardError.ReadToEnd()); - - while (output[0] != '{') output = output[1..]; - JsonArray? data = (JsonNode.Parse(output) as JsonObject)?["dotnet-tools-outdated"] as JsonArray; - if (data is not null) - { - foreach (JsonNode? node in data) - { - if (node is not JsonObject element) continue; - - bool unlisted = element["becomeUnlisted"]?.GetValue() ?? false; - string id = element["packageName"]?.ToString() ?? ""; - string version = element["currentVer"]?.ToString() ?? ""; - string newVersion = element["availableVer"]?.ToString() ?? ""; - - if (unlisted) - { - Logger.Warn($".NET package {id} is unlisted, not showing it..."); - continue; - }; - - Packages.Add(new( - CoreTools.FormatAsName(id), id, version, newVersion, DefaultSource, this, - new(PackageScope.Global) - )); - - } - } - else - { - logger.AddToStdErr("\"JsonArray? data\" was null!"); - } - - p.WaitForExit(); - logger.Close(p.ExitCode); - - return Packages; - } - - protected override IReadOnlyList GetInstalledPackages_UnSafe() + protected override IReadOnlyList _getInstalledPackages_UnSafe() { List Packages = []; foreach (var options in new OverridenInstallationOptions[] { new(PackageScope.Local), new(PackageScope.Global) }) diff --git a/src/UniGetUI.PackageEngine.Managers.Generic.NuGet/BaseNuGet.cs b/src/UniGetUI.PackageEngine.Managers.Generic.NuGet/BaseNuGet.cs index 0b615ac3bf..6ed71bc383 100644 --- a/src/UniGetUI.PackageEngine.Managers.Generic.NuGet/BaseNuGet.cs +++ b/src/UniGetUI.PackageEngine.Managers.Generic.NuGet/BaseNuGet.cs @@ -1,7 +1,11 @@ +using System.Text; using System.Text.RegularExpressions; using System.Web; +using UniGetUI.Core.Classes; using UniGetUI.Core.Data; +using UniGetUI.Core.Logging; using UniGetUI.Core.Tools; +using UniGetUI.PackageEngine.Enums; using UniGetUI.PackageEngine.Interfaces; using UniGetUI.PackageEngine.ManagerClasses.Classes; using UniGetUI.PackageEngine.ManagerClasses.Manager; @@ -104,6 +108,79 @@ protected sealed override IReadOnlyList FindPackages_UnSafe(string quer return Packages; } + + protected override IReadOnlyList GetAvailableUpdates_UnSafe() + { + int errors = 0; + var logger = TaskLogger.CreateNew(LoggableTaskType.ListUpdates); + + var installedPackages = TaskRecycler>.RunOrAttach(GetInstalledPackages); + var Packages = new List(); + + Dictionary> sourceMapping = new(); + + foreach (var package in installedPackages) + { + var uri = package.Source; + if (!sourceMapping.ContainsKey(uri)) sourceMapping[uri] = new(); + sourceMapping[uri].Add(package); + } + + foreach (var pair in sourceMapping) + { + var packageIds = new StringBuilder(); + var packageVers = new StringBuilder(); + var packageIdVersion = new Dictionary(); + foreach (var package in pair.Value) + { + packageIds.Append(package.Id + "|"); + packageVers.Append(package.VersionString + "|"); + packageIdVersion[package.Id.ToLower()] = package.VersionString; + } + + var SearchUrl = $"{pair.Key.Url.ToString().Trim('/')}/GetUpdates()" + + $"?packageIds=%27{HttpUtility.UrlEncode(packageIds.ToString().Trim('|'))}%27" + + $"&versions=%27{HttpUtility.UrlEncode(packageVers.ToString().Trim('|'))}%27" + + $"&includePrerelease=0&includeAllVersions=0"; + + using HttpClient client = new(CoreData.GenericHttpClientParameters); + client.DefaultRequestHeaders.UserAgent.ParseAdd(CoreData.UserAgentString); + HttpResponseMessage response = client.GetAsync(SearchUrl).GetAwaiter().GetResult(); + + if (!response.IsSuccessStatusCode) + { + logger.Error($"Failed to fetch api at Url={SearchUrl} with status code {response.StatusCode}"); + errors++; + } + else + { + string SearchResults = response.Content.ReadAsStringAsync().GetAwaiter().GetResult(); + MatchCollection matches = Regex.Matches(SearchResults, "([\\s\\S]*?)<\\/entry>"); + + foreach (Match match in matches) + { + if (!match.Success) continue; + + string id = Regex.Match(match.Value, "([^<]+)").Groups[1].Value; + string new_version = Regex.Match(match.Value, "([^<]+)").Groups[1].Value; + // Match title = Regex.Match(match.Value, "([^<>]+)<\\/title>"); + + logger.Log($"Found package {id} version {new_version} on source {pair.Key.Name}"); + Packages.Add(new Package(CoreTools.FormatAsName(id), id, packageIdVersion[id.ToLower()], new_version, pair.Key, this)); + } + } + } + + logger.Close(errors); + return Packages; + } + + protected sealed override IReadOnlyList GetInstalledPackages_UnSafe() + => TaskRecycler>.RunOrAttach(_getInstalledPackages_UnSafe); + + protected abstract IReadOnlyList _getInstalledPackages_UnSafe(); + + } } diff --git a/src/UniGetUI.PackageEngine.Managers.PowerShell/Helpers/PowerShellPkgOperationHelper.cs b/src/UniGetUI.PackageEngine.Managers.PowerShell/Helpers/PowerShellPkgOperationHelper.cs index 2ce8884c1e..f23005f14e 100644 --- a/src/UniGetUI.PackageEngine.Managers.PowerShell/Helpers/PowerShellPkgOperationHelper.cs +++ b/src/UniGetUI.PackageEngine.Managers.PowerShell/Helpers/PowerShellPkgOperationHelper.cs @@ -55,7 +55,8 @@ protected override OperationVeredict _getOperationResult( { string output_string = string.Join("\n", processOutput); - if (!package.OverridenOptions.RunAsAdministrator != true && output_string.Contains("AdminPrivilegesAreRequired")) + if (package.OverridenOptions.RunAsAdministrator is not true && + (output_string.Contains("AdminPrivilegesAreRequired") || output_string.Contains("AdminPrivilegeRequired"))) { package.OverridenOptions.RunAsAdministrator = true; return OperationVeredict.AutoRetry; diff --git a/src/UniGetUI.PackageEngine.Managers.PowerShell/PowerShell.cs b/src/UniGetUI.PackageEngine.Managers.PowerShell/PowerShell.cs index 27587123ab..7aa0cd5dbb 100644 --- a/src/UniGetUI.PackageEngine.Managers.PowerShell/PowerShell.cs +++ b/src/UniGetUI.PackageEngine.Managers.PowerShell/PowerShell.cs @@ -55,94 +55,8 @@ public PowerShell() SourcesHelper = new PowerShellSourceHelper(this); OperationHelper = new PowerShellPkgOperationHelper(this); } - protected override IReadOnlyList GetAvailableUpdates_UnSafe() - { - Process p = new() - { - StartInfo = new ProcessStartInfo - { - FileName = Status.ExecutablePath, - Arguments = "-NoProfile", - RedirectStandardOutput = true, - RedirectStandardError = true, - RedirectStandardInput = true, - UseShellExecute = false, - CreateNoWindow = true, - StandardOutputEncoding = System.Text.Encoding.UTF8, - StandardInputEncoding = new UTF8Encoding(false), - } - }; - - IProcessTaskLogger logger = TaskLogger.CreateNew(LoggableTaskType.ListUpdates, p); - - p.Start(); - - string command = """ - function Test-GalleryModuleUpdate { - param ( - [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [string] $Name, - [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [version] $Version, - [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [string] $Repository, - [switch] $NeedUpdateOnly - ) - process { - $URLs = @{} - @(Get-PSRepository).ForEach({$URLs[$_.Name] = If ($_.Uri) {$_.Uri.AbsoluteUri} Else {$_.SourceLocation}}) - $page = Invoke-WebRequest -Uri ($URLs[$Repository] + "/package/$Name") -UseBasicParsing -Maximum 0 -ea Ignore - [version]$latest = Split-Path -Path ($page.Headers.Location -replace "$Name." -replace ".nupkg") -Leaf - $needsupdate = $Latest -gt $Version - if ($needsupdate) { - Write-Output($Name + "|" + $Version.ToString() + "|" + $Latest.ToString() + "|" + $Repository) - } - } - } - Get-InstalledModule | Test-GalleryModuleUpdate - - - exit - """; - p.StandardInput.WriteLine(command); - logger.AddToStdIn(command); - p.StandardInput.Close(); - - string? line; - List Packages = []; - while ((line = p.StandardOutput.ReadLine()) is not null) - { - logger.AddToStdOut(line); - if (line.StartsWith(">>")) - { - continue; - } - - string[] elements = line.Split('|'); - if (elements.Length < 4) - { - continue; - } - - for (int i = 0; i < elements.Length; i++) - { - elements[i] = elements[i].Trim(); - } - - if (elements[1] + ".0" == elements[2] || elements[1] + ".0.0" == elements[2]) - { - continue; - } - - Packages.Add(new Package(CoreTools.FormatAsName(elements[0]), elements[0], elements[1], - elements[2], SourcesHelper.Factory.GetSourceOrDefault(elements[3]), this)); - } - - logger.AddToStdErr(p.StandardError.ReadToEnd()); - p.WaitForExit(); - logger.Close(p.ExitCode); - - return Packages; - } - protected override IReadOnlyList GetInstalledPackages_UnSafe() + protected override IReadOnlyList _getInstalledPackages_UnSafe() { Process p = new() { diff --git a/src/UniGetUI.PackageEngine.Managers.PowerShell7/Helpers/PowerShell7PkgOperationHelper.cs b/src/UniGetUI.PackageEngine.Managers.PowerShell7/Helpers/PowerShell7PkgOperationHelper.cs index 731bb5df68..6bdcbd6ef4 100644 --- a/src/UniGetUI.PackageEngine.Managers.PowerShell7/Helpers/PowerShell7PkgOperationHelper.cs +++ b/src/UniGetUI.PackageEngine.Managers.PowerShell7/Helpers/PowerShell7PkgOperationHelper.cs @@ -52,7 +52,8 @@ protected override OperationVeredict _getOperationResult( { string output_string = string.Join("\n", processOutput); - if (!package.OverridenOptions.RunAsAdministrator != true && output_string.Contains("AdminPrivilegesAreRequired")) + if (package.OverridenOptions.RunAsAdministrator is not true && + (output_string.Contains("AdminPrivilegesAreRequired") || output_string.Contains("AdminPrivilegeRequired"))) { package.OverridenOptions.RunAsAdministrator = true; return OperationVeredict.AutoRetry; diff --git a/src/UniGetUI.PackageEngine.Managers.PowerShell7/PowerShell7.cs b/src/UniGetUI.PackageEngine.Managers.PowerShell7/PowerShell7.cs index 965e20f501..3df8db6c55 100644 --- a/src/UniGetUI.PackageEngine.Managers.PowerShell7/PowerShell7.cs +++ b/src/UniGetUI.PackageEngine.Managers.PowerShell7/PowerShell7.cs @@ -55,150 +55,8 @@ public PowerShell7() SourcesHelper = new PowerShell7SourceHelper(this); OperationHelper = new PowerShell7PkgOperationHelper(this); } - protected override IReadOnlyList GetAvailableUpdates_UnSafe() - { - Process p = new() - { - StartInfo = new ProcessStartInfo - { - FileName = Status.ExecutablePath, - Arguments = "-NoProfile", - RedirectStandardOutput = true, - RedirectStandardError = true, - RedirectStandardInput = true, - UseShellExecute = false, - CreateNoWindow = true, - StandardOutputEncoding = System.Text.Encoding.UTF8, - StandardInputEncoding = new UTF8Encoding(false), - } - }; - - IProcessTaskLogger logger = TaskLogger.CreateNew(LoggableTaskType.ListUpdates, p); - - p.Start(); - - string command = """ - function Get-MaxVersion { - param ( - [Parameter(Mandatory, ValueFromPipeline)] [PSCustomObject] $InputObject - ) - - begin { - $maxVersions = @{} - $moduleObjects = @{} - } - - process { - if (-not $maxVersions.ContainsKey($InputObject.Name)) { - $maxVersions[$InputObject.Name] = $InputObject.Version - $moduleObjects[$InputObject.Name] = $InputObject - } elseif ($InputObject.Version -gt $maxVersions[$InputObject.Name]) { - $maxVersions[$InputObject.Name] = $InputObject.Version - $moduleObjects[$InputObject.Name] = $InputObject - } - } - - end { - $moduleObjects.GetEnumerator() | ForEach-Object { - $_.Value - } - } - } - - function Test-GalleryModuleUpdate_Legacy { - param ( - [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [string] $Name, - [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [version] $Version, - [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [string] $Repository, - [switch] $NeedUpdateOnly - ) - process { - $URLs = @{} - @(Get-PSRepository).ForEach({$URLs[$_.Name] = If ($_.Uri) {$_.Uri.AbsoluteUri} Else {$_.SourceLocation}}) - $page = Invoke-WebRequest -Uri ($URLs[$Repository] + "/package/$Name") -UseBasicParsing -ea Ignore - [version]$latest = Split-Path -Path ($page.BaseResponse.RequestMessage.RequestUri -replace "$Name." -replace ".nupkg") -Leaf - $needsupdate = $Latest -gt $Version - if ($needsupdate) { - Write-Output($Name + "|" + $Version.ToString() + "|" + $Latest.ToString() + "|" + $Repository) - } - } - } - - function Test-GalleryModuleUpdate { - param ( - [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [string] $Name, - [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [version] $Version, - [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [string] $Repository, - [switch] $NeedUpdateOnly - ) - process { - $URLs = @{} - @(Get-PSRepository).ForEach({$URLs[$_.Name] = If ($_.Uri) {$_.Uri.AbsoluteUri} Else {$_.SourceLocation}}) - - $packageUrl = "$($URLs[$Repository])/FindPackagesById()?id='$Name'&`$filter=IsLatestVersion" - $page = Invoke-WebRequest -Uri $packageUrl -UseBasicParsing -ea Ignore - $latestVersionMatch = [regex]::Match($page.Content, '(.*?)') - if ($latestVersionMatch.Success) { - [version]$latest = $latestVersionMatch.Groups[1].Value - $needsupdate = $latest -gt $Version - if ($needsupdate) { - Write-Output($Name + "|" + $Version.ToString() + "|" + $latest.ToString() + "|" + $Repository) - } - } else { - Write-Warning("Could not parse version for package " + $Name) - Test-GalleryModuleUpdate_Legacy -Name $Name -Version $Version -Repository $Repository -NeedUpdateOnly:$NeedUpdateOnly - } - } - } - - Get-PSResource | Get-MaxVersion | Test-GalleryModuleUpdate - - - - exit - """; - p.StandardInput.WriteLine(command); - logger.AddToStdIn(command); - p.StandardInput.Close(); - - string? line; - List Packages = []; - while ((line = p.StandardOutput.ReadLine()) is not null) - { - logger.AddToStdOut(line); - if (line.StartsWith(">>")) - { - continue; - } - - string[] elements = line.Split('|'); - if (elements.Length < 4) - { - continue; - } - - for (int i = 0; i < elements.Length; i++) - { - elements[i] = elements[i].Trim(); - } - - if (elements[1] + ".0" == elements[2] || elements[1] + ".0.0" == elements[2]) - { - continue; - } - - Packages.Add(new Package(CoreTools.FormatAsName(elements[0]), elements[0], elements[1], - elements[2], SourcesHelper.Factory.GetSourceOrDefault(elements[3]), this)); - } - - logger.AddToStdErr(p.StandardError.ReadToEnd()); - p.WaitForExit(); - logger.Close(p.ExitCode); - - return Packages; - } - protected override IReadOnlyList GetInstalledPackages_UnSafe() + protected override IReadOnlyList _getInstalledPackages_UnSafe() { Process p = new() {