public void TestPackageCompatibilityResult() { var versions = new SortedSet <string> { "1.0.0", "1.0.1-beta", "2.0.0", }; var packageVersionPair = new PackageVersionPair { PackageId = "MyNugetPackage", PackageSourceType = PackageSourceType.NUGET, Version = "1.0.0" }; var packageDetails = new PackageDetails { Name = "MyNugetPackage", Versions = versions, Targets = new Dictionary <string, SortedSet <string> > { { "netcoreapp3.1", versions } } }; var compatResults = PackageCompatibility.IsCompatibleAsync(Task.FromResult(packageDetails), packageVersionPair, NullLogger.Instance); var recommendation = PackageCompatibility.GetPackageAnalysisResult(compatResults, packageVersionPair, "netcoreapp3.1").Result; Assert.AreEqual(2, compatResults.Result.CompatibleVersions.Count); Assert.AreEqual(1, recommendation.CompatibilityResults["netcoreapp3.1"].CompatibleVersions.Count); Assert.AreEqual("2.0.0", recommendation.Recommendations.RecommendedActions[0].Description); }
public void TestIsCompatibleAsync_ReturnsIncompatible_PackageVersionNotInTargetVersions() { var versions = new SortedSet <string> { "4.0.0", "4.5.0" }; var packageVersionPair = new PackageVersionPair { PackageId = "System.DirectoryServices", PackageSourceType = PackageSourceType.NUGET, Version = "5.0.0" }; var packageDetails = new PackageDetails { Name = "System.DirectoryServices", Versions = versions, Targets = new Dictionary <string, SortedSet <string> > { { "net5.0", versions } } }; var compatResults = PackageCompatibility.IsCompatibleAsync(Task.FromResult(packageDetails), packageVersionPair, NullLogger.Instance); Assert.AreEqual(0, compatResults.Result.CompatibleVersions.Count); Assert.AreEqual(Compatibility.INCOMPATIBLE, compatibilityResult.Compatibility); }
void CreatePackageCompatibility(string packageFrameworkName) { package = FakePackage.CreatePackageWithVersion("MyPackage", "1.2.3.4"); FrameworkName packageFramework = VersionUtility.ParseFrameworkName(packageFrameworkName); packageCompatibility = new PackageCompatibility(project, package, packageFramework); }
public static PackageCompatibility Combine(this PackageCompatibility self, PackageCompatibility other) { if (self == PackageCompatibility.Unknown || other == PackageCompatibility.Unknown) return PackageCompatibility.Unknown; else return (PackageCompatibility)MathF.Min((int)self, (int)other); }
public static bool IsAtLeast(this PackageCompatibility self, PackageCompatibility other) { if (self == PackageCompatibility.Unknown) { return(false); } return((int)self >= (int)other); }
protected void GetUpdateCompatibility(PackageManager manager) { PackageCompatibility compatibility = manager.GetForwardCompatibility(this.NewestPackageInfo); lock (this.asyncDataLock) { this.updateCompatibility = compatibility; } }
public static PackageCompatibility Combine(this PackageCompatibility self, PackageCompatibility other) { if (self == PackageCompatibility.Unknown || other == PackageCompatibility.Unknown) { return(PackageCompatibility.Unknown); } else { return((PackageCompatibility)MathF.Min((int)self, (int)other)); } }
private bool ConfirmCompatibility(IEnumerable <PackageInfo> packages) { PackageCompatibility compatibility = PackageCompatibility.Definite; foreach (PackageInfo package in packages) { PackageCompatibility otherCompat = this.packageManager.GetCompatibilityLevel(package); compatibility = compatibility.Combine(otherCompat); } return(this.ConfirmCompatibility(compatibility)); }
private bool ConfirmCompatibility(PackageCompatibility compatibility) { if (compatibility.IsAtLeast(PackageCompatibility.Likely)) { return(true); } DialogResult result = MessageBox.Show(this, PackageManagerFrontendRes.MsgConfirmIncompatibleOperation_Desc, PackageManagerFrontendRes.MsgConfirmIncompatibleOperation_Caption, MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2); return(result == DialogResult.Yes); }
/// <summary> /// Determines compatibility between the current package installs and the specified target package. /// Works for both updates and new installs. /// </summary> /// <param name="target"></param> /// <returns></returns> public PackageCompatibility GetCompatibilityLevel(PackageInfo target) { // If the target package is already installed in the matching version, assume compatibility if (this.localPackages.Any(local => local.Id == target.Id && local.Version == target.Version)) { return(PackageCompatibility.Definite); } // Determine all packages that might be updated or installed PackageInfo[] touchedPackages = this.GetDeepDependencies(new[] { target }).ToArray(); // Generate a mapping to already installed packages Dictionary <PackageInfo, LocalPackage> localMap = new Dictionary <PackageInfo, LocalPackage>(); foreach (PackageInfo package in touchedPackages) { LocalPackage local = this.localPackages.FirstOrDefault(p => p.Id == package.Id); if (local == null) { continue; } localMap.Add(package, local); } // Determine the maximum version difference between target and installed PackageCompatibility compatibility = PackageCompatibility.Definite; foreach (var pair in localMap) { Version targetVersion = pair.Key.Version; Version localVersion = pair.Value.Version; if (localVersion.Major != targetVersion.Major) { compatibility = compatibility.Combine(PackageCompatibility.Unlikely); } else if (localVersion.Minor != targetVersion.Minor) { compatibility = compatibility.Combine(PackageCompatibility.Likely); } } return(compatibility); }
protected void GetUpdateCompatibility(PackageManager manager) { PackageCompatibility compatibility = manager.GetCompatibilityLevel(this.NewestPackageInfo); lock (this.asyncDataLock) { this.compatibility = compatibility; } }
private ProjectAnalysisResult AnalyzeProject( string project, string solutionFileName, List <AnalyzerResult> analyzers, List <ProjectResult> analysisActions, bool isIncremental = false, string targetFramework = DEFAULT_TARGET) { try { var analyzer = analyzers.Find((a) => a.ProjectResult?.ProjectFilePath != null && a.ProjectResult.ProjectFilePath.Equals(project)); var projectFeatureType = analysisActions.Find((a) => a.ProjectFile != null && a.ProjectFile.Equals(project))?.FeatureType.ToString(); var projectActions = analysisActions.FirstOrDefault(p => p.ProjectFile == project)?.ProjectActions ?? new ProjectActions(); if (analyzer == null || analyzer.ProjectResult == null) { _logger.LogError("Unable to build {0}.", project); return(null); } var sourceFileToCodeTokens = analyzer.ProjectResult.SourceFileResults.Select((sourceFile) => { return(SourceFileToCodeTokens(sourceFile)); }).ToDictionary(p => p.Key, p => p.Value); var sourceFileToCodeEntityDetails = CodeEntityModelToCodeEntities.Convert(sourceFileToCodeTokens, analyzer); var namespaces = sourceFileToCodeEntityDetails.Aggregate(new HashSet <string>(), (agg, cur) => { agg.UnionWith(cur.Value.Select(i => i.Namespace).Where(i => i != null)); return(agg); }); var targetframeworks = analyzer.ProjectResult.TargetFrameworks.Count == 0 ? new List <string> { analyzer.ProjectResult.TargetFramework } : analyzer.ProjectResult.TargetFrameworks; var nugetPackages = analyzer.ProjectResult.ExternalReferences.NugetReferences .Select(r => CodeEntityModelToCodeEntities.ReferenceToPackageVersionPair(r)) .ToHashSet(); var nugetPackageNameLookup = nugetPackages.Select(package => package.PackageId).ToHashSet(); var subDependencies = analyzer.ProjectResult.ExternalReferences.NugetDependencies .Select(r => CodeEntityModelToCodeEntities.ReferenceToPackageVersionPair(r)) .ToHashSet(); var sdkPackages = namespaces.Select(n => new PackageVersionPair { PackageId = n, Version = "0.0.0", PackageSourceType = PackageSourceType.SDK }).Where(pair => !nugetPackageNameLookup.Contains(pair.PackageId)); var allPackages = nugetPackages .Union(subDependencies) .Union(sdkPackages) .ToList(); Dictionary <PackageVersionPair, Task <PackageDetails> > packageResults; if (isIncremental) { packageResults = _handler.GetNugetPackages(allPackages, solutionFileName, isIncremental: true, incrementalRefresh: true); } else { packageResults = _handler.GetNugetPackages(allPackages, null, isIncremental: false, incrementalRefresh: false); } var recommendationResults = _recommendationHandler.GetApiRecommendation(namespaces.ToList()); var packageAnalysisResults = nugetPackages.Select(package => { var result = PackageCompatibility.IsCompatibleAsync(packageResults.GetValueOrDefault(package, null), package, _logger, targetFramework); var packageAnalysisResult = PackageCompatibility.GetPackageAnalysisResult(result, package, targetFramework); return(new Tuple <PackageVersionPair, Task <PackageAnalysisResult> >(package, packageAnalysisResult)); }).ToDictionary(t => t.Item1, t => t.Item2); var portingActionResults = ProjectActionsToRecommendedActions.Convert(projectActions); var SourceFileAnalysisResults = CodeEntityModelToCodeEntities.AnalyzeResults( sourceFileToCodeEntityDetails, packageResults, recommendationResults, portingActionResults, targetFramework); var compatibilityResults = GenerateCompatibilityResults(SourceFileAnalysisResults, analyzer.ProjectResult.ProjectFilePath, analyzer.ProjectBuildResult?.PrePortCompilation != null); return(new ProjectAnalysisResult { ProjectName = analyzer.ProjectResult.ProjectName, ProjectFilePath = analyzer.ProjectResult.ProjectFilePath, TargetFrameworks = targetframeworks, PackageReferences = nugetPackages.ToList(), ProjectReferences = analyzer.ProjectResult.ExternalReferences.ProjectReferences.ConvertAll(p => new ProjectReference { ReferencePath = p.AssemblyLocation }), PackageAnalysisResults = packageAnalysisResults, IsBuildFailed = analyzer.ProjectResult.IsBuildFailed() || analyzer.ProjectBuildResult.IsSyntaxAnalysis, Errors = analyzer.ProjectResult.BuildErrors, ProjectGuid = analyzer.ProjectResult.ProjectGuid, ProjectType = analyzer.ProjectResult.ProjectType, FeatureType = projectFeatureType, SourceFileAnalysisResults = SourceFileAnalysisResults, MetaReferences = analyzer.ProjectBuildResult.Project.MetadataReferences.Select(m => m.Display).ToList(), PreportMetaReferences = analyzer.ProjectBuildResult.PreportReferences, ProjectRules = projectActions.ProjectRules, ExternalReferences = analyzer.ProjectResult.ExternalReferences, ProjectCompatibilityResult = compatibilityResults }); } catch (Exception ex) { _logger.LogError("Error while analyzing {0}, {1}", project, ex); return(new ProjectAnalysisResult { ProjectName = Path.GetFileNameWithoutExtension(project), ProjectFilePath = project, TargetFrameworks = new List <string>(), PackageReferences = new List <PackageVersionPair>(), ProjectReferences = new List <ProjectReference>(), PackageAnalysisResults = new Dictionary <PackageVersionPair, Task <PackageAnalysisResult> >(), IsBuildFailed = true, Errors = new List <string> { string.Format("Error while analyzing {0}, {1}", project, ex) }, ProjectGuid = null, ProjectType = null, SourceFileAnalysisResults = new List <SourceFileAnalysisResult>() }); } finally { CommonUtils.RunGarbageCollection(_logger, "PortingAssistantAnalysisHandler.AnalyzeProject"); } }
public static PackageCompatibility Combine(this PackageCompatibility self, PackageCompatibility other) { return (PackageCompatibility)MathF.Min((int)self, (int)other); }
public override void Draw(TreeNodeAdv node, DrawContext context) { Graphics g = context.Graphics; Rectangle targetRect = new Rectangle( context.Bounds.X + this.LeftMargin, context.Bounds.Y, context.Bounds.Width - this.LeftMargin, context.Bounds.Height); // Retrieve item information PackageItem item = node.Tag as PackageItem; Version itemVersion = null; Version newVersion = null; PackageCompatibility compatibility = PackageCompatibility.None; bool highlightItemVersion = item is LocalPackageItem; bool isInstalled = false; bool isUpToDate = false; if (item != null) { isInstalled = item.InstalledPackageInfo != null; compatibility = item.Compatibility; if (item.InstalledPackageInfo != null) { itemVersion = item.InstalledPackageInfo.Version; } else if (item.ItemPackageInfo != null) { itemVersion = item.ItemPackageInfo.Version; } if (item.NewestPackageInfo != null) { newVersion = item.NewestPackageInfo.Version; } if (itemVersion != null && newVersion != null) { isUpToDate = itemVersion >= newVersion; } } string itemVersionText = PackageManager.GetDisplayedVersion(itemVersion); string newVersionText = isInstalled && !isUpToDate?PackageManager.GetDisplayedVersion(newVersion) : string.Empty; // Determine background color and icon based on versioning Brush backgroundBrush = null; Image icon = null; if (isInstalled) { backgroundBrush = new SolidBrush(Color.FromArgb(32, 128, 128, 128)); } if (newVersion != null && itemVersion != null) { if (isInstalled) { if (newVersion <= itemVersion) { icon = Properties.PackageManagerFrontendResCache.IconUpToDate; } else if (compatibility == PackageCompatibility.Definite) { icon = Properties.PackageManagerFrontendResCache.IconSafeUpdate; } else if (compatibility == PackageCompatibility.Likely) { icon = Properties.PackageManagerFrontendResCache.IconLikelySafeUpdate; } else if (compatibility == PackageCompatibility.Unlikely) { icon = Properties.PackageManagerFrontendResCache.IconLikelyUnsafeUpdate; } else if (compatibility == PackageCompatibility.None) { icon = Properties.PackageManagerFrontendResCache.IconIncompatibleUpdate; } } else { if (compatibility == PackageCompatibility.Unlikely) { icon = Properties.PackageManagerFrontendResCache.IconLikelyUnsafeInstall; } else if (compatibility == PackageCompatibility.None) { icon = Properties.PackageManagerFrontendResCache.IconIncompatibleInstall; } } } // Calculate drawing layout and data StringFormat stringFormat = new StringFormat { Trimming = StringTrimming.EllipsisCharacter, Alignment = StringAlignment.Near, FormatFlags = StringFormatFlags.NoWrap }; Rectangle currentVersionRect; Rectangle newestVersionRect; Rectangle iconRect; { SizeF currentVersionSize; SizeF newestVersionSize; Size iconSize; // Base info { newestVersionSize = g.MeasureString(newVersionText, context.Font, targetRect.Width, stringFormat); currentVersionSize = g.MeasureString(itemVersionText, context.Font, targetRect.Width, stringFormat); iconSize = icon != null ? icon.Size : Size.Empty; } // Alignment info { Size totalTextSize = new Size( (int)Math.Max(currentVersionSize.Width, newestVersionSize.Width), (int)(currentVersionSize.Height + newestVersionSize.Height)); int leftSpacing = (targetRect.Width - totalTextSize.Width - iconSize.Width - 4) / 2; int iconIndent = iconSize.Width + 4 + leftSpacing; iconRect = new Rectangle( targetRect.X + leftSpacing, targetRect.Y + targetRect.Height / 2 - iconSize.Height / 2, iconSize.Width, iconSize.Height); newestVersionRect = new Rectangle( targetRect.X + iconIndent, targetRect.Y + Math.Max((targetRect.Height - totalTextSize.Height) / 2, 0), targetRect.Width - iconIndent, (int)newestVersionSize.Height); currentVersionRect = new Rectangle( targetRect.X + iconIndent, targetRect.Y + (int)newestVersionSize.Height + Math.Max((targetRect.Height - totalTextSize.Height) / 2, 0), targetRect.Width - iconIndent, targetRect.Height - (int)newestVersionSize.Height); } } // Draw background and version texts if (backgroundBrush != null) { g.FillRectangle(backgroundBrush, targetRect); } if (icon != null) { g.DrawImageUnscaledAndClipped(icon, iconRect); } { bool bothVisible = !string.IsNullOrWhiteSpace(itemVersionText) && !string.IsNullOrWhiteSpace(newVersionText); highlightItemVersion = highlightItemVersion || !bothVisible; g.DrawString(newVersionText, context.Font, new SolidBrush(Color.FromArgb((highlightItemVersion ? 128 : 255) / (context.Enabled ? 1 : 2), this.Parent.ForeColor)), newestVersionRect, stringFormat); g.DrawString(itemVersionText, context.Font, new SolidBrush(Color.FromArgb((highlightItemVersion ? 255 : 128) / (context.Enabled ? 1 : 2), this.Parent.ForeColor)), currentVersionRect, stringFormat); } }
public static bool Satisfies(this PackageCompatibility self, PackageCompatibility other) { return (int)self >= (int)other; }
/// <summary> /// Given the specified set of packages, this method returns a new set of the same packages where each version is the newest one /// that can be safely updated to, given the specified minimum forward compatibility level. If a package cannot be updated at all, /// it will be omitted in the resulting list. /// </summary> /// <param name="packages"></param> /// <param name="minCompatibility"></param> /// <returns></returns> public IEnumerable <PackageInfo> GetSafeUpdateConfig(IEnumerable <PackageInfo> packages, PackageCompatibility minCompatibility) { List <PackageInfo> safeUpdateList = new List <PackageInfo>(); PackageInfo[] targetPackages = packages.ToArray(); for (int i = 0; i < targetPackages.Length; i++) { PackageInfo package = targetPackages[i]; PackageInfo update = this.QueryPackageInfo(package.PackageName.VersionInvariant); if (update.Version <= package.Version) { continue; } // ToDo: Implement this safeUpdateList.Add(update); } return(safeUpdateList); }
private ProjectAnalysisResult AnalyzeProject( string project, List <AnalyzerResult> analyzers, Dictionary <string, ProjectActions> analysisActions, string targetFramework = "netcoreapp3.1") { try { using var analyzer = analyzers.Find((a) => a.ProjectResult?.ProjectFilePath != null && a.ProjectResult.ProjectFilePath.Equals(project)); var projectActions = new ProjectActions(); analysisActions.TryGetValue(project, out projectActions); if (analyzer == null || analyzer.ProjectResult == null) { _logger.LogError("Unable to build {0}.", project); return(null); } var sourceFileToInvocations = analyzer.ProjectResult.SourceFileResults.Select((sourceFile) => { var invocationsInSourceFile = sourceFile.AllInvocationExpressions(); _logger.LogInformation("API: SourceFile {0} has {1} invocations pre-filter", sourceFile.FileFullPath, invocationsInSourceFile.Count()); return(KeyValuePair.Create(sourceFile.FileFullPath, invocationsInSourceFile)); }).ToDictionary(p => p.Key, p => p.Value); var sourceFileToCodeEntityDetails = InvocationExpressionModelToInvocations.Convert(sourceFileToInvocations, analyzer); var namespaces = sourceFileToCodeEntityDetails.Aggregate(new HashSet <string>(), (agg, cur) => { agg.UnionWith(cur.Value.Select(i => i.Namespace).Where(i => i != null)); return(agg); }); var targetframeworks = analyzer.ProjectResult.TargetFrameworks.Count == 0 ? new List <string> { analyzer.ProjectResult.TargetFramework } : analyzer.ProjectResult.TargetFrameworks; var nugetPackages = analyzer.ProjectResult.ExternalReferences.NugetReferences .Select(r => InvocationExpressionModelToInvocations.ReferenceToPackageVersionPair(r)) .ToHashSet(); var subDependencies = analyzer.ProjectResult.ExternalReferences.NugetDependencies .Select(r => InvocationExpressionModelToInvocations.ReferenceToPackageVersionPair(r)) .ToHashSet(); var sdkPackages = namespaces.Select(n => new PackageVersionPair { PackageId = n, Version = "0.0.0", PackageSourceType = PackageSourceType.SDK }); var allPackages = nugetPackages .Union(subDependencies) .Union(sdkPackages) .ToList(); var packageResults = _handler.GetNugetPackages(allPackages, null); var recommendationResults = _recommendationHandler.GetApiRecommendation(namespaces.ToList()); var packageAnalysisResults = nugetPackages.Select(package => { var result = PackageCompatibility.IsCompatibleAsync(packageResults.GetValueOrDefault(package, null), package, _logger, targetFramework); var packageAnalysisResult = PackageCompatibility.GetPackageAnalysisResult(result, package, targetFramework); return(new Tuple <PackageVersionPair, Task <PackageAnalysisResult> >(package, packageAnalysisResult)); }).ToDictionary(t => t.Item1, t => t.Item2); var portingActionResults = ProjectActionsToRecommendedActions.Convert(projectActions); var SourceFileAnalysisResults = InvocationExpressionModelToInvocations.AnalyzeResults( sourceFileToCodeEntityDetails, packageResults, recommendationResults, portingActionResults, targetFramework); return(new ProjectAnalysisResult { ProjectName = analyzer.ProjectResult.ProjectName, ProjectFilePath = analyzer.ProjectResult.ProjectFilePath, TargetFrameworks = targetframeworks, PackageReferences = nugetPackages.ToList(), ProjectReferences = analyzer.ProjectResult.ExternalReferences.ProjectReferences.ConvertAll(p => new ProjectReference { ReferencePath = p.AssemblyLocation }), PackageAnalysisResults = packageAnalysisResults, IsBuildFailed = analyzer.ProjectResult.IsBuildFailed(), Errors = analyzer.ProjectResult.BuildErrors, ProjectGuid = analyzer.ProjectResult.ProjectGuid, ProjectType = analyzer.ProjectResult.ProjectType, SourceFileAnalysisResults = SourceFileAnalysisResults }); } catch (Exception ex) { _logger.LogError("Error while analyzing {0}, {1}", project, ex); return(new ProjectAnalysisResult { ProjectName = Path.GetFileNameWithoutExtension(project), ProjectFilePath = project, TargetFrameworks = new List <string>(), PackageReferences = new List <PackageVersionPair>(), ProjectReferences = new List <ProjectReference>(), PackageAnalysisResults = new Dictionary <PackageVersionPair, Task <PackageAnalysisResult> >(), IsBuildFailed = true, Errors = new List <string> { string.Format("Error while analyzing {0}, {1}", project, ex) }, ProjectGuid = null, ProjectType = null, SourceFileAnalysisResults = new List <SourceFileAnalysisResult>() }); } }
public static PackageCompatibility Combine(this PackageCompatibility self, PackageCompatibility other) { return((PackageCompatibility)MathF.Min((int)self, (int)other)); }
public static bool Satisfies(this PackageCompatibility self, PackageCompatibility other) { return((int)self >= (int)other); }
public static bool IsAtLeast(this PackageCompatibility self, PackageCompatibility other) { if (self == PackageCompatibility.Unknown) return false; return (int)self >= (int)other; }
/// <summary> /// Given the specified set of packages, this method returns a new set of the same packages where each version is the newest one /// that can be safely updated to, given the specified minimum forward compatibility level. If a package cannot be updated at all, /// it will be omitted in the resulting list. /// </summary> /// <param name="packages"></param> /// <param name="minCompatibility"></param> /// <returns></returns> public IEnumerable<PackageInfo> GetSafeUpdateConfig(IEnumerable<PackageInfo> packages, PackageCompatibility minCompatibility) { List<PackageInfo> safeUpdateList = new List<PackageInfo>(); PackageInfo[] targetPackages = packages.ToArray(); for (int i = 0; i < targetPackages.Length; i++) { PackageInfo package = targetPackages[i]; PackageInfo update = this.QueryPackageInfo(package.PackageName.VersionInvariant); if (update.Version <= package.Version) continue; // ToDo: Implement this safeUpdateList.Add(update); } return safeUpdateList; }
public static bool IsAtLeast(this PackageCompatibility self, PackageCompatibility other) { return((int)self >= (int)other); }
void CreatePackageCompatibility (string packageFrameworkName) { package = FakePackage.CreatePackageWithVersion ("MyPackage", "1.2.3.4"); FrameworkName packageFramework = VersionUtility.ParseFrameworkName (packageFrameworkName); packageCompatibility = new PackageCompatibility (project, package, packageFramework); }
/// <summary> /// Given the specified set of packages, this method returns a new set of the same packages where each version is the newest one /// that can be safely updated to, given the specified minimum forward compatibility level. If a package cannot be updated at all, /// it will be omitted in the resulting list. /// </summary> /// <param name="packages"></param> /// <param name="minCompatibility"></param> /// <returns></returns> public IEnumerable <PackageInfo> GetSafeUpdateConfig(IEnumerable <LocalPackage> packages, PackageCompatibility minCompatibility = PackageCompatibility.Likely) { var localInfo = packages.Select(p => p.Info ?? this.QueryPackageInfo(p.PackageName)).ToArray(); return(this.GetSafeUpdateConfig(localInfo, minCompatibility)); }
/// <summary> /// Given the specified set of packages, this method returns a new set of the same packages where each version is the newest one /// that can be safely updated to, given the specified minimum forward compatibility level. If a package cannot be updated at all, /// it will be omitted in the resulting list. /// </summary> /// <param name="packages"></param> /// <param name="minCompatibility"></param> /// <returns></returns> public IEnumerable<PackageInfo> GetSafeUpdateConfig(IEnumerable<LocalPackage> packages, PackageCompatibility minCompatibility = PackageCompatibility.Likely) { var localInfo = packages.Select(p => p.Info ?? this.QueryPackageInfo(p.PackageName)).ToArray(); return this.GetSafeUpdateConfig(localInfo, minCompatibility); }
/// <summary> /// Determines compatibility between the current package installs and the specified target package. /// Works for both updates and new installs. /// </summary> /// <param name="target"></param> /// <returns></returns> public PackageCompatibility GetCompatibilityLevel(PackageInfo target) { // If the target package is already installed in the matching version, assume compatibility if (this.setup.GetPackage(target.Id, target.Version) != null) { return(PackageCompatibility.Definite); } // Determine all packages that might be updated or installed this.dependencyWalker.Clear(); this.dependencyWalker.WalkGraph(target); List <PackageInfo> touchedPackages = this.dependencyWalker.VisitedPackages.ToList(); // Verify properly specified dependencies for Duality packages if (target.IsDualityPackage) { // If none of the targets deep dependencies is anyhow related to Duality, assume they're incomplete and potentially incompatible bool anyDualityDependency = false; foreach (PackageInfo package in touchedPackages) { if (DualityPackageNames.Any(name => string.Equals(name, package.Id))) { anyDualityDependency = true; break; } } if (!anyDualityDependency) { return(PackageCompatibility.None); } } // Generate a mapping to already installed packages Dictionary <PackageInfo, LocalPackage> localMap = new Dictionary <PackageInfo, LocalPackage>(); foreach (PackageInfo package in touchedPackages) { LocalPackage local = this.setup.GetPackage(package.Id); if (local == null) { continue; } localMap.Add(package, local); } // Determine the maximum version difference between target and installed PackageCompatibility compatibility = PackageCompatibility.Definite; foreach (var pair in localMap) { Version targetVersion = pair.Key.Version; Version localVersion = pair.Value.Version; if (localVersion.Major != targetVersion.Major) { compatibility = compatibility.Combine(PackageCompatibility.Unlikely); } else if (localVersion.Minor != targetVersion.Minor) { compatibility = compatibility.Combine(PackageCompatibility.Likely); } } return(compatibility); }