Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add back bundled winget compatibility #2440

Merged
merged 2 commits into from
Jul 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,269 @@
using System.Diagnostics;
using UniGetUI.Core.Logging;
using UniGetUI.PackageEngine.Classes.Manager.ManagerHelpers;
using UniGetUI.PackageEngine.PackageClasses;

namespace UniGetUI.PackageEngine.Managers.WingetManager;

internal static partial class BundledWinGetLegacyMethods
{
public static async Task<Package[]> FindPackages_UnSafe(WinGet Manager, string query)
{
List<Package> Packages = new();
Process p = new();
ProcessStartInfo startInfo = new()
{
FileName = Manager.WinGetBundledPath,
Arguments = Manager.Properties.ExecutableCallArgs + " search \"" + query + "\" --accept-source-agreements",
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true,
StandardOutputEncoding = System.Text.Encoding.UTF8
};
p.StartInfo = startInfo;
p.Start();

string OldLine = "";
int IdIndex = -1;
int VersionIndex = -1;
int SourceIndex = -1;
bool DashesPassed = false;
string line;
string output = "";
while ((line = await p.StandardOutput.ReadLineAsync()) != null)
{
output += line + "\n";
if (!DashesPassed && line.Contains("---"))
{
string HeaderPrefix = OldLine.Contains("SearchId") ? "Search" : "";
IdIndex = OldLine.IndexOf(HeaderPrefix + "Id");
VersionIndex = OldLine.IndexOf(HeaderPrefix + "Version");
SourceIndex = OldLine.IndexOf(HeaderPrefix + "Source");
DashesPassed = true;
}
else if (DashesPassed && IdIndex > 0 && VersionIndex > 0 && IdIndex < VersionIndex && VersionIndex < line.Length)
{
int offset = 0; // Account for non-unicode character length
while (line[IdIndex - offset - 1] != ' ' || offset > (IdIndex - 5))
offset++;
string name = line[..(IdIndex - offset)].Trim();
string id = line[(IdIndex - offset)..].Trim().Split(' ')[0];
string version = line[(VersionIndex - offset)..].Trim().Split(' ')[0];
ManagerSource source;
if (SourceIndex == -1 || SourceIndex >= line.Length)
source = Manager.DefaultSource;
else
{
string sourceName = line[(SourceIndex - offset)..].Trim().Split(' ')[0];
source = Manager.SourceProvider.SourceFactory.GetSourceOrDefault(sourceName);
}
Packages.Add(new Package(name, id, version, source, Manager));
}
OldLine = line;
}

output += await p.StandardError.ReadToEndAsync();
await Task.Run(p.WaitForExit);

return Packages.ToArray();

}

public static async Task<Package[]> GetAvailableUpdates_UnSafe(WinGet Manager)
{
List<Package> Packages = new();
Process p = new();
ProcessStartInfo startInfo = new()
{
FileName = Manager.WinGetBundledPath,
Arguments = Manager.Properties.ExecutableCallArgs + " update --include-unknown --accept-source-agreements",
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true,
StandardOutputEncoding = System.Text.Encoding.UTF8
};
p.StartInfo = startInfo;
p.Start();

string OldLine = "";
int IdIndex = -1;
int VersionIndex = -1;
int NewVersionIndex = -1;
int SourceIndex = -1;
bool DashesPassed = false;
string line;
string output = "";
while ((line = await p.StandardOutput.ReadLineAsync()) != null)
{
output += line + "\n";

if (line.Contains("have pins"))
continue;

if (!DashesPassed && line.Contains("---"))
{
string HeaderPrefix = OldLine.Contains("SearchId") ? "Search" : "";
string HeaderSuffix = OldLine.Contains("SearchId") ? "Header" : "";
IdIndex = OldLine.IndexOf(HeaderPrefix + "Id");
VersionIndex = OldLine.IndexOf(HeaderPrefix + "Version");
NewVersionIndex = OldLine.IndexOf("Available" + HeaderSuffix);
SourceIndex = OldLine.IndexOf(HeaderPrefix + "Source");
DashesPassed = true;
}
else if (line.Trim() == "")
{
DashesPassed = false;
}
else if (DashesPassed && IdIndex > 0 && VersionIndex > 0 && NewVersionIndex > 0 && IdIndex < VersionIndex && VersionIndex < NewVersionIndex && NewVersionIndex < line.Length)
{
int offset = 0; // Account for non-unicode character length
while (line[IdIndex - offset - 1] != ' ' || offset > (IdIndex - 5))
offset++;
string name = line[..(IdIndex - offset)].Trim();
string id = line[(IdIndex - offset)..].Trim().Split(' ')[0];
string version = line[(VersionIndex - offset)..(NewVersionIndex - offset)].Trim();
string newVersion;
if (SourceIndex != -1)
newVersion = line[(NewVersionIndex - offset)..(SourceIndex - offset)].Trim();
else
newVersion = line[(NewVersionIndex - offset)..].Trim().Split(' ')[0];

ManagerSource source;
if (SourceIndex == -1 || SourceIndex >= line.Length)
source = Manager.DefaultSource;
else
{
string sourceName = line[(SourceIndex - offset)..].Trim().Split(' ')[0];
source = Manager.SourceProvider.SourceFactory.GetSourceOrDefault(sourceName);
}

Packages.Add(new Package(name, id, version, newVersion, source, Manager));
}
OldLine = line;
}

output += await p.StandardError.ReadToEndAsync();
await Task.Run(p.WaitForExit);

return Packages.ToArray();
}

public static async Task<Package[]> GetInstalledPackages_UnSafe(WinGet Manager)
{
List<Package> Packages = new();
Process p = new();
ProcessStartInfo startInfo = new()
{
FileName = Manager.WinGetBundledPath,
Arguments = Manager.Properties.ExecutableCallArgs + " list --accept-source-agreements",
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true,
StandardOutputEncoding = System.Text.Encoding.UTF8
};
p.StartInfo = startInfo;
p.Start();

string OldLine = "";
int IdIndex = -1;
int VersionIndex = -1;
int SourceIndex = -1;
int NewVersionIndex = -1;
bool DashesPassed = false;
string line;
string output = "";
while ((line = await p.StandardOutput.ReadLineAsync()) != null)
{
try
{
output += line + "\n";
if (!DashesPassed && line.Contains("---"))
{
string HeaderPrefix = OldLine.Contains("SearchId") ? "Search" : "";
string HeaderSuffix = OldLine.Contains("SearchId") ? "Header" : "";
IdIndex = OldLine.IndexOf(HeaderPrefix + "Id");
VersionIndex = OldLine.IndexOf(HeaderPrefix + "Version");
NewVersionIndex = OldLine.IndexOf("Available" + HeaderSuffix);
SourceIndex = OldLine.IndexOf(HeaderPrefix + "Source");
DashesPassed = true;
}
else if (DashesPassed && IdIndex > 0 && VersionIndex > 0 && IdIndex < VersionIndex && VersionIndex < line.Length)
{
int offset = 0; // Account for non-unicode character length
while (((IdIndex - offset) <= line.Length && line[IdIndex - offset - 1] != ' ') || offset > (IdIndex - 5))
offset++;
string name = line[..(IdIndex - offset)].Trim();
string id = line[(IdIndex - offset)..].Trim().Split(' ')[0];
if (NewVersionIndex == -1 && SourceIndex != -1) NewVersionIndex = SourceIndex;
else if (NewVersionIndex == -1 && SourceIndex == -1) NewVersionIndex = line.Length - 1;
string version = line[(VersionIndex - offset)..(NewVersionIndex - offset)].Trim();

ManagerSource source;
if (SourceIndex == -1 || (SourceIndex - offset) >= line.Length)
{
source = GetLocalSource(Manager, id); // Load Winget Local Sources
}
else
{
string sourceName = line[(SourceIndex - offset)..].Trim().Split(' ')[0].Trim();
source = Manager.SourceProvider.SourceFactory.GetSourceOrDefault(sourceName);
}
Packages.Add(new Package(name, id, version, source, Manager));
}
OldLine = line;
}
catch (Exception e)
{
Logger.Error(e);
}
}

output += await p.StandardError.ReadToEndAsync();
await Task.Run(p.WaitForExit);

return Packages.ToArray();
}

private static ManagerSource GetLocalSource(WinGet Manager, string id)
{
try
{
// Check if source is android
bool AndroidValid = true;
foreach (char c in id)
if (!"abcdefghijklmnopqrstuvwxyz.…".Contains(c))
{
AndroidValid = false;
break;
}
if (AndroidValid && id.Count(x => x == '.') >= 2)
return Manager.AndroidSubsystemSource;

// Check if source is Steama
if ((id == "Steam" || id.Contains("Steam App ")) && id.Split("Steam App").Count() >= 2 && id.Split("Steam App")[1].Trim().Count(x => !"1234567890".Contains(x)) == 0)
return Manager.SteamSource;

// Check if source is Ubisoft Connect
if (id == "Uplay" || id.Contains("Uplay Install ") && id.Split("Uplay Install").Count() >= 2 && id.Split("Uplay Install")[1].Trim().Count(x => !"1234567890".Contains(x)) == 0)
return Manager.UbisoftConnectSource;

// Check if source is GOG
if (id.EndsWith("_is1") && id.Split("_is1")[0].Count(x => !"1234567890".Contains(x)) == 0)
return Manager.GOGSource;

// Check if source is Microsoft Store
if (id.Count(x => x == '_') == 1 && (id.Split('_')[^1].Length == 14 | id.Split('_')[^1].Length == 13 | id.Split('_')[^1].Length <= 13 && id[^1] == '…'))
return Manager.MicrosoftStoreSource;

return Manager.LocalPcSource;
}
catch (Exception ex)
{
Logger.Error(ex);
return Manager.LocalPcSource;
}
}
}
46 changes: 36 additions & 10 deletions src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Text;
using UniGetUI.Core.Data;
using UniGetUI.Core.Logging;
using UniGetUI.Core.SettingsEngine;
using UniGetUI.Core.Tools;
using UniGetUI.PackageEngine.Classes.Manager.Classes;
using UniGetUI.PackageEngine.Classes.Manager.ManagerHelpers;
Expand All @@ -18,23 +19,26 @@ public class WinGet : PackageManager
new public static string[] FALSE_PACKAGE_NAMES = new string[] { "", "e(s)", "have", "the", "Id" };
new public static string[] FALSE_PACKAGE_IDS = new string[] { "", "e(s)", "have", "an", "'winget", "pin'", "have", "an", "Version" };
new public static string[] FALSE_PACKAGE_VERSIONS = new string[] { "", "have", "an", "'winget", "pin'", "have", "an", "Version" };
private LocalWingetSource LocalPcSource { get; set; }
private LocalWingetSource AndroidSubsystemSource { get; set; }
private LocalWingetSource SteamSource { get; set; }
private LocalWingetSource UbisoftConnectSource { get; set; }
private LocalWingetSource GOGSource { get; set; }
private LocalWingetSource MicrosoftStoreSource { get; set; }
public LocalWingetSource LocalPcSource { get; set; }
public LocalWingetSource AndroidSubsystemSource { get; set; }
public LocalWingetSource SteamSource { get; set; }
public LocalWingetSource UbisoftConnectSource { get; set; }
public LocalWingetSource GOGSource { get; set; }
public LocalWingetSource MicrosoftStoreSource { get; set; }

