Single Package Version per Solution

Topics: General
Coordinator
Apr 29, 2011 at 5:50 PM
Edited Apr 29, 2011 at 7:07 PM

Hi All,

I recently posted a survey about usage patterns for assemblies and it was no surprise that a vast majority have no use for two different versions of an assembly in the same solution.

We discussed 2 solutions to this issue. One was using a fixed folder name for package folders. That actually doesn't solve this problem, it solves a different problem, source control churn. We're going to hold off on implementing that for now because it's a huge change. But we do plan to get to it.

What we're going to focus on is the second part of the problem. Treating packages as global to the solution. This means that packages are no longer side-by-side within a solution. So you can't have Log4Net 1.0 in one project and Log4Net 1.1 in another. It also means you can't have jQuery 1.5.1 in one project and 1.5.2 in another.

Without further ado, I present the proposed feature outline for what we plan to do and its implications.

Spec: Single Package Version per Solution

Note this is closely related in some ways to the spec for Updating All Packages in a solution.

Please provide feedback. I will be blogging about this soon but I have a ton of meetings today :( so won't get to it later. So please set a thoughtful tone for those who will flood in later. :P

May 2, 2011 at 5:26 PM
This looks pretty good to me.
May 2, 2011 at 5:40 PM

In my opinion nuget is a tool that speeds up development when you have default requirements so it seems better focusing on this rather than making it capable for every particular requirement

May 2, 2011 at 6:01 PM

I assume the single version would be per platform, right?  For example, if I have a solution that has a regular C# library, a SL library and a WinPhone library, and they all use Rx, then those should version independently?  There may be bug fixes or regressions in some of the platforms but not others.  Updating the WP version shouldn't force the regular CLR version to update, etc.

May 2, 2011 at 6:21 PM

I like this idea.  The proposal is straightforward and while there are some fringe cases, I agree with the proposal of throwing an error for the devs to decide how to proceed.  The needs of the many, as they say.

May 2, 2011 at 7:08 PM

The original idea was to be able to change the behavior back if necessary, but to default to global per solution. Not sure where that ended up though.

Just out of curiosity, do you have all of those project types in the same solution?

____
Rob
"Be passionate in all you do"

http://devlicio.us/blogs/rob_reynolds
http://ferventcoder.com
http://twitter.com/ferventcoder

Coordinator
May 2, 2011 at 8:14 PM

Maintaining two different systems turns this into a much bigger work item. We thought we could make it work by letting packages that don't have assemblies have the old behavior.

May 3, 2011 at 5:39 AM

I think that this issue could be solved much easier - just separate installation of packages to solution and adding those to projects. It might look like this form PS command line:

Simple usage:

Install-Package log4net - just installs package to solution

Add-Package log4net - adds package to project from installed in solution

 

Multi version usage:

Install-Package log4net -version 1.0 - installs 1.0 version of package

Install-Package log4net -version 1.1 - installs 1.1 version of package (if version is not provided, installs latest)

Add-Package log4net - adds package with highest version number

Add-Package log4net -version 1.0 - adds package with particular version

 

May 3, 2011 at 5:45 AM
Edited May 3, 2011 at 7:27 AM

Updating of packages might look like this:

If there is only one package per solution:

Update-Package log4net

If update to particular version:

Update-Package log4net -destinationVersion 1.1

If there are two different versions:

Update-Package log4net  - updates only package with highest version number to latest

Update-Package log4net -version 1.0 - updates particular version to latest

Update-Pakcage log4net -version 1.0 -destinationVersion 1.1 - updates package of particular version to particular destination version

 

Updating should update all references in projects.

For me it seems easier to understand and use.

May 3, 2011 at 2:22 PM

I see two things that need to be addressed.

1. Platforms. Many times I have my solution support a web site and a say a WP7 client both referencing say Json.NET. I don't necessarily want to upgrade the client and the server to the same version (maybe I'm not ready to push a new version out to the clients yet). So I absolutely have to have support for distinct platforms. Otherwise I'm creating one solution per platform and that's a mess to manage. I know this problem is about versions of packages in a solution, but I think the platform scenarios need to be taken into consideration.

2. Consolidating versions. In the "fix" for each scenario (project A references Log4Net 1.0 and project B references 1.1) all packages are upgraded to a single version. I find this to be wasteful. If we really don't need per-project versioning then why do I need multiple packages? Maybe I'm reading this wrong. So the updates to all projects will point at Log4Net 1.1 now and we'll a) drop the old versions from the packages b) consolidate them into the latest version and c) update all references to the latest version? As long as the upgrade to the latest version is around the versioning and takes into account the platform issues raised in #1 that should work.

