예제 #1
0
        /* =========================================================================================== */

        public void ExecuteRelevantPatches(IEnumerable <ISnPatch> candidates, PatchExecutionContext context)
        {
            var patchesToExec = candidates.ToList();

            while (true)
            {
                var installedComponents = LoadInstalledComponents();
                var executables         = GetExecutablePatches(patchesToExec, installedComponents, context, out _);
                if (executables.Length == 0)
                {
                    break;
                }

                var faulty = ExecutePatches(executables, context);

                if (faulty == null)
                {
                    break;
                }

                RemoveNotExecutables(context, patchesToExec);
                if (patchesToExec.Count == 0)
                {
                    break;
                }
            }
        }
예제 #2
0
        private void RemoveNotExecutables(PatchExecutionContext context, List <ISnPatch> patchesToExec)
        {
            var patches = context.Errors.SelectMany(x => x.FaultyPatches);

            foreach (var patch in patches)
            {
                patchesToExec.Remove(patch);
            }
        }
예제 #3
0
 internal PatchManager(PatchExecutionContext context)
 {
     _context = context;
 }
예제 #4
0
 public PatchManager(RepositoryStartSettings settings, Action <PatchExecutionLogRecord> logCallback)
 {
     _context = new PatchExecutionContext(settings, logCallback);
 }
예제 #5
0
        public ISnPatch[] GetExecutablePatches(IEnumerable <ISnPatch> candidates,
                                               SnComponentDescriptor[] installedComponents, PatchExecutionContext context, out SnComponentDescriptor[] componentsAfter)
        {
            var patches = candidates.ToArray();

            var installedIds = installedComponents
                               .Where(x => x.Version != null && x.Version > NullVersion)
                               .Select(x => x.ComponentId)
                               .ToArray();

            var installers = patches
                             .Where(x => x.Type == PackageType.Install && !installedIds.Contains(x.ComponentId))
                             .OrderBy(x => x.ComponentId)
                             .ToArray();
            var installerGroups = installers.GroupBy(x => x.ComponentId);
            var duplicates      = installerGroups.Where(x => x.Count() > 1).Select(x => x.Key).ToArray();

            if (duplicates.Length > 0)
            {
                // Duplicates are not allowed
                foreach (var id in duplicates)
                {
                    var message       = "There is a duplicated installer for the component " + id;
                    var faultyPatches = installers.Where(inst => inst.ComponentId == id).ToArray();
                    var error         = new PatchExecutionError(PatchExecutionErrorType.DuplicatedInstaller, faultyPatches, message);
                    var logRecord     = new PatchExecutionLogRecord(PatchExecutionEventType.DuplicatedInstaller, faultyPatches.First(), message);
                    context.Errors.Add(error);
                    context.LogCallback(logRecord);
                }

                // Set unchanged list as output
                componentsAfter = installedComponents.ToArray();
                return(new ISnPatch[0]);
            }

            // Order patches by componentId and versions
            var orderedSnPatches = patches
                                   .Where(x => x.Type == PackageType.Patch)
                                   .OrderBy(x => x.ComponentId).ThenBy(x => x.Version)
                                   .ToArray();

            // ------------------------------------------------------------ sorting by dependencies
            var inputList        = installers.Union(orderedSnPatches).ToList();
            var outputList       = new List <ISnPatch>();                                 // patches in right order to execute
            var installed        = new List <SnComponentDescriptor>(installedComponents); // all simulated components.
            var currentlyManaged = new List <ISnPatch>();                                 // temporary list in one iteration.

            while (true)
            {
                foreach (var item in inputList)
                {
                    if (CheckPrerequisites(item, installed, out var skipExecution, out var error))
                    {
                        currentlyManaged.Add(item);
                        outputList.Add(item);

                        if (item is SnPatch snPatch)
                        {
                            // Modify version and dependencies of the installed components.
                            var patchedComponent = installed.Single(x => x.ComponentId == snPatch.ComponentId);
                            patchedComponent.Version      = (Version)snPatch.Version.Clone();
                            patchedComponent.Dependencies = snPatch.Dependencies?.ToArray();
                        }
                        else if (item is ComponentInstaller installer)
                        {
                            // Add to installed components.
                            installed.Add(new SnComponentDescriptor(installer.ComponentId, installer.Version,
                                                                    installer.Description, installer.Dependencies?.ToArray()));
                        }
                        else
                        {
                            throw new SnNotSupportedException();
                        }
                    }
예제 #6
0
 public IEnumerable <ISnPatch> GetExecutablePatches(IEnumerable <ISnPatch> candidates, PatchExecutionContext context)
 {
     return(GetExecutablePatches(candidates, LoadInstalledComponents(), context, out _));
 }
예제 #7
0
 internal ISnPatch ExecuteRelevantPatches(IEnumerable <ISnPatch> candidates,
                                          SnComponentDescriptor[] installedComponents, PatchExecutionContext context)
 {
     return(ExecutePatches(
                GetExecutablePatches(candidates, installedComponents, context, out _), context));
 }