Example #1
0
        /// <summary>
        /// detects issues and prints them to the log. use filterPackages if its wanted to filter the issues based on newly installed packages.
        /// </summary>
        private static Issue CheckPackages(IEnumerable <PackageDef> packages, IEnumerable <PackageDef> newPackages, LogEventType severity)
        {
            var tree = DependencyAnalyzer.BuildAnalyzerContext(packages.ToList());

            if (newPackages != null)
            {
                tree = tree.FilterRelated(newPackages.ToList());
            }
            if (tree.BrokenPackages.Count == 0)
            {
                return(Issue.None);
            }
            foreach (var pkg in tree.BrokenPackages)
            {
                foreach (var issue in tree.GetIssues(pkg))
                {
                    switch (issue.IssueType)
                    {
                    case DependencyIssueType.Missing:
                        log.TraceEvent(severity, 0, $"Package '{pkg.Name}' depends on '{issue.PackageName}' which will not be installed.");
                        break;

                    case DependencyIssueType.DependencyMissing:
                        log.TraceEvent(severity, 0, $"Package '{pkg.Name}' depends on '{issue.PackageName} which itself will be broken (See message related to other plugin).");
                        break;

                    case DependencyIssueType.IncompatibleVersion:
                        log.TraceEvent(severity, 0, $"Package '{pkg.Name}' depends on '{issue.PackageName}' version '{issue.ExpectedVersion}', but '{issue.LoadedVersion}' will be installed.");
                        break;
                    }
                }
            }
            return(Issue.BrokenPackages);
        }
Example #2
0
        /// <summary>
        /// detects issues and prints them to the log. use filterPackages if its wanted to filter the issues based on newly installed packages.
        /// </summary>
        public static Issue CheckInstalledPackages(string installDir)
        {
            var packages = new Installation(installDir).GetPackages();
            var tree     = DependencyAnalyzer.BuildAnalyzerContext(packages.ToList());

            if (tree.BrokenPackages.Count == 0)
            {
                return(Issue.None);
            }
            log.Error("Package Dependency Warning");
            foreach (var pkg in tree.BrokenPackages)
            {
                log.Warning("The Package '{0}' has the following dependency issues:", pkg.Name);
                foreach (var issue in tree.GetIssues(pkg))
                {
                    switch (issue.IssueType)
                    {
                    case DependencyIssueType.Missing:
                        log.Info("  * The package depends on '{0}' (v{1}) which is not installed.", issue.PackageName, issue.ExpectedVersion);
                        break;

                    case DependencyIssueType.DependencyMissing:
                        log.Info("  * The package depends on '{0} which has issues.", issue.PackageName);
                        log.Info("    See message related to other packages.");
                        break;

                    case DependencyIssueType.IncompatibleVersion:
                        log.Info("  * The package depends on '{0}' version '{1}', but '{2}' was installed.", issue.PackageName, issue.ExpectedVersion, issue.LoadedVersion);
                        break;
                    }
                }
            }
            return(Issue.BrokenPackages);
        }
Example #3
0
        /// <summary>
        ///  Builds a DependencyTree based on the dependencies between the packages.
        /// </summary>
        /// <param name="packages"></param>
        /// <returns></returns>
        public static DependencyAnalyzer BuildAnalyzerContext(List <PackageDef> packages)
        {
            Dictionary <string, PackageDef>             packagesLookup = packages.GroupBy(p => p.Name).Select(p => p.First()).ToDictionary(pkg => pkg.Name);
            Dictionary <PackageDef, List <PackageDef> > dependers      = packages.ToDictionary(pkg => pkg, pkg => new List <PackageDef>());
            HashSet <PackageDef> broken_packages = new HashSet <PackageDef>();

            foreach (var package in packages)
            {
                foreach (var dep in package.Dependencies)
                {
                    if (false == packagesLookup.ContainsKey(dep.Name))
                    { // missing: create placeholder. null means missing.
                        packagesLookup[dep.Name] = new PackageDef {
                            Dependencies = new List <PackageDependency>(), Name = dep.Name, Version = null, Files = new List <PackageFile>()
                        };
                        dependers[packagesLookup[dep.Name]] = new List <PackageDef>();
                    }

                    var loadedpackage = packagesLookup[dep.Name];
                    if (false == dep.Version.IsCompatible(loadedpackage.Version) || null == loadedpackage.Version)
                    {
                        broken_packages.Add(package);
                    }

                    dependers[packagesLookup[dep.Name]].Add(package);
                }
            }

            // find nth order broken packages
            // if a dependency is broken, the depender is also broken.
            Stack <PackageDef> newBroken = new Stack <PackageDef>(broken_packages);

            while (newBroken.Count > 0)
            {
                var item = newBroken.Pop();
                var deps = dependers[item];
                foreach (var dep in deps)
                {
                    if (!broken_packages.Contains(dep))
                    {
                        broken_packages.Add(dep);
                        newBroken.Push(dep);
                    }
                }
            }

            DependencyAnalyzer deptree = new DependencyAnalyzer();

            deptree.BrokenPackages = broken_packages.ToList().AsReadOnly();
            deptree.packagesLookup = packagesLookup;
            deptree.dependers      = dependers;
            return(deptree);
        }
