Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Guarantee same version of nuget packages

We have a framework that is split up into lots of separate projects in one solution. I now want to create NuGet packages for each separate project, but guarantee that only one version of the framework can be used in one solution (possibly across several projects).

For example, say the framework is made up of two projects:

Framework
   Framework_1
   Framework_2

Now when using this framework one project might reference Framework_1, while another project references Framework_2. I want to make sure that both packages have the same version (bonus points if there's an easy single-step process to upgrade to a newer version)

I thought I would just define one solution level Framework package that all other packages depend on strictly. The problem is that NuGet has no problems simply installing several versions of the solution level package.

Basically I tried the following:

Solution-level nuspec file:

<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
  <metadata>
    <id>My.Framework</id>
    <version>1.0.0</version>
    <title>My.Framework</title>
    <authors>voo</authors>
    <owners>voo</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Some Framework Solution Package</description>
    <copyright>Copyright ©  2015</copyright>
  </metadata>
</package>

And one nuspec package for one part:

<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
  <metadata>
    <id>My.Framework.BL</id>
    <version>1.0.0</version>
    <title>My.Framework.BL</title>
    <authors>voo</authors>
    <owners>voo</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Business Layer</description>
    <copyright>Copyright ©  2015</copyright>
    <dependencies> 
        <dependency id="My.Framework" version="[1.0.0]"/>
    </dependencies>
  </metadata>
</package>

The problem now is if I tried to install, say another My.Framework.EF package with version 1.0.1 and an explicit dependency on My.Framework 1.0.1 Visual Studio would just install My.Framework twice - once with version 1.0.0 and once with 1.0.1.

like image 418
Voo Avatar asked Jun 16 '15 12:06

Voo


People also ask

How do I trust a NuGet package?

Look at package author in Visual Studio. Refer to nuget.org to look at package owners and number of downloads (and sometimes source code) If the package owners somewhat match the author in Visual Studio, and the package seems generally trusted in the community, then add the package reference.

How do I reference an existing NuGet package from a new project?

NET Core project. After you install a NuGet package, you can then make a reference to it in your code with the using <namespace> statement, where <namespace> is the name of package you're using. After you've made a reference, you can then call the package through its API.


2 Answers

you can constrain the version of your package by using the following syntax in your packages.config like :

<package id="jQuery" version="1.9.1" allowedVersions="[1.9.1]" />

Also from original nuget documentation : When you create a NuGet package, you can specify dependencies for the package in the .nuspec file.

<dependency id="ExamplePackage" version="[1,3)" />

In the example, version 1 and version 2.9 would be acceptable, but not 0.9 or 3.0.

I asume you can limit it this way to a single or certain range of versions. Here you can read more about it.

like image 116
Mladen Oršolić Avatar answered Oct 16 '22 16:10

Mladen Oršolić


You can create a simple unit test inside your solution to warn you when you have a problem. The code is below.

You will need to install-package NuGet.Core inside your unit-test project for the below code to work.

using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NuGet;

[TestClass]
public class NugetPackagesTest
{
    /// <summary>
    /// This test method makes sure that we do not install different versions of the same nuget package
    /// across the solution. For example this test will fail if one project references EntityFramework
    /// version 6.1.3 and another project references version 6.2.0. Having different versions of the same
    /// package installed often results in unexpected and hard-to-understand errors.
    /// </summary>
    [TestMethod]
    public void PackagesAccrossProjectsAreOfSameVersion()
    {
        var dir = GetSolutionRoot();

        Debug.Assert(dir != null, nameof(dir) + " != null");

        var filePaths = Directory.GetFiles(dir.FullName, "*packages.config", SearchOption.AllDirectories);
        var installedPackages = filePaths
            .Select(t => new PackageReferenceFile(t))
            .SelectMany(t => t.GetPackageReferences().Select(x => new { File = t, Package = x }))
            .GroupBy(t => t.Package.Id)
            .ToList();

        foreach (var package in installedPackages)
        {
            var versions = package
                .Select(t => t.Package.Version.ToNormalizedString())
                .Distinct()
                .ToList();

            var report = package
                .Select(t => $"{t.Package.Version} @ {t.File.FullPath}")
                .OrderBy(t => t);

            Assert.IsTrue(
                versions.Count == 1,
                $"Multiple versions of package {package.Key} are installed: {string.Join(", ", versions)}.\n" +
                $"{string.Join("\n", report)}");
        }
    }

    private static DirectoryInfo GetSolutionRoot()
    {
        var current = AppDomain.CurrentDomain.BaseDirectory;
        var dir = Directory.GetParent(current);

        while (dir != null)
        {
            // TODO: replace with name your solution's folder.
            if (dir.Name == "MySolution")
            {
                dir = dir.Parent;
                break;
            }

            dir = dir.Parent;
        }

        return dir;
    }
}
like image 41
niaher Avatar answered Oct 16 '22 15:10

niaher