Squirrel.Windows icon indicating copy to clipboard operation
Squirrel.Windows copied to clipboard

Latest Full package should be downloaded if there is no delta package for that version

Open Hacko007 opened this issue 4 years ago • 3 comments

Squirrel version(s) 1.9.0

Description If you mix building of versions with delta and no delta it will fail to download versions that have no delta

Steps to recreate

  1. Create initial version and install it (V1)
  2. Create new version (V2) with delta. Do not upgrade yet
  3. Create new version (V3) using --no-delta flag.
  4. Run App.

Expected behavior App should download only version V3 full package

Actual behavior App downloads only V2 delta

Additional information _Logic should be like if you have two greater versions in sequence with only full package then only latest full package should be downloaded. Ie: Installed version is V1 Your Release file looks like

--- app-v1-full.nupkg --- --- app-v2-delta.nupkg --- --- app-v2-full.nupkg --- --- app-v3-full.nupkg --- --- app-v4-delta.nupkg --- --- app-v4-full.nupkg --- --- app-v5-full.nupkg ---

Today app-v2-delta.nupkg and app-v4-delta.nupkg is downloaded. We should download app-v5-full.nupkg _

Hacko007 avatar Oct 10 '19 08:10 Hacko007

I ran into the inverse situation, where a delta is missing from an older version, but exists for the latest, it also fails to update from V1 to V4. ex. --- app-v1-full.nupkg --- --- app-v3-full.nupkg --- --- app-v4-delta.nupkg --- --- app-v4-full.nupkg ---

This should also drop back to downloading the latest full package.

For my situation, the full package is small enough that I'm going to stop making deltas due to this problem.

FuntimeMS avatar Jan 27 '21 01:01 FuntimeMS

This is already what happens - attempting to do a delta update will fail, then it will fall back to applying a full update

anaisbetts avatar Jan 27 '21 10:01 anaisbetts

Huh, maybe I need to post this as a new issue then, because I'm getting a failure to update with an exception being thrown.

Here's the log:

2021-01-26 17:46:56.768 -05:00 [DBG] Beginning to download update...
2021-01-26 17:46:56.963 -05:00 [DBG] ... done downloading.
2021-01-26 17:46:56.963 -05:00 [DBG] Beginning to apply release...
2021-01-26 17:46:58.037 -05:00 [ERR] CheckForUpdates threw exception
System.AggregateException: One or more errors occurred. ---> System.ComponentModel.Win32Exception: The system cannot find the file specified
   at DeltaCompressionDotNet.MsDelta.MsDeltaCompression.ApplyDelta(String deltaFilePath, String oldFilePath, String newFilePath)
   at Squirrel.DeltaPackageBuilder.applyDiffToFile(String deltaPath, String relativeFilePath, String workingDirectory)
   at Squirrel.DeltaPackageBuilder.<>c__DisplayClass3_1.<ApplyDeltaPackage>b__4(String file)
   at Squirrel.EnumerableExtensions.ForEach[TSource](IEnumerable`1 source, Action`1 onNext)
   at Squirrel.DeltaPackageBuilder.ApplyDeltaPackage(ReleasePackage basePackage, ReleasePackage deltaPackage, String outputFile)
   at Squirrel.UpdateManager.ApplyReleasesImpl.<>c__DisplayClass8_0.<createFullPackagesFromDeltas>b__3()
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Squirrel.UpdateManager.ApplyReleasesImpl.<createFullPackagesFromDeltas>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Squirrel.UpdateManager.ApplyReleasesImpl.<ApplyReleases>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Squirrel.UpdateManager.<ApplyReleases>d__10.MoveNext()
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at IpcOsRestoreToolCreator.Bootstrapper.<CheckForUpdates>d__35.MoveNext()
---> (Inner Exception #0) System.ComponentModel.Win32Exception (0x80004005): The system cannot find the file specified
   at DeltaCompressionDotNet.MsDelta.MsDeltaCompression.ApplyDelta(String deltaFilePath, String oldFilePath, String newFilePath)
   at Squirrel.DeltaPackageBuilder.applyDiffToFile(String deltaPath, String relativeFilePath, String workingDirectory)
   at Squirrel.DeltaPackageBuilder.<>c__DisplayClass3_1.<ApplyDeltaPackage>b__4(String file)
   at Squirrel.EnumerableExtensions.ForEach[TSource](IEnumerable`1 source, Action`1 onNext)
   at Squirrel.DeltaPackageBuilder.ApplyDeltaPackage(ReleasePackage basePackage, ReleasePackage deltaPackage, String outputFile)
   at Squirrel.UpdateManager.ApplyReleasesImpl.<>c__DisplayClass8_0.<createFullPackagesFromDeltas>b__3()
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Squirrel.UpdateManager.ApplyReleasesImpl.<createFullPackagesFromDeltas>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Squirrel.UpdateManager.ApplyReleasesImpl.<ApplyReleases>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Squirrel.UpdateManager.<ApplyReleases>d__10.MoveNext()<---

2021-01-26 17:46:58.077 -05:00 [DBG] CheckForUpdates finished

And here's the function:

        private async Task CheckForUpdates()
        {
            Log.Debug($"CheckForUpdates:  '{UserSettings.UpdateUrl}'");
            bool updateToApply = false;
            try
            {
                // https://madstt.dk/squirrel-the-basic/
                using (var mgr = new UpdateManager(UserSettings.UpdateUrl))
                {
                    var updateInfo = await mgr.CheckForUpdate();
                    if (updateInfo.ReleasesToApply.Any())
                    {
                        var newVersion = updateInfo.FutureReleaseEntry.Version;

                        string msg = $"New version available: '{ newVersion }'. Install?";
                        Log.Information(msg);
                        var result = MessageBox.Show(msg, $"IpcOsRestoreToolCreator Update", MessageBoxButton.YesNo);
                        if (result == MessageBoxResult.Yes)
                        {
                            // What happens is that we check the `updateInfo` for any releases to apply.
                            // This would be any new releases. If this is the case we ask the user whether to install the latest release.
                            // If this is the case to call the `DownloadReleases()` method on the `UpdateManager` object. Upon downloaded, we can apply the release.

                            Log.Debug("Beginning to download update...");
                            mgr.DownloadReleases(updateInfo.ReleasesToApply).Wait();
                            Log.Debug("... done downloading.");

                            Log.Debug("Beginning to apply release...");
                            mgr.ApplyReleases(updateInfo).Wait();
                            Log.Debug("... done applying.");
                            // This step will change shortcut pointers from the current installed release to the newly downloaded.

                            Log.Debug("Creating uninstaller...");
                            mgr.CreateUninstallerRegistryEntry().Wait();
                            Log.Debug("... done creating uninstaller.");

                            updateToApply = true;
                        }
                    }
                }

                if (updateToApply)
                {
                    // Restart must be outside the using statement
                    Log.Information("Restarting into new version");
                    UpdateManager.RestartApp();
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex, "CheckForUpdates threw exception");
                //throw;
            }
            Log.Debug("CheckForUpdates finished");

        }

I implemented this function in Sept 2020 based on a some documentation that I found.
Do I need to update my CheckForUpdates function? I also note that I am using Squirrel.Windows NuGet package v2.0.0, and I see a v2.0.1 available.

FuntimeMS avatar Jan 27 '21 15:01 FuntimeMS