I think the edge case where you need project A to reference one version and project B to be another just means you need to maintain separate solutions.

Coordinator
May 3, 2011 at 3:15 PM

1. That’s a good point and could be problematic under this plan.

2. Yes, we’d get rid of the old version.

I talked to a former consultant who worked on a lot of projects and he pointed out that there are a lot of valid reasons that you might have multiple versions of the same assembly.

For example, it happened quite often during a migration of code from one version of some library to another that they’d do it all in one solution.

I’m starting to worry that we may be too aggressive with this change if we don’t support the old model. For example, suppose you really really do need 2 different versions. Bil’s example of different platforms is a good one. How would you figure out how to do it?

If we make this change, it’d be very difficult.

I started to wonder if the real problem is not the lack of “unification”. But the real problem is lack of transparency. It’s not obvious nor clear when we’re about to put you in a state with different versions of the same assembly.

Perhaps what we should do is keep the current model, but prompt you when we detect these conditions so you can get yourself in a state that you want.

For example:

PM> Install-Package Log4Net 1.0 –Project MyConsoleApp

Log4Net 1.0 Installed.

PM> Install-Package Log4Net 1.1 –Project MvcApplication1

Log4Net 1.1 Installed. Still using an older version of Log4Net 1.0 in project MyConsoleApp. Run Update-Package Log4Net to update all Log4Net installs to the latest version.

We could even have a flag that would apply this new behavior.

PM> Install-Package Log4Net 1.1 –Project MvcApplication1 -UpgradeAllToThisVersion

Thoughts?

May 3, 2011 at 3:31 PM
So install-package -version is really how you could have the old model then? I'd be down for that.

How does install-package work if you already have an older version installed in the project (project meaning csproj, not solution)? Does it go ahead and install over the top of that?

Otherwise install-package log4net should install the already existing one in the solution. I am human, I go for the shorter keystrokes.

To sum it up:

Install-package packageName
  • installs already existing package in solution
  • upgrades an existing package in that project only
Install-package packageName -version versionNumber
  • installs that version of a package in the project whether it is in the solution or not
  • this is your model to have different versions
update-package packageName
  • solution level update of a package.
  • If multiple versions exist, they are all collapsed to a single version

In this case if you are needing several versions of a package which is not what most see as a regular workflow then you would always use install-package and never update-package.

For everyone else the normal workflow is update-package.


Thoughts?
____
Rob
"Be passionate in all you do"

http://devlicio.us/blogs/rob_reynolds
http://ferventcoder.com
http://twitter.com/ferventcoder
May 3, 2011 at 3:33 PM
A couple of small edits:

Install-package packageName
  • installs already existing package in solution
  • installs a package from feed if not found in solution
Install-package packageName -version versionNumber
  • installs that version of a package in the project whether it is in the solution or not
  • this is your model to have different versions
  • upgrades an existing package in that project only
update-package packageName
  • solution level update of a package.
  • If multiple versions exist, they are all collapsed to a single version
Coordinator
May 3, 2011 at 3:36 PM

Just to clarify. You’re suggesting that Install-Package wouldn’t always install the latest?

For example, I have a solution with ConsoleApp and MvcApplication1. ConsoleApp has Log4Net 1.0 installed (even though Log4Net 1.1 is available in the feed). When I run:

Install-Package Log4Net –Project MvcApplication1

It sounds like you’re suggesting that we install Log4Net 1.0 into MvcApplication1 since that’s the one already installed in the solution rather than installing Log4Net 1.1 into this project.

I kind of like that as it makes upgrade an explicit operation. If you really wanted all projects to have Log4Net 1.1, you could simply run: Update-Package Log4Net and be done.

May 3, 2011 at 3:55 PM
It definitely simplifies things for me. With the hyper maintenance issue (from the other discussion), I realized a project needed the same packages as another project in the same solution. I didn't want it to get the latest one (some error w/the latest in the local feed), I wanted to use the one I already had and just bring it over. I had to manually go through the steps of getting that version there. That could happen when I realize a couple of days after the first that I need the package elsewhere or when creating a new project in the solution.

For me - since I want the same version across the solution, I want install-package to come from what I already have if not explicitly asking for a different version.


Coordinator
May 3, 2011 at 3:59 PM

