I have a number of solutions which share the same projects in different folders, for example,
Common folder
- common 1
- common 2
Contracts folder
- contracts for project A
- contracts for Project B
Application 1 folder (in this folder I have my solution file)
- Solution A
- nuget creates packages folder there
Application 2 folder
- Solution B
- nuget creates packages folder there
packages folder( I need this folder at top level, so all projects can reference it)
With this structure Nuget creates two packages folder inside of Application 1 and Application 2
But all of this projects and solutions related to each other, so logically it's better to have only one packages folder.
Is it possible to set in nuget only one folder and use that folder for all solutions?
Or should I structure my solutions and projects another way?
You can do this by adding nuget.config files to each solution with following contents
<settings>
<repositoryPath>..\Packages</repositoryPath>
</settings>
Make sure that they all point to the same folder.
When you make this file, you have to restart Visual Studio to make it use this setting ( or at least close and open the solution).
But more practical would be to create just one nuget.config that all solutions make use of. Just make sure it resides on a folder higher then any solution file you wish to include. When restoring, the nuget manager searches for this file, starting from next to the solution file and if not found, start looking higher up the folder structure.
Sharing a repository between 2 solutions isn't really possible, as if you update a package in solution A the projects in solution b won't be updated unless they're also in solution A (and may have their package automatically deleted because solution A doesn't use them anymore). Basically meaning having 2 solution files is redundant or you're going to break the other solution with no way of knowing.
How are the solutions related to each other? Maybe there's another way to solve the problem if we have a bit more information.
Related
Under c:\Users\<USER NAME>\.nuget\packages\ directory, there are some folders looks similar, for example:
System.IO.FileSystem.4.3.0
system.io.filesystem (and there are sub-folder "4.3.0" under it)
See attached figure.
My question: why are there similar Nuget package folders in .nuget\Packages directory? Can I delete one of them?
Possibly you used an old version of NuGet or Visual Studio on your machine, which used the old format. The other option is that you have a nuget.config that forces that solution packages folder to be your user profile's global packages folder. I really don't recommend this.
Maybe starting with NuGet 3.0 (Visual Studio 2015), NuGet uses the tolower(packageid)\tolower(packageversion)\ folder structure. I'm too lazy to test old versions to validate that earlier versions used something different. Or maybe NuGet has always used the same format for the global packages folder, making the packages.config answer the only possibility. But I really think that lowercase normalisation was something that was added and didn't always exist.
projects that use packages.config have always used the unmodified PackageId.PackageVersion format in the solution packages folder. I believe it was deemed too risky as a breaking change that some customers depend on to change in the solution packages folder. So, if anyone had the misguided idea that they could save disk space by making all their solutions share the same packages folder by using the same one for all solutions, and the folder they used is the global packages folder, then the two different parts of NuGet which intentially use different folder naming conventions, will write to the same directory.
As long as you're not in the middle of a build, it's always safe to delete folders in any packages folder (global packages, as your question is about, or a solution packages folder). If a project needs a package that was deleted, NuGet will download it again, so if you have a download quota, or a slow internet connection, maybe be mindful. Otherwise you can be as liberal with deleting folders as you like. Just make sure to delete the entire folder. There's only one file NuGet looks for when restoring, so if you delete other files but leave that one, NuGet will think it's downloaded and extracted properly, but your machine will behave differently to other machines.
We have a build step that installs and updates the nuget packages in a solution on out build server (TeamCity). Recently this has stopped doing the updates correctly. I have investigated this and found that the problem seems to be that the update command in nuget is not updating all the projects in the soltution. I can replicate this on my local machine.
When I run this command:
.nuget\NuGet.exe update Our.Company.sln -Source http:/ourTcServer:8888/guestAuth/app/nuget/v1/FeedService.svc -RepositoryPath packages -verbosity detailed
I get this a list of 10 projects it is going to update
Found 10 projects with a packages.config file. (
Company.Project1.csproj,
Company.Project2.csproj,
Company.Project3.csproj,
Company.Project4.csproj,
Company.Project4.SubProject1.csproj,
Company.Project4.SubProject2.csproj,
Company.Project1.SubProject1.csproj,
Company.Project1.SubProject2.csproj,
Company.Project2.SubProject1.csproj,
Company.Project2.SubProject1.FurtherSubProject1.csproj)
However the solution contains 13 projects and these all contain packages.config files and as far as I can tell are no different to any of the other projects. The projects are a single project and its subprojects and our projects directory structure matches the projects names (so project1.subproject1 implies that subproject1 is in a folder inside project1) in case that is important. The projects with the issue are all in a project which has the specific names like :
Company.Something.SomethingElse.Routing
Company.Something.SomethingElse.Routing.Tests
Company.Something.SomethingElse.Routing.Tests.Specifications
In case the routing part of the name causes a problem (we had a problem before using the word Resources at the end of our package name)
We have 50+ solutions that all use the same build configuration and steps and it works fine for all of them. This solution seems to be the only one which is not updating correctly.
Does anyone know why this might be the case? Or does anyone know what the code that finds packages in a solution does which might cause it not to find some packages.config files? Or anything that might help track down this issue?
Ok so the issue was that we had renamed some of our projects and so the .csproj files and had not removed to old, unused project files and nuget has a piece of code which finds the projectfile into which it it going to update the references of the updated packages. It does this by finding all the files which are .csproj (or whatever project file flavour you are using) in the same directory as the packages.config. If this does not result in exactly 1 file then it throws an exception, which is subsequently caught and ignored and nothing is logged, so you are non the wiser.
Hopefully this will help someone else in the future. Maybe me.
I found that the problem I ran into was that my projects were not in the same directory tree of the solution.
The nuget.exe update command when given solution file searches for packages.config files using the solution directory as the starting point instead of looking at each project file in the solution.
From the nuget code on GitHub:
string[] packagesConfigFiles = Directory.GetFiles(
solutionDir, "*.config", SearchOption.AllDirectories);
You can see that they are just looking for *.config files starting in the solution directory.
My projects and solutions are organized like this:
/Libraries/Shared/Shared.csproj
/Programs/NTService/NTService.csproj
/Programs/NTService.sln
In this case, if I run update on the NTService.sln file it will only update the NTService.csproj references because it is in the same directory tree as the NTService.sln file.
Since it just looks at all packages in the whole tree, I just put a solution file at the root of my repository and then run the update on that. It doesn't matter what projects are in that solution file.
I'm in the process of converting a handful of projects from ripple to Paket. The way I do this is install Paket, then take my ripple.config and copy my sources and nugets over to my paket.dependencies, taking care to == the versions that I have fixed. Then I .paket/paket install over and over and over again trying to resolve versioning errors that come up from that.
After that, I open all my .csproj files and add an extra ..\ to all the HintPaths before opening my project and manually resolving whatever errors pop up.
Is there a better way to do this? I know there's a ripple-to-paket converter but I not only couldn't get it to work, but many people I work with say that it's terrible.
Thank you.
1 add a paket.references file in each project's folder
In each of your project files' folder, you should create a paket.references and list there the package name (only, the other info is kept consistent in your paket.dependencies in your root folder).
2 make sure the actual reference are handled with paket
you can manually remove the reference in the project files (either from VS or edit the project file), and call paket install which will add them (according to paket.references in the project's folder) with an additional <Paket>True</Paket> node (making it clear that this reference is handled by paket itself)
I think this is it.
UPDATE:
So it turns out that we may have found a bug in Visual Studio 2003 (I know...no surprise). We found out that if the solutions were added to the repository using Visual Studio (using Add Solution to Source Control) everything went fine...go figure.
So we're converting our VSS repository (if it can be called that) to Perforce and we're running into issues with projects included in multiple solutions.
Our repository might look like this...
//Depot
DevMain
Solution1
Project1 (Builds to a DLL)
Solution2 (Has Project1 as a project reference)
Project2
Solution3 (Has Project1 as a project reference)
Project3
When using the integrated Source Control in Visual Studio for Solution2 it complains that the projects are not under the current solutions folder and we may want to move it. Because multiple solutions reference Project 1 we can never organize it where one solution won't complain...
Is the best practice to just build Project1 to DLL and store it in a Lib folder? Or is there a better way?
Thanks.
We had a similar problem and were approaching it very much like #Toby Allen mentions in his answer, via client specs. However, in time this becomes very painful (setting up a new team member becomes more and more difficult as client specs become more and more convoluted; also automation is much more complicated because things are... "in flux" :-) ).
Eventually, we evolved our strategy to use a directory structure and branching instead. The directory structure is as follows:
//depot
/products
/(product_name)
/doc
/lib
/(3rd_party_libname)
(DLLs)
/(another_3rd_party_libname)
(DLLs)
/src
/Project1
(files, csproj, vbproj, etc)
/Project2
(files, csproj, vbproj, etc)
/Project3
(files, csproj, vbproj, etc)
Solution1.sln (includes src/Project1)
Solution2.sln (includes src/Project1, src/Project2)
Solution3.sln (includes src/Project1, src/Project3)
/(another_product_name)
/doc
/lib
/src
(solutions)
/shared
/(shared_lib_name)
/doc
/lib
/src
(solutions)
/(another_shared_lib_name)
/doc
/lib
/src
(solutions)
Note that the same structure is repeated throughout the structure (doc/lib/src/solutions). Lib contains "external" libraries - 3rd party libraries that are included in project references. Src contains a flat list of all projects that are part of a particular product. Solutions are then used to "combine" projects in any number of ways. I think of src directory as a container with "what is available", solutions are then picking from this container and combining projects (as needed).
Libraries that are shared among multiple products go into shared directory. Once in shared directory, they are treated as independent from products - they have their own release cycle and are never joined to products as source. Shared libraries are pulled into products by branching the shared library release assembly/assemblies into product's lib directory -> from product's perspective there is no difference between a 3rd party library and a shared library. This allows us to control what product is using what version of a shared library (when a product wants new features, it has to explicitely branch in newer release of a shared library, just like it would include a new release of a 3rd party library, with all pros and cons that go with it).
In summary, our structure has concept of two "types" of shared libraries:
projects local to a product, used by multiple solutions (included in a flat list of projects in src directory, multiple solutions can reference them)
projects used by multiple products (added to shared directory, treated as 3rd party libraries with releases independant from products)
The solution should be to rebind Solution1 to the source control server each time it's added to a new project. (It's under File->Source Control->Change Source Control.)
This should only need to be done once per desktop per solution.
I don't know much about using Visual Studio with Perforce, but you might consider creating workspace views that map Project1 into Solution2, Solution3, etc., where needed.
If I understand correctly you want how your files are stored on disk to differ from how it is stored in Perforce. If this is the case, and you cant simply redefine the reference within VS, then a cleverly designed client can do the trick.
Client: Client_Solution2
Description:
Created by Me.
Root: C:/Development/Solutions
View:
//depot/Devmain/Solution1/... //Client_Solution2/Solution2/Solution1/...
//depot/Devmain/Solution2/... //Client_Solution2/Solution2/...
This will give you a structure where Solution1 is a sub directory of solution 2.
I have a bit of code for a dll that is needed by two or more projects in eclipse. Currently each project has a copy of the code and builds the DLL separately. I want to separate the dll code into a separate eclipse project so there is a common location. But I want to avoid the situation where we have to build the dll in the one project, then copy the dll back to the other projects and check the dll to each respective project. This will create a dll for each project that isn't traceable to the exact code that it was built with.
Is there a way to somehow symbolically link the dlls to another eclipse project that is using CVS as the version control system so that it is possible to tell which version of the code was used to create the dll? Am I making this too complicated or missing something obvious?
I thought about working sets in the package manager for eclipse, but I have to investigate more on how to use them with CVS to avoid making it a nightmare for the next person who checks it out and can't figure out why their project won't compile.
Thanks.
What about creating a new folder in a separate project. In the advanced section of creating a new folder there is an option to link to another location on the file system.
Or you could also create a container project that makes use of a projectset.psf file. Have the projectset file link to the different projects in your repository. When you want to check out that project, check out the container instead and right click on the projectset file and select Import Project Set...
If you are working with one workspace, you end up with three projects, each mirrored in CVS: One is the dll, the others are the projects using the dll (configured as a project dependency of these projects upon the dll project).
With three projects I wouldn't aim for working sets - they are good for managing a lot of projects within one workspace, for three projects, I'd consider them overkill. I usually tend to aim for several workspaces instead of working sets.
Regarding the next person working with these projects: You need to keep some kind of documentation about how to setup your projects. You might say that your eclipse project files do just that (as they define a project dependency upon another project) but this is for the machine - humans tend to like other communication means.
If you are worried about changes to the dll being incompatible to one project (because the person applying these changes doesn't care about the other project), aim for a build server. This will build all projects and dependent projects whenever something under version control changes, run all tests, provide a build number and package it all ready for use. This way you can be sure that - whatever is in your deliverable - can be reproduced, because the buildserver is not able to make local (uncommitted) changes to the code. Also a buildserver will signal failure (either broken API or broken tests) at the moment of the last commit (well - a few minutes later) and place the burden of repairing the damage on the one causing the damage.