mirror of
https://github.com/velopack/velopack.git
synced 2025-10-25 15:19:22 +00:00
Get CheckForUpdates into its own inner class
This commit is contained in:
@@ -43,6 +43,12 @@ namespace Squirrel
|
||||
/// <param name="progress">A Observer which can be used to report Progress -
|
||||
/// will return values from 0-100 and Complete, or Throw</param>
|
||||
Task ApplyReleases(UpdateInfo updateInfo, Action<int> progress = null);
|
||||
|
||||
/// <summary>
|
||||
/// Completely uninstalls the targeted app
|
||||
/// </summary>
|
||||
/// <returns>Completion</returns>
|
||||
async Task FullUninstall();
|
||||
}
|
||||
|
||||
public static class EasyModeMixin
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Splat;
|
||||
@@ -12,7 +13,22 @@ namespace Squirrel
|
||||
{
|
||||
class CheckForUpdates : IEnableLogger
|
||||
{
|
||||
public async Task<UpdateInfo> CheckForUpdate(bool ignoreDeltaUpdates = false, Action<int> progress = null)
|
||||
readonly string rootAppDirectory;
|
||||
|
||||
// TODO: rip this out
|
||||
readonly FrameworkVersion appFrameworkVersion = FrameworkVersion.Net45;
|
||||
|
||||
public CheckForUpdates(string rootAppDirectory)
|
||||
{
|
||||
this.rootAppDirectory = rootAppDirectory;
|
||||
}
|
||||
|
||||
public async Task<UpdateInfo> CheckForUpdate(
|
||||
string localReleaseFile,
|
||||
string updateUrlOrPath,
|
||||
bool ignoreDeltaUpdates = false,
|
||||
Action<int> progress = null,
|
||||
IFileDownloader urlDownloader = null)
|
||||
{
|
||||
progress = progress ?? (_ => { });
|
||||
|
||||
@@ -20,7 +36,7 @@ namespace Squirrel
|
||||
|
||||
bool shouldInitialize = false;
|
||||
try {
|
||||
var file = File.OpenRead(LocalReleaseFile);
|
||||
var file = File.OpenRead(localReleaseFile);
|
||||
|
||||
// NB: sr disposes file
|
||||
using (var sr = new StreamReader(file, Encoding.UTF8)) {
|
||||
@@ -38,7 +54,7 @@ namespace Squirrel
|
||||
|
||||
// Fetch the remote RELEASES file, whether it's a local dir or an
|
||||
// HTTP URL
|
||||
if (isHttpUrl(updateUrlOrPath)) {
|
||||
if (Utility.IsHttpUrl(updateUrlOrPath)) {
|
||||
this.Log().Info("Downloading RELEASES file from {0}", updateUrlOrPath);
|
||||
|
||||
try {
|
||||
@@ -87,73 +103,74 @@ namespace Squirrel
|
||||
var remoteReleases = ReleaseEntry.ParseReleaseFile(releaseFile);
|
||||
progress(66);
|
||||
|
||||
if (!remoteReleases.IsEmpty()) {
|
||||
if (remoteReleases.Any()) {
|
||||
ret = determineUpdateInfo(localReleases, remoteReleases, ignoreDeltaUpdates);
|
||||
}
|
||||
|
||||
progress(100);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
async Task initializeClientAppDirectory()
|
||||
{
|
||||
// On bootstrap, we won't have any of our directories, create them
|
||||
var pkgDir = Path.Combine(rootAppDirectory, "packages");
|
||||
if (Directory.Exists(pkgDir)) {
|
||||
await Utility.DeleteDirectory(pkgDir);
|
||||
async Task initializeClientAppDirectory()
|
||||
{
|
||||
// On bootstrap, we won't have any of our directories, create them
|
||||
var pkgDir = Path.Combine(rootAppDirectory, "packages");
|
||||
if (Directory.Exists(pkgDir)) {
|
||||
await Utility.DeleteDirectory(pkgDir);
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(pkgDir);
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(pkgDir);
|
||||
}
|
||||
UpdateInfo determineUpdateInfo(IEnumerable<ReleaseEntry> localReleases, IEnumerable<ReleaseEntry> remoteReleases, bool ignoreDeltaUpdates)
|
||||
{
|
||||
var packageDirectory = Utility.PackageDirectoryForAppDir(rootAppDirectory);
|
||||
localReleases = localReleases ?? Enumerable.Empty<ReleaseEntry>();
|
||||
|
||||
UpdateInfo determineUpdateInfo(IEnumerable<ReleaseEntry> localReleases, IEnumerable<ReleaseEntry> remoteReleases, bool ignoreDeltaUpdates)
|
||||
{
|
||||
localReleases = localReleases ?? Enumerable.Empty<ReleaseEntry>();
|
||||
if (remoteReleases == null) {
|
||||
this.Log().Warn("Release information couldn't be determined due to remote corrupt RELEASES file");
|
||||
throw new Exception("Corrupt remote RELEASES file");
|
||||
}
|
||||
|
||||
if (remoteReleases == null) {
|
||||
this.Log().Warn("Release information couldn't be determined due to remote corrupt RELEASES file");
|
||||
throw new Exception("Corrupt remote RELEASES file");
|
||||
if (localReleases.Count() == remoteReleases.Count()) {
|
||||
this.Log().Info("No updates, remote and local are the same");
|
||||
|
||||
var latestFullRelease = findCurrentVersion(remoteReleases);
|
||||
var currentRelease = findCurrentVersion(localReleases);
|
||||
|
||||
var info = UpdateInfo.Create(currentRelease, new[] {latestFullRelease}, packageDirectory, appFrameworkVersion);
|
||||
return info;
|
||||
}
|
||||
|
||||
if (ignoreDeltaUpdates) {
|
||||
remoteReleases = remoteReleases.Where(x => !x.IsDelta);
|
||||
}
|
||||
|
||||
if (!localReleases.Any()) {
|
||||
this.Log().Warn("First run or local directory is corrupt, starting from scratch");
|
||||
|
||||
var latestFullRelease = findCurrentVersion(remoteReleases);
|
||||
return UpdateInfo.Create(findCurrentVersion(localReleases), new[] {latestFullRelease}, packageDirectory, appFrameworkVersion);
|
||||
}
|
||||
|
||||
if (localReleases.Max(x => x.Version) > remoteReleases.Max(x => x.Version)) {
|
||||
this.Log().Warn("hwhat, local version is greater than remote version");
|
||||
|
||||
var latestFullRelease = findCurrentVersion(remoteReleases);
|
||||
return UpdateInfo.Create(findCurrentVersion(localReleases), new[] {latestFullRelease}, packageDirectory, appFrameworkVersion);
|
||||
}
|
||||
|
||||
return UpdateInfo.Create(findCurrentVersion(localReleases), remoteReleases, packageDirectory, appFrameworkVersion);
|
||||
}
|
||||
|
||||
if (localReleases.Count() == remoteReleases.Count()) {
|
||||
this.Log().Info("No updates, remote and local are the same");
|
||||
static ReleaseEntry findCurrentVersion(IEnumerable<ReleaseEntry> localReleases)
|
||||
{
|
||||
if (!localReleases.Any()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var latestFullRelease = findCurrentVersion(remoteReleases);
|
||||
var currentRelease = findCurrentVersion(localReleases);
|
||||
|
||||
var info = UpdateInfo.Create(currentRelease, new[] {latestFullRelease}, PackageDirectory,appFrameworkVersion);
|
||||
return info;
|
||||
return localReleases.MaxBy(x => x.Version).SingleOrDefault(x => !x.IsDelta);
|
||||
}
|
||||
|
||||
if (ignoreDeltaUpdates) {
|
||||
remoteReleases = remoteReleases.Where(x => !x.IsDelta);
|
||||
}
|
||||
|
||||
if (!localReleases.Any()) {
|
||||
this.Log().Warn("First run or local directory is corrupt, starting from scratch");
|
||||
|
||||
var latestFullRelease = findCurrentVersion(remoteReleases);
|
||||
return UpdateInfo.Create(findCurrentVersion(localReleases), new[] {latestFullRelease}, PackageDirectory, appFrameworkVersion);
|
||||
}
|
||||
|
||||
if (localReleases.Max(x => x.Version) > remoteReleases.Max(x => x.Version)) {
|
||||
this.Log().Warn("hwhat, local version is greater than remote version");
|
||||
|
||||
var latestFullRelease = findCurrentVersion(remoteReleases);
|
||||
return UpdateInfo.Create(findCurrentVersion(localReleases), new[] {latestFullRelease}, PackageDirectory, appFrameworkVersion);
|
||||
}
|
||||
|
||||
return UpdateInfo.Create(findCurrentVersion(localReleases), remoteReleases, PackageDirectory, appFrameworkVersion);
|
||||
}
|
||||
|
||||
static ReleaseEntry findCurrentVersion(IEnumerable<ReleaseEntry> localReleases)
|
||||
{
|
||||
if (!localReleases.Any()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return localReleases.MaxBy(x => x.Version).SingleOrDefault(x => !x.IsDelta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Squirrel
|
||||
{
|
||||
public sealed partial class UpdateManager
|
||||
{
|
||||
class DownloadReleases : IEnableLogger
|
||||
class DownloadReleases : IEnableLogger
|
||||
{
|
||||
public async Task DownloadReleases(IEnumerable<ReleaseEntry> releasesToDownload, Action<int> progress = null)
|
||||
{
|
||||
@@ -33,16 +33,6 @@ namespace Squirrel
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static bool isHttpUrl(string urlOrPath)
|
||||
{
|
||||
try {
|
||||
var url = new Uri(urlOrPath);
|
||||
return new[] {"https", "http"}.Contains(url.Scheme.ToLowerInvariant());
|
||||
} catch (Exception) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Task checksumAllPackages(IEnumerable<ReleaseEntry> releasesDownloaded)
|
||||
{
|
||||
|
||||
@@ -41,21 +41,26 @@ namespace Squirrel
|
||||
this.urlDownloader = urlDownloader ?? new FileDownloader();
|
||||
}
|
||||
|
||||
public string PackageDirectory {
|
||||
get { return Path.Combine(rootAppDirectory, "packages"); }
|
||||
}
|
||||
|
||||
public string LocalReleaseFile {
|
||||
get { return Path.Combine(PackageDirectory, "RELEASES"); }
|
||||
}
|
||||
|
||||
public async Task FullUninstall(Version version = null)
|
||||
public Task<UpdateInfo> CheckForUpdate(bool ignoreDeltaUpdates, Action<int> progress = null)
|
||||
{
|
||||
version = version ?? new Version(255, 255, 255, 255);
|
||||
this.Log().Info("Uninstalling version '{0}'", version);
|
||||
var checkForUpdate = new CheckForUpdates(rootAppDirectory);
|
||||
return checkForUpdate.CheckForUpdate(Utility.LocalReleaseFileForAppDir(rootAppDirectory), updateUrlOrPath, ignoreDeltaUpdates, progress, urlDownloader);
|
||||
}
|
||||
|
||||
public Task DownloadReleases(IEnumerable<ReleaseEntry> releasesToDownload, Action<int> progress = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task ApplyReleases(UpdateInfo updateInfo, Action<int> progress = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public async Task FullUninstall()
|
||||
{
|
||||
await acquireUpdateLock();
|
||||
await fullUninstall(version);
|
||||
await fullUninstall();
|
||||
}
|
||||
|
||||
IEnumerable<DirectoryInfo> getReleases()
|
||||
@@ -75,18 +80,22 @@ namespace Squirrel
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
async Task fullUninstall(Version version)
|
||||
async Task fullUninstall(Version version = null)
|
||||
{
|
||||
version = version ?? new Version(255, 255, 255, 255);
|
||||
this.Log().Info("Uninstalling version '{0}'", version);
|
||||
|
||||
|
||||
// find all the old releases (and this one)
|
||||
var directoriesToDelete = getOldReleases(version)
|
||||
.Concat(new [] { getDirectoryForRelease(version) })
|
||||
.Where(d => d.Exists)
|
||||
.Select(d => d.FullName);
|
||||
|
||||
await directoriesToDelete.ForEachAsync(x => deleteDirectoryWithFallbackToNextReboot(x));
|
||||
await directoriesToDelete.ForEachAsync(x => Utility.DeleteDirectoryWithFallbackToNextReboot(x));
|
||||
|
||||
if (!getReleases().Any()) {
|
||||
await deleteDirectoryWithFallbackToNextReboot(rootAppDirectory);
|
||||
await Utility.DeleteDirectoryWithFallbackToNextReboot(rootAppDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,17 +152,5 @@ namespace Squirrel
|
||||
{
|
||||
return new DirectoryInfo(Path.Combine(rootAppDirectory, "app-" + releaseVersion));
|
||||
}
|
||||
|
||||
async Task deleteDirectoryWithFallbackToNextReboot(string dir)
|
||||
{
|
||||
try {
|
||||
await Utility.DeleteDirectory(dir);
|
||||
} catch (UnauthorizedAccessException ex) {
|
||||
var message = String.Format("Uninstall failed to delete dir '{0}', punting to next reboot", dir);
|
||||
this.Log().WarnException(message, ex);
|
||||
|
||||
Utility.DeleteDirectoryAtNextReboot(dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ using System.Collections.Concurrent;
|
||||
|
||||
namespace Squirrel
|
||||
{
|
||||
public static class Utility
|
||||
static class Utility
|
||||
{
|
||||
public static IEnumerable<FileInfo> GetAllFilesRecursively(this DirectoryInfo rootPath)
|
||||
{
|
||||
@@ -201,6 +201,16 @@ namespace Squirrel
|
||||
return Tuple.Create(path, (Stream) File.OpenWrite(path));
|
||||
}
|
||||
|
||||
public static string PackageDirectoryForAppDir(string rootAppDirectory)
|
||||
{
|
||||
return Path.Combine(rootAppDirectory, "packages");
|
||||
}
|
||||
|
||||
public static string LocalReleaseFileForAppDir(string rootAppDirectory)
|
||||
{
|
||||
return Path.Combine(PackageDirectoryForAppDir(rootAppDirectory), "RELEASES");
|
||||
}
|
||||
|
||||
static TAcc scan<T, TAcc>(this IEnumerable<T> This, TAcc initialValue, Func<TAcc, T, TAcc> accFunc)
|
||||
{
|
||||
TAcc acc = initialValue;
|
||||
@@ -213,6 +223,28 @@ namespace Squirrel
|
||||
return acc;
|
||||
}
|
||||
|
||||
public static bool IsHttpUrl(string urlOrPath)
|
||||
{
|
||||
try {
|
||||
var url = new Uri(urlOrPath);
|
||||
return new[] {"https", "http"}.Contains(url.Scheme.ToLowerInvariant());
|
||||
} catch (Exception) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task DeleteDirectoryWithFallbackToNextReboot(string dir)
|
||||
{
|
||||
try {
|
||||
await Utility.DeleteDirectory(dir);
|
||||
} catch (UnauthorizedAccessException ex) {
|
||||
var message = String.Format("Uninstall failed to delete dir '{0}', punting to next reboot", dir);
|
||||
LogHost.Default.WarnException(message, ex);
|
||||
|
||||
Utility.DeleteDirectoryAtNextReboot(dir);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DeleteDirectoryAtNextReboot(string directoryPath)
|
||||
{
|
||||
var di = new DirectoryInfo(directoryPath);
|
||||
|
||||
Reference in New Issue
Block a user