I see. What if it always tried to install the latest version but told you that you already had another version installed? Is it good enough to make you aware of the issue?

The reason I suggest this is I’m thinking about the Add Package Dialog. We always show the latest version in that dialog. It could be confusing if you’re looking at log4net 1.1, but we install log4net 1.0 because you already had that one installed.

One idea is we do install the latest, but give you an option to upgrade the existing instances to the same version as the one you’re installing.

Other options:

· The dialog simply behaves differently and keeps the current behavior.

· The issue I mentioned is not so bad and we make it behave the same as the console.

May 3, 2011 at 4:06 PM
I'd like to see it query your installed version and pull back that version from the feed and show you its information. This sounds on the surface like a substantial change though.

Since most people who would use that are likely to be in the camp of single version per solution I'd like to see its behavior lean the same way.


May 4, 2011 at 1:19 AM
Edited May 4, 2011 at 1:20 AM

You could solve a lot of issues if you seperate projects in different solutions based on two selection criteria:

  • The Product Dependency (PD) you are targeting (in our company we have product dependencies like DotNet3, DotNet4, SL4 (Silverlight 4), Spf2010 (SharePoint Foundation 2010) etc.
  • Functional Area's (FA): being the functional part you are working on like News or Portal.

We have a solution per functional area, and our code is organized as follows:

  • src\<PD>\<FA>\<PD><FA>.sln
  • src\<PD>\<FA>\Project1
  • src\<PD>\<FA>\Project2
  • :

If you now use a Package folder per solution it is much more natural to have one package version per solution:

  • You update the code of a whole functional area when you update to a newer version of a package
  • Due to separation per product dependency you never have for example a SL4 and DotNet4 assembly in the same solution (so never different versions of a package in a solution)

See http://solutionsfactory.macaw.nl for more information on how we structure code.

 

 

 

Coordinator
May 4, 2011 at 5:11 AM

We're starting to think that we'll go with our original unification plan and simply allow side by side as a flag when using Install-Package. Thus if you really need a side-by-side install of a package, you'd use the new -AllowSideBySide flag.

I think it'd be real confusing for the dialog not to show the latest version. Also, it'd be a substantial change. If we really believe most of the time people want all their packages kept in sync to the same version as the others, then this would be the best default behavior.

Thoughts?

Coordinator
May 4, 2011 at 3:37 PM

I should add more explanation. :) We discussed Rob's proposal, but that still leads to a lot of cases where you get out of sync. For example, going back to a solution with a console app and an mvc app.

  • ConsoleApp: Install Log4Net 1.0
  • MvcApp: Install Elmah -> Log4Net 1.1

In this case, the console app has log4net 1.0 installed. In the MVC application, we try to install Elmah which depends on Log4Net verison 1.1 or greater. Thus we'd end up installing log4net 1.1 in one project, and you'd have 1.0 in another.

Now if we believe our survey results, that's a situation most folks don't want to get into by default. They'd rather have log4net sync'd to the same version. So under our proposal, by default, we'd upgrade log4net in the console app to be the same version as the one we're installing in the MVC app.

But, under this revised proposal, we'll allow side-by-side if you specify a flag.

For example:

  • ConsoleApp: SuperLogger 1.0 -> Install Log4Net 1.0 exactly
  • MvcApp: Install Elmah -> Log4Net 1.1

