コード例 #1
0
        public async Task CreatePatchAsync(string oldRootPath, string newRootPath, string patchPath)
        {
            var oldPaths = DirectoryPathIterator.GetChildPathsRecursive(oldRootPath).ToArray();
            var newPaths = DirectoryPathIterator.GetChildPathsRecursive(newRootPath).ToArray();

            var instructions = new List <FilePatchInstruction>();

            RxLogger.Logger.Instance.Write($"There are {instructions.Count} instructions in this update package");

            Directory.CreateDirectory(patchPath + Path.DirectorySeparatorChar + "full");
            Directory.CreateDirectory(patchPath + Path.DirectorySeparatorChar + "delta");

            var allPaths = oldPaths.Union(newPaths).ToArray();

            foreach (var path in allPaths)
            {
                string oldPath = oldRootPath + Path.DirectorySeparatorChar + path;
                string newPath = newRootPath + Path.DirectorySeparatorChar + path;
                string oldHash = GetHash(oldPath);
                string newHash = GetHash(newPath);

                string compressedHash = null;
                string deltaHash      = null;

                DateTime oldLastWriteTime = File.Exists(oldPath) ? new FileInfo(oldPath).LastWriteTimeUtc : DateTime.MinValue;
                DateTime newLastWriteTime = File.Exists(newPath) ? new FileInfo(newPath).LastWriteTimeUtc : DateTime.MinValue;
                long     fullReplaceSize  = 0;
                long     deltaSize        = 0;
                bool     hasDelta         = false;

                if (newHash != null)
                {
                    string fullPath = patchPath + Path.DirectorySeparatorChar + "full" + Path.DirectorySeparatorChar + newHash;
                    await PatchBuilder.CompressAsync(newPath, fullPath);

                    compressedHash = await SHA256.GetFileHashAsync(fullPath);

                    fullReplaceSize = new FileInfo(fullPath).Length;

                    if (oldHash != null && oldHash != newHash)
                    {
                        string deltaPath = patchPath + Path.DirectorySeparatorChar + "delta" + Path.DirectorySeparatorChar + newHash + "_from_" + oldHash;
                        await PatchBuilder.CreatePatchAsync(oldPath, newPath, deltaPath);

                        if (new FileInfo(deltaPath).Length >= new FileInfo(fullPath).Length)
                        {
                            File.Delete(deltaPath);
                        }
                        else
                        {
                            deltaHash = await SHA256.GetFileHashAsync(deltaPath);

                            deltaSize = new FileInfo(deltaPath).Length;
                            hasDelta  = true;
                        }
                    }
                }

                instructions.Add(new FilePatchInstruction
                {
                    Path             = path,
                    OldHash          = oldHash,
                    NewHash          = newHash,
                    CompressedHash   = compressedHash,
                    DeltaHash        = deltaHash,
                    OldLastWriteTime = oldLastWriteTime,
                    NewLastWriteTime = newLastWriteTime,
                    FullReplaceSize  = fullReplaceSize,
                    DeltaSize        = deltaSize,
                    HasDelta         = hasDelta,
                });
            }

            string instructionsString = JsonConvert.SerializeObject(instructions);

            File.WriteAllText(patchPath + Path.DirectorySeparatorChar + "instructions.json", instructionsString);
        }
