示例#1
0
        public void UpdateFullArchive()
        {
            string TestName         = $"UpdateFullArchive_DefaultUpdateDir_Logging";
            string AppDir           = Path.Combine(Helper.BaseDirectory, TestName, "app");
            string UpdateDir        = Path.Combine(Helper.BaseDirectory, TestName, "update");
            string DefaultUpdateDir = Path.Combine(AppDir, "update");
            string UpdateFiles      = Path.Combine(Helper.BaseDirectory, TestName, "updateFiles");

            // Cleanup prior test
            if (Directory.Exists(AppDir))
            {
                Directory.Delete(AppDir, true);
            }
            if (Directory.Exists(UpdateDir))
            {
                Directory.Delete(UpdateDir, true);
            }
            if (Directory.Exists(UpdateFiles))
            {
                Directory.Delete(UpdateFiles, true);
            }

            // Prepare
            Helper.CopyDirectory(Path.Combine(Helper.TestFilesDirectory, "app_v1"), AppDir);
            Helper.CopyDirectory(Path.Combine(Helper.TestFilesDirectory, "updatedir_v3"), UpdateFiles);
            // force full archive update by making sure its smaller than the patches
            string     updateInfoFile = Path.Combine(UpdateFiles, "update.json");
            UpdateInfo updateInfo     = UpdateInfo.Deserialize(File.ReadAllText(updateInfoFile));

            updateInfo.PatchTrail[updateInfo.PatchTrail.Count - 1].SizeInBytes = updateInfo.FullAppArchiveSize * 2;
            File.WriteAllText(updateInfoFile, updateInfo.Serialize());

            // Start app
            string  arguments = $"{new Uri(UpdateFiles).ToString()} true";
            Process app       = Process.Start(Path.Combine(AppDir, Helper.AppName), arguments);

            app.WaitForExit();
            Assert.Equal(0, app.ExitCode);

            Thread.Sleep(Helper.UPDATER_TIMEOUT); // wait for the updater to patch the files

            Assert.True(Directory.Exists(DefaultUpdateDir));
            Directory.Move(DefaultUpdateDir, UpdateDir);

            Assert.True(Helper.DirectoriesEqual(Path.Combine(Helper.TestFilesDirectory, "app_v3"), AppDir));
        }
 private void OpenFile(string filename)
 {
     textBox1.Text = filename;
     if (File.Exists(filename))
     {
         try
         {
             using (var file = File.OpenRead(filename))
             {
                 var deserialized = UpdateInfo.Deserialize(file);
                 CurrentUpdateInfos = deserialized;
             }
             return;
         }
         catch (Exception ex)
         {
             Console.WriteLine(ex);
             MessageBox.Show("Failed to read the file - " + ex.Message, "Open file", MessageBoxButtons.OK, MessageBoxIcon.Error);
         }
     }
     CurrentUpdateInfos = new UpdateInfo.Updates();
 }
