Skip to content

Commit

Permalink
Merge pull request #2982 from marticliment/updater-improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
marticliment authored Nov 17, 2024
2 parents 40d06f0 + af06b27 commit bbb5c49
Show file tree
Hide file tree
Showing 19 changed files with 535 additions and 170 deletions.
4 changes: 2 additions & 2 deletions UniGetUI.iss
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

#define MyAppVersion "3.1.2"
#define MyAppVersion "3.1.4-beta1"
#define MyAppName "UniGetUI (formerly WingetUI)"
#define MyAppPublisher "Martí Climent"
#define MyAppURL "https://github.com/marticliment/UniGetUI"
Expand All @@ -23,7 +23,7 @@ AppPublisher={#MyAppPublisher}
AppPublisherURL="https://www.marticliment.com/unigetui/"
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
VersionInfoVersion=3.1.2.0
VersionInfoVersion=3.1.4.0
DefaultDirName="{autopf64}\UniGetUI"
DisableProgramGroupPage=yes
DisableDirPage=no
Expand Down
1 change: 1 addition & 0 deletions scripts/BuildNumber
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
70
22 changes: 17 additions & 5 deletions scripts/apply_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,26 @@
os.chdir(os.path.join(os.path.dirname(__file__), "..")) # move to root project

try:
floatval = input("Enter version code (X.XXX) : ")
# floatval = input("Enter version code (X.XXX) : ")
# versionCode = float(floatval)
versionName = str(input("Enter version name (string) : "))

if floatval == "":
if versionName == "":
print("Version changer script aborted")
exit()

BuildNumber = -1
c = ""
if os.path.exists("scripts/BuildNumber"):
with open("scripts/BuildNumber", "r") as f:
c = f.read()

BuildNumber = int(c) if c != "" else int(input("Build number file was empty. Insert (integer) build number: "))-1
print(f"Build number set to {BuildNumber+1}")
with open("scripts/BuildNumber", "w") as f:
f.write(str(BuildNumber+1))


versionCode = float(floatval)
versionName = str(input("Enter version name (string) : "))
versionISS = str(input("Enter version (X.X.X.X) : "))

def fileReplaceLinesWith(filename: str, list: dict[str, str], encoding="utf-8"):
Expand All @@ -32,7 +44,7 @@ def fileReplaceLinesWith(filename: str, list: dict[str, str], encoding="utf-8"):

fileReplaceLinesWith("src/UniGetUI.Core.Data/CoreData.cs", {
" public const string VersionName = ": f" \"{versionName}\"; // Do not modify this line, use file scripts/apply_versions.py\n",
" public const double VersionNumber = ": f" {versionCode}; // Do not modify this line, use file scripts/apply_versions.py\n",
" public const int BuildNumber = ": f" {BuildNumber+1}; // Do not modify this line, use file scripts/apply_versions.py\n",
}, encoding="utf-8-sig")

fileReplaceLinesWith("src/SharedAssemblyInfo.cs", {
Expand Down
2 changes: 2 additions & 0 deletions scripts/translation_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ def get_all_strings():
r'<[a-zA-Z0-9]+:ButtonCard' + MAIN_WILDCARD + r'+Text=["\'].+["\']' + MAIN_WILDCARD + r'*\/?>': lambda match: match.split(" Text=\"")[1].split("\"")[0].encode('raw_unicode_escape').decode('unicode_escape'),
r'<[a-zA-Z0-9]+:ButtonCard' + MAIN_WILDCARD + r'+ButtonText=["\'].+["\']' + MAIN_WILDCARD + r'*\/?>': lambda match: match.split(" ButtonText=\"")[1].split("\"")[0].encode('raw_unicode_escape').decode('unicode_escape'),
r'<[a-zA-Z0-9]+:CheckboxCard' + MAIN_WILDCARD + r'+Text=["\'].+["\']' + MAIN_WILDCARD + r'*\/?>': lambda match: match.split(" Text=\"")[1].split("\"")[0].encode('raw_unicode_escape').decode('unicode_escape'),
r'<[a-zA-Z0-9]+:CheckboxButtonCard' + MAIN_WILDCARD + r'+CheckboxText=["\'].+["\']' + MAIN_WILDCARD + r'*\/?>': lambda match: match.split(" Text=\"")[1].split("\"")[0].encode('raw_unicode_escape').decode('unicode_escape'),
r'<[a-zA-Z0-9]+:CheckboxButtonCard' + MAIN_WILDCARD + r'+ButtonText=["\'].+["\']' + MAIN_WILDCARD + r'*\/?>': lambda match: match.split(" Text=\"")[1].split("\"")[0].encode('raw_unicode_escape').decode('unicode_escape'),
r'<[a-zA-Z0-9]+:ComboboxCard' + MAIN_WILDCARD + r'+Text=["\'].+["\']' + MAIN_WILDCARD + r'*\/?>': lambda match: match.split(" Text=\"")[1].split("\"")[0].encode('raw_unicode_escape').decode('unicode_escape'),
r'<[a-zA-Z0-9]+:BetterMenuItem' + MAIN_WILDCARD + r'+Text=["\'].+["\']' + MAIN_WILDCARD + r'*\/?>': lambda match: match.split(" Text=\"")[1].split("\"")[0].encode('raw_unicode_escape').decode('unicode_escape'),
r'<[a-zA-Z0-9]+:NavButton' + MAIN_WILDCARD + r'+Text=["\'].+["\']' + MAIN_WILDCARD + r'*\/?>': lambda match: match.split(" Text=\"")[1].split("\"")[0].encode('raw_unicode_escape').decode('unicode_escape'),
Expand Down
6 changes: 3 additions & 3 deletions src/SharedAssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
[assembly: AssemblyTitle("UniGetUI")]
[assembly: AssemblyDefaultAlias("UniGetUI")]
[assembly: AssemblyCopyright("2024, Martí Climent")]
[assembly: AssemblyVersion("3.1.2.0")]
[assembly: AssemblyFileVersion("3.1.2.0")]
[assembly: AssemblyInformationalVersion("3.1.2")]
[assembly: AssemblyVersion("3.1.4.0")]
[assembly: AssemblyFileVersion("3.1.4.0")]
[assembly: AssemblyInformationalVersion("3.1.4-beta1")]
[assembly: SupportedOSPlatform("windows10.0.19041")]
5 changes: 1 addition & 4 deletions src/UniGetUI.Core.Data.Tests/CoreTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,9 @@ public void CheckDirectoryAttributes(string directory)
public void CheckOtherAttributes()
{
Assert.NotEmpty(CoreData.VersionName);
Assert.NotEqual(0, CoreData.VersionNumber);
Assert.NotEqual(0, CoreData.BuildNumber);
Assert.True(File.Exists(CoreData.IgnoredUpdatesDatabaseFile), "The Ignored Updates database file does not exist, but it should have been created automatically.");

int notif_3 = CoreData.UpdatesAvailableNotificationTag;
int notif_4 = CoreData.UpdatesAvailableNotificationTag;
Assert.True(notif_3 == notif_4, "The UpdatesAvailableNotificationId must be always the same");
Assert.NotEqual(0, CoreData.UpdatesAvailableNotificationTag);

Assert.True(Directory.Exists(CoreData.UniGetUIExecutableDirectory), "Directory where the executable is located does not exist");
Expand Down
3 changes: 2 additions & 1 deletion src/UniGetUI.Core.Data/CoreData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ private static int GetCodePage()
}

public const string VersionName = "3.1.4-beta1"; // Do not modify this line, use file scripts/apply_versions.py
public const double VersionNumber = 3.14; // Do not modify this line, use file scripts/apply_versions.py
public const int BuildNumber = 70; // Do not modify this line, use file scripts/apply_versions.py

public const string UserAgentString = $"UniGetUI/{VersionName} (https://marticliment.com/unigetui/; [email protected])";

Expand Down Expand Up @@ -169,6 +169,7 @@ public static string IgnoredUpdatesDatabaseFile
/// The ID of the notification that is used to inform the user that updates are available
/// </summary>
public const int UpdatesAvailableNotificationTag = 1234;
public const int UniGetUICanBeUpdated = 1235;


/// <summary>
Expand Down
40 changes: 40 additions & 0 deletions src/UniGetUI.Core.Tools/Tools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
using System.Diagnostics;
using System.Globalization;
using System.Net;
using System.Net.NetworkInformation;
using System.Security.Cryptography;
using System.Security.Principal;
using System.Text;
using UniGetUI.Core.Classes;
using UniGetUI.Core.Data;
using UniGetUI.Core.Language;
using UniGetUI.Core.Logging;
Expand Down Expand Up @@ -542,5 +544,43 @@ public static ProcessStartInfo UpdateEnvironmentVariables(ProcessStartInfo info)
}
return info;
}


/// <summary>
/// Pings the update server and 3 well-known sites to check for internet availability
/// </summary>
public static async Task WaitForInternetConnection()
=> await (await TaskRecycler<Task>.RunOrAttachAsync(_waitForInternetConnection));

public static async Task _waitForInternetConnection()
{
Logger.Debug("Checking for internet connectivity. Pinging google.com, microsoft.com, couldflare.com and marticliment.com");
string[] hosts = ["google.com", "microsoft.com", "cloudflare.com", "marticliment.com"];
while (true)
{
foreach (var host in hosts)
{
using (var pinger = new Ping())
{
try
{
PingReply reply = await pinger.SendPingAsync(host, 10);
if (reply.Status is IPStatus.Success)
{
Logger.Debug($"{host} responded successfully to ping, internet connection was validated.");
return;
}

Logger.Debug($"Could not ping {host}!");
}
catch (Exception ex)
{
Logger.Debug($"Could not ping {host} with error {ex.Message}. Are you connected to the internet?");
}
}
}
await Task.Delay(TimeSpan.FromSeconds(5));
}
}
}
}
2 changes: 1 addition & 1 deletion src/UniGetUI.Interface.BackgroundApi/BackgroundApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ public void BuildV1WidgetsApi()
return 401;
}
return CoreData.VersionNumber.ToString();
return CoreData.BuildNumber.ToString();
});

