1
0
Fork 0

2025-02-28

This commit is contained in:
Gennadiy 2025-02-28 19:13:08 +03:00
parent c008881b5e
commit c4abf84468
27 changed files with 62 additions and 719 deletions

1
.gitignore vendored
View file

@ -1,4 +1,3 @@
.idea
*.iml
.token_*
.repo_*

View file

@ -4,31 +4,9 @@
<a href='.'>.</a>
├─ <a href='archive'>archive</a>
│ ├─ <a href='archive/README.md'>README.md</a>
│ ├─ <a href='archive/gif-animatin-with-bash-script.md'>gif-animatin-with-bash-script.md</a>
│ ├─ <a href='archive/parallelizing-bash-scripts.md'>parallelizing-bash-scripts.md</a>
│ └─ <a href='archive/round-robin.md'>round-robin.md</a>
├─ <a href='bash_scripts'>bash_scripts</a>
│ ├─ <a href='bash_scripts/README.en.md'>README.en.md</a>
│ ├─ <a href='bash_scripts/README.md'>README.md</a>
│ ├─ <a href='bash_scripts/archive_backup.sh'>archive_backup.sh</a>
│ ├─ <a href='bash_scripts/archive_cleanup.sh'>archive_cleanup.sh</a>
│ ├─ <a href='bash_scripts/archive_packaging.sh'>archive_packaging.sh</a>
│ ├─ <a href='bash_scripts/info_param.sh'>info_param.sh</a>
│ ├─ <a href='bash_scripts/info_references.sh'>info_references.sh</a>
│ ├─ <a href='bash_scripts/info_tree_license.sh'>info_tree_license.sh</a>
│ ├─ <a href='bash_scripts/repo_compose.sh'>repo_compose.sh</a>
│ ├─ <a href='bash_scripts/repo_forgejo.tmpl.sh'>repo_forgejo.tmpl.sh</a>
│ ├─ <a href='bash_scripts/repo_forgejo2.tmpl.sh'>repo_forgejo2.tmpl.sh</a>
│ ├─ <a href='bash_scripts/repo_gitlab.tmpl.sh'>repo_gitlab.tmpl.sh</a>
│ ├─ <a href='bash_scripts/repo_local.tmpl.sh'>repo_local.tmpl.sh</a>
│ ├─ <a href='bash_scripts/repo_orchestrate.sh'>repo_orchestrate.sh</a>
│ ├─ <a href='bash_scripts/repo_pages2.sh'>repo_pages2.sh</a>
│ └─ <a href='bash_scripts/repo_testing.smpl.sh'>repo_testing.smpl.sh</a>
├─ <a href='pictures'>pictures</a>
│ ├─ <a href='pictures/README.md'>README.md</a>
│ ├─ <a href='pictures/color-tomato-theme.jpg'>color-tomato-theme.jpg</a>
│ ├─ <a href='pictures/older-tomato-theme.jpg'>older-tomato-theme.jpg</a>
│ ├─ <a href='pictures/pomodoro.jpg'>pomodoro.jpg</a>
│ └─ <a href='pictures/website.jpg'>website.jpg</a>
├─ <a href='.gitattributes'>.gitattributes</a>
├─ <a href='.gitignore'>.gitignore</a>
├─ <a href='CONTRIBUTING.md'>CONTRIBUTING.md</a>

View file

