В этой статье я хочу помочь разобраться в структуре пакетных менеджеров под 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. Первый — самодельная времянка. Второй — официальный провайдер, который недавно только вышел. Ну вы видите по версиям.
Поделиться с друзьями
Комментарии (20)
Steed
18.06.2017 22:08А я-то думал: куда делся удобный command-line'овый nuget.exe. Жаль, что унификация через powershell слелана так, что без мануала нужную команду не угадаешь.
Спасибо за статью, отличный формат для вводного курса «как это в целом вообще устроено». То самое, чего больше всего не хватает в мануалах, особенно MSDN.
keydon2
Намного хуже в винде отсутствие не пакетного менеджера, а приницпа «наследил — убери». До сих пор не понимаю как можно было додуматься сохранять настройки в реестр, вместо того, чтобы писать в конфигурационные файлы в папках системы\приложения\драйверов. И в целом бОльшая часть приложений написано таким образом, что не удаляют за собой полностью, в том числе и от мелкософта(ваша любимая VS например очень мусорит). Заодно это источник многих ошибок, которые очень тяжко потом ловить и фиксить. Это кстати одна из причин почему винду проще переставить, чем очистить.
Singaporian
Не уверен, что реестр — плохо. Представьте, что вы на Debian. У вас установлен пакет, у которого в конфиге что-то изменено. И вот вышел апдейт, вы хотите обновить. И apt предоставит вам экран, где спросит оставить ли версию мейнтейнеров, оставить ли адаптированную или сравнить версии.
А теперь представьте, что вы обновляете 100500 машин и участие в подобных диалогах вам недоступно.
А вот если вы что-то меняете в реестре, то изменение всегда атомарное. И дельта «конфигов» между версиями ляжет нормально.
Но вот то, что реестр сложнее чистится — это согласен конечно.
Carburn
В реестре пишется в отдельную папку приложения, в чем проблема? Кстати сейчас реестр использовать не рекомендуют.