Esempio n. 1
0
        public void VersionRangeSet_CombineTwoRanges(string expected, string rangeA, string rangeB)
        {
            // Arrange
            var a = VersionRange.Parse(rangeA);
            var b = VersionRange.Parse(rangeB);

            // Act
            var ranges = new List <VersionRange>()
            {
                a, b
            };
            var combined = VersionRange.Combine(ranges);

            var rangesRev = new List <VersionRange>()
            {
                b, a
            };
            var combinedRev = VersionRange.Combine(rangesRev);

            // Assert
            Assert.Equal(expected, combined.ToNormalizedString());

            // Verify the order has no effect
            Assert.Equal(expected, combinedRev.ToNormalizedString());
        }
Esempio n. 2
0
        public void VersionRangeSet_CombineEmptyRangeList()
        {
            // Arrange
            var ranges = new List <VersionRange>()
            {
            };

            // Act
            var combined = VersionRange.Combine(ranges);

            // Assert
            Assert.Equal(VersionRange.None.ToNormalizedString(), combined.ToNormalizedString());
        }
Esempio n. 3
0
        public void VersionRangeSet_SpecialCaseRangeCombine_NonePlusOne()
        {
            // Arrange
            var ranges = new List <VersionRange>()
            {
                VersionRange.None, VersionRange.Parse("[1.0.0]")
            };

            // Act
            var combined = VersionRange.Combine(ranges);

            // Assert
            Assert.Equal("[1.0.0, 1.0.0]", combined.ToNormalizedString());
        }
Esempio n. 4
0
        public void VersionRangeSet_SpecialCaseRangeCombine_NoneAll()
        {
            // Arrange
            var ranges = new List <VersionRange>()
            {
                VersionRange.None, VersionRange.All
            };

            // Act
            var combined = VersionRange.Combine(ranges);

            // Assert
            Assert.Equal(VersionRange.All.ToNormalizedString(), combined.ToNormalizedString());
        }
Esempio n. 5
0
        public void VersionRangeSet_CombineSingleRangeList()
        {
            // Arrange
            var a      = VersionRange.Parse("[1.0.0, )");
            var ranges = new List <VersionRange>()
            {
                a
            };

            // Act
            var combined = VersionRange.Combine(ranges);

            // Assert
            Assert.Equal(a.ToNormalizedString(), combined.ToNormalizedString());
        }
Esempio n. 6
0
        public void VersionRangeSet_SpecialCaseRangeCombine_AllStablePlusStable()
        {
            // Arrange
            var stable = new VersionRange(new NuGetVersion("1.0.0"), true, new NuGetVersion("2.0.0"), true);
            var ranges = new List <VersionRange>()
            {
                VersionRange.AllStable, stable
            };

            // Act
            var combined = VersionRange.Combine(ranges);

            // Assert
            Assert.Equal(VersionRange.AllStable.ToNormalizedString(), combined.ToNormalizedString());
        }
Esempio n. 7
0
        public void VersionRangeSet_SpecialCaseRangeCombine_Nones()
        {
            // Arrange
            var ranges = new List <VersionRange>()
            {
                VersionRange.None, VersionRange.None, VersionRange.None
            };

            // Act
            var combined = VersionRange.Combine(ranges);

            // Assert
            Assert.Equal(VersionRange.None.ToNormalizedString(), combined.ToNormalizedString());
            Assert.False(combined.IncludePrerelease);
        }
Esempio n. 8
0
        public void VersionRangeSet_SpecialCaseRangeCombine_AllStablePlusPre()
        {
            // Arrange
            var pre    = new VersionRange(new NuGetVersion("1.0.0"), true, new NuGetVersion("2.0.0"), true, includePrerelease: true);
            var ranges = new List <VersionRange>()
            {
                VersionRange.AllStable, pre
            };

            // Act
            var combined = VersionRange.Combine(ranges);

            // Assert
            Assert.Equal(VersionRange.All.ToNormalizedString(), combined.ToNormalizedString());
            Assert.True(combined.IncludePrerelease);
        }
