From 4fb8930c3ef226d7b720a217aae22637c26e0519 Mon Sep 17 00:00:00 2001 From: golovin Date: Sun, 29 Dec 2024 10:39:47 +0300 Subject: [PATCH] 2024-12-29 --- DIRECTORY_TREE.md | 3 +- archive/parallelizing-bash-scripts.md | 2 +- bash_scripts/README.en.md | 7 +- bash_scripts/README.md | 1 + bash_scripts/archive_backup.sh | 4 +- bash_scripts/archive_cleanup.sh | 6 +- bash_scripts/archive_packaging.sh | 6 +- bash_scripts/info_param.sh | 4 +- bash_scripts/info_references.sh | 45 ++++----- bash_scripts/info_tree_license.sh | 26 ++--- bash_scripts/repo_compose.sh | 134 +++++++++++++------------- bash_scripts/repo_gitea.tmpl.sh | 45 ++++----- bash_scripts/repo_gitlab.tmpl.sh | 68 +++++-------- bash_scripts/repo_local.tmpl.sh | 12 +-- bash_scripts/repo_orchestrate.sh | 51 ++++++---- bash_scripts/repo_testing.smpl.sh | 35 +++++++ 16 files changed, 225 insertions(+), 224 deletions(-) create mode 100755 bash_scripts/repo_testing.smpl.sh diff --git a/DIRECTORY_TREE.md b/DIRECTORY_TREE.md index 51df0b1..42cc1dd 100644 --- a/DIRECTORY_TREE.md +++ b/DIRECTORY_TREE.md @@ -19,7 +19,8 @@ │ ├─ repo_gitea.tmpl.sh │ ├─ repo_gitlab.tmpl.sh │ ├─ repo_local.tmpl.sh -│ └─ repo_orchestrate.sh +│ ├─ repo_orchestrate.sh +│ └─ repo_testing.smpl.sh ├─ pictures │ ├─ README.md │ ├─ color-tomato-theme.jpg diff --git a/archive/parallelizing-bash-scripts.md b/archive/parallelizing-bash-scripts.md index 422c497..8426f36 100644 --- a/archive/parallelizing-bash-scripts.md +++ b/archive/parallelizing-bash-scripts.md @@ -71,7 +71,7 @@ time_ms="$(date '+%s%3N')" # вывод строк массива и вызов функции для каждой из них в параллельном режиме printf '%s\0' "${array[@]}" | xargs -L1 -0 -P0 bash -c # время работы в миллисекундах -echo "Общее время выполнения: $(("$(date '+%s%3N')" - "$time_ms")) мс." +echo "Общее время выполнения: $(($(date '+%s%3N') - time_ms)) мс." ``` ## Вывод diff --git a/bash_scripts/README.en.md b/bash_scripts/README.en.md index fd1aa6a..93054c7 100644 --- a/bash_scripts/README.en.md +++ b/bash_scripts/README.en.md @@ -11,10 +11,11 @@ Creating an archive, switching the domain, composing scripts and creating reposi | | [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_gitea.tmpl.sh](repo_gitea.tmpl.sh) | Script template without parameters to create a remote repository gitea. | -| | [repo_gitlab.tmpl.sh](repo_gitlab.tmpl.sh) | Script template without parameters to create a remote repository gitlab. | -| | [repo_local.tmpl.sh](repo_local.tmpl.sh) | Script template without parameters to create a local repository git. | +| | [repo_gitea.tmpl.sh](repo_gitea.tmpl.sh) | Template of a script without parameters to create a remote repository gitea. | +| | [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_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 diff --git a/bash_scripts/README.md b/bash_scripts/README.md index 141d5c9..6a88a42 100644 --- a/bash_scripts/README.md +++ b/bash_scripts/README.md @@ -15,6 +15,7 @@ | | [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_testing.smpl.sh](repo_testing.smpl.sh) | Образец скрипта для тестирования доступности страниц в вёб-интерфейсе на сервере. | ## Каталоги проектов diff --git a/bash_scripts/archive_backup.sh b/bash_scripts/archive_backup.sh index 60e82d7..3e1b2bf 100755 --- a/bash_scripts/archive_backup.sh +++ b/bash_scripts/archive_backup.sh @@ -1,9 +1,9 @@ #!/bin/bash echo "Создание общего архива для каталогов проектов на текущую дату." -cd ../.. # выходим из папки и из репозитория +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" +eval "7z a -tzip '$filename' . -xr!'.git' $exclusions" | grep -E '\S' diff --git a/bash_scripts/archive_cleanup.sh b/bash_scripts/archive_cleanup.sh index f5bb6db..a80de01 100755 --- a/bash_scripts/archive_cleanup.sh +++ b/bash_scripts/archive_cleanup.sh @@ -1,7 +1,7 @@ #!/bin/bash echo "Удаление файлов и папок из каталогов проектов перед восстановлением архива." -echo "ОТМЕНА" && exit 0 # предохранитель -cd ../.. # выходим из папки и из репозитория +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 @@ -9,4 +9,4 @@ find . -mindepth 1 -maxdepth 1 -type d -not -name ".idea" | while read -r dir; d # внутри репозитория — удаление всех вложенных файлов и папок, кроме папки ".git" find "$dir" -mindepth 1 -maxdepth 1 -type f,d -not -name ".git" -exec rm -r {} \; done -echo "Общее время выполнения: $(("$(date '+%s%3N')" - "$time_ms")) мс." +echo "Общее время выполнения: $(($(date '+%s%3N') - time_ms)) мс." diff --git a/bash_scripts/archive_packaging.sh b/bash_scripts/archive_packaging.sh index 5c051a9..e77d70e 100755 --- a/bash_scripts/archive_packaging.sh +++ b/bash_scripts/archive_packaging.sh @@ -9,8 +9,8 @@ function packaging { cp -v "pomodoro$1.zip" .. } export -f packaging -cd ../.. # выходим из папки и из репозитория +cd ../.. # выход из папки и из репозитория time_ms="$(date '+%s%3N')" # запуск параллельной обработки репозиториев всех вёб-сайтов -printf '%s\0' {1..6} | xargs -I{} -n1 -0 -P0 bash -c 'packaging "{}"' -echo "Общее время выполнения: $(("$(date '+%s%3N')" - "$time_ms")) мс." +printf 'packaging "%s"\0' {1..6} | xargs -n1 -0 -P0 bash -c +echo "Общее время выполнения: $(($(date '+%s%3N') - time_ms)) мс." diff --git a/bash_scripts/info_param.sh b/bash_scripts/info_param.sh index 2e0aa98..3debf68 100755 --- a/bash_scripts/info_param.sh +++ b/bash_scripts/info_param.sh @@ -1,5 +1,5 @@ -#!/bin/bash +#!/bin/false #domain="gitea.com" domain="git.org.ru" #domain="hub.mos.ru" -echo "Переключение домена удалённого репозитория: $domain" +echo "Домен удалённого репозитория: $domain" diff --git a/bash_scripts/info_references.sh b/bash_scripts/info_references.sh index 3f608ff..c5a2101 100755 --- a/bash_scripts/info_references.sh +++ b/bash_scripts/info_references.sh @@ -1,30 +1,23 @@ #!/bin/bash echo "Обновление домена удалённого репозитория в перекрёстных ссылках в описаниях." -export domain="git.org.ru" && source info_param.sh +domain="git.org.ru" && source info_param.sh # название домена в верхнем регистре -export DOMAIN="${domain^^}" -# обработка информационных файлов -function references { - echo "$domain => $1" - # сбрасываем значения параметров - sed -i "s|gitea\.com|tmp_stub|g" "$1" - sed -i "s|GITEA\.COM|TMP_STUB|g" "$1" - sed -i "s|git\.org\.ru|tmp_stub|g" "$1" - sed -i "s|GIT\.ORG\.RU|TMP_STUB|g" "$1" - sed -i "s|hub\.mos\.ru|tmp_stub|g" "$1" - sed -i "s|HUB\.MOS\.RU|TMP_STUB|g" "$1" - # устанавливаем значения параметров - sed -i "s|tmp_stub|$domain|g" "$1" - sed -i "s|TMP_STUB|$DOMAIN|g" "$1" - if [ "$domain" == "hub.mos.ru" ]; then - sed -i "s|src/branch|blob|g" "$1" - else - sed -i "s|blob|src/branch|g" "$1" - fi -} -export -f references -cd ../.. # выходим из папки и из репозитория +DOMAIN="${domain^^}" +# шаблоны для подстановки +expr+=("s|gitea\.com|$domain|g") +expr+=("s|GITEA\.COM|$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" -print0 | xargs -I{} -n1 -0 -P0 bash -c 'references "{}"' -echo "Общее время выполнения: $(("$(date '+%s%3N')" - "$time_ms")) мс." +# запуск параллельной обработки файлов "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)) мс." diff --git a/bash_scripts/info_tree_license.sh b/bash_scripts/info_tree_license.sh index 09a10c7..385809d 100755 --- a/bash_scripts/info_tree_license.sh +++ b/bash_scripts/info_tree_license.sh @@ -12,17 +12,13 @@ function directory_tree { local head="$2" local tail="$3" # префикс для текущего элемента - if [ "one" == "$4" ]; then - echo -n "/" - else - echo -ne "\n$head" - fi + [ "one" == "$4" ] && printf '%s' "/" || printf '\n%s' "$head" # текущий элемент дерева - echo -n "${path##*/}" + printf '%s' "${path##*/}" # рекурсивные вызовы для подкаталогов if [ -d "$path" ]; then local list # массив файлов и каталогов - readarray -t list <<<"$(list_directory_contents "$path")" + readarray -t list < <(list_directory_contents "$path") local size=${#list[@]} # длина массива local i # счётчик for ((i = 0; i < size; i++)); do @@ -47,19 +43,15 @@ function tree_license { cp -f ../pomodoro/CONTRIBUTING.md . cp -f ../pomodoro/*LICENSE* . fi - # строка исключений для "ls" из списка ".gitignore" — неотслеживаемые файлы + # строка исключений для "ls" из списка неотслеживаемых файлов ".gitignore" exclusions="-I'.git' $(sed -E "s|^(.*)$|-I'\1'|" .gitignore | tr '\n' ' ')" # помещаем дерево в контейнер, добавляем заголовок и выводим в файл - { - echo "## Дерево каталогов" - echo -ne "\n
"
-    directory_tree .
-    echo -e "\n
" - } >DIRECTORY_TREE.md + printf '%s\n' "## Дерево каталогов" "" "
" \
+    "$(directory_tree . | grep '\S')" "
" >DIRECTORY_TREE.md } export -f tree_license directory_tree list_directory_contents -cd ../.. # выходим из папки и из репозитория +cd ../.. # выход из папки и из репозитория time_ms="$(date '+%s%3N')" # запуск параллельной обработки всех репозиториев, расположенных на одном уровне с текущим, кроме папки ".idea" -find . -mindepth 1 -maxdepth 1 -type d -not -name ".idea" -print0 | xargs -I{} -n1 -0 -P0 bash -c 'tree_license "{}"' -echo "Общее время выполнения: $(("$(date '+%s%3N')" - "$time_ms")) мс." +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)) мс." diff --git a/bash_scripts/repo_compose.sh b/bash_scripts/repo_compose.sh index 11287c8..fcd87ce 100755 --- a/bash_scripts/repo_compose.sh +++ b/bash_scripts/repo_compose.sh @@ -2,83 +2,85 @@ echo "Создание скриптов из шаблонов с параметрами и сохранение их в каталогах проектов." export domain="git.org.ru" && source info_param.sh export basedir="$PWD" # текущая папка -# обновление списка исключений -function update_gitignore { - # добавляем исключение в список ".gitignore", если оно ещё не добавлено - if [ ! -f "$1/.gitignore" ] || [ "$(grep -cF ".repo_*" "$1/.gitignore")" == 0 ]; then - echo ".repo_*" >>"$1/.gitignore" - echo "Обновлён файл: $1/.gitignore" - fi -} # создание скриптов из шаблонов с параметрами function compose { echo "Обработка: $1" - update_gitignore "$1" - # параметры для шаблонов - dir="${1##*/}" - owner="golovin" - repo="$dir" - description="" - if [[ "$dir" =~ "pomodoro" ]]; then - if [[ "$dir" =~ [[:digit:]] ]]; then - owner="pomodoro" - repo="${dir//[^[:digit:]]/}" - case "$repo" in - "1") description="Трёхмерная графика на JavaScript" ;; - "2") description="Декартово произведение, комбинаторика" ;; - "3") description="Умножение матриц и повороты" ;; - "4") description="Практическая философия, поэзия и юмор" ;; - "5") description="Рисуем картинки текстом" ;; - "6") description="Пустой" ;; - *) return ;; # шесть помидорных вёб-сайтов - esac - description+=" — https://$owner$repo.mircloud.ru" - else - description="Описание и оглавление" - fi - elif [[ "$dir" =~ "color-tomato" ]]; then - description="Тема оформления / Цветной помидор" - elif [[ "$dir" =~ "older-tomato" ]]; then - description="Тема оформления / Старый помидор" + # добавление исключения в список неотслеживаемых файлов, если оно ещё не добавлено + if [ ! -f "$1/.gitignore" ] || [ "$(grep -cF ".repo_*" "$1/.gitignore")" == 0 ]; then + echo ".repo_*" >>"$1/.gitignore" && echo "Обновлён файл: $1/.gitignore" fi + # значения для параметров + owner="golovin" && 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-tomato*) description="Тема оформления / Цветной помидор" ;; + older-tomato*) description="Тема оформления / Старый помидор" ;; + *) return ;; # шесть помидорных вёб-сайтов и три репозитория пользователя + esac wiki="" # оглавление по страницам вёб-сайта - if [ -f "$dir/WIKI.md" ]; then + if [ -f "$1/WIKI.md" ]; then if [ "$domain" == "hub.mos.ru" ]; then - wiki="$(uni2ascii -aU -qpsn "$dir/WIKI.md")" + wiki="$(uni2ascii -aU -qpsn "$1/WIKI.md")" else - wiki="$(basenc "$dir/WIKI.md" --base64 -w0)" + wiki="$(basenc "$1/WIKI.md" --base64 -w0)" fi fi + file="DIRECTORY_TREE.md" # тестирование вёб-интерфейса + if [ "$domain" == "hub.mos.ru" ]; then + folder="blob" && wiki_home="-/wikis/home" + else + folder="src/branch" && wiki_home="wiki" + fi + # одинаковая шапка "shebang" для всех трёх скриптов + echo "#!/bin/bash" | tee "$1/.repo_remote.sh" "$1/.repo_local.sh" >"$1/.repo_testing.sh" + # параметры для удалённого репозитория + param_remote+=("domain='$domain'") + param_remote+=("owner='$owner'") + param_remote+=("user='golovin'") + param_remote+=("repo='$repo'") + param_remote+=("description='$description'") + param_remote+=("wiki='$wiki'") + if [ "$domain" == "hub.mos.ru" ]; then + param_remote+=("token='$(cat "$basedir/.token_gitlab")'") + template_remote="repo_gitlab.tmpl.sh" + else + param_remote+=("token='$(cat "$basedir/.token_gitea")'") + template_remote="repo_gitea.tmpl.sh" + fi # скрипт для создания удалённого репозитория - { - echo "#!/bin/bash" - echo "domain=\"$domain\"" - echo "owner=\"$owner\"" - echo "user=\"golovin\"" - echo "repo=\"$repo\"" - echo "description=\"$description\"" - echo "wiki=\"$wiki\"" - if [ "$domain" == "hub.mos.ru" ]; then - echo "token=\"$(cat "$basedir/.token_gitlab")\"" - cat "$basedir/repo_gitlab.tmpl.sh" - else - echo "token=\"$(cat "$basedir/.token_gitea")\"" - cat "$basedir/repo_gitea.tmpl.sh" - fi - } >"$dir/.repo_remote.sh" && chmod +x "$dir/.repo_remote.sh" + printf '%s\n' "${param_remote[@]}" >>"$1/.repo_remote.sh" + tail -n+2 "$basedir/$template_remote" >>"$1/.repo_remote.sh" + chmod +x "$1/.repo_remote.sh" + # параметры для локального репозитория + param_local+=("domain='$domain'") + param_local+=("owner='$owner'") + param_local+=("repo='$repo'") + param_local+=("dir='$1'") # скрипт для создания локального репозитория - { - echo "#!/bin/bash" - echo "domain=\"$domain\"" - echo "owner=\"$owner\"" - echo "repo=\"$repo\"" - echo "dir=\"$dir\"" - cat "$basedir/repo_local.tmpl.sh" - } >"$dir/.repo_local.sh" && chmod +x "$dir/.repo_local.sh" + printf '%s\n' "${param_local[@]}" >>"$1/.repo_local.sh" + tail -n+2 "$basedir/repo_local.tmpl.sh" >>"$1/.repo_local.sh" + chmod +x "$1/.repo_local.sh" + # параметры для тестирования вёб-интерфейса + param_testing+=("'https://$domain/$owner/$repo/$folder/master/$file' '$file'") + if [ "$wiki" ]; then + param_testing+=("'https://$domain/$owner/$repo/$wiki_home' 'Home'") + fi + # скрипт для тестирования вёб-интерфейса + printf 'pages+=("%s")\n' "${param_testing[@]}" >>"$1/.repo_testing.sh" + tail -n+21 "$basedir/repo_testing.smpl.sh" >>"$1/.repo_testing.sh" + chmod +x "$1/.repo_testing.sh" } -export -f compose update_gitignore -cd ../.. # выходим из папки и из репозитория +export -f compose +cd ../.. # выход из папки и из репозитория time_ms="$(date '+%s%3N')" # запуск параллельной обработки всех репозиториев, расположенных на одном уровне с текущим, кроме папки ".idea" -find . -mindepth 1 -maxdepth 1 -type d -not -name ".idea" -print0 | xargs -I{} -n1 -0 -P0 bash -c 'compose "{}"' -echo "Общее время выполнения: $(("$(date '+%s%3N')" - "$time_ms")) мс." +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)) мс." diff --git a/bash_scripts/repo_gitea.tmpl.sh b/bash_scripts/repo_gitea.tmpl.sh index 58e6755..d3e7796 100644 --- a/bash_scripts/repo_gitea.tmpl.sh +++ b/bash_scripts/repo_gitea.tmpl.sh @@ -1,71 +1,62 @@ -if [ -z "$domain" ] || [ -z "$token" ] || [ -z "$owner" ] || [ -z "$repo" ] || [ -z "$description" ] || [ -z "$user" ]; then +#!/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 -seconds=5 time_ms="$(date '+%s%3N')" if [ -z "$1" ] || [ "$1" == "delete" ]; then echo "Удаление старого репозитория." - curl -X DELETE "https://$domain/api/v1/repos/$owner/$repo" \ + curl -i -X DELETE "https://$domain/api/v1/repos/$owner/$repo" \ -H "Authorization: token $token" \ - -H "Accept: application/json" -i - echo "Ожидание $seconds с." - sleep "$seconds" + -H "Accept: application/json" fi if [ -z "$1" ] || [ "$1" == "create" ]; then echo "Создание нового репозитория пользователя." - curl -X POST "https://$domain/api/v1/user/repos" \ + 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\" }" -i - echo "Ожидание $seconds с." - sleep "$seconds" + -H "Content-Type: application/json" -d "{ \"name\": \"$repo\", \"description\": \"$description\" }" if [ "$user" != "$owner" ]; then echo "Перемещение репозитория в группу." - curl -X POST "https://$domain/api/v1/repos/$user/$repo/transfer" \ + 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\" }" -i - echo "Ожидание $seconds с." - sleep "$seconds" + -H "Content-Type: application/json" -d "{ \"new_owner\": \"$owner\" }" fi fi if [ -z "$1" ] || [ "$1" == "options" ]; then if [ "$wiki" ]; then echo "Добавление страницы wiki в репозиторий." - curl -X POST "https://$domain/api/v1/repos/$owner/$repo/wiki/new" \ + 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\" }" -i + -H "Content-Type: application/json" -d "{ \"content_base64\": \"$wiki\", \"title\": \"Home\" }" has_wiki=true else has_wiki=false fi echo "Изменение свойств репозитория / отключение ненужного." - curl -X PATCH "https://$domain/api/v1/repos/$owner/$repo" \ + 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_actions\": false, - \"has_issues\": false, - \"has_packages\": false, - \"has_projects\": false, - \"has_pull_requests\": false, - \"has_releases\": false, - \"has_wiki\": $has_wiki }" -i + \"has_projects\": false, \"has_issues\": false, + \"has_releases\": false, \"has_actions\": false, + \"has_packages\": false, \"has_pull_requests\": false, + \"has_wiki\": $has_wiki }" echo "Добавление аватарки для репозитория." picture="$repo" if [ "$user" != "$owner" ]; then picture="website" fi avatar=$(basenc "../pomodoro/pictures/$picture.jpg" --base64 -w0) - curl -X POST "https://$domain/api/v1/repos/$owner/$repo/avatar" \ + 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\" }" -i + -H "Content-Type: application/json" -d "{ \"image\": \"$avatar\" }" fi if [ -z "$1" ]; then - echo "Общее время выполнения: $(("$(date '+%s%3N')" - "$time_ms")) мс." + echo "Общее время выполнения: $(($(date '+%s%3N') - time_ms)) мс." fi diff --git a/bash_scripts/repo_gitlab.tmpl.sh b/bash_scripts/repo_gitlab.tmpl.sh index dc4b0be..2e0520e 100644 --- a/bash_scripts/repo_gitlab.tmpl.sh +++ b/bash_scripts/repo_gitlab.tmpl.sh @@ -1,35 +1,29 @@ -if [ -z "$domain" ] || [ -z "$token" ] || [ -z "$owner" ] || [ -z "$repo" ] || [ -z "$description" ] || [ -z "$user" ]; then +#!/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 -seconds=5 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\"}" + -H "Content-Type: application/json" -d "{ \"permanently_remove\": \"true\", \"full_path\": \"$owner/$repo\" }" echo - echo "Ожидание $seconds с." - sleep "$seconds" 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\"}" + -H "Content-Type: application/json" -d "{ \"name\": \"$repo\", \"description\": \"$description\" }" echo - echo "Ожидание $seconds с." - sleep "$seconds" 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 - echo "Ожидание $seconds с." - sleep "$seconds" fi fi if [ -z "$1" ] || [ "$1" == "options" ]; then @@ -37,7 +31,7 @@ if [ -z "$1" ] || [ "$1" == "options" ]; 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\"}" + -H "Content-Type: application/json" -d "{ \"content\": \"$wiki\", \"title\": \"Home\" }" echo has_wiki="enabled" else @@ -47,40 +41,22 @@ if [ -z "$1" ] || [ "$1" == "options" ]; then 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\"}" + \"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 echo "Добавление аватарки для репозитория." picture="$repo" @@ -93,5 +69,5 @@ if [ -z "$1" ] || [ "$1" == "options" ]; then echo fi if [ -z "$1" ]; then - echo "Общее время выполнения: $(("$(date '+%s%3N')" - "$time_ms")) мс." + echo "Общее время выполнения: $(($(date '+%s%3N') - time_ms)) мс." fi diff --git a/bash_scripts/repo_local.tmpl.sh b/bash_scripts/repo_local.tmpl.sh index 5f52033..0182bd3 100644 --- a/bash_scripts/repo_local.tmpl.sh +++ b/bash_scripts/repo_local.tmpl.sh @@ -1,10 +1,10 @@ -if [ -z "$domain" ] || [ -z "$owner" ] || [ -z "$repo" ] || [ -z "$dir" ]; then +#!/bin/false +if [[ -z "$domain" || -z "$owner" || -z "$repo" || -z "$dir" ]]; then echo "Не указаны обязательные параметры." && exit 1 fi echo "Создание локального репозитория, подключение к удалённому и передача данных." -seconds=3 time_ms="$(date '+%s%3N')" -# строка исключений для "find" из списка ".gitignore" — неотслеживаемые файлы +# строка исключений для "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|'; } @@ -16,8 +16,6 @@ git commit -m "Инициализация / $dir" if [ "$domain" == "hub.mos.ru" ]; then echo "Второй пуш, потому что лингвист с первого раза не срабатывает." git push -u "$domain" master - echo "Ожидание $seconds с." - sleep $seconds fi git add CONTRIBUTING.md git add \*LICENSE* @@ -49,6 +47,6 @@ while read -r file size; do echo "Обработка: $file" git add "$file" git commit -m "${file#*/} / $(BKM "$size")" -done < <(eval "find . -type f $exclusions -printf '%h/%f %s\n'" | LC_COLLATE=C sort -r) +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")) мс." +echo "Общее время выполнения: $(($(date '+%s%3N') - time_ms)) мс." diff --git a/bash_scripts/repo_orchestrate.sh b/bash_scripts/repo_orchestrate.sh index eb3ead1..83affbd 100755 --- a/bash_scripts/repo_orchestrate.sh +++ b/bash_scripts/repo_orchestrate.sh @@ -1,23 +1,34 @@ #!/bin/bash echo "Параллельное выполнение скриптов и создание репозиториев для каталогов проектов." -# Для всех репозиториев на одном уровне с текущим формируем скрипт в одну строчку и выполняем эти скрипты в параллельном режиме. -# Скрипт в одну строчку — это выполнение одного из заранее подготовленных других скриптов для локальных и удалённых репозиториев. -# Формируем и выполняем скрипты в несколько шагов с разными параметрами и по дороге сохраняем отчёты о выполнении. -# Параллельное выполнение скриптов на последующем шаге начинается после завершения всех потоков на предыдущем шаге. -cd ../.. # выходим из папки и из репозитория +# выполнение скриптов внутри каталога +function orchestrate { + cd "$1" || return + while true; do + while true; do + # 1 Удаление репозитория на сервере + ./.repo_remote.sh "delete" >.repo_remote.log + # 2 Создание репозитория на сервере + ./.repo_remote.sh "create" >>.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 >.repo_local.log + # 5 Изменение настроек репозитория на сервере, отключение ненужного + ./.repo_remote.sh "options" >>.repo_remote.log + # 6 Проверка доступности вёб-интерфейса на сервере + case "$(./.repo_testing.sh | grep -cF '[91m')" in + 0) break ;; *) echo "Ошибка доступности вёб-интерфейса: $1" ;; + esac + done +} +export -f orchestrate +cd ../.. # выход из папки и из репозитория time_ms="$(date '+%s%3N')" -# 1 Удаление репозиториев на сервере -find . -mindepth 1 -maxdepth 1 -type d -printf \ - 'cd %h/%f && ./.repo_remote.sh "delete" >.repo_remote.log\0' | xargs -L1 -0 -P0 bash -c -# 2 Создание репозиториев на сервере -find . -mindepth 1 -maxdepth 1 -type d -printf \ - 'cd %h/%f && ./.repo_remote.sh "create" >>.repo_remote.log\0' | xargs -L1 -0 -P0 bash -c -# 3 Проверка корректности пересоздания репозиториев на сервере — выход в случае ошибки -find . -mindepth 2 -maxdepth 2 -type f -name ".repo_remote.log" -exec grep -cE '^HTTP\/[1,2].{,2}? [4,5]' {} \; | - tr -d '0\n' | xargs -r bash -c 'exit 1' || { echo "Ошибка 400-500. Невозможно подключение к серверу." && exit 1; } -# 4 Создание локальных репозиториев и отправка данных на сервер -# 5 Изменение настроек репозиториев на сервере, отключение ненужного -find . -mindepth 1 -maxdepth 1 -type d -printf \ - 'cd %h/%f && ./.repo_local.sh >.repo_local.log\0 - cd %h/%f && ./.repo_remote.sh "options" >>.repo_remote.log\0' | xargs -L1 -0 -P0 bash -c -echo "Общее время выполнения: $(("$(date '+%s%3N')" - "$time_ms")) мс." +# запуск параллельной обработки всех каталогов проектов, расположенных на одном уровне с текущим +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" diff --git a/bash_scripts/repo_testing.smpl.sh b/bash_scripts/repo_testing.smpl.sh new file mode 100755 index 0000000..f823a8d --- /dev/null +++ b/bash_scripts/repo_testing.smpl.sh @@ -0,0 +1,35 @@ +#!/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 '(?<=).*(?=)' | 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)) мс."