Библиотека модулей Raku: Зеркалируем репозитории | Raku Module Library: Mirroring repositories
Популярность языка программирования зависит не только (и не столько) от его дизайна и реализации, но и от огромного числа сторонних вещей. Таких, как качество и количество документации, удобная среда разработки, отзывчивое сообщество единомышленников, библиотека модулей на все случаи жизни и прочее. Сегодня как раз про библиотеку модулей языка Raku
. А точнее, про систему их хранения и распространения.
Что есть в природе
Если посмотреть в миры Java, Python, JavaScript, Perl — всё примерно одинаково. Есть де-факто центральный публичный репозиторий (Nexus, PyPI, npm-registry, CPAN), есть сколько-то альтернатив и зеркал, есть возможность поднять свой.
Что есть в мире Raku
Основной менеджер пакетов для Raku
называется zef
. Сейчас он работает следующим образом: берёт с какого-то сервера индекс, анализирует его и скачивает необходимые перечисленные в нём модули. Так можно делать с несколькими серверами.
Изначально, в качестве сервера для распространения модулей служил GitHub
. Это дешёвое и сердитое решение. Индексы считают на сторонней машине про cron и выкладывают в отдельный git репозиторий. Сейчас в этом ‘сервере’ хранятся индексы о более чем восьмистах версий различных модулей. Эта схема получила название p6с
. Минусы её очевидны — завязывание на одну проприетарную платформу, которая изначально спроектирована для других целей.
Второй попыткой стала проба использовать CPAN
для нужд Raku
. Если без подробностей, то модули в Perl
и Raku
немного отличаются по структуре, и CPAN
пришлось грубо допиливать. В конечном итоге он стал просто хранилищем, неким FTP сервером. Индексы так же считают на сторонней машине про cron и выкладывают в отдельный git репозиторий. На данный момент это самая большая библиотека модулей — их там больше 2700 версий.
Третьей попыткой, почти год назад, стал проект fez
. Если CPAN
предоставлял только возможности FTP сервера, то fez
решил идти дальше и добавил несколько полезных вещей. Таких, как улучшенная система авторизации, правильная работа с номерами версий модулей, мгновенная индексация на стороне репозитория. Плюс, так как это специальный проект, созданный именно для нужд Raku
, то он имеет отличные возможности для качественного развития.
Первое время я с настороженностью относился к fez
, но в последствии изменил своё мнение. Проект достаточно стабильный и отлично выполняет свои функции.
Что хочется ещё
Для успокоения души мне не хватает зеркал сервера fez
. Для чего нужно зеркало вообще?
Дело в том, что мы живём во время, когда информационные сети стали неимоверно сложными, а желания их контролировать слишком высокими. Где-то специально, где-то случайно закрывается доступ к очень большим, важным и привычным ресурсам. Нет уверенности в том, что завтра утром ты сможешь получить доступ к своим данным, хранящимся где-то там. Благо это или нет, но это стало нашей сегодняшней реальностью. От сюда есть вполне естественное желание диверсифицировать риски. Один из способов — иметь зеркало библиотеки модулей.
Хочешь сделать что-то хорошо - сделай сам
Хорошо сделать не обещаю, но так как альтернатив никаких, то сойдёт любое решение. Ниже я покажу как можно локально развернуть зеркало для модулей, хранящихся в CPAN
и fez
(p6c
используется малоактивно, и зеркалировать git хостинг это отдельная задача). Нам понадобится curl
, grep
, awk
, sed
, sh
и docker
.
Исходя из логики работы zef
, принципиально нужно:
- Скачать индексный файл;
- Скачать все перечисленные в нём архивы с модулями;
- Повторить 1 и 2 для каждого репозитория;
- Поднять и настроить nginx, чтобы он умел отдавать скачанные индексы и архивы;
- Сказать
zef
по какому адресу лежит зеркало.
Скачиваем индексный файл
Все настройки zef
лежат в файле config.json
. В документации к zef
сказано, чтобы узнать с каким дефолтным конфигом запускается zef
, нужно выполнить zef --help
:
> zef --help [..] CONFIGURATION ~/.rakubrew/versions/moar-2021.10/install/share/perl6/site/ resources/250C9FFF9756350CAA0F60C1873CDD80F2EB7A77.json [..] > cat ~/.rakubrew/versions/moar-2021.10/install/share/perl6/site/ resources/250C9FFF9756350CAA0F60C1873CDD80F2EB7A77.json [..] { "short-name": "fez", "enabled": 1, "module": "Zef::Repository::Ecosystems", "options": { "name": "fez", "auto-update": 1, "uses-path": true, "mirrors": [ "http://360.zef.pm/" ] } },
В разделе mirrors
конфигурации для fez
видим URI — то что нам нужно.
> mkdir -p ~/local-zef/local-fez && cd ~/local-zef/local-fez local-fez> curl https://360.zef.pm -o index.json
Скачиваем архивы модулей
В индексе fez
относительный путь архиву модуля лежит в поле path
. Например:
{ [..] "name": "fez", "path": "F/EZ/FEZ/259a4732c97520938ce7310b3a1330db75bf91d0.tar.gz", "perl": "6.c", [..] "source-url": "https://github.com/tony-o/raku-fez.git", "version": "17" }
Сейчас нужно вытащить все значения path
и составить один большой curl
запрос. Немного sed-awk
-магии:
local-fez> grep -o '"path":"[^"]*"' index.json | \ awk -F\" '{print $4}' | \ sed 's|\(.*\)| -o \1 https://360.zef.pm/\1|g' | \ awk -v d="" '{s=(NR==1?s:s d)$0}END{print s}' | \ sed 's/\(.*\)/curl -Z --create-dirs \1/' | \ sh DL% UL% Dled Uled Xfers Live Qd Total Current Left Speed 100 -- 36.6M 0 623 0 0 0:00:06 0:00:11 --:--:-- 5440k local-fez> ls A D G J M P T W B E H K N R U Y C F I L O S V index.json
Повторяем для CPAN
Таким же образом можно скачать индекс и весь архив для CPAN
:
> mdkir -p ~/local-zef/local-cpan && cd ~/local-zef/local-cpan local-cpan> curl https://raw.githubusercontent.com/ugexe/Perl6-ecosystems/master/cpan1.json -o index.json local-cpan> grep -o '"source-url": "[^"]*"' index.json | \ awk -F\" '{print $4}' | \ sed 's|http://www.cpan.org/authors/id/\(.*\)|\1|g' | \ sed 's|\(.*\)| -o \1 http://www.cpan.org/authors/id/\1|g' | \ awk -v d="" '{s=(NR==1?s:s d)$0}END{print s}' | \ sed 's|\(.*\)|curl -Z --create-dirs \1|' | \ sh DL% UL% Dled Uled Xfers Live Qd Total Current Left Speed 100 -- 337M 0 2767 0 0 0:00:54 0:00:41 --:--:-- 6308k local-cpan> rm -rf ./git: local-cpan> sed 's|"source-url": "http://www.cpan.org/authors/id|"source-url": "http://localhost/local-cpan|g' index.json > index-fix-uri.json local-cpan> ls A G N V B H P W C J R Y D K S index-fix-uri.json E L T index.json F M U
Различия в ситуации со CPAN
следующие:
- Путь к архиву абсолютный и лежит в поле
source-url
. Соответственно, нам нужно подправить индексный файл, чтобы путь вёл не наcpan.org
, а на нашlocalhost
; - В индексе упоминаются несколько (около шести) устаревших модуля с неверными
source-url
. Они порождают папкуgit:
, которая нам совершенно не нужна.
Поднимаем и настраиваем nginx
Для начала нужно написать конфигурационный файл для nginx
:
cd ~/local-zef local-zef> vim nginx.conf [..] local-zef> cat nginx.conf events { worker_connections 1024; } http { server { listen 80; root /usr/share/nginx/html; location /local-fez { index /local-fez/index.json; } location /local-cpan { index /local-cpan/index-fix-uri.json; } } }
Затем поднимаем nginx
в docker
, монтируем папку с архивами и индексами, и подкладываем нашу конфигурацию:
cd ~/local-zef local-zef> docker run -it -p 80:80 \ -v /$PWD://usr/share/nginx/html:ro \ -v /$PWD/nginx.conf://etc/nginx/nginx.conf:ro \ --name=local-zef \ nginx:alpine
После этих манипуляций у нас имеется поднятый web-сервер, который отдаст индексы для fez
и cpan
по адресам http://localhost/local-zef
и http://localhost/local-cpan
соответственно. Кроме того, с сервера можно скачать архивы по ссылкам из индекса.
Настраиваем zef
Я предпочитаю завести отдельный конфиг для zef
. Относительно оригинального в нём нужно поменять пути до хранилища и временной папки, а так же имена и uri в разделах про fez
и cpan
репозитории:
cd ~/local-zef local-zef> cp ~/.rakubrew/versions/moar-2021.10/install/share/perl6/site/resources/250C9FFF9756350CAA0F60C1873CDD80F2EB7A77.json zef.json local-zef> vim zef.json [..] local-zef> cat zef.json [..] "StoreDir" : "$*HOME/.zef/store_local", "TempDir" : "$*HOME/.zef/tmp_local", [..] { "short-name": "local-fez", "enabled": 1, "module": "Zef::Repository::Ecosystems", "options": { "name": "local-fez", "auto-update": 1, "uses-path": true, "mirrors": [ "http://127.0.0.1/local-fez/" ] } } [..] { "short-name" : "local-cpan", "enabled" : 1, "module" : "Zef::Repository::Ecosystems", "options" : { "name" : "local-cpan", "auto-update" : 1, "mirrors" : [ "http://127.0.0.1/local-cpan/" ] } }
Теперь мы можем установить модуль из локального зеркала таким образом:
zef --config=~/local-zef/zef.json install LogP6
Централизованный архив всех модулей Raku
Существует проект REA (The Raku Programming Language Ecosystem Archive), в который регулярно собираются все когда-либо опубликованные модули. Кроме того, есть специальный модуль Raku, который позволяет иметь похожий архив самостоятельно. Пока что zef
не умеет работать с этим архивом как источником данных, но есть смысл написать отдельный плагин.
Заключение
Я очень надеюсь, что проект fez
будет продолжать активно развиваться. По словам автора, сейчас fez это набор из AWS-ламбда, S3 и Сloudfront, но никак не код. Думаю, есть смысл написать реализацию fez
в коде. Тогда можно будет легко разворачивать реальные альтернативные сервера, например для корпоративных целей. Пожелаем удачи!
English version