/// <inheritdoc cref="IUpdateCreator.CreateFullPackage"/> public bool CreateFullPackage( ApplicationMetadata applicationMetadata, string applicationLocation, SemanticVersion version, string fullUpdateLocation, OSPlatform?intendedOs = null, Action <double>?progress = null) { if (!Directory.Exists(applicationLocation)) { _logger.Error("{0} doesn't exist, can't create update", applicationLocation); return(false); } _logger.Debug("Creating full update file"); var zipArchive = CreateZipArchive(fullUpdateLocation); var files = Directory.EnumerateFiles(applicationLocation, "*", SearchOption.AllDirectories).ToArray(); var tempFolder = new TemporaryFolder(applicationMetadata.TempFolder); var progressReport = new ProgressReport(files.Length, progress); void Cleanup() { zipArchive.Dispose(); tempFolder.Dispose(); progressReport.DoneCleanup(); } foreach (var file in files) { //We will process the file as a "new" file as we always want to copy it over using var fileStream = File.OpenRead(file); if (AddNewFile(zipArchive, fileStream, file.RemovePath(applicationLocation))) { progressReport.ProcessedFile(); continue; } //if we can't add it then hard fail, can't do anything to save this _logger.Error("Wasn't able to process file, bailing"); Cleanup(); return(false); } //Add the loader into the package if (ShouldMakeLoader && !AddLoaderFile(tempFolder, applicationMetadata, zipArchive, version, applicationLocation)) { _logger.Error("Wasn't able to create loader for this application"); Cleanup(); return(false); } progressReport.ProcessedFile(); Cleanup(); return(true); }
public bool CreateDeltaPackage( ApplicationMetadata applicationMetadata, string newVersionLocation, SemanticVersion newVersion, string baseVersionLocation, SemanticVersion oldVersion, string outputFolder, string deltaUpdateLocation, OSPlatform?intendedOs = null, Action <double>?progress = null) { if (!Directory.Exists(newVersionLocation) || !Directory.Exists(baseVersionLocation)) { _logger.Error("One of the folders don't exist, can't create delta update...."); return(false); } _logger.Debug("Creating delta file"); var zipArchive = CreateZipArchive(deltaUpdateLocation); var tempFolder = new TemporaryFolder(applicationMetadata.TempFolder); void Cleanup() { lock (zipArchive) { zipArchive.Dispose(); } tempFolder.Dispose(); progress?.Invoke(1); } //Get all the files that are in the new version (Removing the Path so we only have the relative path of the file) var newVersionFiles = Directory.EnumerateFiles(newVersionLocation, "*", SearchOption.AllDirectories) .RemovePath(newVersionLocation).ToArray(); //and get the files from the old version var baseVersionFiles = Directory.EnumerateFiles(baseVersionLocation, "*", SearchOption.AllDirectories) .RemovePath(baseVersionLocation).ToArray(); //Find any files that are in both version and process them based on if they had any changes var sameFiles = newVersionFiles.Where(x => baseVersionFiles.Contains(x)).ToArray(); var newFiles = newVersionFiles.Where(x => !sameFiles.Contains(x)).ToArray(); var progressReport = new ProgressReport(newFiles.Length + sameFiles.Length, progress); var deltaFiles = new List <string>(sameFiles.Length); //First process any files that didn't change, don't even count them in the progress as it will be quick af _logger.Information("Processing files that are in both versions"); foreach (var maybeDeltaFile in sameFiles) { _logger.Debug("Processing possible delta file {0}", maybeDeltaFile); var newFileLocation = Path.Combine(newVersionLocation, maybeDeltaFile); /*See if we got a delta file, if so then store it for * processing after files that haven't changed*/ if (IsDeltaFile(Path.Combine(baseVersionLocation, maybeDeltaFile), newFileLocation)) { deltaFiles.Add(maybeDeltaFile); continue; } //Add a pointer to the file that hasn't changed _logger.Debug("{0} hasn't changed, processing as unchanged file", maybeDeltaFile); using var fileStream = File.OpenRead(newFileLocation); if (AddSameFile(zipArchive, maybeDeltaFile, SHA256Util.CreateSHA256Hash(fileStream))) { progressReport.ProcessedFile(); continue; } _logger.Warning("We wasn't able to add {0} as a file that was unchanged, adding as a \"new\" file", maybeDeltaFile); //We wasn't able to add the file as a pointer, try to add it as a new file if (!AddNewFile(zipArchive, fileStream, maybeDeltaFile)) { //Hard bail if we can't even do that _logger.Error("Wasn't able to process {0} as a new file as well, bailing", maybeDeltaFile); Cleanup(); return(false); } progressReport.ProcessedFile(); } //TODO: add "moved files" //Now process files that was added into the new version _logger.Information("Processing files that only exist in the new version"); foreach (var newFile in newFiles) { _logger.Debug("Processing new file {0}", newFile); //Process new file using var fileStream = File.OpenRead(Path.Combine(newVersionLocation, newFile)); if (AddNewFile(zipArchive, fileStream, newFile)) { progressReport.ProcessedFile(); continue; } //if we can't add it then hard fail, can't do anything to save this _logger.Error("Wasn't able to process new file, bailing"); Cleanup(); return(false); } //Now process files that changed var result = Parallel.ForEach(deltaFiles, (deltaFile, state) => { var deltaFileLocation = Path.Combine(newVersionLocation, deltaFile); _logger.Debug("Processing changed file {0}", deltaFile); //Try to add the file as a delta file if (AddDeltaFile(tempFolder, zipArchive, Path.Combine(baseVersionLocation, deltaFile), deltaFileLocation, intendedOs, (pro) => progressReport.PartialProcessedFile(pro))) { progressReport.ProcessedFile(); return; } //If we can't make the file as a delta file try to create it as a "new" file _logger.Warning("Wasn't able to make delta file, adding file as \"new\" file"); using var fileStream = File.OpenRead(Path.Combine(newVersionLocation, deltaFileLocation)); if (AddNewFile(zipArchive, fileStream, deltaFile)) { progressReport.ProcessedFile(); return; } //Hard bail if we can't even do that _logger.Error("Wasn't able to process file as a new file, bailing"); Cleanup(); state.Break(); }); //This will return false if something failed if (!result.IsCompleted) { return(false); } if (ShouldMakeLoader && !AddLoaderFile( tempFolder, applicationMetadata, zipArchive, newVersion, newVersionLocation, intendedOs, oldVersion, outputFolder)) { _logger.Error("Wasn't able to create loader for this application"); Cleanup(); return(false); } progressReport.ProcessedFile(); //We have created the delta file if we get here, do cleanup and then report as success! _logger.Information("We are done with creating the delta file, cleaning up"); Cleanup(); return(true); }