Esempio n. 9
0
        public void VersionRangeSet_SpecialCaseRangeCombine_All()
        {
            // Arrange
            var ranges = new List <VersionRange>()
            {
                VersionRange.AllStable, VersionRange.All,
                VersionRange.AllFloating, VersionRange.AllStableFloating, VersionRange.None
            };

            // Act
            var combined = VersionRange.Combine(ranges);

            // Assert
            Assert.Equal(VersionRange.All.ToNormalizedString(), combined.ToNormalizedString());
            Assert.True(combined.IncludePrerelease);
        }
        private static List <SourcePackageDependencyInfo> InnerPruneImpossiblePackages(List <SourcePackageDependencyInfo> packages, ISet <string> mustKeep)
        {
            if (packages.Count == 0)
            {
                return(packages);
            }

            var dependencyRangesByPackageId = new Dictionary <string, IList <VersionRange> >(StringComparer.OrdinalIgnoreCase);

            //  (1) Adds all package Ids including leaf nodes that have no dependencies
            foreach (var package in packages)
            {
                if (!dependencyRangesByPackageId.ContainsKey(package.Id))
                {
                    dependencyRangesByPackageId.Add(package.Id, new List <VersionRange>());
                }
            }

            //  (2) Create a look-up of every dependency that refers to a particular package Id
            foreach (var package in packages)
            {
                foreach (var dependency in package?.Dependencies)
                {
                    IList <VersionRange> dependencyVersionRanges;
                    if (dependencyRangesByPackageId.TryGetValue(dependency.Id, out dependencyVersionRanges))
                    {
                        dependencyVersionRanges.Add(dependency.VersionRange);
                    }
                }
            }

            //  (3) Per package Id combine all the dependency ranges into a wider 'worst-case' range
            var dependencyByPackageId = new Dictionary <string, VersionRange>(StringComparer.OrdinalIgnoreCase);

            foreach (var item in dependencyRangesByPackageId)
            {
                dependencyByPackageId.Add(item.Key, VersionRange.Combine(item.Value));
            }

            //  (4) Remove any packages that fall out side of the worst case range while making sure not to remove the packages we must keep
            var result = packages.Where(
                package => dependencyByPackageId[package.Id].Satisfies(package.Version) || mustKeep.Contains(package.Id))
                         .ToList();

            return(result);
        }
Esempio n. 11
0
        public void VersionRangeSet_RemoveEmptyRanges()
        {
            // Arrange
            var ranges = new List <VersionRange>()
            {
                VersionRange.None,
                VersionRange.Parse("(5.0.0, 5.0.0)"),
                VersionRange.Parse("(3.0.0-alpha, 3.0.0-alpha)"),
                VersionRange.Parse("[1.0.0, 2.0.0]")
            };

            // Act
            var combined = VersionRange.Combine(ranges);

            // Assert
            Assert.Equal("[1.0.0, 2.0.0]", combined.ToNormalizedString());
        }
Esempio n. 12
0
        public void VersionRangeSet_SpecialCaseRangeCombine_All()
        {
            // Arrange
            var ranges = new List <VersionRange>()
            {
#pragma warning disable CS0618 // Type or member is obsolete
                VersionRange.AllStable, VersionRange.All,
                VersionRange.AllFloating, VersionRange.AllStableFloating, VersionRange.None
#pragma warning restore CS0618 // Type or member is obsolete
            };

            // Act
            var combined = VersionRange.Combine(ranges);

            // Assert
            Assert.Equal(VersionRange.All.ToNormalizedString(), combined.ToNormalizedString());
        }
        private VersionRange NeededRange(VersionRange alreadySearched, VersionRange possibleSubSet)
        {
            if (alreadySearched == null || _versionRangeComparer.Equals(alreadySearched, EmptyRange))
            {
                return(possibleSubSet);
            }

            if (_versionRangeComparer.Equals(possibleSubSet, EmptyRange))
            {
                return(EmptyRange);
            }

            // full overlap scenarios
            if (possibleSubSet.IsSubSetOrEqualTo(alreadySearched))
            {
                return(EmptyRange);
            }
            else if (possibleSubSet.IsSubSetOrEqualTo(alreadySearched))
            {
                return(possibleSubSet);
            }

            // we need a partial range
            //  [  ]
            //    [    ]
            if (possibleSubSet.HasLowerBound && alreadySearched.Satisfies(possibleSubSet.MinVersion))
            {
                // already searched the lower set
                return(new VersionRange(possibleSubSet.MinVersion, possibleSubSet.IsMinInclusive,
                                        alreadySearched.MaxVersion, alreadySearched.IsMaxInclusive,
                                        possibleSubSet.IncludePrerelease || alreadySearched.IncludePrerelease));
            }
            else if (possibleSubSet.HasUpperBound && alreadySearched.Satisfies(possibleSubSet.MaxVersion))
            {
                // already searched the higher set
                return(new VersionRange(alreadySearched.MinVersion, alreadySearched.IsMinInclusive,
                                        possibleSubSet.MaxVersion, possibleSubSet.IsMaxInclusive,
                                        possibleSubSet.IncludePrerelease || alreadySearched.IncludePrerelease));
            }
            else
            {
                // TODO: improve this
                return(VersionRange.Combine(new VersionRange[] { alreadySearched, possibleSubSet }));
            }
        }
