// Copyright Keysight Technologies 2012-2019
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at http://mozilla.org/MPL/2.0/.
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace OpenTap.Package
{
internal static class DependencyChecker
{
static TraceSource log = OpenTap.Log.CreateSource("Packages");
///
/// detects issues and prints them to the log. use filterPackages if its wanted to filter the issues based on newly installed packages.
///
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;
}
///
/// detects issues and prints them to the log. use filterPackages if its wanted to filter the issues based on newly installed packages.
///
private static Issue CheckPackages(IEnumerable packages, IEnumerable 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}' is requested.");
break;
}
}
}
return Issue.BrokenPackages;
}
static Issue checkPackages(IEnumerable installedPackages, string[] packages, LogEventType severity)
{
var packages_new = new List();
foreach (string pkg in packages)
{
if (!File.Exists(pkg))
{
log.Warning("Package does not exists.");
return Issue.MissingPackage;
}
packages_new.Add(PackageDef.FromPackage(pkg));
}
var new_names = packages_new.Select(pkg => pkg.Name).ToArray();
var after_installation = packages_new.Concat(installedPackages.Where(pkg => new_names.Contains(pkg.Name) == false)).ToList();
return CheckPackages(after_installation, packages_new, severity);
}
public enum Issue
{
None,
BrokenPackages,
MissingPackage
}
public static Issue CheckDependencies(Installation installation, IEnumerable newPackages, LogEventType severity = LogEventType.Error)
{
return checkPackages(installation.GetPackages(), newPackages.Select(Path.GetFullPath).ToArray(), severity);
}
public static Issue CheckDependencies(IEnumerable installedPackages, IEnumerable newPackages, LogEventType severity = LogEventType.Error)
{
var newNames = newPackages.Select(pkg => pkg.Name).ToArray();
var afterInstallation = newPackages.Concat(installedPackages.Where(pkg => newNames.Contains(pkg.Name) == false)).ToList();
return CheckPackages(afterInstallation, newPackages, severity);
}
}
}