In this scenario, SuperLogger is dependent on log4net 1.0 exactly (generally we don't recommend doing this with packages). Now when you attempt to install Elmah, we'll show an error because of a conflict with a package in another project. You can resolve the error by using the -SideBySide flag.

The downside to this is for those who use the dialog. What should happen? There's no way to specify a flag using the dialog, so we a few options:

  • Show a warning and allowing this to succeed as a side-by-side install.
  • Prompt the user and allow them to either cancel the install or allow side-by-side install.
  • Fail the install

Thoughts?

Editor
May 4, 2011 at 4:45 PM

My bigest concern is the idea that NuGet should impose a particular solution structure on my project by blocking certain scenarios, like multi-versions of a pacakge in a single solution. The various scenarios where this is useful have already been discussed here so I'll just say that I agree with the idea of having it default to single version per solution, but it absolutely must support side-by-side as well.

For the dialog case Phil's latest example, I think it's OK to fail in this case, with a suitable message explaining why. At least for an initial release. Adding a further prompt to either cancel or use side-by-side could be added later if it was deemed necessary. Otherwise, use the console.

May 4, 2011 at 5:15 PM

I suggest you do allow for multiple versions within a solution. There are many situations where one would want to have different versions for different projects in the same solution. For example, when you are developing for different targets (platforms) and you need different behaviours that are contained in the upgraded instance, but also want to remain "old-school" for the project you do not want to upgrade or can not upgrade due to platform/target specifics.

May 4, 2011 at 6:41 PM
Seems reasonable. I was hoping for not always getting the latest version if I have a current version of an item but I understand the issues with dependencies. I have a workaround that I can use if I need to stay on a particular version and otherwise if it upgrades everything for me when I don't mind the version then that sounds like it will work really well.

As Damien has pointed out, I also am on board with having the ability to go side-by-side if necessary should be there. I don't know if that was under question at any point but I wanted to point that out. Is that the best name for the switch though? With the explanation I understand what it means, but just looking at the SideBySide switch without any context its not immediately clear to me what I would use it for. Something that tells me that keys to multiple versions of a package might be helpful. Even SideBySideVersions tells me that is about having more than one version of a package. Or AllowMultiplePackageVersionsToBeInstalledWithThisSolutionBecauseIWouldLikeForToUseMultipleVersionsInThisSolutionSideBySide. Or something like that. ;)

Stay classy. :D
Coordinator
May 4, 2011 at 10:38 PM

I wonder if there’s an award for the longest PowerShell switch ever. ;) You know we don’t get paid by character, right?

Your comment about wanting to stick to a specific version made me think of something. Do we need a feature to allow locking a package? For example:

Install-Package Log4Net –Version 1.0.0 –Lock

Lock-Package Log4Net –Project MvcApplication

And what that would do is ensure that never got upgraded by accident. You’d have to explicitly upgrade it. It would never get upgraded because of dependency version leveling etc.

Not sure if it’s important or not. ;)

As for the name of -AllowSideBySide, I think our docs can help clarify. Unless anyone comes up with a better name, we’ll go with that. J

May 4, 2011 at 10:56 PM
We could change it to AllowMultiplePackageVersions for short.
May 6, 2011 at 2:58 PM

What do you think about my suggested solution?

It would allow multiple package versions and same time single package version per solution.

Developer
May 6, 2011 at 6:49 PM

@pioners: when we first started NuGet way back, we actually had separate commands for getting packages into the solution, and for installing them into specific projects. While it made more sense to us because it reflects how it works, most people found it pretty confusing, which is what led us to unify the two concepts.

May 6, 2011 at 8:23 PM

I must say that I can feel with pioners1001. NuGet is positioned as a Library Package Manager, which in my opinion is way too small and bad naming in the Visual Studio Tools menu. Of course, it is great for distributing, versioning and managing libraries and references to libraries, but that is just part of the deal. In my opinion it should be a general package manager for everything needed in developing your software product. This means there are packages at the project, solution and "above solution" level. There are packages for libraries, for scaffolding (T4Scaffoling, ...), for tools (Chocolatey), for everything. I would like to start with an empty folder, and from there build collect your tools, scaffolders, validators, guidance, libraries etc. etc. to build your software product. This is the way I try to prototype the version next of our software factory. Now I combine NuGet.exe command line version and the NuGet Library Manager in Visual studio with nuget configuration files for solution level package folders, but it is not as straight forward and clear as I think it could be. So my votes for some menu entry changes and clearity in package "levels".

 

May 9, 2011 at 4:12 AM

@davidebbo : Thanks, for reply. I didn't know that, but still think that separated commands would be much easier to use in large solutions. For 1-2 projects in VS solution current solution are the best.

May 9, 2011 at 8:21 PM
Edited May 9, 2011 at 8:24 PM

Out of all the work you guys have to do on nuget is this seriously the best usage of time now?

This feature done wrong could cause nuget to collapse for the very reason nuget was created. DLL Hell.

Suppose I have a package A that depends on JSON.NET X, they release a new version JSON.NET Y.

I now want to install package B that uses JSON.NET Y.

What happens here?

I stop using nuget?

**Edit:** is this a completely supported scenario outlined in

Coordinator
Wed at 11:37 AM?
Coordinator
May 9, 2011 at 8:25 PM

No, you install JSON.NET Y and now both projects are using JSON.NET Y. Based on what we’ve heard from most people, that’s what they want.

Most packages only specify a min version of support, so this would work in most cases just fine. But suppose package A specified an exact match dependency on version X (as in it can’t work with version Y), we will allow you to install JSON.NET Y by using the –AllowMultipleVersion flag.

