From b27ccfab1743656744f23dda74aed47c5fb1340a Mon Sep 17 00:00:00 2001 From: ChsBuffer <33744752+chsbuffer@users.noreply.github.com> Date: Sat, 13 Mar 2021 00:15:22 +0800 Subject: [PATCH] Add more comments to Updater Updater Keeps disabled file LazyLoad Global.Mutex Fix AfterUpdate Release Global.Mutex --- Netch/Controllers/UpdateChecker.cs | 36 +++---- Netch/Global.cs | 4 +- Netch/Updater/Updater.cs | 161 +++++++++++++++++++---------- 3 files changed, 124 insertions(+), 77 deletions(-) diff --git a/Netch/Controllers/UpdateChecker.cs b/Netch/Controllers/UpdateChecker.cs index 472ee8f7..d8056e4e 100644 --- a/Netch/Controllers/UpdateChecker.cs +++ b/Netch/Controllers/UpdateChecker.cs @@ -69,31 +69,25 @@ namespace Netch.Controllers } } - public static bool GetFileNameAndHashFromMarkdownForm(in string text, out string fileName, out string sha256, string? keyword = null) + public static void GetLatestUpdateFileNameAndHash(out string fileName, out string sha256, string? keyword = null) { - IEnumerable matches; - try - { - matches = Regex.Matches(text, @"^\| (?.*) \| (?.*) \|\r?$", RegexOptions.Multiline).Cast().Skip(2); - } - catch (Exception e) - { - Logging.Error(e.ToString()); - throw new Exception(i18N.Translate("Find update filename and hash failed")); - } + fileName = string.Empty; + sha256 = string.Empty; + + var matches = Regex.Matches(LatestRelease.body, @"^\| (?.*) \| (?.*) \|\r?$", RegexOptions.Multiline) + .Cast() + .Skip(2); + /* + Skip(2) + + | 文件名 | SHA256 | + | :- | :- | + */ Match match = keyword == null ? matches.First() : matches.First(m => m.Groups["filename"].Value.Contains(keyword)); - if (match != null) - { - fileName = match.Groups["filename"].Value; - sha256 = match.Groups["sha256"].Value; - return true; - } - - fileName = string.Empty; - sha256 = string.Empty; - return false; + fileName = match.Groups["filename"].Value; + sha256 = match.Groups["sha256"].Value; } } } \ No newline at end of file diff --git a/Netch/Global.cs b/Netch/Global.cs index c4cc8fa6..0ddb2523 100644 --- a/Netch/Global.cs +++ b/Netch/Global.cs @@ -30,7 +30,9 @@ namespace Netch /// private static readonly Lazy LazyMainForm = new(() => new MainForm()); - public static readonly Mutex Mutex = new(false, "Global\\Netch"); + private static readonly Lazy LazyMutex = new(() => new Mutex(false, "Global\\Netch")); + + public static Mutex Mutex => LazyMutex.Value; #if DEBUG public static bool Testing = false; diff --git a/Netch/Updater/Updater.cs b/Netch/Updater/Updater.cs index 76ea574e..4e239ee0 100644 --- a/Netch/Updater/Updater.cs +++ b/Netch/Updater/Updater.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Diagnostics; using System.IO; using System.Linq; @@ -13,45 +14,130 @@ namespace Netch.Updater { public class Updater { - private static IEnumerable _keepDirectory = new List(new[] {"data", "mode\\Custom"}); - private readonly string _targetPath; - private readonly string _tempFolder; - private readonly string _updateFilePath; + #region Download Update and apply update - private Updater(string updateFilePath, string targetPath) + /// + /// Download Update and apply update + /// + /// + /// + /// + /// + /// + public static void DownloadAndUpdate(string downloadFolder, + string installFolder, + DownloadProgressChangedEventHandler onDownloadProgressChanged, + string? keyword = null) { - _targetPath = targetPath; + UpdateChecker.GetLatestUpdateFileNameAndHash(out var updateFileName, out var sha256, keyword); + + var updateFileFullName = Path.Combine(downloadFolder, updateFileName); + var updater = new Updater(updateFileFullName, installFolder); + + if (File.Exists(updateFileFullName)) + { + if (Utils.Utils.SHA256CheckSum(updateFileFullName) == sha256) + { + updater.ApplyUpdate(); + return; + } + + File.Delete(updateFileFullName); + } + + DownloadUpdate(onDownloadProgressChanged, updateFileFullName, sha256); + updater.ApplyUpdate(); + } + + #endregion + + private readonly string _installFolder; + private readonly string _tempFolder; + private readonly string _updateFile; + + private Updater(string updateFile, string installFolder) + { + _installFolder = installFolder; _tempFolder = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); Directory.CreateDirectory(_tempFolder); - _updateFilePath = Path.GetFullPath(updateFilePath); - _keepDirectory = _keepDirectory.Select(s => Path.Combine(targetPath, s)); + _updateFile = Path.GetFullPath(updateFile); } + #region Download Update + + /// + /// Download Update File + /// + /// + /// + /// + /// + private static void DownloadUpdate(DownloadProgressChangedEventHandler onDownloadProgressChanged, string fileFullPath, string sha256) + { + using WebClient client = new(); + try + { + client.DownloadProgressChanged += onDownloadProgressChanged; + client.DownloadFile(new Uri(UpdateChecker.LatestRelease.assets[0].browser_download_url), fileFullPath); + } + finally + { + client.DownloadProgressChanged -= onDownloadProgressChanged; + } + + if (Utils.Utils.SHA256CheckSum(fileFullPath) != sha256) + throw new MessageException(i18N.Translate("The downloaded file has the wrong hash")); + } + + #endregion + + #region Apply Update + + private static readonly ImmutableArray KeepFolders = new List {"data", "mode\\Custom"}.ToImmutableArray(); + private void ApplyUpdate() { + // extract Update file to {tempFolder}\extract var extractPath = Path.Combine(_tempFolder, "extract"); int exitCode; if ((exitCode = Extract(extractPath, true)) != 0) throw new Exception(i18N.Translate($"7za exit with code {exitCode}")); + // rename install directory files with .old suffix unless in keep folders MarkFilesOld(); - MoveAllFilesOver(Path.Combine(extractPath, "Netch"), _targetPath); + // move {tempFolder}\extract\Netch to install folder + MoveAllFilesOver(Path.Combine(extractPath, "Netch"), _installFolder); + // save, release mutex, then exit Configuration.Save(); - Global.Mutex.ReleaseMutex(); + Global.MainForm.Invoke(new Action(() => { Global.Mutex.ReleaseMutex(); })); Process.Start(Global.NetchExecutable); Global.MainForm.Exit(true, false); } private void MarkFilesOld() { - foreach (var file in Directory.GetFiles(_targetPath, "*", SearchOption.AllDirectories)) + // extend keepFolders relative path to fullpath + var extendedKeepFolders = KeepFolders.Select(d => Path.Combine(_installFolder, d)).ToImmutableArray(); + + // weed out keep files + List removedFiles = new(); + foreach (var file in Directory.GetFiles(_installFolder, "*", SearchOption.AllDirectories)) { - if (_keepDirectory.Any(p => file.StartsWith(p))) + if (extendedKeepFolders.Any(p => file.StartsWith(p))) continue; + if (Path.GetFileName(file) is "disabled") + continue; + + removedFiles.Add(file); + } + + // rename files + foreach (var file in removedFiles) + { try { File.Move(file, file + ".old"); @@ -65,13 +151,15 @@ namespace Netch.Updater private int Extract(string destDirName, bool overwrite) { + // release 7za.exe to {tempFolder}\7za.exe var temp7za = Path.Combine(_tempFolder, "7za.exe"); if (!File.Exists(temp7za)) File.WriteAllBytes(temp7za, Resources._7za); + // run 7za var argument = new StringBuilder(); - argument.Append($" x \"{_updateFilePath}\" -o\"{destDirName}\""); + argument.Append($" x \"{_updateFile}\" -o\"{destDirName}\""); if (overwrite) argument.Append(" -y"); @@ -107,6 +195,10 @@ namespace Netch.Updater } } + #endregion + + #region Clean files marked as old when start + public static void CleanOld(string targetPath) { foreach (var f in Directory.GetFiles(targetPath, "*.old", SearchOption.AllDirectories)) @@ -120,47 +212,6 @@ namespace Netch.Updater } } - public static void DownloadAndUpdate(string downloadPath, - string targetPath, - DownloadProgressChangedEventHandler onDownloadProgressChanged, - string? keyword = null) - { - if (!UpdateChecker.GetFileNameAndHashFromMarkdownForm(UpdateChecker.LatestRelease.body, out var fileName, out var sha256, keyword)) - throw new MessageException(i18N.Translate("parse release note failed")); - - var fileFullPath = Path.Combine(downloadPath, fileName); - var updater = new Updater(fileFullPath, targetPath); - - if (File.Exists(fileFullPath)) - { - if (Utils.Utils.SHA256CheckSum(fileFullPath) == sha256) - { - updater.ApplyUpdate(); - return; - } - - File.Delete(fileFullPath); - } - - DownloadUpdate(onDownloadProgressChanged, fileFullPath, sha256); - updater.ApplyUpdate(); - } - - private static void DownloadUpdate(DownloadProgressChangedEventHandler onDownloadProgressChanged, string fileFullPath, string sha256) - { - using WebClient client = new(); - try - { - client.DownloadProgressChanged += onDownloadProgressChanged; - client.DownloadFile(new Uri(UpdateChecker.LatestRelease.assets[0].browser_download_url), fileFullPath); - } - finally - { - client.DownloadProgressChanged -= onDownloadProgressChanged; - } - - if (Utils.Utils.SHA256CheckSum(fileFullPath) != sha256) - throw new MessageException(i18N.Translate("The downloaded file has the wrong hash")); - } + #endregion } } \ No newline at end of file