Example #4
0
        private bool CheckPackageAndDependencies(List <PackageDef> installed, List <string> packagePaths)
        {
            var packages = packagePaths.Select(PackageDef.FromXml).ToList();

            installed.RemoveIf(i => packages.Any(u => u.Name == i.Name && u.Version == i.Version));
            var analyzer           = DependencyAnalyzer.BuildAnalyzerContext(installed);
            var packagesWithIssues = new List <PackageDef>();

            foreach (var inst in installed)
            {
                if (analyzer.GetIssues(inst).Any(i => packages.Any(p => p.Name == i.PackageName)))
                {
                    packagesWithIssues.Add(inst);
                }
            }

            if (packages.Any(p => p.Files.Any(f => f.FileName.ToLower().EndsWith("OpenTap.dll"))))
            {
                log.Error("OpenTAP cannot be uninstalled.");
                return(false);
            }

            if (packagesWithIssues.Any())
            {
                log.Warning("Plugin Dependecy Conflict.");

                var question = string.Format("One or more installed packages depend on {0}. Uninstalling might cause these packages to break:\n{1}",
                                             string.Join(" and ", packages.Select(p => p.Name)),
                                             string.Join("\n", packagesWithIssues.Select(p => p.Name + " " + p.Version)));

                var req = new ContinueRequest {
                    message = question, Response = ContinueResponse.Continue
                };
                UserInput.Request(req, true);

                return(req.Response == ContinueResponse.Continue);
            }
            else
            {
                foreach (var bundle in packages.Where(p => p.IsBundle()).ToList())
                {
                    log.Warning("Package '{0}' is a bundle and has installed:\n{1}\n\nThese packages must be uninstalled separately.\n",
                                bundle.Name,
                                string.Join("\n", bundle.Dependencies.Select(d => d.Name)));
                }

                return(true);
            }
        }
Example #5
0
        private void GetPackageInfo(PackageDef package, List <PackageVersion> packageVersions,
                                    Installation installation)
        {
            var allPackages      = installation.GetPackages();
            var latestVersion    = packageVersions?.Max(p => p.Version);
            var packageInstalled = allPackages.Contains(package);

            if (!packageInstalled)
            {
                allPackages.Add(package);
            }

            var tree   = DependencyAnalyzer.BuildAnalyzerContext(allPackages);
            var issues = tree.GetIssues(package);

            ParseDescription(package.Description);

            // Get similar releases to get available platforms and architectures
            var similarReleases = packageVersions.Where(x =>
                                                        x.Version.Major == package.Version.Major && x.Version.Minor == package.Version.Minor).ToList();

            AddWritePair("Package Name", package.Name);

            AddWritePair("Group", package.Group);

            var installedVersion = installation.GetPackages().Where(x => x.Name == package.Name)?.FirstOrDefault()?.Version;
            var installedString  = installedVersion == null ? "(not installed)" : $"({installedVersion} installed)";

            AddWritePair("Version", $"{package.Version} {installedString}");

            if (latestVersion != null && installedVersion != null && latestVersion != installedVersion)
            {
                AddWritePair("Newest Version in Repository", $"{latestVersion}");
            }

            AddWritePair("Compatible Architectures", string.Join(Environment.NewLine, similarReleases.Select(x => x.Architecture).Distinct()));
            AddWritePair("Compatible Platforms", string.Join(Environment.NewLine, similarReleases.Select(x => x.OS).Distinct()));

            if (packageInstalled == false)
            {
                AddWritePair("Compatibility Issues", issues.Any()
                    ? $"{(string.Join(Environment.NewLine, issues.Select(x => $"{x.PackageName} - {x.IssueType.ToString()}")))}"
                    : "none");
            }

            AddWritePair("Owner", package.Owner);
            var licenseString = (package.LicenseRequired ?? "").Replace("&", " and ").Replace("|", " or ");

            AddWritePair("License Required", licenseString);
            AddWritePair("SourceUrl", package.SourceUrl);
            if (package.PackageSource is IRepositoryPackageDefSource repoPkg)
            {
                AddWritePair("Repository", repoPkg.RepositoryUrl);
            }
            AddWritePair("Package Type", package.FileType);
            AddWritePair("Package Class", package.Class);

            var tags = package.Tags?.Split(new string[] { " ", "," }, StringSplitOptions.RemoveEmptyEntries);

            if (tags?.Length > 0)
            {
                AddWritePair("Package Tags", string.Join(" ", tags));
            }

            if (package.Dependencies.Count > 0)
            {
                AddWritePair("Dependencies", string.Join(Environment.NewLine, package.Dependencies.Select(x => x.Name)));
            }

            foreach (var(key, value) in SubTags)
            {
                AddWritePair(key, value);
            }

            AddWritePair("Description", Description);

            if (IncludeFiles)
            {
                if (package.Files.Count > 0)
                {
                    AddWritePair("Files", string.Join(Environment.NewLine, package.Files.Select(x => x.RelativeDestinationPath.Replace("\\", "/"))));
                }
            }

            if (IncludePlugins)
            {
                var plugins = package.Files.Select(x => x.Plugins);

                var sb = new StringBuilder();
                foreach (var plugin in plugins)
                {
                    foreach (var p in plugin)
                    {
                        var name = p.Name;
                        var desc = p.Description;
                        sb.Append(!string.IsNullOrWhiteSpace(desc) ? $"{name} ({desc}){Environment.NewLine}" : $"{name}{Environment.NewLine}");
                    }
                }
                AddWritePair("Plugins", sb.ToString());
            }

            WritePairs();
        }