PowerShell Package Management - Repository vs Provider vs Source
Asked Answered
T

1

12

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:

  • A PSRepository can provide zero or more PowerShell modules. A PSRepository must have one, and only one, PackageProvider. An example of a repository is PSGallery.
  • A PackageProvider can serve zero or more PSRepository objects. A PackageProvider must have one or more PackageSource objects. A PackageProvider is sometimes referred to as a "Package Manager". Some examples of package providers include NuGet, Chocolatey, or PowerShellGet.
  • A PackageSource must serve one and only one PackageProvider. Some examples of package sources include nuget.org, MyCustomVSTSFeed, or PSGallery.

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?
Tigon answered 28/3, 2018 at 21:37 Comment(5)
Maybe a repository is a combination of provider and source? And sources only have a provider property because sources only work with certain providers?Tigon
And why does Find-Package not work with PackageSources but PSRepository locations?Ragucci
As an aside it looks like they will be changing the way some of this works with a major version update of PowerShellGet in 7.2. Here's an article by the projects principal engineering managerMizzenmast
Good find! PowerShellGet 3.0 looks promising.Tigon
@Mizzenmast I have added a note to the answer now that Preview 11 of PowerShellGet 3.0 is out. Thanks for bringing this up!Daphinedaphna
D
5

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:

  • A PackageProvider is the equivalent of a package manager; think APT/dpkg, pacman, Homebrew, Chocolatey/NuGet, or winget. These utilise the framework to manage software on Windows using the concept of packages.
  • A PackageSource serves a single PackageProvider and is where the provider gets its packages from.

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:

  • To limit changes made to within the PowerShell universe; none of the PowerShellGet Cmdlets modify operating system components or software.
  • To differentiate between module packages and script packages, and to install them in the correct locations.
  • To permit manual updating of the above with the Update-* Cmdlets.
  • To permit publishing of packages back to the PSRepository source.

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:

Daphinedaphna answered 1/3, 2021 at 14:30 Comment(1)
Wonderful! Thank you very much! I was viewing the inheritance structure upside-down. I've written some pseudo-code to help visualize what you've said.Tigon

© 2022 - 2024 — McMap. All rights reserved.