private PatchResult CreateIncrementalPatch() { if (cancel) { return(PatchResult.Failed); } Directory.CreateDirectory(incrementalPatchOutputPath); Directory.CreateDirectory(incrementalPatchTempPath); incrementalPatch = new IncrementalPatchInfo { FromVersion = previousVersion, ToVersion = version }; Log(Localization.Get(StringId.CreatingIncrementalPatch)); Stopwatch timer = Stopwatch.StartNew(); DirectoryInfo rootDirectory = new DirectoryInfo(rootPath); TraverseIncrementalPatchRecursively(rootDirectory, ""); if (cancel) { return(PatchResult.Failed); } Log(Localization.Get(StringId.CompressingPatchIntoOneFile)); string compressedPatchPath = incrementalPatchOutputPath + incrementalPatch.PatchVersion() + PatchParameters.INCREMENTAL_PATCH_FILE_EXTENSION; ZipUtils.CompressFolder(incrementalPatchTempPath, compressedPatchPath, compressionFormatIncrementalPatch); Log(Localization.Get(StringId.WritingIncrementalPatchInfoToXML)); PatchUtils.SerializeIncrementalPatchInfoToXML(incrementalPatch, incrementalPatchOutputPath + incrementalPatch.PatchVersion() + PatchParameters.INCREMENTAL_PATCH_INFO_EXTENSION); versionInfo.IncrementalPatches.Add(new IncrementalPatch(previousVersion, version, new FileInfo(compressedPatchPath), incrementalPatch.Files.Count, compressionFormatIncrementalPatch)); PatchUtils.DeleteDirectory(incrementalPatchTempPath); Log(Localization.Get(StringId.IncrementalPatchCreatedInXSeconds, timer.ElapsedSeconds())); return(PatchResult.Success); }
private PatchResult CreateInstallerPatch() { if (cancel) { return(PatchResult.Failed); } Directory.CreateDirectory(installerPatchOutputPath); string compressedPatchPath = installerPatchOutputPath + PatchParameters.INSTALLER_PATCH_FILENAME; Log(Localization.Get(StringId.CreatingInstallerPatch)); Stopwatch timer = Stopwatch.StartNew(); Log(Localization.Get(StringId.CompressingXToY, rootPath, compressedPatchPath)); ZipUtils.CompressFolder(rootPath, compressedPatchPath, compressionFormatInstallerPatch, ignoredPathsRegex); if (cancel) { return(PatchResult.Failed); } Log(Localization.Get(StringId.PatchCreatedInXSeconds, timer.ElapsedSeconds())); FileInfo installerPatch = new FileInfo(compressedPatchPath); versionInfo.InstallerPatch = new InstallerPatch(installerPatch, compressionFormatInstallerPatch); // Calculate compression ratio long uncompressedTotal = 0L, compressedTotal = installerPatch.Length; for (int i = 0; i < versionInfo.Files.Count; i++) { uncompressedTotal += versionInfo.Files[i].FileSize; } Log(Localization.Get(StringId.CompressionRatioIsX, ((double)compressedTotal * 100 / uncompressedTotal).ToString("F2"))); return(PatchResult.Success); }
private bool DownloadAndUpdateFiles(List <VersionItem> filesToDownload, List <VersionItem> filesToUpdate) { string rootPath = comms.SelfPatching ? comms.DecompressedFilesPath : comms.RootPath; for (int i = 0, j = 0; i < filesToUpdate.Count; i++) { if (comms.Cancel) { return(false); } VersionItem item = filesToUpdate[i]; string downloadAbsolutePath = comms.DownloadsPath + item.Path; if (filesToDownload.Count > 0 && filesToDownload[j] == item) { comms.Stage = PatchStage.DownloadingFiles; // Download the file Directory.CreateDirectory(Path.GetDirectoryName(downloadAbsolutePath)); comms.Log(Localization.Get(StringId.DownloadingXthFile, j + 1, filesToDownload.Count, item.Path, item.CompressedFileSize.ToMegabytes())); Stopwatch downloadTimer = Stopwatch.StartNew(); FileInfo downloadedFile = comms.DownloadManager.DownloadFileFromURLToPath(comms.VersionInfo.GetDownloadURLFor(item), downloadAbsolutePath, item.CompressedFileSize); if (downloadedFile == null) { comms.FailReason = PatchFailReason.DownloadError; comms.FailDetails = Localization.Get(StringId.E_XCouldNotBeDownloaded, item.Path); return(false); } else if (!downloadedFile.MatchesSignature(item.CompressedFileSize, item.CompressedMd5Hash)) { comms.FailReason = PatchFailReason.CorruptDownloadError; comms.FailDetails = Localization.Get(StringId.E_DownloadedFileXIsCorrupt, item.Path); return(false); } else { comms.Log(Localization.Get(StringId.XDownloadedInYSeconds, item.Path, downloadTimer.ElapsedSeconds())); } j++; } if (comms.Cancel) { return(false); } comms.Stage = PatchStage.UpdatingFiles; comms.Log(Localization.Get(StringId.UpdatingXthFile, i + 1, filesToUpdate.Count, item.Path)); string targetAbsolutePath = rootPath + item.Path; Directory.CreateDirectory(Path.GetDirectoryName(targetAbsolutePath)); ZipUtils.DecompressFile(downloadAbsolutePath, targetAbsolutePath, comms.VersionInfo.CompressionFormat); File.Delete(downloadAbsolutePath); ReportProgress(1, 0L); } return(true); }
private PatchResult CreateRepairPatch() { if (cancel) { return(PatchResult.Failed); } Directory.CreateDirectory(repairPatchOutputPath); Log(Localization.Get(StringId.CreatingRepairPatch)); Stopwatch timer = Stopwatch.StartNew(); // Compress repair patch files and move them to the destination Log(Localization.Get(StringId.CompressingFilesToDestination)); Stopwatch compressTimer = Stopwatch.StartNew(); // Check if we can use existing repair patch files for files that didn't change since the last patch string previousRepairPatchFilesRoot = null; if (previousVersionInfo != null && previousVersionInfo.CompressionFormat == compressionFormatRepairPatch) { previousRepairPatchFilesRoot = previousPatchFilesRoot + PatchParameters.REPAIR_PATCH_DIRECTORY + Path.DirectorySeparatorChar; if (!Directory.Exists(previousRepairPatchFilesRoot)) { previousRepairPatchFilesRoot = null; } } for (int i = 0; i < versionInfo.Files.Count; i++) { if (cancel) { return(PatchResult.Failed); } VersionItem patchItem = versionInfo.Files[i]; string fromAbsolutePath = rootPath + patchItem.Path; string toAbsolutePath = repairPatchOutputPath + patchItem.Path + PatchParameters.REPAIR_PATCH_FILE_EXTENSION; if (previousRepairPatchFilesRoot != null) { VersionItem previousPatchItem = previousVersionInfo.Files.Find((item) => item.Path == patchItem.Path); if (previousPatchItem != null && previousPatchItem.FileSize == patchItem.FileSize && previousPatchItem.Md5Hash == patchItem.Md5Hash) { if (dontCreatePatchFilesForUnchangedFiles) { patchItem.CompressedFileSize = previousPatchItem.CompressedFileSize; patchItem.CompressedMd5Hash = previousPatchItem.CompressedMd5Hash; continue; } FileInfo previousCompressedFile = new FileInfo(previousRepairPatchFilesRoot + patchItem.Path + PatchParameters.REPAIR_PATCH_FILE_EXTENSION); if (previousCompressedFile.Exists && previousCompressedFile.MatchesSignature(previousPatchItem.CompressedFileSize, previousPatchItem.CompressedMd5Hash)) { Log(Localization.Get(StringId.CopyingXToPatch, previousCompressedFile.FullName)); PatchUtils.CopyFile(previousCompressedFile.FullName, toAbsolutePath); patchItem.CompressedFileSize = previousPatchItem.CompressedFileSize; patchItem.CompressedMd5Hash = previousPatchItem.CompressedMd5Hash; continue; } } } Log(Localization.Get(StringId.CompressingXToY, fromAbsolutePath, toAbsolutePath)); compressTimer.Reset(); compressTimer.Start(); ZipUtils.CompressFile(fromAbsolutePath, toAbsolutePath, compressionFormatRepairPatch); Log(Localization.Get(StringId.CompressionFinishedInXSeconds, compressTimer.ElapsedSeconds())); patchItem.OnCompressed(new FileInfo(toAbsolutePath)); } if (cancel) { return(PatchResult.Failed); } Log(Localization.Get(StringId.PatchCreatedInXSeconds, timer.ElapsedSeconds())); // Calculate compression ratio long uncompressedTotal = 0L, compressedTotal = 0L; for (int i = 0; i < versionInfo.Files.Count; i++) { uncompressedTotal += versionInfo.Files[i].FileSize; compressedTotal += versionInfo.Files[i].CompressedFileSize; } Log(Localization.Get(StringId.CompressionRatioIsX, ((double)compressedTotal * 100 / uncompressedTotal).ToString("F2"))); return(PatchResult.Success); }
public PatchResult Run() { if (comms.Cancel) { return(PatchResult.Failed); } if (comms.IsUnderMaintenance()) { return(PatchResult.Failed); } if (patchInfo.Files.Count > 0) { PatchUtils.DeleteDirectory(patchDecompressPath); Directory.CreateDirectory(patchDecompressPath); } if (comms.Cancel) { return(PatchResult.Failed); } Stopwatch timer = Stopwatch.StartNew(); if (patchInfo.Files.Count > 0) { FileInfo patchFile = new FileInfo(patchDownloadPath); if (!patchFile.Exists || !patchFile.MatchesSignature(patchInfo.CompressedFileSize, patchInfo.CompressedMd5Hash)) { comms.Stage = PatchStage.DownloadingFiles; Stopwatch downloadTimer = Stopwatch.StartNew(); comms.Log(Localization.Get(StringId.DownloadingPatchX, patchInfo.PatchVersion())); patchFile = comms.DownloadManager.DownloadFileFromURLToPath(patchInfo.DownloadURL, patchDownloadPath, patchInfo.CompressedFileSize); if (patchFile == null) { comms.FailReason = PatchFailReason.DownloadError; comms.FailDetails = Localization.Get(StringId.E_PatchXCouldNotBeDownloaded, patchInfo.PatchVersion()); return(PatchResult.Failed); } else if (!patchFile.MatchesSignature(patchInfo.CompressedFileSize, patchInfo.CompressedMd5Hash)) { comms.FailReason = PatchFailReason.CorruptDownloadError; comms.FailDetails = Localization.Get(StringId.E_DownloadedFileXIsCorrupt, patchInfo.PatchVersion()); return(PatchResult.Failed); } else { comms.Log(Localization.Get(StringId.XDownloadedInYSeconds, patchInfo.PatchVersion(), downloadTimer.ElapsedSeconds())); } } if (comms.Cancel) { return(PatchResult.Failed); } comms.Stage = PatchStage.ExtractingFilesFromArchive; comms.Log(Localization.Get(StringId.DecompressingPatchX, patchInfo.PatchVersion())); ZipUtils.DecompressFolderLZMA(patchFile.FullName, patchDecompressPath); comms.Stage = PatchStage.UpdatingFiles; comms.Log(Localization.Get(StringId.UpdatingXFiles, patchInfo.Files.Count)); int failedItemCount = 0; for (int i = 0; i < patchInfo.Files.Count; i++) { if (comms.Cancel) { return(PatchResult.Failed); } string fileRelativePath = patchInfo.Files[i].Path; string diffFileAbsolutePath = patchDecompressPath + fileRelativePath; if (!File.Exists(diffFileAbsolutePath)) { comms.Log(Localization.Get(StringId.E_DiffOfXDoesNotExist, Path.GetFileName(fileRelativePath))); failedItemCount++; continue; } string decompressAbsolutePath = comms.DecompressedFilesPath + fileRelativePath; if (comms.SelfPatching && ApplyDiffToFile(decompressAbsolutePath, diffFileAbsolutePath, decompressAbsolutePath, i)) { continue; } string localFileAbsolutePath = comms.RootPath + fileRelativePath; string targetPath = comms.SelfPatching ? decompressAbsolutePath : localFileAbsolutePath; if (!ApplyDiffToFile(localFileAbsolutePath, diffFileAbsolutePath, targetPath, i)) { failedItemCount++; } } comms.Log(Localization.Get(StringId.XFilesUpdatedSuccessfully, patchInfo.Files.Count - failedItemCount, patchInfo.Files.Count)); } if (patchInfo.RenamedFiles.Count > 0) { comms.Log(Localization.Get(StringId.RenamingXFiles, patchInfo.RenamedFiles.Count)); if (!RenameItems(patchInfo.RenamedFiles)) { return(PatchResult.Failed); } } // Updating version code to the latest one will be done by SimplePatchTool, after checking // whether or not all files are correctly updated if (patchInfo.ToVersion < comms.VersionInfo.Version) { comms.UpdateVersion(patchInfo.ToVersion); } if (patchInfo.Files.Count > 0) { PatchUtils.DeleteDirectory(patchDecompressPath); File.Delete(patchDownloadPath); } comms.Log(Localization.Get(StringId.PatchAppliedInXSeconds, timer.ElapsedSeconds())); return(PatchResult.Success); }
protected override PatchResult Execute() { if (comms.Cancel) { return(PatchResult.Failed); } if (comms.IsUnderMaintenance()) { return(PatchResult.Failed); } string rootPath = comms.SelfPatching ? comms.DecompressedFilesPath : comms.RootPath; string patchDecompressPath = comms.GetDecompressPathForPatch(PatchParameters.INSTALLER_PATCH_DIRECTORY); string patchDownloadPath = comms.CachePath + PatchParameters.INSTALLER_PATCH_FILENAME; InstallerPatch patchInfo = comms.VersionInfo.InstallerPatch; Stopwatch timer = Stopwatch.StartNew(); comms.Stage = PatchStage.CalculatingFilesToUpdate; comms.Log(Localization.Get(StringId.CalculatingNewOrChangedFiles)); List <VersionItem> filesToUpdate = comms.FindFilesToUpdate(); if (filesToUpdate.Count == 0) { return(PatchResult.AlreadyUpToDate); } if (comms.Cancel) { return(PatchResult.Failed); } InitializeProgress(filesToUpdate.Count, patchInfo.PatchSize); PatchUtils.DeleteDirectory(patchDecompressPath); Directory.CreateDirectory(patchDecompressPath); FileInfo patchFile = new FileInfo(patchDownloadPath); if (!patchFile.Exists || !patchFile.MatchesSignature(patchInfo.PatchSize, patchInfo.PatchMd5Hash)) { comms.Stage = PatchStage.DownloadingFiles; Stopwatch downloadTimer = Stopwatch.StartNew(); comms.Log(Localization.Get(StringId.DownloadingPatchX, PatchParameters.INSTALLER_PATCH_FILENAME)); patchFile = comms.DownloadManager.DownloadFileFromURLToPath(comms.VersionInfo.GetDownloadURLFor(patchInfo), patchDownloadPath, patchInfo.PatchSize); if (patchFile == null) { comms.FailReason = PatchFailReason.DownloadError; comms.FailDetails = Localization.Get(StringId.E_XCouldNotBeDownloaded, PatchParameters.INSTALLER_PATCH_FILENAME); return(PatchResult.Failed); } else if (!patchFile.MatchesSignature(patchInfo.PatchSize, patchInfo.PatchMd5Hash)) { comms.FailReason = PatchFailReason.CorruptDownloadError; comms.FailDetails = Localization.Get(StringId.E_DownloadedFileXIsCorrupt, PatchParameters.INSTALLER_PATCH_FILENAME); return(PatchResult.Failed); } else { comms.Log(Localization.Get(StringId.XDownloadedInYSeconds, PatchParameters.INSTALLER_PATCH_FILENAME, downloadTimer.ElapsedSeconds())); } } else { ReportProgress(0, patchInfo.PatchSize); } if (comms.Cancel) { return(PatchResult.Failed); } comms.Stage = PatchStage.ExtractingFilesFromArchive; comms.Log(Localization.Get(StringId.DecompressingPatchX, PatchParameters.INSTALLER_PATCH_FILENAME)); ZipUtils.DecompressFolder(patchFile.FullName, patchDecompressPath, patchInfo.CompressionFormat); comms.Stage = PatchStage.UpdatingFiles; comms.Log(Localization.Get(StringId.UpdatingXFiles, filesToUpdate.Count)); for (int i = 0; i < filesToUpdate.Count; i++) { if (comms.Cancel) { return(PatchResult.Failed); } string fileRelativePath = filesToUpdate[i].Path; string targetAbsolutePath = rootPath + fileRelativePath; comms.Log(Localization.Get(StringId.UpdatingXthFile, i + 1, filesToUpdate.Count, fileRelativePath)); Directory.CreateDirectory(Path.GetDirectoryName(targetAbsolutePath)); PatchUtils.CopyFile(patchDecompressPath + fileRelativePath, targetAbsolutePath); ReportProgress(1, 0L); } PatchUtils.DeleteDirectory(patchDecompressPath); File.Delete(patchDownloadPath); comms.Log(Localization.Get(StringId.PatchAppliedInXSeconds, timer.ElapsedSeconds())); return(PatchResult.Success); }