В этой статье я хочу помочь разобраться в структуре пакетных менеджеров под Windows. Статья нацелена больше на тех, кто, как и я, пришли из мира Linux, где принято заходить в понимание процессов ниже уровня абстракций.
Уверен, что абстракции вы уже прочитали и без меня:
Но это мало того грубо, так еще и неправда.
Итак, какие типы пакетов мы знаем из мира 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.
Далее, если мы хотим поставить какой-то питоний пакет, то мы пишем:
OneGet преобразует это в:
А теперь мы хотим поставить пакет NuGet и запускаем:
В этот раз команда вызвала:
Я соврал. На самом деле Install-Package не вызывает эти команды в бэкграунде — пакетные менеджеры более не используются. Выпали из пищевой цепочки. Вместо них установлены специализированные пакетные провайдеры (считайте плагины PowerShell) для управления инородными пакетами. И эти провайдеры занимаются задачей установки вместо привычных нам пакетных менеджеров. А OneGet над ними начальник. За зависимостями следят сами провайдеры.
И тут мы знакомимся с третьим NuGet — NuGet-пакетный провайдер. Я с самого начала статьи мечтал взорвать ваш мозг: NuGet — это пакетный провайдер, который пришел на смену пакетному менеджеру NuGet(nuget.exe), чтобы управлять пакетами NuGet(.nupkg).
Здесь очень важный момент. Старые пакетные менеджеры имели каждый свой список репозиториев (Source в терминологии Windows):
Или:
OneGet опирается не на них, а на заменивших их провайдеров. А список репозиториев один для всех, но с указанием, кому какой репозиторий принадлежит — по аналогии с внешними ключами БД.
Смотрим сначала список пакетных провайдеров:
А теперь смотрим кому какой репозиторий принадлежит:
Теперь я сделаю паузу и отвлекусь на один из странных пакетных провайдеров — PowerShellGet. Этот провайдер призван устанавливать модули самого PowerShell. Появился он в PowerShell 2 — еще до прихода PackageManager(aka OneGet). Но они друг другу не ровня. PowerShellGet — это один из рядовых пакетных провайдеров, умеющих делать только свой тип пакетов, а не управленец пакетными провайдерами, как OneGet.
Его тип пакетов — .nupkg, содержимое которых — модули PowerShell. Поэтому не удивляйтесь, что его репозиторий PSGallery имеет формат NuGet:
И сейчас вы могли заметить следующую тонкость: список репозиториев в PackageManager выполняется командой Get-PackageSource, а не Get-PSRepository.
Дело в том, что работа этого модуля, как я сказал выше, устанавливать модули PowerShell. В комплект установки входит и регистрация новых командлетов, что он и сделал. Этот командлет дает дополнительные поля при регистрации репозитория (например PublishLocation). Этого не видно, если использовать стандартный командлет:
Последнее: Chocolatey.
Вот все говорят, что Chocolatey — надстройка над NuGet. Оно как бы так, но не совсем. Chocolatey использует те же spec'и, но не полностью. Вместо полноценного пакета он зачастую использует скачивание .msi или чего угодно другого и последующую silent-установку. То есть в то время, как пакетный провайдер NuGet или пакетный менеджер nuget.exe устанавливает только нативные NuGet-пакеты, Chocolatey устанавливает их же + все то, что что другие устанавливать не умеют. Поэтому база пакетов Chocolatey такая внушительная по сравнению с базой NuGet. И поэтому в пакетах Chocolatey столько скриптов много.
Возможно вы заметили, что есть два провайдера Chocolatey и ChocolateyGet. Первый — самодельная времянка. Второй — официальный провайдер, который недавно только вышел. Ну вы видите по версиям.
Уверен, что абстракции вы уже прочитали и без меня:
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. Первый — самодельная времянка. Второй — официальный провайдер, который недавно только вышел. Ну вы видите по версиям.
