Терминология OneGet, NuGet, Chocolatey, PowerShellGet — разложим по полочкам

Habrahabr 1

В этой статье я хочу помочь разобраться в структуре пакетных менеджеров под Windows. Статья нацелена больше на тех, кто, как и я, пришли из мира Linux, где принято заходить в понимание процессов ниже уровня абстракций. Уверен, что абстракции вы уже прочитали и без меня:

chocolatey для установки приложений, nuget — для установки зависимостей разработчиком.
Но это мало того грубо, так еще и неправда.

Итак, какие типы пакетов мы знаем из мира Linux? Внимание: не пакетные менеджеры, а именно сами пакеты. Самые распространенные условно делятся на две группы: ОС-зависимые (deb, rpm) или языко-зависимые (как правило, tar-болы). В принципе можно сказать, что первая группа — это приложения (утилиты), а вторые — зависимости (библиотеки). Но иногда это не так: среди пакетов ОС есть библиотеки, а среди языковых пакетов есть пакеты, устанавливающие еще и утилиты (например stdeb в pip или elastalert в npm) — если их устанавливать глобально, то получится как пакет ОС.

Возвращаемся к Windows. Изначально здесь придумали тоже формат пакета. Сделан он был на замену старому формату msi/msu потому, что старый формат имел достаточно высокий входной порог для понимания, как его автоматизировать [вполне вероятно, что я сейчас брежу]. В общем и целом новый формат очень похож на rpm. У него даже есть spec-файл. Имя ему — NuGet, но расширение .nupkg. Внутри этого пакета есть директории, файлы и инсталляционные скрипты — все нам, линуксойдам, привычно и знакомо.

Теперь давайте вспомним, какие пакетные менеджеры мы знаем. Для ОС это apt, yum,… Для языковых: pip, gem, npm, cpan, cpm,… Что для Windows? Тут мы знакомимся с новым NuGet. Есть NuGet-пакет, а есть одноименный nuget.exe — утилита, которая умеет эти пакеты скачивать и разархивировать.

Какой расклад мы получаем: Debian: apt(deb) + pip + npm + gem +… RHEL: yum(rpm) + pip + npm + gem +… Windows: nuget(nupkg) + pip + npm + gem +… обратите внимание, для msi пакетного менеджера так и не создали (это не совсем так, но пока для простоты).

И вот здесь начинается отличие от Linux. В мире Windows появился какой-то талантливый парень, который решил, что он хочет устанавливать все одной командой. И начал писать open-source'ный проект OneGet (его проприетарное название: PackageManager, который является одним из модулей PowerShell версии >=5.0). OneGet — это абстрактный интерфейс, который умеет разговаривать с каждым пакетным менеджером на его языке. OneGet публикует для нас набор унифицированных команд. Например, команду Install-Package, которая является wrapper'ом каждый раз для разных команд. Что получается: мы подключаем к OneGet несколько пакетных менеджеров. Например: NuGet, PIP, NPM. Далее, если мы хотим поставить какой-то питоний пакет, то мы пишем:

Install-Package <имя pip-пакета>
OneGet преобразует это в:
pip install <имя pip-пакета>
А теперь мы хотим поставить пакет NuGet и запускаем:
Install-Package <имя nupkg-пакета>
В этот раз команда вызвала:
nuget install <имя nupkg-пакета>

Я соврал. На самом деле Install-Package не вызывает эти команды в бэкграунде — пакетные менеджеры более не используются, выпали из пищевой цепочки. Вместо них установлены специализированные пакетные провайдеры (считайте плагины PowerShell) для управления инородными пакетами. И эти провайдеры занимаются задачей установки вместо привычных нам пакетных менеджеров. А OneGet над ними начальник. За зависимостями следят сами провайдеры.

И тут мы знакомимся с третьим NuGet — NuGet-пакетный провайдер. Я с самого начала статьи мечтал взорвать ваш мозг: NuGet — это пакетный провайдер, который пришел на смену пакетному менеджеру NuGet(nuget.exe), чтобы управлять пакетами NuGet(.nupkg).

Здесь очень важный момент. Старые пакетные менеджеры имели каждый свой список репозиториев (Source в терминологии Windows):

PS C:\> nuget source list
Registered Sources:

  1.  nuget.org [Enabled]
      https://api.nuget.org/v3/index.json
  2.  ABC [Enabled]
      http://<тут_я_спрятал_IP>/artifactory/api/nuget/<имя_репо>
Или:
PS C:\> gem sources
*** CURRENT SOURCES ***

