// returns true if there was no integrity errors, false if there was and repair was performed
        private bool PerformInternal(PatchKit.Unity.Patcher.Cancellation.CancellationToken cancellationToken)
        {
            int installedVersionId = Context.App.GetInstalledVersionId();

            VersionIntegrity results = CheckIntegrity(cancellationToken, installedVersionId);
            var filesNeedFixing      = FilesNeedFixing(results);

            if (filesNeedFixing.Count() == 0)
            {
                DebugLogger.Log("No missing or invalid size files.");
                return(true);
            }

            // need to collect some data about the application to calculate the repair cost and make decisions

            int latestVersionId = Context.App.GetLatestVersionId(true, cancellationToken);

            AppContentSummary installedVersionContentSummary
                = Context.App.RemoteMetaData.GetContentSummary(installedVersionId, cancellationToken);

            AppContentSummary latestVersionContentSummary
                = Context.App.RemoteMetaData.GetContentSummary(latestVersionId, cancellationToken);

            bool isNewVersionAvailable = installedVersionId < latestVersionId;

            long contentSize = isNewVersionAvailable
                ? latestVersionContentSummary.Files.Sum(f => f.Size)
                : installedVersionContentSummary.Files.Sum(f => f.Size);

            double repairCost = CalculateRepairCost(installedVersionContentSummary, filesNeedFixing);

            // increasing repair costs that reinstallation will be done for 1/3 of the content size
            repairCost *= IncreaseRepairCost;


            if (_lowestVersionWithContentId > installedVersionId)
            {
                DebugLogger.Log(
                    "Repair is impossible because lowest version with content id is "
                    + _lowestVersionWithContentId +
                    " and currently installed version id is "
                    + installedVersionId +
                    ". Reinstalling.");

                ReinstallContent(cancellationToken);
            }
            else if (repairCost < contentSize)
            {
                DebugLogger.Log(string.Format("Repair cost {0} is smaller than content cost {1}, repairing...", repairCost, contentSize));
                IAppUpdaterStrategy repairStrategy = _strategyResolver.Create(StrategyType.Repair, Context);
                repairStrategy.Update(cancellationToken);
            }
            else
            {
                DebugLogger.Log(string.Format("Content cost {0} is smaller than repair {1}. Reinstalling.", contentSize, repairCost));
                ReinstallContent(cancellationToken);
            }

            return(false);
        }
Beispiel #2
0
        public AppUpdaterRepairAndDiffStrategy(AppUpdaterContext context, UpdaterStatus status)
        {
            Assert.IsNotNull(context, "Context is null");

            _repairStrategy = new AppUpdaterRepairStrategy(context, status);
            _diffStrategy   = new AppUpdaterDiffStrategy(context, status);
        }
Beispiel #3
0
        private bool TryHandleFallback(PatchKit.Unity.Patcher.Cancellation.CancellationToken cancellationToken)
        {
            var fallbackType = _strategyResolver.GetFallbackStrategy(_strategy.GetStrategyType());

            if (fallbackType == StrategyType.None)
            {
                return(false);
            }

            _strategy = _strategyResolver.Create(fallbackType, Context);

            _strategy.Update(cancellationToken);

            return(true);
        }
        private bool TryHandleFallback(CancellationToken cancellationToken)
        {
            var fallbackType = _strategyResolver.GetFallbackStrategy(_strategy.GetStrategyType());

            if (fallbackType == StrategyType.None)
            {
                return(false);
            }

            Context.App.ReloadTemporaryDirectories(); // FIX: Bug #724

            _strategy = _strategyResolver.Create(fallbackType, Context);

            _strategy.Update(cancellationToken);

            return(true);
        }
