/// <summary> /// Get warning message for missing minimum dependencies. /// </summary> public static RestoreLogMessage GetMissingLowerBoundMessage(ResolvedDependencyKey dependency, params string[] targetGraphs) { NuGetLogCode code; var message = string.Empty; var parent = DiagnosticUtility.FormatIdentity(dependency.Parent); var dependencyRange = DiagnosticUtility.FormatDependency(dependency.Child.Name, dependency.Range); var missingChild = DiagnosticUtility.FormatExpectedIdentity(dependency.Child.Name, dependency.Range); var resolvedChild = DiagnosticUtility.FormatIdentity(dependency.Child); if (HasMissingLowerBound(dependency.Range)) { // Range does not have a lower bound, the best match can only be approximate. message = string.Format(CultureInfo.CurrentCulture, Strings.Warning_MinVersionNonInclusive, parent, dependencyRange, resolvedChild); code = NuGetLogCode.NU1602; } else { // The minimum version does not exist. message = string.Format(CultureInfo.CurrentCulture, Strings.Warning_MinVersionDoesNotExist, parent, dependencyRange, missingChild, resolvedChild); code = NuGetLogCode.NU1603; } return(RestoreLogMessage.CreateWarning(code, message, dependency.Child.Name, targetGraphs)); }
/// <summary> /// True if the dependency version range has a min version that matches the resolved version. /// </summary> public static bool DependencyRangeHasMissingExactMatch(ResolvedDependencyKey dependency) { // Ignore floating if (dependency.Range.IsFloating) { return(false); } // Ignore projects if (dependency.Child.Type != LibraryType.Package) { return(false); } return(!dependency.Range.IsMinInclusive || dependency.Range.MinVersion != dependency.Child.Version); }
public static RestoreTargetGraph Create( RuntimeGraph runtimeGraph, IEnumerable <GraphNode <RemoteResolveResult> > graphs, RemoteWalkContext context, ILogger log, NuGetFramework framework, string runtimeIdentifier) { var install = new HashSet <RemoteMatch>(); var flattened = new HashSet <GraphItem <RemoteResolveResult> >(); var unresolved = new HashSet <LibraryRange>(); var conflicts = new Dictionary <string, HashSet <ResolverRequest> >(); var analyzeResult = new AnalyzeResult <RemoteResolveResult>(); var resolvedDependencies = new HashSet <ResolvedDependencyKey>(); foreach (var graph in graphs) { var result = graph.Analyze(); analyzeResult.Combine(result); } graphs.ForEach(node => { if (node == null || node.Key == null) { return; } if (node.Disposition != Disposition.Rejected) { if (node.Disposition == Disposition.Acceptable) { // This wasn't resolved. It's a conflict. HashSet <ResolverRequest> ranges; if (!conflicts.TryGetValue(node.Key.Name, out ranges)) { ranges = new HashSet <ResolverRequest>(); conflicts[node.Key.Name] = ranges; } // OuterNode may be null if the project itself conflicts with a package name var requestor = node.OuterNode == null ? node.Item.Key : node.OuterNode.Item.Key; ranges.Add(new ResolverRequest(requestor, node.Key)); } if (node?.Item?.Key?.Type == LibraryType.Unresolved) { if (node.Key.VersionRange != null) { unresolved.Add(node.Key); } return; } // Don't add rejected nodes since we only want to write reduced nodes // to the lock file flattened.Add(node.Item); } if (node?.OuterNode != null && node.Item.Key.Type != LibraryType.Unresolved) { var dependencyKey = new ResolvedDependencyKey( parent: node.OuterNode.Item.Key, range: node.Key.VersionRange, child: node.Item.Key); resolvedDependencies.Add(dependencyKey); } // If the package came from a remote library provider, it needs to be installed locally // Rejected nodes are included here to avoid downloading them from remote sources // each time the lock file is generated. var isRemote = context.RemoteLibraryProviders.Contains(node.Item.Data.Match.Provider); if (isRemote) { install.Add(node.Item.Data.Match); } }); return(new RestoreTargetGraph( conflicts.Select(p => new ResolverConflict(p.Key, p.Value)), framework, runtimeIdentifier, runtimeGraph, graphs, install, flattened, unresolved, analyzeResult, resolvedDependencies)); }