@ -6,9 +6,9 @@ JavaScript and open license RF instead of MIT — there are a lot of changes and
remains the same — nothing has changed. Series of static websites «Pomodori» — not to be bored and not to
forget how to write programs, when there is no work.
- [codeberg&period;org](https://codeberg&period;org/pomodoro) — latest version.
- [git&period;org&period;ru](https://git&period;org&period;ru/pomodoro) — history of changes.
- [hub&period;mos&period;ru](https://hub&period;mos&period;ru/pomodoro) — history of changes.
- [codeberg&period;org](https://codeberg&period;org/pomodoro) — latest test version.
- [git&period;org&period;ru](https://git&period;org&period;ru/pomodoro) — history of changes monthly.
- [hub&period;mos&period;ru](https://hub&period;mos&period;ru/pomodoro) — history of changes monthly.
### Content
@ -27,6 +27,12 @@ secondly, not all of them — are mistakes.
4. [Practical philosophy, poetry and humor](https://pomodoro4.mircloud.ru/) without translation.
5. [Drawing pictures with text](https://pomodoro5.mircloud.ru/en/).
The creative process began in 2016, but even earlier I wrote some things for myself. Activation of creativity
occurs, when there is no work. Mature thoughts become separate projects, and immature ones go as parts of this
project.
- [Archive of incomplete publications](archive/README.md) without translation.
### Design
Two design themes for Jekyll in the Liquid template language: «Color tomato» was written earlier using
@ -38,17 +44,7 @@ so they can be used together on the same site.
- [Color tomato](https://git.org.ru/golovin/color-tomato-theme/src/branch/master/README.en.md) — color selection during the build.
- [Older tomato](https://git.org.ru/golovin/older-tomato-theme/src/branch/master/README.en.md) — lightweight decoration theme.
### Process
The creative process began in 2016, but even earlier I wrote some things for myself. Activation of
creativity occurs, when there is no work. Mature thoughts become separate projects, and immature ones
go as parts of this project. Over time, there are more parts, so automation comes in handy here too.
- [Process management](bash_scripts/README.en.md) — scripts Bash.
- [Avatars for repositories](pictures/README.md) — pictures.
- [Incomplete publications](archive/README.md) — archive without translation.
### Build
### Automation
Previously, a custom Java program was used to generate a site from templates. After generating, the
obfuscation was performed with a dictionary substitution cipher for all classes, variables and functions
@ -59,6 +55,8 @@ Now the site is generated by Jekyll, the template language is Liquid, syntax hig
time, and the content of the pages is in Markdown format. Process management is performed by Bash scripts.
The thought does not leave me, that I *made a senseless swap* — in general, nothing has changed.
- [Dispatcher](https://git.org.ru/golovin/dispatcher/src/branch/master/README.en.md) — suite of Bash scripts for creating and publishing Git repositories in the directories of projects.
### License
Previously, I attached the MIT license to my projects on the Internet, but when the open license

View file

@ -5,9 +5,9 @@
открытая лицензия РФ вместо MIT — изменений много и везде, но суть осталась прежней — ничего не изменилось. Серия
статических вёб-сайтов «Помидоры» — чтобы не скучать и чтобы не забыть, как программы писать, когда работы нет.
- [codeberg&period;org](https://codeberg&period;org/pomodoro) — последняя версия.
- [git&period;org&period;ru](https://git&period;org&period;ru/pomodoro) — история изменений.
- [hub&period;mos&period;ru](https://hub&period;mos&period;ru/pomodoro) — история изменений.
- [codeberg&period;org](https://codeberg&period;org/pomodoro) — последняя тестовая версия.
- [git&period;org&period;ru](https://git&period;org&period;ru/pomodoro) — история изменений помесячно.
- [hub&period;mos&period;ru](https://hub&period;mos&period;ru/pomodoro) — история изменений помесячно.
### Содержание
@ -26,6 +26,11 @@
4. [Практическая философия, поэзия и юмор](https://pomodoro4.mircloud.ru).
5. [Рисуем картинки текстом](https://pomodoro5.mircloud.ru).
Творческий процесс начался в 2016 году, но и раньше какие-то вещи я писал для себя. Активизация творчества наступает,
когда работы нет. Созревшие мысли становятся отдельными проектами, а несозревшие идут как части этого проекта.
- [Архив незавершённых публикаций](archive/README.md).
### Оформление
Две темы оформления для Jekyll на языке шаблонов Liquid: «Цветной помидор» был написан раньше с
@ -37,33 +42,23 @@
- [Цветной помидор](https://git.org.ru/golovin/color-tomato-theme/src/branch/master/README.md) — выбор цвета во время сборки.
- [Старый помидор](https://git.org.ru/golovin/older-tomato-theme/src/branch/master/README.md) — легковесная тема оформления.
### Процесс
### Автоматизация
Творческий процесс начался в 2016 году, но и раньше какие-то вещи я писал для себя. Активизация творчества
наступает, когда работы нет. Созревшие мысли становятся отдельными проектами, а несозревшие идут как части
этого проекта. Со временем частей становится больше, поэтому автоматизация пригождается и здесь тоже.
Раньше сборку сайта из шаблонов выполняла кастомная программа на Java. После сборки выполнялась обфускация шифром
замены по словарю для всех классов, переменных и функций HTML, CSS и JS. Блоки кода оставлялись без обфускации,
а подсветка синтаксиса выполнялась на клиенте. *Обусификатор* — уникальное решение, больше не используется.
- [Управление процессами](bash_scripts/README.md) — скрипты Bash.
- [Аватарки для репозиториев](pictures/README.md) — картинки.
- [Незавершённые публикации](archive/README.md) — архив.
Теперь сборку сайта выполняет Jekyll, язык шаблонов Liquid, подсветка синтаксиса во время сборки, а содержание
страниц в формате Markdown. Управление процессами выполняется скриптами Bash. Меня не покидает мысль, что я
*поменял шило на мыло* — в целом ничего не изменилось.
### Сборка
Раньше сборку сайта из шаблонов выполняла кастомная программа на Java. После сборки выполнялась обфускация
шифром замены по словарю для всех классов, переменных и функций HTML, CSS и JS. Блоки кода оставлялись без
обфускации, а подсветка синтаксиса выполнялась на клиенте. *Обусификатор* — уникальное решение, больше не
используется.
Теперь сборку сайта выполняет Jekyll, язык шаблонов Liquid, подсветка синтаксиса во время
сборки, а содержание страниц в формате Markdown. Управление процессами выполняют скрипты Bash.
Меня не покидает мысль, что я *поменял шило на мыло* — в целом ничего не изменилось.
- [Диспетчер](https://git.org.ru/golovin/dispatcher/src/branch/master/README.md) — набор скриптов Bash для создания и публикации репозиториев Git в каталогах проектов.
### Лицензия
Раньше к своим проектам в интернете прикладывал лицензию MIT, но когда появилась открытая лицензия РФ
— перешёл на неё, сразу внёс небольшие изменения в текст и дополнил от себя, хотя я не юрист. Основной
смысл лицензии остался прежним — программа предоставляется бесплатно, но без каких-либо гарантий,
и автор программы — это я.
Раньше к своим проектам в интернете прикладывал лицензию MIT, но когда появилась открытая лицензия РФ — перешёл
на неё, сразу внёс небольшие изменения в текст и дополнил от себя, хотя я не юрист. Основной смысл лицензии
остался прежним — программа предоставляется бесплатно, но без каких-либо гарантий, и автор программы — это я.
- [OPEN_LICENSE.txt](OPEN_LICENSE.txt) — основной текст лицензии и пояснение к нему без
изменений, можно найти в интернете. Из него удалил лишние пробелы и пробельные символы,

View file

@ -1,5 +1,6 @@
| Незавершённые публикации | Язык | Обновление |
|------------------------------------------------------------------|------|------------|
| [Распараллеливание скриптов Bash](parallelizing-bash-scripts.md) | Bash | 2024.09.05 |
| [Циклический алгоритм распределения задач](round-robin.md) | Java | 2023.06.05 |
| Незавершённые публикации | Язык | Обновление |
|-------------------------------------------------------------------------|------|------------|
| [Анимация Gif с помощью скрипта Bash](gif-animatin-with-bash-script.md) | Bash | 2025.02.11 |
| [Распараллеливание скриптов Bash](parallelizing-bash-scripts.md) | Bash | 2024.09.05 |
| [Циклический алгоритм распределения задач](round-robin.md) | Java | 2023.06.05 |

View file

@ -0,0 +1,25 @@
# Анимация Gif с помощью скрипта Bash
Три шага преобразований лучше выполнять по отдельности, чтобы визуально убедиться в результатах. Сначала
создаём серию скриншотов, выкидываем лишние или одинаковые, если таковые попались. После этого вырезаем
релевантную часть из всех изображений и сохраняем в отдельные файлы. Затем объединяем части в один
анимационный файл.
```bash
#!/bin/bash
folder="$HOME/screenshot" # Каталог для скриншотов должен существовать.
#-----------------------------------------------------------------------------------------------;
# Создание 30 скриншотов по 3 штуки в секунду и сохранение их в каталоге.
for i in {01..30}; do
xfce4-screenshooter -f -s "$folder/screenshot${i}.gif"
sleep 0.333
done
#-----------------------------------------------------------------------------------------------;
# Обрезка изображений и сохранение релевантных частей в этом же каталоге, ШхВ нового изображения и ШхВ отступ.
for i in {01..30}; do
convert -verbose -strip "$folder/screenshot${i}.gif" -crop 640x480+320+230 +repage "$folder/animation${i}.gif"
done
#-----------------------------------------------------------------------------------------------;
# Анимация в бесконечном цикле из полученных изображений с задержкой 0.5 секунды на кадре и ещё 3 секунды на последнем кадре.
convert -verbose -loop 0 -delay 50 "$folder"/animation{01..30}.gif -delay 300 "$folder"/animation30.gif "$folder"/animation.gif
```

View file

@ -1,42 +0,0 @@
# [Process management](README.md)
Creating an archive, switching the domain, composing scripts and creating repositories for publishing.
| № | Bash scripts | Actions performed |
|---|:-----------------------------------------------|:------------------------------------------------------------------------------------------------|
| 1 | [**archive_backup.sh**](archive_backup.sh) | Creating a common archive for the directories of projects on the current date. |
| | [archive_cleanup.sh](archive_cleanup.sh) | Deleting files and folders from the directories of projects before restoring the archive. |
| | [archive_packaging.sh](archive_packaging.sh) | Building websites, packaging and copying archives for deployment. |
| 2 | [**info_param.sh**](info_param.sh) | Parameter for other scripts. Switching the domain of the remote repository. |
| | [info_references.sh](info_references.sh) | Updating the domain of a remote repository in cross-references in descriptions. |
| | [info_tree_license.sh](info_tree_license.sh) | Building a directory tree for each project and copying license files. |
| 3 | [**repo_compose.sh**](repo_compose.sh) | Creating scripts from templates with parameters and saving them in the directories of projects. |
| | [repo_forgejo.tmpl.sh](repo_forgejo.tmpl.sh) | Template of a script without parameters to create a remote repository forgejo. |
| | [repo_forgejo2.tmpl.sh](repo_forgejo2.tmpl.sh) | Template of a script without parameters to deploy a website on the server codeberg. |
| | [repo_gitlab.tmpl.sh](repo_gitlab.tmpl.sh) | Template of a script without parameters to create a remote repository gitlab. |
| | [repo_local.tmpl.sh](repo_local.tmpl.sh) | Template of a script without parameters to create a local repository git. |
| 4 | [**repo_orchestrate.sh**](repo_orchestrate.sh) | Parallel execution of scripts and creation of repositories for the directories of projects. |
| | [repo_pages2.sh](repo_pages2.sh) | Parallel execution of scripts and deploying the websites on the server codeberg. |
| | [repo_testing.smpl.sh](repo_testing.smpl.sh) | Sample of a script for testing the accessibility of pages in the web-interface on the server. |
## Directories of projects
Local project directories are located on the same level. On the server,
repositories with websites are moved to a separate group, and the rest
of the repositories remain with the user. The directory structure for
[codeberg&period;org](https://codeberg&period;org/golovin),
[git&period;org&period;ru](https://git&period;org&period;ru/golovin) and
[hub&period;mos&period;ru](https://hub&period;mos&period;ru/golovin).
<pre>
.
├─ <a href='https://git.org.ru/golovin/color-tomato-theme/src/branch/master/DIRECTORY_TREE.md'>color-tomato-theme</a>
├─ <a href='https://git.org.ru/golovin/older-tomato-theme/src/branch/master/DIRECTORY_TREE.md'>older-tomato-theme</a>
├─ <a href='https://git.org.ru/golovin/pomodoro/src/branch/master/DIRECTORY_TREE.md'>pomodoro</a>
├─ <a href='https://git.org.ru/pomodoro/1/src/branch/master/DIRECTORY_TREE.md'>pomodoro1</a>
├─ <a href='https://git.org.ru/pomodoro/2/src/branch/master/DIRECTORY_TREE.md'>pomodoro2</a>
├─ <a href='https://git.org.ru/pomodoro/3/src/branch/master/DIRECTORY_TREE.md'>pomodoro3</a>
├─ <a href='https://git.org.ru/pomodoro/4/src/branch/master/DIRECTORY_TREE.md'>pomodoro4</a>
├─ <a href='https://git.org.ru/pomodoro/5/src/branch/master/DIRECTORY_TREE.md'>pomodoro5</a>
└─ <a href='https://git.org.ru/pomodoro/6/src/branch/master/DIRECTORY_TREE.md'>pomodoro6</a>
</pre>

View file

@ -1,42 +0,0 @@
# [Управление процессами](README.en.md)
Создание архива, переключение домена, составление скриптов и создание репозиториев для публикации.
| № | Скрипты Bash | Выполняемые действия |
|---|:-----------------------------------------------|:----------------------------------------------------------------------------------|
| 1 | [**archive_backup.sh**](archive_backup.sh) | Создание общего архива для каталогов проектов на текущую дату. |
| | [archive_cleanup.sh](archive_cleanup.sh) | Удаление файлов и папок из каталогов проектов перед восстановлением архива. |
| | [archive_packaging.sh](archive_packaging.sh) | Сборка вёб-сайтов, упаковка и копирование архивов для развёртывания. |
| 2 | [**info_param.sh**](info_param.sh) | Параметр для других скриптов. Переключение домена удалённого репозитория. |
| | [info_references.sh](info_references.sh) | Обновление домена удалённого репозитория в перекрёстных ссылках в описаниях. |
| | [info_tree_license.sh](info_tree_license.sh) | Построение дерева каталогов для каждого проекта и копирование файлов лицензии. |
| 3 | [**repo_compose.sh**](repo_compose.sh) | Создание скриптов из шаблонов с параметрами и сохранение их в каталогах проектов. |
| | [repo_forgejo.tmpl.sh](repo_forgejo.tmpl.sh) | Шаблон скрипта без параметров для создания удалённого репозитория forgejo. |
| | [repo_forgejo2.tmpl.sh](repo_forgejo2.tmpl.sh) | Шаблон скрипта без параметров для развёртывания вёб-сайта на сервере codeberg. |
| | [repo_gitlab.tmpl.sh](repo_gitlab.tmpl.sh) | Шаблон скрипта без параметров для создания удалённого репозитория gitlab. |
| | [repo_local.tmpl.sh](repo_local.tmpl.sh) | Шаблон скрипта без параметров для создания локального репозитория git. |
| 4 | [**repo_orchestrate.sh**](repo_orchestrate.sh) | Параллельное выполнение скриптов и создание репозиториев для каталогов проектов. |
| | [repo_pages2.sh](repo_pages2.sh) | Параллельное выполнение скриптов и развёртывание вёб-сайтов на сервере codeberg. |
| | [repo_testing.smpl.sh](repo_testing.smpl.sh) | Образец скрипта для тестирования доступности страниц в вёб-интерфейсе на сервере. |
## Каталоги проектов
Локальные каталоги проектов расположены на одном уровне. На сервере
репозитории с вёб-сайтами переходят в отдельную группу, а остальные
репозитории остаются у пользователя. Структура каталогов для
[codeberg&period;org](https://codeberg&period;org/golovin),
[git&period;org&period;ru](https://git&period;org&period;ru/golovin) и
[hub&period;mos&period;ru](https://hub&period;mos&period;ru/golovin).
<pre>
.
├─ <a href='https://git.org.ru/golovin/color-tomato-theme/src/branch/master/DIRECTORY_TREE.md'>color-tomato-theme</a>
├─ <a href='https://git.org.ru/golovin/older-tomato-theme/src/branch/master/DIRECTORY_TREE.md'>older-tomato-theme</a>
├─ <a href='https://git.org.ru/golovin/pomodoro/src/branch/master/DIRECTORY_TREE.md'>pomodoro</a>
├─ <a href='https://git.org.ru/pomodoro/1/src/branch/master/DIRECTORY_TREE.md'>pomodoro1</a>
├─ <a href='https://git.org.ru/pomodoro/2/src/branch/master/DIRECTORY_TREE.md'>pomodoro2</a>
├─ <a href='https://git.org.ru/pomodoro/3/src/branch/master/DIRECTORY_TREE.md'>pomodoro3</a>
├─ <a href='https://git.org.ru/pomodoro/4/src/branch/master/DIRECTORY_TREE.md'>pomodoro4</a>
├─ <a href='https://git.org.ru/pomodoro/5/src/branch/master/DIRECTORY_TREE.md'>pomodoro5</a>
└─ <a href='https://git.org.ru/pomodoro/6/src/branch/master/DIRECTORY_TREE.md'>pomodoro6</a>
</pre>

View file

@ -1,9 +0,0 @@
#!/bin/bash
echo "Создание общего архива для каталогов проектов на текущую дату."
cd ../.. # выход из папки и из репозитория
filename="pomodoro-$(date '+%Y-%m-%d').zip"
# сводная строка исключений для всех проектов из файлов ".gitignore"
exclusions="$(find . -maxdepth 2 -type f -name '.gitignore' -exec \
sed -E "s|^(.*)$|-xr!'\1'|" {} \; | sort | uniq | tr '\n' ' ')"
rm -f "$filename"
eval "7z a -tzip '$filename' . -xr!'.git' $exclusions" | grep -E '\S'

View file

@ -1,12 +0,0 @@
#!/bin/bash
echo "Удаление файлов и папок из каталогов проектов перед восстановлением архива."
echo "Предохранитель: ОТМЕНА" && exit 0
cd ../.. # выход из папки и из репозитория
time_ms="$(date '+%s%3N')"
# обход всех репозиториев, расположенных на одном уровне с текущим, кроме папки ".idea"
find . -mindepth 1 -maxdepth 1 -type d -not -name ".idea" | while read -r dir; do
echo "Обработка: $dir"
# внутри репозитория — удаление всех вложенных файлов и папок, кроме папки ".git"
find "$dir" -mindepth 1 -maxdepth 1 -type f,d -not -name ".git" -exec rm -r {} \;
done
echo "Общее время выполнения: $(($(date '+%s%3N') - time_ms)) мс."

View file

@ -1,16 +0,0 @@
#!/bin/bash
echo "Сборка вёб-сайтов, упаковка и копирование архивов для развёртывания."
# обработка репозитория вёб-сайта
function packaging {
echo "Обработка: $1"
cd "./$1" || return
./build.sh >/dev/null
./package.sh >/dev/null
cp -v "$1.zip" ..
}
export -f packaging
cd ../.. # выход из папки и из репозитория
time_ms="$(date '+%s%3N')"
# запуск параллельной обработки репозиториев всех вёб-сайтов
printf 'packaging "pomodoro%s"\0' {1..6} | xargs -n1 -0 -P0 bash -c
echo "Общее время выполнения: $(($(date '+%s%3N') - time_ms)) мс."

View file

@ -1,5 +0,0 @@
#!/bin/false
#domain="codeberg.org"
domain="git.org.ru"
#domain="hub.mos.ru"
echo "Домен удалённого репозитория: $domain"

View file

@ -1,23 +0,0 @@
#!/bin/bash
echo "Обновление домена удалённого репозитория в перекрёстных ссылках в описаниях."
domain="git.org.ru" && source info_param.sh
# название домена в верхнем регистре
DOMAIN="${domain^^}"
# шаблоны для подстановки
expr+=("s|codeberg\.org|$domain|g")
expr+=("s|CODEBERG\.ORG|$DOMAIN|g")
expr+=("s|git\.org\.ru|$domain|g")
expr+=("s|GIT\.ORG\.RU|$DOMAIN|g")
expr+=("s|hub\.mos\.ru|$domain|g")
expr+=("s|HUB\.MOS\.RU|$DOMAIN|g")
if [ "$domain" == "hub.mos.ru" ]; then
expr+=("s|src/branch|blob|g")
else
expr+=("s|blob|src/branch|g")
fi
cd ../.. # выход из папки и из репозитория
time_ms="$(date '+%s%3N')"
# запуск параллельной обработки файлов "README" и подстановка значений по шаблонам
find . -type f -name "README*.md" -printf '%p\0' | xargs -I{} -n1 -0 -P0 bash -c \
"echo '$domain => {}' && sed -i $(printf " -e '%s'" "${expr[@]}") '{}'"
echo "Общее время выполнения: $(($(date '+%s%3N') - time_ms)) мс."

View file

@ -1,58 +0,0 @@
#!/bin/bash
echo "Построение дерева каталогов для каждого проекта и копирование файлов лицензии."
# дерево каталогов со ссылками
function directory_tree {
# аргументы
local path="$1"
local head="$2"
local tail="$3"
# получить содержимое каталога
if [ -d "$path" ]; then
# сначала заглавные буквы, потом строчные, сначала каталоги, потом файлы
ls_sorted="LC_COLLATE=C ls -A --group-directories-first $exclusions $path"
# отсортированный массив файлов и каталогов
local list && readarray -t list < <(eval "$ls_sorted")
# длина массива
local size=${#list[@]}
# пропустить пустой каталог
[ "$size" == 0 ] && return
fi
# префикс текущего элемента, сворачивать синглтоны в одну строку
[ "$4" == "one" ] && printf '%s' "/" || printf '\n%s' "$head"
# текущий элемент дерева — относительная гиперссылка
printf '%s' "<a href='${path#*/}'>${path##*/}</a>"
# рекурсивные вызовы для подкаталогов
if [ -d "$path" ]; then
local i # счётчик
for ((i = 0; i < size; i++)); do
if ((size == 1)); then
directory_tree "$path/${list[$i]}" "$tail" "$tail" "one"
elif ((i < size - 1)); then
directory_tree "$path/${list[$i]}" "$tail├─ " "$tail"
else
directory_tree "$path/${list[$i]}" "$tail└─ " "$tail "
fi
done
fi
}
# копирование файлов лицензии и построение дерева каталогов
function tree_license {
echo "Обработка: $1"
cd "$1" || return
# копирование файлов из этого репозитория во все остальные
if [ "$1" != "./pomodoro" ]; then
cp --remove-destination ../pomodoro/CONTRIBUTING.md .
cp --remove-destination ../pomodoro/*LICENSE* .
fi
# строка исключений для "ls" из списка неотслеживаемых файлов ".gitignore"
exclusions="-I'.git' $(sed -E "s|^(.*)$|-I'\1'|" .gitignore | tr '\n' ' ')"
# помещаем дерево в контейнер, добавляем заголовок и выводим в файл
printf '%s\n' "## Дерево каталогов" "" "<pre>" \
"$(directory_tree . | grep '\S')" "</pre>" >DIRECTORY_TREE.md
}
export -f tree_license directory_tree
cd ../.. # выход из папки и из репозитория
time_ms="$(date '+%s%3N')"
# запуск параллельной обработки всех репозиториев, расположенных на одном уровне с текущим, кроме папки ".idea"
find . -mindepth 1 -maxdepth 1 -type d -not -name ".idea" -printf 'tree_license "%p"\0' | xargs -n1 -0 -P0 bash -c
echo "Общее время выполнения: $(($(date '+%s%3N') - time_ms)) мс."

View file

@ -1,91 +0,0 @@
#!/bin/bash
echo "Создание скриптов из шаблонов с параметрами и сохранение их в каталогах проектов."
export domain="git.org.ru" && source info_param.sh
export basedir="$PWD" # текущая папка
# создание скриптов внутри каталога
function compose {
echo "Обработка: $1"
cd "$1" || return
# добавление скриптов в список неотслеживаемых файлов, если ещё не добавлено
if [[ ! -f ".gitignore" || "$(grep -cF ".repo_*" ".gitignore")" == 0 ]]; then
echo ".repo_*" >>".gitignore" && echo "Обновлён файл: $1/.gitignore"
fi
# подготовка значений для параметров
user="golovin" && owner="$user" && repo="$1"
case "$1" in
*[1-6]) owner="pomodoro" && repo="${1//$owner/}" ;;&
*1) description="Трёхмерная графика на JavaScript" ;;&
*2) description="Декартово произведение, комбинаторика" ;;&
*3) description="Умножение матриц и повороты" ;;&
*4) description="Практическая философия, поэзия и юмор" ;;&
*5) description="Рисуем картинки текстом" ;;&
*6) description="Пустой" ;;&
*[1-6]) description+=" — https://$owner$repo.mircloud.ru" ;;
pomodoro) description="Описание и управление" ;;
color*) description="Тема оформления / Цветной помидор" ;;
older*) description="Тема оформления / Старый помидор" ;;
*) return ;; # шесть помидорных вёб-сайтов и три сопутствующих проекта
esac
if [ "$domain" == "hub.mos.ru" ]; then
[ -f "WIKI.md" ] && wiki="$(uni2ascii -aU -qpsn "WIKI.md")"
model="gitlab" && folder="blob" && wiki_home="-/wikis/home"
else
[ -f "WIKI.md" ] && wiki="$(basenc "WIKI.md" --base64 -w0)"
model="forgejo" && folder="src/branch" && wiki_home="wiki"
fi
if [ "$domain" == "codeberg.org" ]; then
if [ -f "WIKI.md" ]; then
wiki="$(sed 's|mircloud\.ru|codeberg.page|g' WIKI.md | basenc --base64 -w0)"
fi
[[ "$1" =~ [1-6] ]] && description="${description//mircloud.ru/codeberg.page}"
fi
file="DIRECTORY_TREE.md"
# создание трёх скриптов в каталоге проекта с одинаковой шапкой для всех
echo "#!/bin/bash" | tee ".repo_remote.sh" ".repo_local.sh" >".repo_testing.sh"
chmod +x ".repo_remote.sh" ".repo_local.sh" ".repo_testing.sh"
# параметры для удалённого репозитория
param_remote+=("domain='$domain'")
param_remote+=("owner='$owner'")
param_remote+=("user='$user'")
param_remote+=("repo='$repo'")
param_remote+=("description='$description'")
param_remote+=("wiki='$wiki'")
param_remote+=("token='$(head -n+1 "$basedir/.token_$model")'")
# скрипт для создания удалённого репозитория
printf '%s\n' "${param_remote[@]}" >>".repo_remote.sh"
tail -n+2 "$basedir/repo_$model.tmpl.sh" >>".repo_remote.sh"
# параметры для локального репозитория
param_local+=("domain='$domain'")
param_local+=("owner='$owner'")
param_local+=("repo='$repo'")
param_local+=("dir='$1'")
# скрипт для создания локального репозитория
printf '%s\n' "${param_local[@]}" >>".repo_local.sh"
tail -n+2 "$basedir/repo_local.tmpl.sh" >>".repo_local.sh"
# параметры для тестирования вёб-интерфейса
param_testing+=("'https://$domain/$owner/$repo/$folder/master/$file' '$file'")
[ "$wiki" ] && param_testing+=("'https://$domain/$owner/$repo/$wiki_home' 'Home'")
# скрипт для тестирования вёб-интерфейса
printf 'pages+=("%s")\n' "${param_testing[@]}" >>".repo_testing.sh"
tail -n+21 "$basedir/repo_testing.smpl.sh" >>".repo_testing.sh"
if [[ "$domain" == "codeberg.org" && "$1" =~ [1-6] ]]; then
# параметры для развёртывания вёб-сайта
param_pages+=("#!/bin/bash")
param_pages+=("domain='$domain'")
param_pages+=("owner='$owner$repo'")
param_pages+=("user='$user'")
param_pages+=("repo='pages'")
param_pages+=("description='$description'")
param_pages+=("token='$(head -n+1 "$basedir/.token_forgejo")'")
# скрипт для развёртывания вёб-сайта
printf '%s\n' "${param_pages[@]}" >".repo_pages2.sh"
tail -n+2 "$basedir/repo_forgejo2.tmpl.sh" >>".repo_pages2.sh"
chmod +x ".repo_pages2.sh"
fi
}
export -f compose
cd ../.. # выход из папки и из репозитория
time_ms="$(date '+%s%3N')"
# запуск параллельной обработки всех репозиториев, расположенных на одном уровне с текущим, кроме папки ".idea"
find . -mindepth 1 -maxdepth 1 -type d -not -name ".idea" -printf 'compose "%f"\0' | xargs -n1 -0 -P0 bash -c
echo "Общее время выполнения: $(($(date '+%s%3N') - time_ms)) мс."

View file

@ -1,57 +0,0 @@
#!/bin/false
if [[ -z "$domain" || -z "$token" || -z "$owner" || -z "$repo" || -z "$description" || -z "$user" ]]; then
echo "Не указаны обязательные параметры." && exit 1
fi
if [ -z "$1" ]; then
echo "Создание удалённого репозитория для текущего каталога."
fi
time_ms="$(date '+%s%3N')"
if [[ -z "$1" || "$1" == "delete" ]]; then
echo "Удаление старого репозитория."
curl -i -X DELETE "https://$domain/api/v1/repos/$owner/$repo" \
-H "Authorization: token $token" \
-H "Accept: application/json"
fi
if [[ -z "$1" || "$1" == "create" ]]; then
echo "Создание нового репозитория пользователя."
curl -i -X POST "https://$domain/api/v1/user/repos" \
-H "Authorization: token $token" \
-H "Accept: application/json" \
-H "Content-Type: application/json" -d "{ \"name\": \"$repo\", \"description\": \"$description\" }"
if [ "$user" != "$owner" ]; then
echo "Перемещение репозитория в группу."
curl -i -X POST "https://$domain/api/v1/repos/$user/$repo/transfer" \
-H "Authorization: token $token" \
-H "Accept: application/json" \
-H "Content-Type: application/json" -d "{ \"new_owner\": \"$owner\" }"
fi
fi
if [[ -z "$1" || "$1" == "options" ]]; then
[ "$wiki" ] && has_wiki=true || has_wiki=false
echo "Изменение свойств репозитория / отключение ненужного."
curl -i -X PATCH "https://$domain/api/v1/repos/$owner/$repo" \
-H "Authorization: token $token" \
-H "Accept: application/json" \
-H "Content-Type: application/json" -d "{
\"has_projects\": false, \"has_issues\": false,
\"has_releases\": false, \"has_actions\": false,
\"has_packages\": false, \"has_pull_requests\": false,
\"has_wiki\": $has_wiki }"
if [ "$wiki" ]; then
echo "Добавление страницы wiki в репозиторий."
curl -i -X POST "https://$domain/api/v1/repos/$owner/$repo/wiki/new" \
-H "Authorization: token $token" \
-H "Accept: application/json" \
-H "Content-Type: application/json" -d "{ \"content_base64\": \"$wiki\", \"title\": \"Home\" }"
fi
echo "Добавление аватарки для репозитория."
[ "$user" != "$owner" ] && picture="website" || picture="$repo"
avatar=$(basenc "../pomodoro/pictures/$picture.jpg" --base64 -w0)
curl -i -X POST "https://$domain/api/v1/repos/$owner/$repo/avatar" \
-H "Authorization: token $token" \
-H "Accept: application/json" \
-H "Content-Type: application/json" -d "{ \"image\": \"$avatar\" }"
fi
if [ -z "$1" ]; then
echo "Общее время выполнения: $(($(date '+%s%3N') - time_ms)) мс."
fi

View file

@ -1,60 +0,0 @@
#!/bin/false
if [[ -z "$domain" || -z "$token" || -z "$owner" || -z "$repo" || -z "$description" || -z "$user" ]]; then
echo "Не указаны обязательные параметры." && exit 1
elif [ "$domain" != "codeberg.org" ]; then
echo "Некорректно указан сервер." && exit 1
fi
cd _site || exit 1
if [ -z "$1" ]; then
echo "Развёртывание копии вёб-сайта на сервере 'codeberg.page'."
fi
time_ms="$(date '+%s%3N')"
if [[ -z "$1" || "$1" == "remote" ]]; then
echo "Удаление старого репозитория на сервере."
curl -i -X DELETE "https://$domain/api/v1/repos/$owner/$repo" \
-H "Authorization: token $token" \
-H "Accept: application/json"
echo "Создание нового репозитория в группе на сервере."
curl -i -X POST "https://$domain/api/v1/orgs/$owner/repos" \
-H "Authorization: token $token" \
-H "Accept: application/json" \
-H "Content-Type: application/json" -d "{
\"name\": \"$repo\", \"description\": \"$description\" }"
echo "Изменение свойств репозитория / отключение ненужного."
curl -i -X PATCH "https://$domain/api/v1/repos/$owner/$repo" \
-H "Authorization: token $token" \
-H "Accept: application/json" \
-H "Content-Type: application/json" -d "{
\"has_projects\": false, \"has_issues\": false,
\"has_releases\": false, \"has_actions\": false,
\"has_packages\": false, \"has_pull_requests\": false,
\"has_wiki\": false }"
echo "Добавление аватарки для репозитория."
avatar=$(basenc "../../pomodoro/pictures/website.jpg" --base64 -w0)
curl -i -X POST "https://$domain/api/v1/repos/$owner/$repo/avatar" \
-H "Authorization: token $token" \
-H "Accept: application/json" \
-H "Content-Type: application/json" -d "{ \"image\": \"$avatar\" }"
fi
if [[ -z "$1" || "$1" == "local" ]]; then
echo "Пересоздание локального репозитория и отправка данных на сервер."
rm -rf ".git" # удаление старого репозитория
git init -b "master"
git remote add "$domain" "git@$domain:$owner/$repo.git"
git add --all
git commit -m "$(date '+%Y-%m-%d')"
git push -u "$domain" "master"
fi
if [ -z "$1" ]; then
echo "Ожидание 3 секунды." && sleep 3
fi
if [[ -z "$1" || "$1" == "testing" ]]; then
echo "Получение списка коммитов для удалённого репозитория."
param="stat=false&verification=false&files=false"
curl -i -X GET "https://$domain/api/v1/repos/$owner/$repo/commits?$param" \
-H "Authorization: token $token" \
-H "Accept: application/json"
fi
if [ -z "$1" ]; then
echo "Общее время выполнения: $(($(date '+%s%3N') - time_ms)) мс."
fi

View file

@ -1,68 +0,0 @@
#!/bin/false
if [[ -z "$domain" || -z "$token" || -z "$owner" || -z "$repo" || -z "$description" || -z "$user" ]]; then
echo "Не указаны обязательные параметры." && exit 1
fi
if [ -z "$1" ]; then
echo "Создание удалённого репозитория для текущего каталога."
fi
time_ms="$(date '+%s%3N')"
if [[ -z "$1" || "$1" == "delete" ]]; then
echo "Удаление старого репозитория."
curl -i -X DELETE "https://$domain/api/v4/projects/$owner%2F$repo" \
-H "PRIVATE-TOKEN: $token" \
-H "Content-Type: application/json" -d "{ \"permanently_remove\": \"true\", \"full_path\": \"$owner/$repo\" }"
echo
fi
if [[ -z "$1" || "$1" == "create" ]]; then
echo "Создание нового репозитория пользователя."
curl -i -X POST "https://$domain/api/v4/projects" \
-H "PRIVATE-TOKEN: $token" \
-H "Content-Type: application/json" -d "{ \"name\": \"$repo\", \"description\": \"$description\" }"
echo
if [ "$user" != "$owner" ]; then
echo "Перемещение репозитория в группу."
curl -i -X PUT "https://$domain/api/v4/projects/$user%2F$repo/transfer?namespace=$owner" \
-H "PRIVATE-TOKEN: $token"
echo
fi
fi
if [[ -z "$1" || "$1" == "options" ]]; then
[ "$wiki" ] && has_wiki="enabled" || has_wiki="disabled"
echo "Изменение свойств репозитория / отключение ненужного."
curl -i -X PUT "https://$domain/api/v4/projects/$owner%2F$repo" \
-H "PRIVATE-TOKEN: $token" \
-H "Content-Type: application/json" -d "{
\"emails_disabled\": \"true\", \"issues_access_level\": \"disabled\",
\"merge_requests_access_level\": \"disabled\", \"operations_access_level\": \"disabled\",
\"builds_access_level\": \"disabled\", \"request_access_enabled\": \"false\",
\"keep_latest_artifact\": \"false\", \"ci_forward_deployment_enabled\": \"false\",
\"ci_separated_caches\": \"false\", \"ci_allow_fork_pipelines_to_run_in_parent_project\": \"false\",
\"jobs_enabled\": \"false\", \"public_builds\": \"false\", \"packages_enabled\": \"false\",
\"merge_requests_enabled\": \"false\", \"issues_enabled\": \"false\", \"lfs_enabled\": \"false\",
\"snippets_enabled\": \"false\", \"container_registry_enabled\": \"false\",
\"wiki_access_level\": \"$has_wiki\", \"container_registry_access_level\": \"disabled\",
\"security_and_compliance_access_level\": \"disabled\", \"pages_access_level\": \"disabled\",
\"analytics_access_level\": \"disabled\", \"forking_access_level\": \"disabled\",
\"releases_access_level\": \"disabled\", \"requirements_access_level\": \"disabled\",
\"environments_access_level\": \"disabled\", \"feature_flags_access_level\": \"private\",
\"infrastructure_access_level\": \"private\", \"monitor_access_level\": \"disabled\",
\"snippets_access_level\": \"disabled\", \"auto_devops_enabled\": \"false\",
\"shared_runners_enabled\": \"false\", \"group_runners_enabled\": \"false\" }"
echo
if [ "$wiki" ]; then
echo "Добавление страницы wiki в репозиторий."
curl -i -X POST "https://$domain/api/v4/projects/$owner%2F$repo/wikis" \
-H "PRIVATE-TOKEN: $token" \
-H "Content-Type: application/json" -d "{ \"content\": \"$wiki\", \"title\": \"Home\" }"
echo
fi
echo "Добавление аватарки для репозитория."
[ "$user" != "$owner" ] && picture="website" || picture="$repo"
curl -i -X PUT "https://$domain/api/v4/projects/$owner%2F$repo" \
-H "PRIVATE-TOKEN: $token" \
-F "avatar=@../pomodoro/pictures/$picture.jpg"
echo
fi
if [ -z "$1" ]; then
echo "Общее время выполнения: $(($(date '+%s%3N') - time_ms)) мс."
fi

View file

@ -1,52 +0,0 @@
#!/bin/false
if [[ -z "$domain" || -z "$owner" || -z "$repo" || -z "$dir" ]]; then
echo "Не указаны обязательные параметры." && exit 1
fi
echo "Создание локального репозитория, подключение к удалённому и передача данных."
time_ms="$(date '+%s%3N')"
# строка исключений для "find" из списка неотслеживаемых файлов ".gitignore"
exclusions="-not -path '*/.git/*' $(sed -E "s|^(.*)$|-not -path '*/\1*'|" .gitignore | tr '\n' ' ')"
# перевести размеры файла в человеко-читаемую строку, отбросить нули из дробной части и добавить пробел
function BKM { numfmt --to=iec --format="%.2f" --suffix="B" "$1" | sed -r 's|,{,1}0{,2}([BKM])| \1|'; }
rm -rf .git
git init -b master
git remote add "$domain" "git@$domain:$owner/$repo.git"
git add .git*
git commit -m "Инициализация / $dir"
if [ "$domain" == "hub.mos.ru" ]; then
echo "Второй пуш, потому что лингвист с первого раза не срабатывает."
git push -u "$domain" master
fi
git add CONTRIBUTING.md
git add \*LICENSE*
git commit -m "Открытая лицензия РФ"
git add DIRECTORY_TREE.md
git add WIKI.md
git add \*README*
git commit -m "Описание проекта"
git add \*.yml
git add \*Gemfile*
git add \*install.sh
git add \*.gemspec
git add \*robots.txt
git commit -m "Настройки"
git add \*.sh
git commit -m "Скрипты bash"
git add \*.min.css
git add \*.min.js
git add \*.woff
git commit -m "Сторонние материалы"
git add \*.bmp
git add \*.gif
git add \*.ico
git add \*.jpg
git add \*.png
git add \*.svg
git commit -m "Картинки"
while read -r file size; do
echo "Обработка: $file"
git add "$file"
git commit -m "${file#*/} / $(BKM "$size")"
done < <(eval "find . -type f $exclusions -printf '%p %s\n'" | LC_COLLATE=C sort -r)
git push -u "$domain" master
echo "Общее время выполнения: $(($(date '+%s%3N') - time_ms)) мс."

View file

@ -1,38 +0,0 @@
#!/bin/bash
echo "Параллельное выполнение скриптов и создание репозиториев для каталогов проектов."
# выполнение скриптов внутри каталога
function orchestrate {
echo "Обработка: $1"
cd "$1" || return
while (($(date '+%s%3N') - time_ms < 120000)); do
while (($(date '+%s%3N') - time_ms < 120000)); do
# 1 Удаление репозитория на сервере
./.repo_remote.sh "delete" 2>/dev/null >.repo_remote.log
# 2 Создание репозитория на сервере
./.repo_remote.sh "create" 2>/dev/null >>.repo_remote.log
# 3 Проверка корректности ответа от сервера при создании репозитория
case "$(tail -n+10 .repo_remote.log | grep -cE '^HTTP/[1,2].{,2}? [4,5]')" in
0) break ;; *) echo "Ошибка 400-500 при подключении к серверу: $1" ;;
esac
done
# 4 Создание локального репозитория и отправка данных на сервер
./.repo_local.sh 2>/dev/null >.repo_local.log
# 5 Изменение настроек репозитория на сервере, отключение ненужного
./.repo_remote.sh "options" 2>/dev/null >>.repo_remote.log
# 6 Проверка доступности данных в вёб-интерфейсе на сервере
for ((tms = "$(date '+%s%3N')"; $(date '+%s%3N') - tms < 3000; )); do
case "$(./.repo_testing.sh | grep -cF '[91m')" in
0) pass=true && break 2 ;; *) echo "Ожидание данных на сервере: $1" ;;
esac
done
done
[ "$pass" != true ] && echo "Ожидание более 2 минут: $1"
}
export -f orchestrate
cd ../.. # выход из папки и из репозитория
export time_ms && time_ms="$(date '+%s%3N')"
# запуск параллельной обработки всех каталогов проектов, расположенных на одном уровне с текущим
find . -mindepth 1 -maxdepth 1 -type d -printf 'orchestrate "%p"\0' | xargs -n1 -0 -P0 bash -c
# замер продолжительности выполнения в миллисекундах, пересчёт в минуты, секунды и миллисекунды
tms="$(($(date '+%s%3N') - time_ms))" && min="$((tms / 1000 / 60))" && sec="$((tms / 1000 % 60))"
ms="$((tms % 1000))" && printf 'Общее время выполнения: %02d:%02d.%03d мс.\n' "$min" "$sec" "$ms"

View file

@ -1,34 +0,0 @@
#!/bin/bash
echo "Параллельное выполнение скриптов и развёртывание вёб-сайтов на сервере codeberg."
# обработка репозитория вёб-сайта
function pages2 {
echo "Обработка: $1"
cd "./$1" || return
for ((time_ms = "$(date '+%s%3N')"; $(date '+%s%3N') - time_ms < 10000; )); do
# 1 Создание удалённого репозитория
./.repo_pages2.sh "remote" 2>/dev/null >.repo_pages2.log
# 2 Проверка корректности ответов от сервера при создании репозитория
case "$(tail -n+10 .repo_pages2.log | grep -cE '^HTTP/[1,2].{,2}? [4,5]')" in
0) remote=true && break ;; *) echo "Ошибка 400-500 при подключении к серверу: $1" ;;
esac
done
if [ "$remote" != true ]; then echo "Ожидание более 10 секунд: $1" && return; else
# 3 Создание локального репозитория и отправка данных на сервер
./.repo_pages2.sh "local" 2>/dev/null >>.repo_pages2.log
fi
for ((time_ms = "$(date '+%s%3N')"; $(date '+%s%3N') - time_ms < 10000; )); do
# 4 Проверка корректности получения данных на сервере
case "$(./.repo_pages2.sh "testing" 2>/dev/null | grep -cE '^HTTP/[1,2].{,2}? [4,5]')" in
0) testing=true && break ;; *) echo "Ожидание данных на сервере: $1" && sleep 1 ;;
esac
done
if [ "$testing" != true ]; then echo "Ожидание более 10 секунд: $1"; fi
}
export -f pages2
cd ../.. # выход из папки и из репозитория
time_ms="$(date '+%s%3N')"
# запуск параллельной обработки репозиториев всех вёб-сайтов
printf 'pages2 "pomodoro%s"\0' {1..6} | xargs -n1 -0 -P0 bash -c
# замер продолжительности выполнения в миллисекундах, пересчёт в минуты, секунды и миллисекунды
tms="$(($(date '+%s%3N') - time_ms))" && min="$((tms / 1000 / 60))" && sec="$((tms / 1000 % 60))"
ms="$((tms % 1000))" && printf 'Общее время выполнения: %02d:%02d.%03d мс.\n' "$min" "$sec" "$ms"

View file

@ -1,35 +0,0 @@
#!/bin/bash
echo "Образец скрипта для тестирования доступности страниц в вёб-интерфейсе на сервере."
domain="git.org.ru" && source "info_param.sh"
# две страницы для тестирования
file="DIRECTORY_TREE.md"
if [ "$domain" == "hub.mos.ru" ]; then
folder="blob" && wiki_home="-/wikis/home"
else
folder="src/branch" && wiki_home="wiki"
fi
# подготовка массива строк — адрес страницы и название файла через пробел
for repo in {1..6}; do
#pages+=("'https://$domain/golovin/$repo/$folder/master/$file' '$file'")
pages+=("'https://$domain/pomodoro/$repo/$folder/master/$file' '$file'")
pages+=("'https://$domain/pomodoro/$repo/$wiki_home' 'Home'")
done
for repo in {pomodoro,older-tomato-theme,color-tomato-theme}; do
pages+=("'https://$domain/golovin/$repo/$folder/master/$file' '$file'")
pages+=("'https://$domain/golovin/$repo/$wiki_home' 'Home'")
done
# тестирование доступности страниц
function testing {
# название файла должно находиться в заголовке страницы, иначе сервер должен вернуть ошибку
case "$(curl "$1" 2>/dev/null | grep -oP '(?<=<title>).*(?=</title>)' | grep -cF "$2")" in
0) color="91" ;; # светло-красный цвет для отсутствующих страниц
*) color="0" ;; # обычный цвет для всех остальных страниц
esac
# текст соответствующего цвета и адрес страницы
printf "\e[${color}m%s\e[0m %s\n" "Страница:" "$1"
}
export -f testing
time_ms="$(date '+%s%3N')"
# запуск параллельного тестирования строк массива и сортировка результатов
printf "testing %s\0" "${pages[@]}" | xargs -n1 -0 -P0 bash -c | sort -r -k2
echo "Общее время выполнения: $(($(date '+%s%3N') - time_ms)) мс."

View file

@ -1,11 +0,0 @@
| Аватарки для репозиториев |
|-----------------------------------------------|
| color-tomato-theme |
| ![color-tomato-theme](color-tomato-theme.jpg) |
| older-tomato-theme |
| ![older-tomato-theme](older-tomato-theme.jpg) |
| pomodoro |
| ![pomodoro](pomodoro.jpg) |
| website |
| ![website](website.jpg) |

Binary file not shown.

Before

(image error) Size: 5.7 KiB

Binary file not shown.

Before

(image error) Size: 5.1 KiB

Binary file not shown.

Before

(image error) Size: 15 KiB

Binary file not shown.

Before

(image error) Size: 17 KiB