Beispiel #5
0
        public void Update(PatchKit.Unity.Patcher.Cancellation.CancellationToken cancellationToken)
        {
            Assert.MethodCalledOnlyOnce(ref _updateHasBeenCalled, "Update");

            if (Context.App.IsInstallationBroken() || Context.App.IsFullyInstalled())
            {
                PreUpdate(cancellationToken);
            }

            DebugLogger.Log("Updating.");

            StrategyType type = _strategyResolver.Resolve(Context, cancellationToken);

            _strategy = _strategyResolver.Create(type, Context);

            try
            {
                _strategy.Update(cancellationToken);
            }
            catch (Exception ex)
            {
                if (ex is OperationCanceledException ||
                    ex is UnauthorizedAccessException ||
                    ex is NotEnoughtDiskSpaceException ||
                    ex is ThreadInterruptedException ||
                    ex is ThreadAbortException)
                {
                    DebugLogger.LogWarning("Strategy caused exception, to be handled further");
                    throw;
                }
                else
                {
                    DebugLogger.LogWarningFormat("Strategy caused exception, being handled by fallback: {0}, Trace: {1}", ex, ex.StackTrace);

                    if (!TryHandleFallback(cancellationToken))
                    {
                        throw;
                    }
                }
            }
        }
        private void PreUpdate(PatchKit.Unity.Patcher.Cancellation.CancellationToken cancellationToken)
        {
            DebugLogger.Log("Pre update integrity check");

            var commandFactory = new AppUpdaterCommandFactory();

            int installedVersionId         = Context.App.GetInstalledVersionId();
            int latestVersionId            = Context.App.GetLatestVersionId();
            int lowestVersionWithContentId = Context.App.GetLowestVersionWithContentId();

            if (lowestVersionWithContentId > installedVersionId)
            {
                DebugLogger.Log(
                    "Repair is impossible because lowest version with content id is "
                    + lowestVersionWithContentId +
                    " and currently installed version id is "
                    + installedVersionId +
                    ". Uninstalling to prepare for content strategy.");

                IUninstallCommand uninstall = commandFactory.CreateUninstallCommand(Context);
                uninstall.Prepare(_status);
                uninstall.Execute(cancellationToken);
                return;
            }

            AppContentSummary installedVersionContentSummary
                = Context.App.RemoteMetaData.GetContentSummary(installedVersionId);

            AppContentSummary latestVersionContentSummary
                = Context.App.RemoteMetaData.GetContentSummary(latestVersionId);

            bool isNewVersionAvailable = installedVersionId < latestVersionId;

            long contentSize = isNewVersionAvailable
                ? latestVersionContentSummary.Size
                : installedVersionContentSummary.Size;

            ICheckVersionIntegrityCommand checkIntegrity = commandFactory
                                                           .CreateCheckVersionIntegrityCommand(
                versionId: installedVersionId,
                context: Context,
                isCheckingHash: false,
                isCheckingSize: true);

            checkIntegrity.Prepare(_status);
            checkIntegrity.Execute(cancellationToken);

            var missingFiles = checkIntegrity.Results.Files
                               .Where(f => f.Status == FileIntegrityStatus.MissingData);

            int missingFilesCount = missingFiles.Count();

            var invalidSizeFiles = checkIntegrity.Results.Files
                                   .Where(f => f.Status == FileIntegrityStatus.InvalidSize);

            int invalidSizeFilesCount = invalidSizeFiles.Count();

            if (missingFilesCount + invalidSizeFilesCount == 0)
            {
                DebugLogger.Log("No missing or invalid size files.");
                return;
            }

            double repairCost = CalculateRepairCost(installedVersionContentSummary, missingFiles.Concat(invalidSizeFiles));

            if (repairCost < contentSize)
            {
                DebugLogger.Log(string.Format("Repair cost {0} is smaller than content cost {1}, repairing...", repairCost, contentSize));
                IAppUpdaterStrategy repairStrategy = _strategyResolver.Create(StrategyType.Repair, Context);
                repairStrategy.Update(cancellationToken);
            }
            else
            {
                DebugLogger.Log("Content cost is smaller than repair. Uninstalling to prepare for content strategy.");
                IUninstallCommand uninstall = commandFactory.CreateUninstallCommand(Context);
                uninstall.Prepare(_status);
                uninstall.Execute(cancellationToken);
            }
        }