Esempio n. 1
0
        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);
        }
Esempio n. 2
0
        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);
        }
Esempio n. 4
0
        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);
        }