Read through the various discussions, there’s a lot of demand for this. Now that we’ve been trying this feature out though, we are debating making unification opt-in instead of opt-out.


It does seem to introduce a lot more error cases that are not obvious to the casual NuGet user.

May 9, 2011 at 8:58 PM
@dotnetchris: Without this feature NuGet creates it's own version of a DLL hell. I speak from experiencing it, not from guessing or estimating that it will happen.

My team has been in a hyper maintenance mode using internal packages.

In our solution we have say 8 projects. We may need to have a particular package in 6 of them. Now when it's time to upgrade a team member has to know to upgrade that package in six places. If they miss or forget even one, they will have two versions of a DLL referenced that may or may not play well together due to breaking changes or whatnot.

The package manager should be smart enough to handle when I have version discrepancies externally (known DLL hell) and keep me from having them internally (nuget dll hell) unless I choose (opt-in) to take on an internal versioning discrepancy.

Getting this right is important. This feature as it stands at current is not setting up developers for success in a long term maintenance situation.
May 9, 2011 at 9:04 PM

When I say feature in the context of my last reply, I mean the way the system works now.

The idea for this is that you would be allowed to go into having multiple versions because there are valid cases for that, but most people use only one version of a dll (package) per solution and don't want to try to handle multiple versions and all of the complexities in builds and runtimes that multiple versions bring.

May 10, 2011 at 1:01 PM

Does Nuget actually have to make an answer for users themselves on this at all (aside from command line i guess)?

This sounds like the update package GUI should then spill over into a tree view of all the projects in your solution that currently use this package and give you a checkbox tree, along with toggle all buttons to pick which projects to upgrade. At this point it's up to the user everytime, you could slide people towards single version in a solution by defaulting to checking all on.

Coordinator
May 10, 2011 at 3:40 PM

We’d like to be a little more prescriptive based on what nearly everyone told us was the pattern they used to work. If most people unify versions, why would we make the normal course of action take more steps? Shouldn’t we optimize for that?

Another approach we’re considering is if there is a conflict, we prompt the user only then and give them a choice to fail the install or allow multiple versions. That way, in the normal course of action, things just work. Only in an exception case, does the user have to make an extra decision.

May 10, 2011 at 10:36 PM
Edited May 11, 2011 at 12:38 PM
Haacked wrote:

We’d like to be a little more prescriptive based on what nearly everyone told us was the pattern they used to work. If most people unify versions, why would we make the normal course of action take more steps? Shouldn’t we optimize for that?

 

Another approach we’re considering is if there is a conflict, we prompt the user only then and give them a choice to fail the install or allow multiple versions. That way, in the normal course of action, things just work. Only in an exception case, does the user have to make an extra decision.

If you would make the default action to check off upgrade for all the projects there is no additional work.You are reviewing what projects will be updated and confirming this.

If I as a nuget user went to add a completely unrelated package that coincidentally used a newer version of a package and my solution changed all over the place I'd be quite taken aback. When stuff is modifying my solution I want to have a very clear idea of what I should expect it to do.

I also don't believe this a question you can easily put into a YES / NO dialog that will be understood well, presenting a tree view of the projects that are about to change "All selected projects are about to be updated to use PACKAGE X 1.5 (We recommend updating all projects to the same version whenever possible)" Would be almost impossible to make a misunderstood decision.

May 11, 2011 at 10:02 PM
Edited May 11, 2011 at 10:02 PM

While you're looking at this I'd like to add a suggestion/wish. That the location of the packages can be defined as being outside the SLNs directory so that it may be shared by many solutions.

The reason is that our application is made up of approx 60 solutions and 330 projects. Having separate copies of packages for every solution makes NuGet very difficult for us to use. If the package location could be defined as a relative path, that would be perfect.

 

workingCopy
 lib
module1
module1.sln
project
project.csproj
...
module2
module2.sln
someProject
someProject.csproj
... 

For common 3rd party references we have relative file references to the appropriate bits in the lib folder. If we could replace lib with a common NuGet package folder.

"So if you could just go ahead and, ah, pull that together, that'd be greaaaat"

