private VersionIntegrity CheckIntegrity( PatchKit.Unity.Patcher.Cancellation.CancellationToken cancellationToken, int installedVersionId ) { ICheckVersionIntegrityCommand checkIntegrity = _commandFactory .CreateCheckVersionIntegrityCommand( versionId: installedVersionId, context: Context, isCheckingHash: CheckHashes, isCheckingSize: true, cancellationToken: cancellationToken); checkIntegrity.Prepare(_status, cancellationToken); checkIntegrity.Execute(cancellationToken); return(checkIntegrity.Results); }
public void Update(CancellationToken cancellationToken) { _logger.LogDebug("Executing content repair strategy."); var installedVersionId = _context.App.GetInstalledVersionId(); string metaDestination = _context.App.DownloadDirectory.GetDiffPackageMetaPath(installedVersionId); var commandFactory = new AppUpdaterCommandFactory(); var validateLicense = commandFactory.CreateValidateLicenseCommand(_context); validateLicense.Prepare(_status, cancellationToken); validateLicense.Execute(cancellationToken); var geolocateCommand = commandFactory.CreateGeolocateCommand(); geolocateCommand.Prepare(_status, cancellationToken); geolocateCommand.Execute(cancellationToken); var resource = _context.App.RemoteData.GetContentPackageResource( installedVersionId, validateLicense.KeySecret, geolocateCommand.CountryCode, cancellationToken); if (!resource.HasMetaUrls()) { throw new ArgumentException("Cannot execute content repair strategy without meta files."); } _logger.LogDebug("Downloading the meta file."); var downloader = new HttpDownloader(metaDestination, resource.GetMetaUrls()); downloader.Download(cancellationToken); ICheckVersionIntegrityCommand checkVersionIntegrityCommand = commandFactory.CreateCheckVersionIntegrityCommand(installedVersionId, _context, true, true, cancellationToken); checkVersionIntegrityCommand.Prepare(_status, cancellationToken); checkVersionIntegrityCommand.Execute(cancellationToken); var meta = Pack1Meta.ParseFromFile(metaDestination); FileIntegrity[] filesIntegrity = checkVersionIntegrityCommand.Results.Files; var contentSummary = _context.App.RemoteMetaData.GetContentSummary(installedVersionId, cancellationToken); foreach (var invalidVersionIdFile in filesIntegrity.Where(x => x.Status == FileIntegrityStatus.InvalidVersion).ToArray()) { var fileName = invalidVersionIdFile.FileName; var file = contentSummary.Files.First(x => x.Path == fileName); var localPath = _context.App.LocalDirectory.Path.PathCombine(file.Path); string actualFileHash = HashCalculator.ComputeFileHash(localPath); if (actualFileHash != file.Hash) { FileOperations.Delete(localPath, cancellationToken); _context.App.LocalMetaData.RegisterEntry(fileName, installedVersionId); invalidVersionIdFile.Status = FileIntegrityStatus.MissingData; } else { _context.App.LocalMetaData.RegisterEntry(fileName, installedVersionId); invalidVersionIdFile.Status = FileIntegrityStatus.Ok; } } Pack1Meta.FileEntry[] brokenFiles = filesIntegrity // Filter only files with invalid size, hash or missing entirely .Where(f => f.Status == FileIntegrityStatus.InvalidHash || f.Status == FileIntegrityStatus.InvalidSize || f.Status == FileIntegrityStatus.MissingData) // Map to file entires from meta .Select(integrity => meta.Files.SingleOrDefault(file => file.Name == integrity.FileName)) // Filter only regular files .Where(file => file.Type == Pack1Meta.RegularFileType) .ToArray(); if (brokenFiles.Length == 0) { _logger.LogDebug("Nothing to repair."); return; } _logger.LogDebug(string.Format("Broken files count: {0}", brokenFiles.Length)); IRepairFilesCommand repairCommand = commandFactory.CreateRepairFilesCommand( installedVersionId, _context, resource, brokenFiles, meta); repairCommand.Prepare(_status, cancellationToken); repairCommand.Execute(cancellationToken); }
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); } }