4

Is there a windows command to download a Nuget packages with its dependencies to a folder so i can transfer them to an offline computer? What i mean is a command that i can give the Nuget package's name and it will download the package and all it's dependencies to a folder as nupkg files.

I know that there are some mirroring tools but actually i'm looking an answer for my specific question using command line if possible.

yekanchi
  • 813
  • 1
  • 12
  • 30

2 Answers2

7

You can use -OutputDirectory parameter of nuget.exe to specify a folder.

example:

nuget install NUnit -Version 3.11.0 -OutputDirectory c:\packages

You need to have nuget.exe in the path enviroment or current folder which is cmd used on. This will output to unpacked dependencies and nukpg files to the selected folder. After this you can just copy the nukpg files to desired location by hand or you can use simple commandline copy script to copy only nukpg files.

There is also a tool named nufetch. it will only download nukpg files, but this tool downloads unnecessary dependency files to. (I recommend using nuget)

miskender
  • 7,460
  • 1
  • 19
  • 23
5

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:

  1. 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
  2. Restore all projects (nuget.exe restore my.sln)
  3. 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 .nupkgs into a flat folder.
  4. Copy the .nupkgs from the device into a folder dedicated to be your offline feed.
  5. 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.
  6. 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 thenupkg`s).
zivkan
  • 12,793
  • 2
  • 34
  • 51
  • I edited my answer, as I found a way to do most of what's needed using command line tools. – zivkan Dec 01 '18 at 18:22
  • "_Restore all projects (nuget.exe restore my.sln)_" That just tells me that "All projects are up-to-date for restore." Is there a way to do this into a new directory? Where is the "globalPackagesFolder"? Was there something I was supposed to do in 1. to replace ``? – ruffin Feb 28 '22 at 18:30
  • If you followed my instructions carefully, the packages are in a folder named `usedPackages`. In the "TL;DR" steps, step 1, where setting the `globalPackagesFolder` config in nuget.config, is where that happens. – zivkan Mar 01 '22 at 14:31