Esempio n. 14
0
        public void VersionRangeSet_CombineMultipleRanges()
        {
            // Arrange
            var ranges = new List <VersionRange>()
            {
                VersionRange.Parse("[1.0.0]"),
                VersionRange.Parse("[2.0.0]"),
                VersionRange.Parse("[3.0.0]"),
                VersionRange.Parse("[4.0.0-beta-1]"),
                VersionRange.Parse("[5.0.1-rc4]"),
            };

            // Act
            var combined = VersionRange.Combine(ranges);

            ranges.Reverse();

            // Assert
            Assert.Equal("[1.0.0, 5.0.1-rc4]", combined.ToNormalizedString());
        }
Esempio n. 15
0
        /// <summary>
        /// Recursive package dependency info gather
        /// </summary>
        private async Task <IEnumerable <PackageDependencyInfo> > Seek(NuGet.Packaging.Core.PackageDependency target, NuGetFramework projectFramework, bool includePrerelease, IEnumerable <string> parents, CancellationToken token)
        {
            // check if we are cancelled
            token.ThrowIfCancellationRequested();

            List <PackageDependencyInfo> results = new List <PackageDependencyInfo>();

            // circular dependency check protection
            if (!parents.Contains(target.Id, StringComparer.OrdinalIgnoreCase))
            {
                await Ensure(target, projectFramework, includePrerelease, token);

                var packages = Get(target, includePrerelease);

                results.AddRange(packages);

                // combine all version ranges found for an id into a single range
                var toSeek = packages.SelectMany(g => g.Dependencies).GroupBy(d => d.Id, StringComparer.OrdinalIgnoreCase)
                             .OrderBy(d => d.Key)
                             .Select(g => new NuGet.Packaging.Core.PackageDependency(g.Key, VersionRange.Combine(g.Select(d => d.VersionRange))));

                // recurse
                Stack <Task <IEnumerable <PackageDependencyInfo> > > tasks = new Stack <Task <IEnumerable <PackageDependencyInfo> > >();

                foreach (NuGet.Packaging.Core.PackageDependency dep in toSeek)
                {
                    // run tasks on another thread
                    var task = Task.Run(async() => await Seek(dep, projectFramework, includePrerelease, parents.Concat(new string[] { target.Id }), token));
                    tasks.Push(task);
                }

                // add child dep results
                foreach (var task in tasks)
                {
                    results.AddRange(await task);
                }
            }

            return(results);
        }
        // Thread safe fetch for the target only, no child dependencies
        private async Task Ensure(NuGet.Packaging.Core.PackageDependency target, NuGetFramework projectFramework, bool includePrerelease, CancellationToken token)
        {
            object lockObj = _lockObjsById.GetOrAdd(target.Id, new object());

            // lock per package Id
            lock (lockObj)
            {
                VersionRange alreadySearched = null;

                if (!_rangeSearched.TryGetValue(target.Id, out alreadySearched))
                {
                    alreadySearched = EmptyRange;
                }

                if (alreadySearched == null || !target.VersionRange.IsSubSetOrEqualTo(alreadySearched))
                {
                    // find what we haven't checked already
                    var needed = NeededRange(alreadySearched, target.VersionRange);

                    // adjust prerelease, is this needed?
                    needed = ModifyRange(needed, includePrerelease);

                    if (!_versionRangeComparer.Equals(needed, EmptyRange))
                    {
                        // server search
                        IEnumerable <IPackage> repoPackages = null;

                        if (_useFindById)
                        {
                            // Ranges fail in some cases for local repos, to work around this just collect every
                            // version of the package to filter later
                            repoPackages = V2Client.FindPackagesById(target.Id);
                        }
                        else
                        {
                            // DataService Repository
                            repoPackages = V2Client.FindPackages(target.Id, GetVersionSpec(needed), includePrerelease, false);
                        }

                        List <VersionRange> currentRanges = new List <VersionRange>();
                        currentRanges.Add(target.VersionRange);

                        if (alreadySearched != null)
                        {
                            currentRanges.Add(alreadySearched);
                        }

                        // update the already searched range
                        VersionRange combined = null;

                        if (_useFindById)
                        {
                            // for local repos we found all possible versions
                            combined = VersionRange.All;
                        }
                        else
                        {
                            // for non-local repos find the real range
                            combined = VersionRange.Combine(currentRanges);
                        }

                        _rangeSearched.AddOrUpdate(target.Id, combined, (k, v) => combined);

                        HashSet <PackageDependencyInfo> foundPackages = null;

                        // add everything to found
                        if (!_found.TryGetValue(target.Id, out foundPackages))
                        {
                            foundPackages = new HashSet <PackageDependencyInfo>(PackageIdentity.Comparer);
                            _found.TryAdd(target.Id, foundPackages);
                        }

                        // add current packages to found
                        IEnumerable <PackageDependencyInfo> packageVersions = repoPackages.Select(p => CreateDependencyInfo(p, projectFramework));
                        foundPackages.UnionWith(packageVersions);
                    }
                }
            }
        }