aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Ava/Modules/Updater/Updater.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ryujinx.Ava/Modules/Updater/Updater.cs')
-rw-r--r--src/Ryujinx.Ava/Modules/Updater/Updater.cs194
1 files changed, 93 insertions, 101 deletions
diff --git a/src/Ryujinx.Ava/Modules/Updater/Updater.cs b/src/Ryujinx.Ava/Modules/Updater/Updater.cs
index 71d978c6..8216333a 100644
--- a/src/Ryujinx.Ava/Modules/Updater/Updater.cs
+++ b/src/Ryujinx.Ava/Modules/Updater/Updater.cs
@@ -31,22 +31,22 @@ namespace Ryujinx.Modules
{
internal static class Updater
{
- private const string GitHubApiURL = "https://api.github.com";
- private static readonly GithubReleasesJsonSerializerContext SerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
+ private const string GitHubApiUrl = "https://api.github.com";
+ private static readonly GithubReleasesJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
- private static readonly string HomeDir = AppDomain.CurrentDomain.BaseDirectory;
- private static readonly string UpdateDir = Path.Combine(Path.GetTempPath(), "Ryujinx", "update");
- private static readonly string UpdatePublishDir = Path.Combine(UpdateDir, "publish");
- private static readonly int ConnectionCount = 4;
+ private static readonly string _homeDir = AppDomain.CurrentDomain.BaseDirectory;
+ private static readonly string _updateDir = Path.Combine(Path.GetTempPath(), "Ryujinx", "update");
+ private static readonly string _updatePublishDir = Path.Combine(_updateDir, "publish");
+ private static readonly int _connectionCount = 4;
private static string _buildVer;
private static string _platformExt;
private static string _buildUrl;
- private static long _buildSize;
- private static bool _updateSuccessful;
- private static bool _running;
+ private static long _buildSize;
+ private static bool _updateSuccessful;
+ private static bool _running;
- private static readonly string[] WindowsDependencyDirs = Array.Empty<string>();
+ private static readonly string[] _windowsDependencyDirs = Array.Empty<string>();
public static async Task BeginParse(Window mainWindow, bool showVersionUpToDate)
{
@@ -99,9 +99,9 @@ namespace Ryujinx.Modules
{
using HttpClient jsonClient = ConstructHttpClient();
- string buildInfoURL = $"{GitHubApiURL}/repos/{ReleaseInformation.ReleaseChannelOwner}/{ReleaseInformation.ReleaseChannelRepo}/releases/latest";
- string fetchedJson = await jsonClient.GetStringAsync(buildInfoURL);
- var fetched = JsonHelper.Deserialize(fetchedJson, SerializerContext.GithubReleasesJsonResponse);
+ string buildInfoUrl = $"{GitHubApiUrl}/repos/{ReleaseInformation.ReleaseChannelOwner}/{ReleaseInformation.ReleaseChannelRepo}/releases/latest";
+ string fetchedJson = await jsonClient.GetStringAsync(buildInfoUrl);
+ var fetched = JsonHelper.Deserialize(fetchedJson, _serializerContext.GithubReleasesJsonResponse);
_buildVer = fetched.Name;
foreach (var asset in fetched.Assets)
@@ -195,23 +195,21 @@ namespace Ryujinx.Modules
}
// Fetch build size information to learn chunk sizes.
- using (HttpClient buildSizeClient = ConstructHttpClient())
+ using HttpClient buildSizeClient = ConstructHttpClient();
+ try
{
- try
- {
- buildSizeClient.DefaultRequestHeaders.Add("Range", "bytes=0-0");
+ buildSizeClient.DefaultRequestHeaders.Add("Range", "bytes=0-0");
- HttpResponseMessage message = await buildSizeClient.GetAsync(new Uri(_buildUrl), HttpCompletionOption.ResponseHeadersRead);
+ HttpResponseMessage message = await buildSizeClient.GetAsync(new Uri(_buildUrl), HttpCompletionOption.ResponseHeadersRead);
- _buildSize = message.Content.Headers.ContentRange.Length.Value;
- }
- catch (Exception ex)
- {
- Logger.Warning?.Print(LogClass.Application, ex.Message);
- Logger.Warning?.Print(LogClass.Application, "Couldn't determine build size for update, using single-threaded updater");
+ _buildSize = message.Content.Headers.ContentRange.Length.Value;
+ }
+ catch (Exception ex)
+ {
+ Logger.Warning?.Print(LogClass.Application, ex.Message);
+ Logger.Warning?.Print(LogClass.Application, "Couldn't determine build size for update, using single-threaded updater");
- _buildSize = -1;
- }
+ _buildSize = -1;
}
Dispatcher.UIThread.Post(async () =>
@@ -248,23 +246,22 @@ namespace Ryujinx.Modules
_updateSuccessful = false;
// Empty update dir, although it shouldn't ever have anything inside it
- if (Directory.Exists(UpdateDir))
+ if (Directory.Exists(_updateDir))
{
- Directory.Delete(UpdateDir, true);
+ Directory.Delete(_updateDir, true);
}
- Directory.CreateDirectory(UpdateDir);
+ Directory.CreateDirectory(_updateDir);
- string updateFile = Path.Combine(UpdateDir, "update.bin");
+ string updateFile = Path.Combine(_updateDir, "update.bin");
TaskDialog taskDialog = new()
{
- Header = LocaleManager.Instance[LocaleKeys.RyujinxUpdater],
- SubHeader = LocaleManager.Instance[LocaleKeys.UpdaterDownloading],
- IconSource = new SymbolIconSource { Symbol = Symbol.Download },
- Buttons = { },
+ Header = LocaleManager.Instance[LocaleKeys.RyujinxUpdater],
+ SubHeader = LocaleManager.Instance[LocaleKeys.UpdaterDownloading],
+ IconSource = new SymbolIconSource { Symbol = Symbol.Download },
ShowProgressBar = true,
- XamlRoot = parent
+ XamlRoot = parent,
};
taskDialog.Opened += (s, e) =>
@@ -301,7 +298,7 @@ namespace Ryujinx.Modules
if (OperatingSystem.IsMacOS())
{
string baseBundlePath = Path.GetFullPath(Path.Combine(executableDirectory, "..", ".."));
- string newBundlePath = Path.Combine(UpdateDir, "Ryujinx.app");
+ string newBundlePath = Path.Combine(_updateDir, "Ryujinx.app");
string updaterScriptPath = Path.Combine(newBundlePath, "Contents", "Resources", "updater.sh");
string currentPid = Environment.ProcessId.ToString();
@@ -328,7 +325,7 @@ namespace Ryujinx.Modules
ProcessStartInfo processStart = new(ryuName)
{
UseShellExecute = true,
- WorkingDirectory = executableDirectory
+ WorkingDirectory = executableDirectory,
};
foreach (string argument in CommandLineState.Arguments)
@@ -347,22 +344,22 @@ namespace Ryujinx.Modules
private static void DoUpdateWithMultipleThreads(TaskDialog taskDialog, string downloadUrl, string updateFile)
{
// Multi-Threaded Updater
- long chunkSize = _buildSize / ConnectionCount;
- long remainderChunk = _buildSize % ConnectionCount;
+ long chunkSize = _buildSize / _connectionCount;
+ long remainderChunk = _buildSize % _connectionCount;
- int completedRequests = 0;
- int totalProgressPercentage = 0;
- int[] progressPercentage = new int[ConnectionCount];
+ int completedRequests = 0;
+ int totalProgressPercentage = 0;
+ int[] progressPercentage = new int[_connectionCount];
- List<byte[]> list = new(ConnectionCount);
- List<WebClient> webClients = new(ConnectionCount);
+ List<byte[]> list = new(_connectionCount);
+ List<WebClient> webClients = new(_connectionCount);
- for (int i = 0; i < ConnectionCount; i++)
+ for (int i = 0; i < _connectionCount; i++)
{
list.Add(Array.Empty<byte>());
}
- for (int i = 0; i < ConnectionCount; i++)
+ for (int i = 0; i < _connectionCount; i++)
{
#pragma warning disable SYSLIB0014
// TODO: WebClient is obsolete and need to be replaced with a more complex logic using HttpClient.
@@ -371,7 +368,7 @@ namespace Ryujinx.Modules
webClients.Add(client);
- if (i == ConnectionCount - 1)
+ if (i == _connectionCount - 1)
{
client.Headers.Add("Range", $"bytes={chunkSize * i}-{(chunkSize * (i + 1) - 1) + remainderChunk}");
}
@@ -388,7 +385,7 @@ namespace Ryujinx.Modules
Interlocked.Exchange(ref progressPercentage[index], args.ProgressPercentage);
Interlocked.Add(ref totalProgressPercentage, args.ProgressPercentage);
- taskDialog.SetProgressBarState(totalProgressPercentage / ConnectionCount, TaskDialogProgressState.Normal);
+ taskDialog.SetProgressBarState(totalProgressPercentage / _connectionCount, TaskDialogProgressState.Normal);
};
client.DownloadDataCompleted += (_, args) =>
@@ -407,10 +404,10 @@ namespace Ryujinx.Modules
list[index] = args.Result;
Interlocked.Increment(ref completedRequests);
- if (Equals(completedRequests, ConnectionCount))
+ if (Equals(completedRequests, _connectionCount))
{
byte[] mergedFileBytes = new byte[_buildSize];
- for (int connectionIndex = 0, destinationOffset = 0; connectionIndex < ConnectionCount; connectionIndex++)
+ for (int connectionIndex = 0, destinationOffset = 0; connectionIndex < _connectionCount; connectionIndex++)
{
Array.Copy(list[connectionIndex], 0, mergedFileBytes, destinationOffset, list[connectionIndex].Length);
destinationOffset += list[connectionIndex].Length;
@@ -421,10 +418,9 @@ namespace Ryujinx.Modules
// On macOS, ensure that we remove the quarantine bit to prevent Gatekeeper from blocking execution.
if (OperatingSystem.IsMacOS())
{
- using (Process xattrProcess = Process.Start("xattr", new List<string> { "-d", "com.apple.quarantine", updateFile }))
- {
- xattrProcess.WaitForExit();
- }
+ using Process xattrProcess = Process.Start("xattr", new List<string> { "-d", "com.apple.quarantine", updateFile });
+
+ xattrProcess.WaitForExit();
}
try
@@ -437,8 +433,6 @@ namespace Ryujinx.Modules
Logger.Warning?.Print(LogClass.Application, "Multi-Threaded update failed, falling back to single-threaded updater.");
DoUpdateWithSingleThread(taskDialog, downloadUrl, updateFile);
-
- return;
}
}
};
@@ -470,31 +464,29 @@ namespace Ryujinx.Modules
// We do not want to timeout while downloading
client.Timeout = TimeSpan.FromDays(1);
- using (HttpResponseMessage response = client.GetAsync(downloadUrl, HttpCompletionOption.ResponseHeadersRead).Result)
- using (Stream remoteFileStream = response.Content.ReadAsStreamAsync().Result)
- {
- using Stream updateFileStream = File.Open(updateFile, FileMode.Create);
+ using HttpResponseMessage response = client.GetAsync(downloadUrl, HttpCompletionOption.ResponseHeadersRead).Result;
+ using Stream remoteFileStream = response.Content.ReadAsStreamAsync().Result;
+ using Stream updateFileStream = File.Open(updateFile, FileMode.Create);
- long totalBytes = response.Content.Headers.ContentLength.Value;
- long byteWritten = 0;
+ long totalBytes = response.Content.Headers.ContentLength.Value;
+ long byteWritten = 0;
- byte[] buffer = new byte[32 * 1024];
+ byte[] buffer = new byte[32 * 1024];
- while (true)
- {
- int readSize = remoteFileStream.Read(buffer);
+ while (true)
+ {
+ int readSize = remoteFileStream.Read(buffer);
- if (readSize == 0)
- {
- break;
- }
+ if (readSize == 0)
+ {
+ break;
+ }
- byteWritten += readSize;
+ byteWritten += readSize;
- taskDialog.SetProgressBarState(GetPercentage(byteWritten, totalBytes), TaskDialogProgressState.Normal);
+ taskDialog.SetProgressBarState(GetPercentage(byteWritten, totalBytes), TaskDialogProgressState.Normal);
- updateFileStream.Write(buffer, 0, readSize);
- }
+ updateFileStream.Write(buffer, 0, readSize);
}
InstallUpdate(taskDialog, updateFile);
@@ -510,7 +502,7 @@ namespace Ryujinx.Modules
{
Thread worker = new(() => DoUpdateWithSingleThreadWorker(taskDialog, downloadUrl, updateFile))
{
- Name = "Updater.SingleThreadWorker"
+ Name = "Updater.SingleThreadWorker",
};
worker.Start();
@@ -520,9 +512,9 @@ namespace Ryujinx.Modules
[SupportedOSPlatform("macos")]
private static void ExtractTarGzipFile(TaskDialog taskDialog, string archivePath, string outputDirectoryPath)
{
- using Stream inStream = File.OpenRead(archivePath);
+ using Stream inStream = File.OpenRead(archivePath);
using GZipInputStream gzipStream = new(inStream);
- using TarInputStream tarStream = new(gzipStream, Encoding.ASCII);
+ using TarInputStream tarStream = new(gzipStream, Encoding.ASCII);
TarEntry tarEntry;
@@ -537,10 +529,8 @@ namespace Ryujinx.Modules
Directory.CreateDirectory(Path.GetDirectoryName(outPath));
- using (FileStream outStream = File.OpenWrite(outPath))
- {
- tarStream.CopyEntryContents(outStream);
- }
+ using FileStream outStream = File.OpenWrite(outPath);
+ tarStream.CopyEntryContents(outStream);
File.SetUnixFileMode(outPath, (UnixFileMode)tarEntry.TarHeader.Mode);
File.SetLastWriteTime(outPath, DateTime.SpecifyKind(tarEntry.ModTime, DateTimeKind.Utc));
@@ -559,24 +549,26 @@ namespace Ryujinx.Modules
private static void ExtractZipFile(TaskDialog taskDialog, string archivePath, string outputDirectoryPath)
{
- using Stream inStream = File.OpenRead(archivePath);
- using ZipFile zipFile = new(inStream);
+ using Stream inStream = File.OpenRead(archivePath);
+ using ZipFile zipFile = new(inStream);
double count = 0;
foreach (ZipEntry zipEntry in zipFile)
{
count++;
- if (zipEntry.IsDirectory) continue;
+ if (zipEntry.IsDirectory)
+ {
+ continue;
+ }
string outPath = Path.Combine(outputDirectoryPath, zipEntry.Name);
Directory.CreateDirectory(Path.GetDirectoryName(outPath));
- using (Stream zipStream = zipFile.GetInputStream(zipEntry))
- using (FileStream outStream = File.OpenWrite(outPath))
- {
- zipStream.CopyTo(outStream);
- }
+ using Stream zipStream = zipFile.GetInputStream(zipEntry);
+ using FileStream outStream = File.OpenWrite(outPath);
+
+ zipStream.CopyTo(outStream);
File.SetLastWriteTime(outPath, DateTime.SpecifyKind(zipEntry.DateTime, DateTimeKind.Utc));
@@ -597,11 +589,11 @@ namespace Ryujinx.Modules
{
if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
{
- ExtractTarGzipFile(taskDialog, updateFile, UpdateDir);
+ ExtractTarGzipFile(taskDialog, updateFile, _updateDir);
}
else if (OperatingSystem.IsWindows())
{
- ExtractZipFile(taskDialog, updateFile, UpdateDir);
+ ExtractZipFile(taskDialog, updateFile, _updateDir);
}
else
{
@@ -648,10 +640,10 @@ namespace Ryujinx.Modules
taskDialog.SetProgressBarState(0, TaskDialogProgressState.Normal);
});
- MoveAllFilesOver(UpdatePublishDir, HomeDir, taskDialog);
+ MoveAllFilesOver(_updatePublishDir, _homeDir, taskDialog);
});
- Directory.Delete(UpdateDir, true);
+ Directory.Delete(_updateDir, true);
}
_updateSuccessful = true;
@@ -738,15 +730,15 @@ namespace Ryujinx.Modules
// NOTE: This method should always reflect the latest build layout.
private static IEnumerable<string> EnumerateFilesToDelete()
{
- var files = Directory.EnumerateFiles(HomeDir); // All files directly in base dir.
+ var files = Directory.EnumerateFiles(_homeDir); // All files directly in base dir.
// Determine and exclude user files only when the updater is running, not when cleaning old files
if (_running && !OperatingSystem.IsMacOS())
{
// Compare the loose files in base directory against the loose files from the incoming update, and store foreign ones in a user list.
- var oldFiles = Directory.EnumerateFiles(HomeDir, "*", SearchOption.TopDirectoryOnly).Select(Path.GetFileName);
- var newFiles = Directory.EnumerateFiles(UpdatePublishDir, "*", SearchOption.TopDirectoryOnly).Select(Path.GetFileName);
- var userFiles = oldFiles.Except(newFiles).Select(filename => Path.Combine(HomeDir, filename));
+ var oldFiles = Directory.EnumerateFiles(_homeDir, "*", SearchOption.TopDirectoryOnly).Select(Path.GetFileName);
+ var newFiles = Directory.EnumerateFiles(_updatePublishDir, "*", SearchOption.TopDirectoryOnly).Select(Path.GetFileName);
+ var userFiles = oldFiles.Except(newFiles).Select(filename => Path.Combine(_homeDir, filename));
// Remove user files from the paths in files.
files = files.Except(userFiles);
@@ -754,9 +746,9 @@ namespace Ryujinx.Modules
if (OperatingSystem.IsWindows())
{
- foreach (string dir in WindowsDependencyDirs)
+ foreach (string dir in _windowsDependencyDirs)
{
- string dirPath = Path.Combine(HomeDir, dir);
+ string dirPath = Path.Combine(_homeDir, dir);
if (Directory.Exists(dirPath))
{
files = files.Concat(Directory.EnumerateFiles(dirPath, "*", SearchOption.AllDirectories));
@@ -798,10 +790,10 @@ namespace Ryujinx.Modules
public static void CleanupUpdate()
{
- foreach (string file in Directory.GetFiles(HomeDir, "*.ryuold", SearchOption.AllDirectories))
+ foreach (string file in Directory.GetFiles(_homeDir, "*.ryuold", SearchOption.AllDirectories))
{
File.Delete(file);
}
}
}
-} \ No newline at end of file
+}