public readonly string PowerShellPath;
public readonly string PowerShellPromptArgs;
public readonly string PowerShellInlineArgs;
public string WinGetBundledPath;

public WinGet() : base()
{
PowerShellPath = Path.Join(Environment.SystemDirectory, "windowspowershell\\v1.0\\powershell.exe");
PowerShellPromptArgs = "-ExecutionPolicy Bypass -NoLogo -NoProfile";
PowerShellInlineArgs = "-ExecutionPolicy Bypass -NoLogo -NoProfile -NonInteractive";

WinGetBundledPath = Path.Join(CoreData.UniGetUIExecutableDirectory, "winget-cli_x64", "winget.exe");

Dependencies = [
new ManagerDependency(
"WinGet PowerShell Module",
Expand Down Expand Up @@ -114,6 +118,9 @@ protected override async Task<Package[]> FindPackages_UnSafe(string query)

protected override async Task<Package[]> GetAvailableUpdates_UnSafe()
{
if (Settings.Get("ForceLegacyBundledWinGet"))
return await BundledWinGetLegacyMethods.GetAvailableUpdates_UnSafe(this);

List<Package> Packages = [];

Process p = new()
Expand Down Expand Up @@ -191,11 +198,22 @@ function Print-WinGetPackage {
await p.WaitForExitAsync();
logger.Close(p.ExitCode);

return Packages.ToArray();
if (Packages.Count() > 0)
{
return Packages.ToArray();
}
else
{
Logger.Warn("WinGet updates returned zero packages, attempting legacy...");
return await BundledWinGetLegacyMethods.GetAvailableUpdates_UnSafe(this);
}
}

protected override async Task<Package[]> GetInstalledPackages_UnSafe()
{
if (Settings.Get("ForceLegacyBundledWinGet"))
return await BundledWinGetLegacyMethods.GetInstalledPackages_UnSafe(this);

List<Package> Packages = [];
Process p = new()
{
Expand Down Expand Up @@ -277,8 +295,16 @@ function Print-WinGetPackage {
logger.AddToStdErr(await p.StandardError.ReadToEndAsync());
await p.WaitForExitAsync();
logger.Close(p.ExitCode);

return Packages.ToArray();

if (Packages.Count() > 0)
{
return Packages.ToArray();
}
else
{
Logger.Warn("WinGet installed packages returned zero packages, attempting legacy...");
return await BundledWinGetLegacyMethods.GetInstalledPackages_UnSafe(this);
}
}

private ManagerSource GetLocalSource(string id)
Expand Down Expand Up @@ -567,7 +593,7 @@ public override async Task RefreshPackageIndexes()
}
}

internal class LocalWingetSource : ManagerSource
public class LocalWingetSource : ManagerSource
{
private readonly string name;
private readonly string __icon_id;
Expand Down
Loading