May 11, 2011 at 10:33 PM
@andypook:
I believe what you are looking for is the nuget command line tool. It will do exactly what you are asking for today (Note that it knows nothing about Visual Studio so you will need to handle adding the references yourself). NuGet inside of visual studio is a per solution tool because visual studio only knows about one solution at a time, so it makes sense it can't do a bunch of awesome for multiple solutions (like running the powershell scripts and automatically adding references to projects) all at the same time. I don't believe we will lean it that way either (but you never know). There are way too many discrepancies and too many possibilities for issues that could pop up by having all of them share a set of libs if we were to try to approach this behavior inside of visual studio.
So short answer, you may want to have a look at the nuget command line tool to manage your packages. I know this isn't the response you were looking for. Oh, but it is. ;-) <waves hand in half crescent>
May 12, 2011 at 10:44 AM
Thanks for the detailed reply.

With the discussion in this thread around versions and dependencies it would seem to me (probably naively) to be not too big a step to allow the solution to "point" at a different package repository. You are obviously correct in stating that there are some circumstances that the sln/ide will not be able to deal with. But that is no different than the current approach of having a common "lib" folder.

It would be a real shame to miss out on the project/sln manipulation features available when you "install" a package into a project for the first time.

On 11 May 2011 23:33, ferventcoder <notifications@codeplex.com> wrote:

From: ferventcoder

@andypook:
I believe what you are looking for is the nuget command line tool. It will do exactly what you are asking for today (Note that it knows nothing about Visual Studio so you will need to handle adding the references yourself). NuGet inside of visual studio is a per solution tool because visual studio only knows about one solution at a time, so it makes sense it can't do a bunch of awesome for multiple solutions (like running the powershell scripts and automatically adding references to projects) all at the same time. I don't believe we will lean it that way either (but you never know). There are way too many discrepancies and too many possibilities for issues that could pop up by having all of them share a set of libs if we were to try to approach this behavior inside of visual studio.
So short answer, you may want to have a look at the nuget command line tool to manage your packages. I know this isn't the response you were looking for. Oh, but it is. ;-) <waves hand in half crescent>

Read the full discussion online.

To add a post to this discussion, reply to this email (nuget@discussions.codeplex.com)

To start a new discussion for this project, email nuget@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe on CodePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at CodePlex.com


Coordinator
May 12, 2011 at 8:41 PM

Hi All, I wanted to provide an update on this.

David Fowler prototyped the unification feature and in testing it out, we found a lot of issues that aren't easily worked around. For example, ASP.NET MVC 3 installs a specific jQuery version and includes a script reference in the default template to that version. Automatic unification could break an MVC 3 project if you install a newer jQuery in another project.

Also, DotNetChris brought up a lot of valid concerns about this.

So what we realized is we're probably taking on too big a bite on this in one iteration. So we're going to scale it back a bit. That'll allow us to let people try the new features and give us feedback (and allow us time to play with them) before we do any drastic changes.

So right now, we're planning the following (Note: this is just a summary. I hope to have time to provide more details later):

1. Update-Package will have support for updating a package in all projects (as well as updating all packages in all projects). The benefit of this is for those who do care about unification, you could run this command from time to time to get all packages up to the latest version assuming there isn't a constraint holding it back.