// Return found updates
Expand Down
1 change: 1 addition & 0 deletions src/UniGetUI.Interface.Enums/Enums.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,5 +91,6 @@ public class NotificationArguments
public const string Show = "openUniGetUI";
public const string ShowOnUpdatesTab = "openUniGetUIOnUpdatesTab";
public const string UpdateAllPackages = "updateAll";
public const string ReleaseSelfUpdateLock = "releaseSelfUpdateLock";
}
}
147 changes: 0 additions & 147 deletions src/UniGetUI/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -228,12 +228,6 @@ private async Task LoadComponentsAsync()
{
try
{
// Run other initializations asynchronously
if (!Settings.Get("DisableAutoUpdateWingetUI"))
{
UpdateUniGetUIIfPossible();
}

IconDatabase.InitializeInstance();
IconDatabase.Instance.LoadIconAndScreenshotsDatabase();

Expand Down Expand Up @@ -404,147 +398,6 @@ public async void DisposeAndQuit(int outputCode = 0)
Environment.Exit(outputCode);
}

private async void UpdateUniGetUIIfPossible(int round = 0)
{
InfoBar? banner = null;
try
{
Logger.Debug("Starting update check");

string fileContents;

using (HttpClient client = new(CoreData.GenericHttpClientParameters))
{
client.Timeout = TimeSpan.FromSeconds(600);
client.DefaultRequestHeaders.UserAgent.ParseAdd(CoreData.UserAgentString);
fileContents = await client.GetStringAsync("https://www.marticliment.com/versions/unigetui.ver");
}

if (!fileContents.Contains("///"))
{
throw new FormatException("The updates file does not follow the FloatVersion///Sha256Hash format");
}

float LatestVersion = float.Parse(fileContents.Split("///")[0].Replace("\n", "").Trim(), CultureInfo.InvariantCulture);
string InstallerHash = fileContents.Split("///")[1].Replace("\n", "").Trim().ToLower();

if (LatestVersion > CoreData.VersionNumber)
{
Logger.Info("Updates found, downloading installer...");
Logger.Info("Current version: " + CoreData.VersionNumber.ToString(CultureInfo.InvariantCulture));
Logger.Info("Latest version : " + LatestVersion.ToString(CultureInfo.InvariantCulture));

banner = MainWindow.UpdatesBanner;
banner.Title = CoreTools.Translate("WingetUI version {0} is being downloaded.", LatestVersion.ToString(CultureInfo.InvariantCulture));
banner.Message = CoreTools.Translate("This may take a minute or two");
banner.Severity = InfoBarSeverity.Informational;
banner.IsOpen = true;
banner.IsClosable = false;

Uri DownloadUrl = new("https://github.com/marticliment/WingetUI/releases/latest/download/UniGetUI.Installer.exe");
string InstallerPath = Path.Join(Directory.CreateTempSubdirectory().FullName, "unigetui-updater.exe");

using (HttpClient client = new(CoreData.GenericHttpClientParameters))
{
client.DefaultRequestHeaders.UserAgent.ParseAdd(CoreData.UserAgentString);
HttpResponseMessage result = await client.GetAsync(DownloadUrl);
using FileStream fs = new(InstallerPath, FileMode.CreateNew);
await result.Content.CopyToAsync(fs);
}

string Hash = "";
SHA256 Sha256 = SHA256.Create();
using (FileStream stream = File.OpenRead(InstallerPath))
{
Hash = Convert.ToHexString(Sha256.ComputeHash(stream)).ToLower();
}

if (Hash == InstallerHash)
{

banner.Title = CoreTools.Translate("WingetUI {0} is ready to be installed.", LatestVersion.ToString(CultureInfo.InvariantCulture));
banner.Message = CoreTools.Translate("The update will be installed upon closing WingetUI");
banner.ActionButton = new Button
{
Content = CoreTools.Translate("Update now")
};
banner.ActionButton.Click += (_, _) => { MainWindow.HideWindow(); };
banner.Severity = InfoBarSeverity.Success;
banner.IsOpen = true;
banner.IsClosable = true;

if (MainWindow.Visible)
{
Logger.Debug("Waiting for mainWindow to be hidden");
}

while (MainWindow.Visible)
{
await Task.Delay(100);
}

if (Settings.Get("DisableAutoUpdateWingetUI"))
{
Logger.Warn("User disabled updates!");
return;
}

Logger.ImportantInfo("The hash matches the expected value, starting update process...");
Process p = new();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = $"/c start /B \"\" \"{InstallerPath}\" /silent";
p.StartInfo.UseShellExecute = true;
p.StartInfo.CreateNoWindow = true;
p.Start();
DisposeAndQuit();
}
else
{
Logger.Error("Hash mismatch, not updating!");
Logger.Error("Current hash : " + Hash);
Logger.Error("Expected hash: " + InstallerHash);
File.Delete(InstallerPath);

banner.Title = CoreTools.Translate("The installer hash does not match the expected value.");
banner.Message = CoreTools.Translate("The update will not continue.");
banner.Severity = InfoBarSeverity.Error;
banner.IsOpen = true;
banner.IsClosable = true;

await Task.Delay(3600000); // Check again in 1 hour
UpdateUniGetUIIfPossible();
}
}
else
{
Logger.Info("UniGetUI is up to date");
await Task.Delay(3600000); // Check again in 1 hour
UpdateUniGetUIIfPossible();
}
}
catch (Exception e)
{
if (banner is not null)
{
banner.Title = CoreTools.Translate("An error occurred when checking for updates: ");
banner.Message = e.Message;
banner.Severity = InfoBarSeverity.Error;
banner.IsOpen = true;
banner.IsClosable = true;
}

Logger.Error(e);

if (round >= 3)
{
return;
}

await Task.Delay(600000); // Try again in 10 minutes
UpdateUniGetUIIfPossible(round + 1);
}
}

public void KillAndRestart()
{
Process.Start(CoreData.UniGetUIExecutableFile);
Expand Down
Loading

0 comments on commit bbb5c49

Please sign in to comment.