private static JProperty WriteTargetDependency(LockFileDependency dependency) { var json = new JObject { [TypeProperty] = dependency.Type.ToString() }; if (dependency.RequestedVersion != null) { json[RequestedProperty] = dependency.RequestedVersion.ToNormalizedString(); } if (dependency.ResolvedVersion != null) { json[ResolvedProperty] = dependency.ResolvedVersion.ToNormalizedString(); } if (dependency.ContentHash != null) { json[ContentHashProperty] = dependency.ContentHash; } if (dependency.Dependencies?.Count > 0) { var ordered = dependency.Dependencies.OrderBy(dep => dep.Id, StringComparer.Ordinal); json[DependenciesProperty] = JsonUtility.WriteObject(ordered, JsonUtility.WritePackageDependency); } return(new JProperty(dependency.Id, json)); }
/// <summary> /// The method will return true if: /// 1. If a transitive dependency from the lock file is now added to the central file. /// or /// 1. If there is a mistmatch between the RequestedVersion of a lock file dependency marked as CentralTransitive and the the version specified in the central package management file. /// or /// 2. If a central version that is a transitive dependency is removed from CPVM the lock file is invalidated. /// </summary> private static (bool, string) HasProjectTransitiveDependencyChanged( IDictionary <string, CentralPackageVersion> centralPackageVersions, IList <LockFileDependency> lockFileCentralTransitiveDependencies, IList <LockFileDependency> lockTransitiveDependencies) { // Transitive dependencies moved to be centraly managed will invalidate the lock file LockFileDependency dependency = lockTransitiveDependencies.FirstOrDefault(dep => centralPackageVersions.ContainsKey(dep.Id)); if (dependency != null) { return(true, string.Format( CultureInfo.CurrentCulture, Strings.PackagesLockFile_ProjectTransitiveDependencyChanged, dependency.Id ) ); } foreach (var lockFileDependencyEnforcedByCPV in lockFileCentralTransitiveDependencies) { if (centralPackageVersions.TryGetValue(lockFileDependencyEnforcedByCPV.Id, out var centralPackageVersion)) { if (centralPackageVersion != null && !EqualityUtility.EqualsWithNullCheck(lockFileDependencyEnforcedByCPV.RequestedVersion, centralPackageVersion.VersionRange)) { return(true, string.Format( CultureInfo.CurrentCulture, Strings.PackagesLockFile_ProjectTransitiveDependencyVersionChanged, lockFileDependencyEnforcedByCPV.RequestedVersion.ToNormalizedString(), centralPackageVersion.VersionRange.ToNormalizedString() ) ); } continue; } // The central version was removed return(true, string.Format( CultureInfo.CurrentCulture, Strings.PackagesLockFile_CentralPackageVersionRemoved, lockFileDependencyEnforcedByCPV.Id ) ); } return(false, string.Empty); }
private static LockFileDependency ReadTargetDependency(string property, JToken json) { var dependency = new LockFileDependency { Id = property, Dependencies = JsonUtility.ReadObject(json[DependenciesProperty] as JObject, JsonUtility.ReadPackageDependency) }; var jObject = json as JObject; var typeString = JsonUtility.ReadProperty <string>(jObject, TypeProperty); if (!string.IsNullOrEmpty(typeString) && Enum.TryParse <PackageDependencyType>(typeString, ignoreCase: true, result: out var installationType)) { dependency.Type = installationType; } var resolvedString = JsonUtility.ReadProperty <string>(jObject, ResolvedProperty); if (!string.IsNullOrEmpty(resolvedString)) { dependency.ResolvedVersion = NuGetVersion.Parse(resolvedString); } var requestedString = JsonUtility.ReadProperty <string>(jObject, RequestedProperty); if (!string.IsNullOrEmpty(requestedString)) { dependency.RequestedVersion = VersionRange.Parse(requestedString); } dependency.ContentHash = JsonUtility.ReadProperty <string>(jObject, ContentHashProperty); return(dependency); }
private static bool HasP2PDependencyChanged(IEnumerable <LibraryDependency> newDependencies, IEnumerable <ProjectRestoreReference> projectRestoreReferences, LockFileDependency projectDependency, DependencyGraphSpec dgSpec) { if (projectDependency == null) { // project dependency doesn't exists in lock file so it's out of sync. return(true); } // If the count is not the same, something has changed. // Otherwise we N^2 walk below determines whether anything has changed. var transitivelyFlowingDependencies = newDependencies.Where( dep => (dep.LibraryRange.TypeConstraint == LibraryDependencyTarget.Package && dep.SuppressParent != LibraryIncludeFlags.All)); if (transitivelyFlowingDependencies.Count() + projectRestoreReferences.Count() != projectDependency.Dependencies.Count) { return(true); } foreach (var dependency in transitivelyFlowingDependencies) { var matchedP2PLibrary = projectDependency.Dependencies.FirstOrDefault(dep => StringComparer.OrdinalIgnoreCase.Equals(dep.Id, dependency.Name)); if (matchedP2PLibrary == null || !EqualityUtility.EqualsWithNullCheck(matchedP2PLibrary.VersionRange, dependency.LibraryRange.VersionRange)) { // P2P dependency has changed and lock file is out of sync. return(true); } } foreach (var dependency in projectRestoreReferences) { var referenceSpec = dgSpec.GetProjectSpec(dependency.ProjectUniqueName); var matchedP2PLibrary = projectDependency.Dependencies.FirstOrDefault(dep => StringComparer.OrdinalIgnoreCase.Equals(dep.Id, referenceSpec.Name)); if (matchedP2PLibrary == null) // Do not check the version for the projects, or else https://github.com/nuget/home/issues/7935 { // P2P dependency has changed and lock file is out of sync. return(true); } } // no dependency changed. Lock file is still valid. return(false); }
private static bool HasP2PDependencyChanged(IEnumerable <LibraryDependency> newDependencies, LockFileDependency projectDependency) { if (projectDependency == null) { // project dependency doesn't exists in lock file so it's out of sync. return(true); } foreach (var dependency in newDependencies.Where(dep => dep.LibraryRange.TypeConstraint == LibraryDependencyTarget.Package)) { var matchedP2PLibrary = projectDependency.Dependencies.FirstOrDefault(dep => StringComparer.OrdinalIgnoreCase.Equals(dep.Id, dependency.Name)); if (matchedP2PLibrary == null || !EqualityUtility.EqualsWithNullCheck(matchedP2PLibrary.VersionRange, dependency.LibraryRange.VersionRange)) { // P2P dependency has changed and lock file is out of sync. return(true); } } // no dependency changed. Lock file is still valid. return(false); }
private static (bool, string) HasP2PDependencyChanged(IEnumerable <LibraryDependency> newDependencies, IEnumerable <ProjectRestoreReference> projectRestoreReferences, LockFileDependency projectDependency, DependencyGraphSpec dgSpec) { // If the count is not the same, something has changed. // Otherwise we N^2 walk below determines whether anything has changed. var transitivelyFlowingDependencies = newDependencies.Where( dep => dep.LibraryRange.TypeConstraint == LibraryDependencyTarget.Package && dep.SuppressParent != LibraryIncludeFlags.All); var transitivelyFlowingProjectReferences = projectRestoreReferences.Where(e => e.PrivateAssets != LibraryIncludeFlags.All); var transitiveDependencies = transitivelyFlowingDependencies.Count() + transitivelyFlowingProjectReferences.Count(); if (transitiveDependencies != projectDependency.Dependencies.Count) { return(true, string.Format( CultureInfo.CurrentCulture, Strings.PackagesLockFile_ProjectReferencesHasChange, projectDependency.Id, transitiveDependencies > 0 ? string.Join(",", transitivelyFlowingDependencies.Select(dep => dep.Name).Concat(projectRestoreReferences.Select(dep => dep.ProjectUniqueName)).OrderBy(dep => dep)) : Strings.None, projectDependency.Dependencies.Count > 0 ? string.Join(",", projectDependency.Dependencies.Select(dep => dep.Id).OrderBy(dep => dep)) : Strings.None ) ); } foreach (var dependency in transitivelyFlowingDependencies) { var matchedP2PLibrary = projectDependency.Dependencies.FirstOrDefault(dep => StringComparer.OrdinalIgnoreCase.Equals(dep.Id, dependency.Name)); if (matchedP2PLibrary == null || !EqualityUtility.EqualsWithNullCheck(matchedP2PLibrary.VersionRange, dependency.LibraryRange.VersionRange)) { // P2P dependency has changed and lock file is out of sync. return(true, string.Format( CultureInfo.CurrentCulture, Strings.PackagesLockFile_ProjectReferenceDependenciesHasChanged, projectDependency.Id ) ); } } foreach (var dependency in transitivelyFlowingProjectReferences) { var referenceSpec = dgSpec.GetProjectSpec(dependency.ProjectUniqueName); var matchedP2PLibrary = projectDependency.Dependencies.FirstOrDefault(dep => StringComparer.OrdinalIgnoreCase.Equals(dep.Id, referenceSpec.Name)); if (matchedP2PLibrary == null) // Do not check the version for the projects, or else https://github.com/nuget/home/issues/7935 { // P2P dependency has changed and lock file is out of sync. return(true, string.Format( CultureInfo.CurrentCulture, Strings.PackagesLockFile_ProjectReferenceDependenciesHasChanged, projectDependency.Id ) ); } } // no dependency changed. Lock file is still valid. return(false, string.Empty); }