2. Bundlr like version range constraints on installed package. (Note: we're not implementing Bundlr yet). The basic idea here is suppose you install a package Foo 2.0 and you know you don't want version 3 ever. But you're fine with 2.*. When you install the package, you can specify a version range instead of a version. Install-Package Foo -Version=[2.0,3.0). That way, even if version 3.* is in the feed, when you run Update-Package on Foo, it'll only upgrade you to the latest 2.* version. Make sense?

3. Solution level Add Package Dialog. When you launch a dialog from the Solution node (not project node), we'll make the Add Package Dialog work in the solution context. In this context, installing a package allows you to choose which projects to install the package into. This will streamline adding a project to multiple projects. Also, from this dialog, you can update packages in multiple projects, etc.

4. Dependency version leveling. When upgrading a package, we can change the version of dependencies to allow the package to upgrade.

May 12, 2011 at 9:43 PM

The Solution level Add Package Dialog sounds great. Will there also be a -solution flag to the install-package cmdlet?

May 13, 2011 at 8:08 AM
Would it a big step therefore to add a solutions setting allowing me to override where the local package directory is? This would allow multiple solutions to share a set of packages. From my understanding of your description this wouldn't add any extra complexity.

Hoping I too will be able play with the NuGet Goodness.

On 12 May 2011 21:41, haacked <notifications@codeplex.com> wrote:

From: haacked

Hi All, I wanted to provide an update on this.

David Fowler prototyped the unification feature and in testing it out, we found a lot of issues that aren't easily worked around. For example, ASP.NET MVC 3 installs a specific jQuery version and includes a script reference in the default template to that version. Automatic unification could break an MVC 3 project if you install a newer jQuery in another project.

Also, DotNetChris brought up a lot of valid concerns about this.

So what we realized is we're probably taking on too big a bite on this in one iteration. So we're going to scale it back a bit. That'll allow us to let people try the new features and give us feedback (and allow us time to play with them) before we do any drastic changes.

So right now, we're planning the following (Note: this is just a summary. I hope to have time to provide more details later):

1. Update-Package will have support for updating a package in all projects (as well as updating all packages in all projects). The benefit of this is for those who do care about unification, you could run this command from time to time to get all packages up to the latest version assuming there isn't a constraint holding it back.

2. Bundlr like version range constraints on installed package. (Note: we're not implementing Bundlr yet). The basic idea here is suppose you install a package Foo 2.0 and you know you don't want version 3 ever. But you're fine with 2.*. When you install the package, you can specify a version range instead of a version. Install-Package Foo -Version=[2.0,3.0). That way, even if version 3.* is in the feed, when you run Update-Package on Foo, it'll only upgrade you to the latest 2.* version. Make sense?

3. Solution level Add Package Dialog. When you launch a dialog from the Solution node (not project node), we'll make the Add Package Dialog work in the solution context. In this context, installing a package allows you to choose which projects to install the package into. This will streamline adding a project to multiple projects. Also, from this dialog, you can update packages in multiple projects, etc.

4. Dependency version leveling. When upgrading a package, we can change the version of dependencies to allow the package to upgrade.

Read the full discussion online.

To add a post to this discussion, reply to this email (nuget@discussions.codeplex.com)

To start a new discussion for this project, email nuget@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe on CodePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at CodePlex.com


May 13, 2011 at 9:06 AM

That would be great in a multiple solutions approach. We have this approach currently in our factory, and using NuGet in that situation would result in a lot of duplication in package storage. On the other hand: if you use different solutions by different teams who can have different version of packages in use, a separate packages folder per solution would be key.

I think the best approach would be to have two levels of packages: a packages folder per solution, and a high-level packages folder, or even as many higher-level packages folders that you need.

You could then do something like below where there are three levels of packages used. You should decide at what level packages are stored, and a lower level package can override a higher level package.

c:\Projects\MyProduct:

  • Packages
    • ProductPackager-1.2.3
  • Src
    • DotNet4
    • SharePoint2010
      • Packages
        • SharePoint2010Assemblies-1.0.0
        • SharePoint2010Scaffolders-1.0.0
      • MyFirstSolution
        • Packages
          • SmartSharePointLib-1.0.0
        • ...
      • MySecondSolution
        • Packages
          • SmartSharePointLib-2.3.4
        • ...

 

 

Coordinator
Sep 27, 2011 at 4:29 PM

We started discussing this in http://nuget.codeplex.com/workitem/1522 and I want to throw one more proposal out there. For now, I'm scoping this discussion to a single solution. We should start a separate thread for multiple solutions.

When we investigated unification with versionless folders, we realized it was too big a change to make and caused so many challenging design problems that we didn't want to devote the next few months of the project to this one feature.

But maybe we can scope this down to make it more manageable as an advanced feature.

Instead of unification, what if we allowed locking individual package installs to a versionless folder. This would not affect how that package is installed in other projects in the same solution.

For example, suppose I have a Solution with 2 projects (ProjectA and ProjectB) and a package named TestStuff 1.0.

When I install TestStuff into ProjectA, I can use a versionless flag.

 

Install-Package TestStuff -versionless

 

Instead of the usual layout, this will install the package with the following layout. We probably need to record this fact in packages.config. Perhaps a versionless="true" attribute.

\packages
    \TestStuff
        \lib
        \tools

If I install TestStuff into ProjectB the normal way, we'd get:

\packages
    \TestStuff
        \lib
        \tools
    \TestStuff.1.0
        \lib
        \tools

So far, the versionless install is treated no differently than a versioned install. Where things get tricky is if we install TestStuff into 2 different projects using the versionless flag.

Install-Package TestStuff -versionless -Project ProjectB

I'll explain why that's tricky in a second.  This leaves us with a packages directory that looks like this with both ProjectA and ProjectB referencing the assemblies in lib. So far so good.

\packages
    \TestStuff
        \lib
        \tools

Suppose I then install TestStuff.Contrib into project B which depends on TestStuff >= 1.1.

In order to install this into ProjectB, it's going to need to upgrade TestStuff to 1.1. Since TestStuff is marked as versionless, we'll unpack the contents to the same place and change project B to reference the new contents. ProjectA, because it's referencing assemblies in the same place, also has its references updated as a side-effect.

Question Is this a good thing? In some cases it's not. What if TestStuff.Contrib had config transformations that ProjectA needed. Or it had PS1 scripts that need to run. ProjectA would not have had the benefits of that. 

Alternatively, what if ProjectA has some other package installed that depends on TestStuff 1.0 only. So now ProjectA is broken because of incompatibilities.

Possible Solution: One solution is we can say, "Sorry, but we don't care!". If you choose to use -Versionless, you opt-in to these potential consequences. For the types of things people are planning to do with -Versionless, it's probably rare that these issues actually cause any problems.

Developer
Sep 27, 2011 at 8:40 PM

My take is that it's fine to say we don't care about it not being 100% correct in the (scenarios you describe), because it's an opt-in. It comes with pros and cons, and those who chose it need to understand that.

Editor
Sep 28, 2011 at 12:43 PM

I think this is a great place to start from.  Opt-in, caveated with a warning regarding this side effect also seems fine.  The ability to set this as your default would be fantastic.

Just so I understand though, the real underlying issue resulting in the potential conflict is the packages directory being used for the side by side temporary installation location for the uninstall/install process, right?  The other issues around ProjectA not having had scripts run etc would then just be a run through all packages.config files listed in repositories.config to identify other dependent projects.  We do something similar already via an extension to reduce the number of OData calls/package downloads on internal servers (provides fully condensed solution-wide packages.config prior to processing).

So it seems there is the possibility (with some dev work and design changes, I admit) that this caveat could be removed at a later date through the use of either temporary location/memory location for unpack prior to uninstall (or similar).  This would leave a levelling/versioning issue, however that seems less a functional failure and more a user choice/decision.

Coordinator
Sep 28, 2011 at 3:48 PM

@Ben yep. We prototyped the implementation a while back and there were some other subtle issues that came up that you wouldn't ordinarily consider until you actually try it. But I don't remember what they are. David Fowler could probably say more about them.

I think the idea here would be to take a very small iterative evolutionary approach. Down the road, we can improve it bit-by-bit. It helps to have parts of it being used so we hash out all the potential issues rather than trying to do it all at once and break a ton of people. :)

We probably need to flesh out the spec to call out all the various edge cases and design issues. Ideally the spec could also call out the various pieces we could add one at a time with design for them. http://nuget.codeplex.com/wikipage?title=Package%20Updates%20Should%20Be%20Global

Unfortunately, i won't get to it soon, but if I had volunteers from the community willing to think hard about this and help us spec it out, I'd provide write access to that document. :)

