If you're looking for a pre-built solution that requires you to only do a little bit of scripting, I'm not aware of such a tool. However, I don't believe it will be particularly difficult for you to do what you want to achieve. The long answer below is because I'm giving lots of details, rather than it being more difficult that I'm making it out to be.
Step 1: Collect packages
Restore all the projects in your repo on an internet-connected computer. If you have any projects using packages.config
, their packages are already collected for you in the solution packages folder. They should also be in the global packages folder, but if you clear your global packages folder and restore when the packages already exist in the solution packages folder, they will not be downloaded/extracted into the global packages folder. Projects that use PackageReference
will only have their packages extracted to the global packages folder.
So, if you restore all your solutions on an internal-connected computer, then the global packages folder will probably contain all the packages you need, but technically you may need to also get packages from the solution packages folder.
One option is to simply copy all packages from your global packages folder, but will probably contain packages that are not required by your solution. If you want to only copy packages used by your solution, then start by copying the packages in the solution packages folder, because they're definitely referenced by something, otherwise they wouldn't exist. Then, write a program that will read every PackageReference
project's obj\project.assets.json
file, because that contains the full dependency graph. Have your project get the list of NuGet packages from all these files, then you have your list of packages you need to copy from the global packages folder.
Another option is to create a nuget.config
file and specify a custom globalPackagesFolder
before doing the restore. If you do this, I recommend you also add your profile's global packages folder as a package source, so that doing the restore is much quicker. As long as your custom global packages folder is empty before you start, then it will contain only the packages used by your solution(s).
Step 2: Choose how you want your offline-computer to acquire the packages
Technically, you can simply copy the solution packages folder from the source computer to the destination computer and copy the global packages folders from the source computer to the destination computer. However, there's always the chance that a tool changes behaviour across different versions of the tool, so I prefer to let tools manage their own data. One example is that the global packages folder contains a .nupkg.sha512
file, and in recent versions of NuGet, also a .nupkg.metadata
file, which do not exist in the solution packages folder. Due to the way NuGet works, it will not work if you copy a solution packages folder into a global packages folder. This may change in the future, but at the time I'm writing this, it won't work.
Therefore, I recommend copying only the .nupkg
files, and on your offline computer, create a nuget.config
file that adds the folder where you copy all the .nupkg
's as a package source. This nuget.config
file doesn't need to be in your repo. You can take advantage of the fact that NuGet accumulates configuration hierarchically and create this nuget.config
on the root of your offline machine (or if you clone all repos to a single location, you can put it there), since it's only required by the offline machine. As long as none of your projects has a nuget.config
that clears the packageSources
section, then all projects in a sub-folder of where the nuget.config
is will automatically use it as a package source.
TL;DR
The easiest way (say you want to script it) is:
- On your internet connected computer, create a
nuget.config
file (dotnet new nugetconfig
, although it creates a horrible nuget.config
that clears package sources, and I can't find a good way to remove the <clear/>
XML element) that
- Sets the
globalPackagesFolder
to a custom path (nuget.exe config -set globalPackagesFolder=usedPackages -configfile nuget.config
), that is currently empty
- Add a
packageSource
to your user profile's global packages folder (nuget.exe sources add -name globalPackagesFolder -Source %USERPROFILE%\.nuget\packages -configfile .\nuget.config
), to improve performance
- Restore all projects (
nuget.exe restore my.sln
)
- Recursively search your custom global packages folder, and copy only the
.nupkg
files (Get-ChildItem .\globalPackagesFolder\ -Recurse -Filter *.nupkg | Copy-Item -Destination .\nupkgs\
if using powershell) to the device that you'll use to transfer to the offline computer. You can (should?) copy the .nupkg
s into a flat folder.
- Copy the
.nupkg
s from the device into a folder dedicated to be your offline feed.
- If you created a script to do the above, then your script can clean up after itself at this point, for example deleting the
nuget.config
file and custom global packages folder.
- Create a
nuget.config
file on your offline computer that adds your offline feed folder as a package source (dotnet new nugetconfig
, delete the <clear/> and change the sample source in the file to the directory you copied the
nupkg`s).