示例#3
0
        public void Start(string AssemblyFileName, string AppDirectory, string OutputDirectory, string WorkingDirectory)
        {
            Log.Info($"Arguments: assemblyFileName={AssemblyFileName} appDir={AppDirectory} outputDir={OutputDirectory} workDir={WorkingDirectory}");
            // prepare
            string SignatureDirectory = Path.Combine(WorkingDirectory, "signatures");

            Directory.CreateDirectory(SignatureDirectory);
            string PatchDirectory = Path.Combine(WorkingDirectory, "patch");

            if (Directory.Exists(PatchDirectory))
            {
                Directory.Delete(PatchDirectory, true);
            }
            Directory.CreateDirectory(PatchDirectory);

            DeltaBuilder.ProgressReport = new ConsoleProgressReporter(); // TODO use logger

            // load patchInfo
            Log.Debug("loading patchInfo");
            PatchInfo patchInfo;
            string    patchInfoFile = Path.Combine(WorkingDirectory, "patch.json");

            if (File.Exists(patchInfoFile))
            {
                patchInfo = PatchInfo.Deserialize(File.ReadAllText(patchInfoFile));
            }
            else
            {
                patchInfo = new PatchInfo();
            }

            // diff files and generate patch
            Log.Debug("generate patch");
            var hasher = xxHashFactory.Instance.Create();

            string[] files = Directory.GetFiles(AppDirectory, "*", SearchOption.AllDirectories);
            for (int i = 0; i < files.Length; i++)
            {
                string filePath    = files[i];
                string relFilePath = Path.GetRelativePath(AppDirectory, filePath);
                Log.Info($"({i + 1}/{files.Length}): {relFilePath}");

                string newHash;
                using (var fileStream = File.OpenRead(filePath))
                    newHash = hasher.ComputeHash(fileStream).AsHexString();

                if (patchInfo.FileHashes.TryGetValue(relFilePath, out string oldHash))
                {
                    if (!oldHash.Equals(newHash))
                    { // found newer version of this file => add delta to patch
                        Log.Trace($"file is newer => calculating delta");
                        // calc delta file
                        string deltaFilePath = Path.Combine(PatchDirectory, $"{relFilePath}.delta");
                        Directory.CreateDirectory(Path.GetDirectoryName(deltaFilePath));
                        string signatureFilePath = Path.Combine(SignatureDirectory, $"{relFilePath}.sig");
                        CalculateDelta(signatureFilePath, filePath, deltaFilePath);
                        // calc new signature
                        if (File.Exists(signatureFilePath))
                        {
                            File.Delete(signatureFilePath);
                        }
                        CalculateSignature(filePath, signatureFilePath);
                        // update hash
                        patchInfo.FileHashes[relFilePath] = newHash;
                    }
                }
                else
                { // completely new file => just add it to the patch
                    Log.Trace($"new file => copy it");
                    // copy file to patchDirectory
                    string newFilePath = Path.Combine(PatchDirectory, relFilePath);
                    Directory.CreateDirectory(Path.GetDirectoryName(newFilePath));
                    File.Copy(filePath, newFilePath);
                    // calc signature
                    string signatureFilePath = Path.Combine(SignatureDirectory, $"{relFilePath}.sig");
                    Directory.CreateDirectory(Path.GetDirectoryName(signatureFilePath));
                    CalculateSignature(filePath, signatureFilePath);
                    // add file+hash to patchInfo
                    patchInfo.FileHashes.Add(relFilePath, newHash);
                }
            }
            Log.Debug("generate patch finished");

            // sanity check: has anything changed?
            if (Directory.GetFiles(PatchDirectory, "*", SearchOption.AllDirectories).Length == 0)
            {
                Log.Warn("No changes found => not generating an empty patch! => exiting");
                Environment.Exit(0);
            }

            // write patch.json
            Log.Debug("Write patch.json");
            File.WriteAllText(patchInfoFile, patchInfo.Serialize());

            // package the patch into a .zip
            Version targetVersion = Assembly.LoadFrom(Path.Combine(AppDirectory, AssemblyFileName)).GetName().Version;
            string  patchFileName = $"patch_{targetVersion.ToString().Replace('.', '_')}.zip";

            Log.Info($"Packaging {patchFileName}");
            string patchFilePath = Path.Combine(OutputDirectory, patchFileName);

            ZipFile.CreateFromDirectory(PatchDirectory, patchFilePath);

            // load update.json
            Log.Debug("Load update.json");
            UpdateInfo updateInfo;
            string     updateInfoFilePath = Path.Combine(OutputDirectory, "update.json");

            if (File.Exists(updateInfoFilePath))
            {
                updateInfo = UpdateInfo.Deserialize(File.ReadAllText(updateInfoFilePath));
            }
            else
            {
                updateInfo = new UpdateInfo();
            }

            // add patch to patchtrail
            Log.Debug("Add patch to patchtrail");
            long fileSize = new FileInfo(patchFilePath).Length;

            updateInfo.PatchTrail.Add(new Patch(targetVersion, "", fileSize));

            // package full app archive into a .zip
            Log.Info($"Packaging {updateInfo.FullAppArchiveName}.zip");
            string fullAppArchiveFilePath = Path.Combine(OutputDirectory, $"{updateInfo.FullAppArchiveName}.zip");

            if (File.Exists(fullAppArchiveFilePath))
            {
                File.Delete(fullAppArchiveFilePath);
            }
            ZipFile.CreateFromDirectory(AppDirectory, fullAppArchiveFilePath);

            // update fullAppArchiveSize
            Log.Debug("Update fullAppArchiveSize");
            fileSize = new FileInfo(fullAppArchiveFilePath).Length;
            updateInfo.FullAppArchiveSize = fileSize;

            // add updater version & filesize
            Log.Debug("add updater version & filesize");
            foreach (string updaterFilePath in new string[] { Path.Combine(OutputDirectory, "updater.exe"), Path.Combine(OutputDirectory, "updater") })
            {
                if (File.Exists(updaterFilePath))
                {
                    updateInfo.UpdaterVersion = new Version(FileVersionInfo.GetVersionInfo(updaterFilePath).FileVersion); // File Version is equal to assembly version
                    updateInfo.UpdaterSize    = new FileInfo(updaterFilePath).Length;
                }
            }

            // write update.json
            Log.Info("Updating update.json");
            File.WriteAllText(updateInfoFilePath, updateInfo.Serialize());

            // clean up patch directory
            Log.Debug("Clean up patch directory");

            if (Directory.Exists(PatchDirectory))
            {
                Directory.Delete(PatchDirectory, true);
            }
        }