Editor
Oct 4, 2011 at 11:46 AM

@haacked happy to have a look at it, and drop you through some thoughts.  Do you want it chucked up on this message, or direct?

Coordinator
Oct 4, 2011 at 8:28 PM

Ben, here's the outdated spec. I'd rather we iterate on it: http://nuget.codeplex.com/wikipage?title=Package%20Updates%20Should%20Be%20Global

Coordinator
Oct 4, 2011 at 8:28 PM

p.s. I made you an editor. Be responsible. ;)

Dec 30, 2011 at 8:40 AM

Hi Everybody :)

Perhaps it's a bit late to add my comments to this feature. But it's something that, for me, should have been like that from the beginning.

So let's begin: .NET allows you to have multiple version of the same assembly. As far as I know you can do that with the GAC or with files with different names (nuget here).

Usually the assembly file name is the same for different versions. So from the first day using nuget I had to remember to update "ALL" references to a library package to avoid having a random version in the output project.

Also as you see in many open source projects there is a "common" libs, packages, bag of common assemblies. You can even improve on that with the feature of not comitting the nuget library packages and downloading them on "checkout/clone".

Therefore, in my little .NET world + few years experience, I cannot understand who will need (for example) two versions of log4net in the same solution. And if he needs them, how he is going to manage them without extra "steps" (I'd say hacks to rename files).

You can also observe how communities work in other languages/frameworks. A virtual GAC with ruby or pyton: rvm and virtualenv. Even if those languages allow you to import a specific version of a library, it seems easier for the people to build virtual environments with specific versions to avoid mistakes.

For me "conceptually" packages per project makes no sense. But speaking csproj/Visual Studio language, you see that projects depend on assemblies, so it seems more "correct" to work per project.

Anyway, great work guys :)