windowspowershellnugetpackage-managementpowershellget

PowerShell Package Management - Repository vs Provider vs Source


I am trying to understand package management in PowerShell, and I am getting an incomplete picture. When I look at the objects PSRepository, PackageProvider, and PackageSource, they all seem to have the following relationships:

I've looked at the following links, but it still doesn't provide a clear picture of how they are related.

  1. Why does a PSRepository have a property called PackageManagementProvider of type string instead of type PackageProvider?
  2. Why does a PSRepository have its own SourceLocation property, if it already has a source reference through its provider?
  3. Why is PSGallery both a PackageSource and a PSRepository?
  4. Why is PowerShellGet both the name of a module that provides access to the gallery, and the name of a PackageProvider?

Solution

  • Update August 2021

    PowerShellGet 3.0 will be fundamentally different from previous versions of the module. It will no longer be dependent on PackageManagment, uses the NuGet APIs and libraries directly (as opposed to nuget.exe) and has new syntax. You can learn more about the ongoing development of PowerShellGet 3.0 from the DevBlogs Article and on GitHub.

    The question and answer on this page are therefore relevant only to PowerShellGet 2.0.


    The best way to think of this is as two spheres; the PackageManagement one and the PowerShellGet one.

    PackageManagement

    PackageManagement (formerly OneGet) is the outer sphere, and is a framework for package delivery in Windows. It is administered through PowerShell, but applies to the whole operating system or user profile. It provides two main classes:

    PowerShellGet

    PowerShellGet is the inner sphere, and is a PowerShell module that uses the PackageManagement framework to deliver packages specifically for PowerShell. It is registered as a PackageProvider, and uses the associated PackageSources to deliver modules and scripts from the PowerShell Gallery, or additional sources. It introduces a new class, called a PSRepository. You can think of this as a virtual wrapper for a PackageSource that only exists in the PowerShellGet sphere.

    When you register a new PSRepository with Register-PSRepository, you'll notice that if you run Get-PackageSource, a new source has been automatically added with the same name and URI, for the PowerShellGet provider. The PSRepository has a few specific functions:

    For (un)installing/updating modules and scripts, PowerShellGet uses the PackageManagement Cmdlets. For publishing scripts and modules, it uses the .NET CLI command dotnet nuget push after wrapping them in a nupkg archive.

    Summary

    In light of the above, we can now answer the four points in the question:

    1. The PSRepository is a custom object and wrapper for a PackageSource; it stores a string property called PackageManagementProvider which can be used with Get-PackageProvider to access the PackageProvider object.
    2. PSRepository objects have custom properties that allow for different URIs for modules, scripts, retrieving and publishing. These are SourceLocation and PublishLocation for modules, and ScriptSourceLocation and ScriptPublishLocation for scripts.
    3. PowerShellGet uses the PackageManagement framework in the background, so every PSRepository has a matching PackageSource used in backend operations.
    4. The PowerShellGet module registers itself as a PackageProvider in its manifest, in order to interact with the framework and provide the customised functionality that it does. It also interacts with the NuGet PackageProvider.

    In short, when you're dealing with software packages outside of PowerShell, you work directly with the PackageManagement framework. When you're dealing with modules and scripts for PowerShell, you work with PowerShellGet, which gives you abstracted access to the framework and NuGet.

    Sources: