Библиотека модулей 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