Пример #1
0
        void applyDiffToFile(string deltaPath, string relativeFilePath, string workingDirectory)
        {
            var inputFile   = Path.Combine(deltaPath, relativeFilePath);
            var finalTarget = Path.Combine(workingDirectory, Regex.Replace(relativeFilePath, @".diff$", ""));

            var tempTargetFile = Path.GetTempFileName();

            // NB: Zero-length diffs indicate the file hasn't actually changed
            if (new FileInfo(inputFile).Length == 0)
            {
                this.Log().Info("{0} exists unchanged, skipping", relativeFilePath);
                return;
            }

            if (relativeFilePath.EndsWith(".diff", StringComparison.InvariantCultureIgnoreCase))
            {
                using (var of = File.OpenWrite(tempTargetFile))
                    using (var inf = File.OpenRead(finalTarget)) {
                        this.Log().Info("Applying Diff to {0}", relativeFilePath);
                        BinaryPatchUtility.Apply(inf, () => File.OpenRead(inputFile), of);
                    }

                try {
                    verifyPatchedFile(relativeFilePath, inputFile, tempTargetFile);
                } catch (Exception) {
                    File.Delete(tempTargetFile);
                    throw;
                }
            }
            else
            {
                using (var of = File.OpenWrite(tempTargetFile))
                    using (var inf = File.OpenRead(inputFile)) {
                        this.Log().Info("Adding new file: {0}", relativeFilePath);
                        inf.CopyTo(of);
                    }
            }

            if (File.Exists(finalTarget))
            {
                File.Delete(finalTarget);
            }

            var targetPath = Directory.GetParent(finalTarget);

            if (!targetPath.Exists)
            {
                targetPath.Create();
            }

            File.Move(tempTargetFile, finalTarget);
        }
Пример #2
0
        void createDeltaForSingleFile(FileInfo targetFile, DirectoryInfo workingDirectory, Dictionary <string, string> baseFileListing)
        {
            // NB: There are three cases here that we'll handle:
            //
            // 1. Exists only in new => leave it alone, we'll use it directly.
            // 2. Exists in both old and new => write a dummy file so we know
            //    to keep it.
            // 3. Exists in old but changed in new => create a delta file
            //
            // The fourth case of "Exists only in old => delete it in new"
            // is handled when we apply the delta package
            var relativePath = targetFile.FullName.Replace(workingDirectory.FullName, "");

            if (!baseFileListing.ContainsKey(relativePath))
            {
                this.Log().Info("{0} not found in base package, marking as new", relativePath);
                return;
            }

            var oldData = File.ReadAllBytes(baseFileListing[relativePath]);
            var newData = File.ReadAllBytes(targetFile.FullName);

            if (bytesAreIdentical(oldData, newData))
            {
                this.Log().Info("{0} hasn't changed, writing dummy file", relativePath);

                File.Create(targetFile.FullName + ".diff").Dispose();
                File.Create(targetFile.FullName + ".shasum").Dispose();
                targetFile.Delete();
                return;
            }

            this.Log().Info("Delta patching {0} => {1}", baseFileListing[relativePath], targetFile.FullName);
            using (var of = File.Create(targetFile.FullName + ".diff")) {
                BinaryPatchUtility.Create(oldData, newData, of);

                var rl = ReleaseEntry.GenerateFromFile(new MemoryStream(newData), targetFile.Name + ".shasum");
                File.WriteAllText(targetFile.FullName + ".shasum", rl.EntryAsString, Encoding.UTF8);
                targetFile.Delete();
            }
        }
Пример #3
0
        public ReleasePackage CreateDeltaPackage(ReleasePackage baseFixture, string outputFile)
        {
            Contract.Requires(baseFixture != null && baseFixture.ReleasePackageFile != null);
            Contract.Requires(!String.IsNullOrEmpty(outputFile) && !File.Exists(outputFile));

            string baseTempPath = null;
            string tempPath     = null;

            using (Utility.WithTempDirectory(out baseTempPath))
                using (Utility.WithTempDirectory(out tempPath)) {
                    var baseTempInfo = new DirectoryInfo(baseTempPath);
                    var tempInfo     = new DirectoryInfo(tempPath);

                    using (var zf = new ZipFile(baseFixture.ReleasePackageFile)) {
                        zf.ExtractAll(baseTempInfo.FullName);
                    }

                    using (var zf = new ZipFile(ReleasePackageFile)) {
                        zf.ExtractAll(tempInfo.FullName);
                    }

                    // Collect a list of relative paths under 'lib' and map them
                    // to their full name. We'll use this later to determine in
                    // the new version of the package whether the file exists or
                    // not.
                    var baseLibFiles = baseTempInfo.GetAllFilesRecursively()
                                       .Where(x => x.FullName.ToLowerInvariant().Contains("lib" + Path.DirectorySeparatorChar))
                                       .ToDictionary(k => k.FullName.Replace(baseTempInfo.FullName, ""), v => v.FullName);

                    var newLibDir = tempInfo.GetDirectories().First(x => x.Name.ToLowerInvariant() == "lib");

                    // NB: There are three cases here that we'll handle:
                    //
                    // 1. Exists only in new => leave it alone, we'll use it directly.
                    // 2. Exists in both old and new => write a dummy file so we know
                    //    to keep it.
                    // 3. Exists in old but changed in new => create a delta file
                    //
                    // The fourth case of "Exists only in old => delete it in new"
                    // is handled when we apply the delta package
                    newLibDir.GetAllFilesRecursively().ForEach(libFile => {
                        var relativePath = libFile.FullName.Replace(tempInfo.FullName, "");

                        if (!baseLibFiles.ContainsKey(relativePath))
                        {
                            this.Log().Info("{0} not found in base package, marking as new", relativePath);
                            return;
                        }

                        var oldData = File.ReadAllBytes(baseLibFiles[relativePath]);
                        var newData = File.ReadAllBytes(libFile.FullName);

                        if (bytesAreIdentical(oldData, newData))
                        {
                            this.Log().Info("{0} hasn't changed, writing dummy file", relativePath);

                            File.Create(libFile.FullName + ".diff").Dispose();
                            File.Create(libFile.FullName + ".shasum").Dispose();
                            libFile.Delete();
                            return;
                        }

                        this.Log().Info("Delta patching {0} => {1}", baseLibFiles[relativePath], libFile.FullName);
                        using (var of = File.Create(libFile.FullName + ".diff")) {
                            BinaryPatchUtility.Create(oldData, newData, of);

                            var rl = ReleaseEntry.GenerateFromFile(new MemoryStream(newData), libFile.Name + ".shasum");
                            File.WriteAllText(libFile.FullName + ".shasum", rl.EntryAsString, Encoding.UTF8);
                            libFile.Delete();
                        }
                    });

                    addDeltaFilesToContentTypes(tempInfo.FullName);

                    using (var zf = new ZipFile(outputFile)) {
                        zf.AddDirectory(tempInfo.FullName);
                        zf.Save();
                    }
                }

            return(new ReleasePackage(outputFile));
        }