В этой статье я хочу помочь разобраться в структуре пакетных менеджеров под 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-пакетный провайдер. Я с самого начала статьи мечтал взорвать ваш
Здесь очень важный момент. Старые пакетные менеджеры имели каждый свой список репозиториев (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. Первый — самодельная времянка. Второй — официальный провайдер, который недавно только вышел. Ну вы видите по версиям.
Автор: Michael