https://rubygems.org
OneGet опирается не на них, а на заменивших их провайдеров. А список репозиториев один для всех, но с указанием, кому какой репозиторий принадлежит — по аналогии с внешними ключами БД.

Смотрим сначала список пакетных менеджеров:

PS C:\> Get-PackageProvider

Name                     Version          DynamicOptions
----                     -------          --------------
Chocolatey               2.8.5.130        SkipDependencies, ContinueOnFailure, ExcludeVers
ChocolateyGet            1.0.0.1          AdditionalArguments
msi                      3.0.0.0          AdditionalArguments
msu                      3.0.0.0
NuGet                    2.8.5.208        Destination, ExcludeVersion, Scope, SkipDependen
PowerShellGet            1.0.0.1          PackageManagementProvider, Type, Scope, AllowClo
Programs                 3.0.0.0          IncludeWindowsInstaller, IncludeSystemComponent

А теперь смотрим кому какой репозиторий принадлежит:
PS C:\> Get-PackageSource

Name                             ProviderName     IsTrusted  Location
----                             ------------     ---------  --------
nuget.org                        NuGet            False      https://api.nuget.org/v3/index.json
PSGallery                        PowerShellGet    False      https://www.powershellgallery....
chocolatey                       Chocolatey       False      http://chocolatey.org/api/v2/

Теперь я сделаю паузу и отвлекусь на один из странных пакетных провайдеров — PowerShellGet. Этот провайдер призван устанавливать модули самого PowerShell. Появился он в PowerShell 2 — еще до прихода PackageManager(aka OneGet). Но они друг другу не ровня. PowerShellGet — это один из рядовых пакетных провайдеров, умеющих делать только свой тип пакетов, а не управленец пакетными провайдерами, как OneGet. Его тип пакетов — .nupkg, содержимое которых — модули PowerShell. Поэтому не удивляйтесь, что его репозиторий PSGallery имеет формат NuGet:

PS C:\> Get-PSRepository -Name "PSGallery" | Format-List * -Force

Name                      : PSGallery
SourceLocation            : https://www.powershellgallery.com/api/v2/
Trusted                   : False
Registered                : True
InstallationPolicy        : Untrusted
PackageManagementProvider : NuGet
PublishLocation           : https://www.powershellgallery.com/api/v2/package/
ScriptSourceLocation      : https://www.powershellgallery.com/api/v2/items/psscript/
ScriptPublishLocation     : https://www.powershellgallery.com/api/v2/package/
ProviderOptions           : {}
И сейчас вы могли заметить следующую тонкость: список репозиториев в PackageManager выполняется командой Get-PackageSource, а не Get-PSRepository. Дело в том, что работа этого модуля, как я сказал выше, устанавливать модули PowerShell. В комплект установки входит и регистрация новых командлетов, что он и сделал. Этот командлет дает дополнительные поля при регистрации репозитория (например PublishLocation). Этого не видно, если использовать стандартный командлет:
PS C:\> Get-PackageSource -Name "PSGallery" | Format-List * -Force

Name         : PSGallery
Location     : https://www.powershellgallery.com/api/v2/
Source       : PSGallery
ProviderName : PowerShellGet
Provider     : Microsoft.PackageManagement.Implementation.PackageProvider
IsTrusted    : False
IsRegistered : True
IsValidated  : False
Details      : {[ScriptPublishLocation, https://www.powershellgallery.com/api/v2/package/], [InstallationPolicy, Untrusted], [PackageManagementProvider, NuGet],
               [ScriptSourceLocation, https://www.powershellgallery.com/api/v2/items/psscript/]...}

Последнее: Chocolatey. Вот все говорят, что Chocolatey — надстройка над NuGet. Оно как бы так, но не совсем. Chocolatey использует те же spec'и, но не полностью. Вместо полноценного пакета он зачастую использует скачивание .msi или чего угодно другого и последующую silent-установку. То есть в то время, как пакетный провайдер NuGet или пакетный менеджер nuget.exe устанавливает только нативные NuGet-пакеты, Chocolatey устанавливает их же + все то, что что другие устанавливать не умеют. Поэтому база пакетов Chocolatey такая внушительная по сравнению с базой NuGet. И поэтому в пакетах Chocolatey столько скриптов много.

Возможно вы заметили, что есть два провайдера Chocolatey и ChocolateyGet. Первый — самодельная времянка. Второй — официальный провайдер, который недавно только вышел. Ну вы видите по версиям.