internal void Combine(PackagingResult other) { Successful &= other.Successful; Terminated |= other.Terminated; NeedRestart |= other.NeedRestart; Errors += other.Errors; }
internal static Dictionary <Version, PackagingResult> ExecuteAssemblyPatches(SnComponentInfo assemblyComponent, RepositoryStartSettings settings = null) { var patchResults = new Dictionary <Version, PackagingResult>(); // If there is no installed component for this id, skip patching. var installedComponent = RepositoryVersionInfo.Instance.Components.FirstOrDefault(c => c.ComponentId == assemblyComponent.ComponentId); if (installedComponent == null) { return(patchResults); } // check which db version is supported by the assembly if (assemblyComponent.SupportedVersion == null || assemblyComponent.SupportedVersion <= installedComponent.Version) { return(patchResults); } // Supported version in the assembly is higher than // the physical version: there should be a patch. if (!(assemblyComponent.Patches?.Any() ?? false)) { throw new InvalidOperationException($"Missing patch for component {installedComponent.ComponentId}. " + $"Installed version is {installedComponent.Version}. " + $"The assembly requires at least version {assemblyComponent.SupportedVersion}."); } foreach (var patch in assemblyComponent.Patches) { // this variable is refreshed in every cycle if (installedComponent == null) { break; } if (patch.MinVersion > patch.MaxVersion || patch.MaxVersion > patch.Version) { // the patch version numbers are the responsibility of the developer of the component SnLog.WriteWarning( $"Patch {patch.Version} for component {assemblyComponent.ComponentId} cannot be executed because it contains invalid version numbers.", properties: new Dictionary <string, object> { { "MinVersion", patch.MinVersion }, { "MaxVersion", patch.MaxVersion } }); continue; } if (!string.IsNullOrEmpty(patch.Contents) && patch.Execute != null) { // ambigous patch definition SnLog.WriteWarning( $"Patch {patch.Version} for component {assemblyComponent.ComponentId} cannot be executed because it contains multiple patch definitions."); continue; } // check if the patch is relevant for the currently installed component version if (patch.MinVersion > installedComponent.Version || patch.MinVersionIsExclusive && patch.MinVersion == installedComponent.Version || patch.MaxVersion < installedComponent.Version || patch.MaxVersionIsExclusive && patch.MaxVersion == installedComponent.Version) { continue; } PackagingResult patchResult; try { if (patch.Contents?.StartsWith("<?xml", StringComparison.InvariantCultureIgnoreCase) ?? false) { // execute manifest patch patchResult = ExecutePatch(patch.Contents, settings); } else if (patch.Execute != null) { // execute code patch patch.Execute(new PatchContext { Settings = settings }); // save the new package info manually based on the patch version number Storage.SavePackageAsync(new Package { ComponentId = assemblyComponent.ComponentId, ComponentVersion = patch.Version, ExecutionResult = ExecutionResult.Successful, PackageType = PackageType.Patch }, CancellationToken.None).GetAwaiter().GetResult(); patchResult = new PackagingResult { NeedRestart = false, Successful = true, Terminated = false, Errors = 0 }; } else { //TODO: handle other patch formats (resource or filesystem path) // unknown patch format patchResult = new PackagingResult { NeedRestart = false, Successful = false, Terminated = false, Errors = 0 }; } } catch (Exception ex) { SnLog.WriteException(ex, $"Error during patch execution for component {assemblyComponent.ComponentId}. Patch target version: {patch.Version}."); throw; } patchResults[patch.Version] = patchResult; // reload installedComponent = RepositoryVersionInfo.Instance.Components.FirstOrDefault(c => c.ComponentId == assemblyComponent.ComponentId); } return(patchResults); }