Пример #1
0
        private bool CheckVersionRequirements(ProfileManifest16 manifest, out IList <StatusReportItem> problems)
        {
            List <StatusReportItem> report = new List <StatusReportItem>();

            if (manifest.VersionsRequired == null)
            {
                problems = report;
                return(true);
            }
            foreach (VersionRequired versionRequired in manifest.VersionsRequired)
            {
                if (!FetchVersion(versionRequired.Product, out Version version))
                {
                    report.Add(new StatusReportItem
                    {
                        Status =
                            $"Helios does not recognize product '{versionRequired.Product}' which is required by this archive",
                        Recommendation =
                            "find a version of this archive for the Helios distribution that you have or manually edit the archive contents at your own risk",
                        Severity = StatusReportItem.SeverityCode.Warning,
                        Flags    = StatusReportItem.StatusFlags.ConfigurationUpToDate
                    });
                    continue;
                }
                if (versionRequired.Minimum != null && version < versionRequired.Minimum)
                {
                    report.Add(new StatusReportItem
                    {
                        Status =
                            $"This archive requires {versionRequired.Product} version {versionRequired.Minimum} or higher. You have version {version}.",
                        Recommendation =
                            $"upgrade {versionRequired.Product} or find a version of this archive for the {versionRequired.Product} version you have",
                        Severity = StatusReportItem.SeverityCode.Warning,
                        Flags    = StatusReportItem.StatusFlags.ConfigurationUpToDate
                    });
                    continue;
                }
                if (versionRequired.Maximum != null && version > versionRequired.Maximum)
                {
                    report.Add(new StatusReportItem
                    {
                        Status =
                            $"This archive requires {versionRequired.Product} version {versionRequired.Maximum} or lower. You have version {version}.",
                        Recommendation =
                            $"find a version of this archive for the {versionRequired.Product} version you have",
                        Severity = StatusReportItem.SeverityCode.Warning,
                        Flags    = StatusReportItem.StatusFlags.ConfigurationUpToDate
                    });
                }
            }

            // return success only if we reported nothing
            problems = report;
            return(!report.Any());
        }
Пример #2
0
        private bool ShowWelcome(IInstallationCallbacks2 callbacks, ProfileManifest16 manifest)
        {
            if (string.IsNullOrEmpty(manifest.Description) && (manifest.Info == null || !manifest.Info.Any()))
            {
                // nothing to present, continue
                return(true);
            }

            List <StructuredInfo> info = new List <StructuredInfo>();

            // add info that has its own properties
            if (manifest.Authors != null)
            {
                info.AddRange(manifest.Authors.Select(manifestAuthor => new StructuredInfo("Author", manifestAuthor)));
            }
            if (!string.IsNullOrEmpty(manifest.License))
            {
                info.Add(new StructuredInfo("License", manifest.License));
            }
            if (!string.IsNullOrEmpty(manifest.Version))
            {
                info.Add(new StructuredInfo("Version", manifest.Version));
            }

            // gather structured info
            if (null != manifest.Info)
            {
                info.AddRange(manifest.Info);
            }

            return(callbacks.DangerPrompt(
                       $"{ArchivePath} Installation",
                       $"Helios is about to install: {manifest.Description ?? ArchivePath}",
                       info,
                       new List <StatusReportItem>()) == InstallationPromptResult.Ok);
        }
Пример #3
0
        public InstallationResult Install(IInstallationCallbacks2 callbacks)
        {
            ProfileManifest16 manifest = null;

            try
            {
                using (ZipArchive archive = ZipFile.Open(_archivePath, ZipArchiveMode.Read))
                {
                    ZipArchiveEntry manifestEntry = archive.Entries.FirstOrDefault(entry =>
                                                                                   entry.FullName.Equals(MANIFEST_PATH, StringComparison.CurrentCultureIgnoreCase));
                    if (manifestEntry != null)
                    {
                        manifest = LoadManifest(manifestEntry);
                        if (manifest == null)
                        {
                            // this cannot happen because we would get a parse failure?  maybe empty file?
                            throw new Exception($"JSON manifest {MANIFEST_PATH} could not be parsed");
                        }

                        // see if we are allowed to install this package
                        if (!CheckVersionRequirements(manifest, out IList <StatusReportItem> problems))
                        {
                            if (RunningVersion.IsDevelopmentPrototype ||
                                ConfigManager.SettingsManager.LoadSetting("ArchiveInstall", "VersionOverride", false))
                            {
                                InstallationPromptResult result = callbacks.DangerPrompt($"{ArchivePath} Installation",
                                                                                         "Installation requirements are not met.  Do you want to install anyway?", problems);
                                if (result == InstallationPromptResult.Cancel)
                                {
                                    return(InstallationResult.Canceled);
                                }
                            }
                            else
                            {
                                callbacks.Failure($"{ArchivePath} cannot be installed", "Installation requirements are not met", problems);
                                return(InstallationResult.Canceled);
                            }
                        }

                        // present welcome screen, if applicable
                        if (!ShowWelcome(callbacks, manifest))
                        {
                            callbacks.Failure($"{ArchivePath} installation canceled", "Installation canceled by user", new List <StatusReportItem>());
                            return(InstallationResult.Canceled);
                        }

                        // process selection and build exclusion list
                        foreach (Choice choice in manifest.Choices)
                        {
                            // filter options based on version requirements
                            List <StatusReportItem> details = new List <StatusReportItem>();
                            foreach (Option option in choice.Options)
                            {
                                if (!CheckVersionRequirements(option, out IList <StatusReportItem> optionDetails))
                                {
                                    // this option is not allowed
                                    details.AddRange(optionDetails);
                                    option.IsValid           = false;
                                    option.ValidityNarrative = "Version requirements not met";
                                }
                            }

                            // check if we still have viable choices
                            if (!choice.Options.Any())
                            {
                                callbacks.Failure($"{ArchivePath} cannot be installed", "None of the options for a required choice are valid for your installation.", details);
                                return(InstallationResult.Fatal);
                            }

                            // fix up dialog if not specified
                            choice.Message = choice.Message ?? "The Profile Archive being installed contains multiple versions of some of its files.  Please choose one version to install:";

                            // wait for response
                            Option selected = PresentChoice(choice);

                            // check if dialog closed or canceled
                            if (selected == null)
                            {
                                return(InstallationResult.Canceled);
                            }

                            // process results
                            if (selected?.PathExclusions != null)
                            {
                                foreach (string path in selected.PathExclusions)
                                {
                                    _pathExclusions.Add(path);
                                }
                            }
                        }
                    }

                    // first check if we have a whole lot of writable files, in which case ask the user if the overwrite strategy should be changed
                    CheckForFirstArchiveInstall(archive);

                    // now unpack everything
                    IList <StatusReportItem> report = archive.Entries
                                                      .Where(NotFilteredVerbose)
                                                      .Select(Unpack)
                                                      .Where(item => item != null)
                                                      .ToList();

                    callbacks.Success($"Installed {ArchivePath}",
                                      $"Files were installed into {Anonymizer.Anonymize(ConfigManager.DocumentPath)}", report);
                }

                return(InstallationResult.Success);
            }
            catch (Exception ex)
            {
                callbacks.Failure($"Failed to install {ArchivePath}",
                                  $"Attempt to install Helios Profile from '{Anonymizer.Anonymize(_archivePath)}' failed",
                                  ReportException(ex));
                return(InstallationResult.Fatal);
            }
        }