コード例 #2
0
        public async Task CreatePatchAsync(string oldRootPath, string newRootPath, string patchPath)
        {
            var oldPaths = DirectoryPathIterator.GetChildPathsRecursive(oldRootPath).ToArray();
            var newPaths = DirectoryPathIterator.GetChildPathsRecursive(newRootPath).ToArray();

            var instructions = new List <FilePatchInstruction>();

            RxLogger.Logger.Instance.Write($"There are {instructions.Count} instructions in this update package");

            Directory.CreateDirectory(patchPath + Path.DirectorySeparatorChar + "full");
            Directory.CreateDirectory(patchPath + Path.DirectorySeparatorChar + "delta");

            var allPaths = oldPaths.Union(newPaths).ToArray();

            foreach (var path in allPaths)
            {
                // oldPath and newPath refer to files
                string oldPath = oldRootPath + Path.DirectorySeparatorChar + path;
                string newPath = newRootPath + Path.DirectorySeparatorChar + path;

                // Hashes of oldPath and newPath
                string oldHash = GetHash(oldPath);
                string newHash = GetHash(newPath);

                // Hashes of the full (compressed) and delta files
                string compressedHash = null;
                string deltaHash      = null;

                long     newSize          = File.Exists(newPath) ? new FileInfo(newPath).Length : 0;                           // New file size
                DateTime oldLastWriteTime = File.Exists(oldPath) ? new FileInfo(oldPath).LastWriteTimeUtc : DateTime.MinValue; // Old last write time
                DateTime newLastWriteTime = File.Exists(newPath) ? new FileInfo(newPath).LastWriteTimeUtc : DateTime.MinValue; // New last write time
                long     fullReplaceSize  = 0;                                                                                 // Size of the full file
                long     deltaSize        = 0;                                                                                 // Size of the delta
                bool     hasDelta         = false;                                                                             // True if there's a delta, false otherwise

                if (newHash != null)
                {
                    // Copy and compress newPath to fullPath
                    string fullPath = patchPath + Path.DirectorySeparatorChar + "full" + Path.DirectorySeparatorChar + newHash;
                    await _patchBuilder.CompressAsync(newPath, fullPath);

                    compressedHash = await Sha256.GetFileHashAsync(fullPath);

                    fullReplaceSize = new FileInfo(fullPath).Length;

                    // Write delta to deltaPath if the old file differs from the new one
                    if (oldHash != null && oldHash != newHash)
                    {
                        // Create delta
                        string deltaPath = patchPath + Path.DirectorySeparatorChar + "delta" + Path.DirectorySeparatorChar + newHash + "_from_" + oldHash;
                        await _patchBuilder.CreatePatchAsync(oldPath, newPath, deltaPath);

                        // Only keep the delta if it's smaller than the full download
                        if (new FileInfo(deltaPath).Length >= new FileInfo(fullPath).Length)
                        {
                            File.Delete(deltaPath);
                        }
                        else
                        {
                            deltaHash = await Sha256.GetFileHashAsync(deltaPath);

                            deltaSize = new FileInfo(deltaPath).Length;
                            hasDelta  = true;
                        }
                    }
                }

                instructions.Add(new FilePatchInstruction
                {
                    Path             = path,
                    OldHash          = oldHash,
                    NewHash          = newHash,
                    CompressedHash   = compressedHash,
                    DeltaHash        = deltaHash,
                    OldLastWriteTime = oldLastWriteTime,
                    NewLastWriteTime = newLastWriteTime,
                    FullReplaceSize  = fullReplaceSize,
                    DeltaSize        = deltaSize,
                    HasDelta         = hasDelta,
                });
            }

            // Write instructions
            try
            {
                RxLogger.Logger.Instance.Write($"Writing Instruction.json out to {patchPath + Path.DirectorySeparatorChar}instructions.json");
                string instructionsString = JsonConvert.SerializeObject(instructions);
                File.WriteAllText(patchPath + Path.DirectorySeparatorChar + "instructions.json", instructionsString);

                RxLogger.Logger.Instance.Write($"Writing Instructions_hash.txt out to {patchPath + Path.DirectorySeparatorChar}instructions_hash.txt");
                // Write SHA256 hash of instructions.json to instructions_hash.txt
                File.WriteAllText(patchPath + Path.DirectorySeparatorChar + "instructions_hash.txt",
                                  await Sha256.GetFileHashAsync(patchPath + Path.DirectorySeparatorChar + "instructions.json"));
            }
            catch (Exception ex)
            {
                RxLogger.Logger.Instance.Write($"Exception while attempting to write instruction JSON or Hash file.\r\n{ex.Message}\r\n{ex.StackTrace}");
            }
        }