gitlab: add project path function to map special chars

Automatic path conversion is limited to GitLab API v4 and will be
removed in the future. It's expected that the caller does the path
conversion on caller side and only passes a valid path to the API within
its limitations.

Hence convert project names to valid paths:
  1. replace single '+' between word boundaries with '-'
  2. replace any other '+' with literal 'plus'
  3. replace any special chars other than '_', '-' and '.' with '-'
  4. replace consecutive '_-' chars with a single '-'
  5. replace 'tree' with 'unix-tree' due to GitLab reserved keyword

Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
This commit is contained in:
Levente Polyak 2023-01-30 21:15:50 +01:00
parent f669a71e84
commit eda3a4aea0
No known key found for this signature in database
GPG Key ID: FC1B547C8D8172C8
3 changed files with 33 additions and 4 deletions

View File

@ -81,16 +81,40 @@ gitlab_api_get_user() {
return 0
}
# Convert arbitrary project names to GitLab valid path names.
#
# GitLab has several limitations on project and group names and also maintains
# a list of reserved keywords as documented on their docs.
# https://docs.gitlab.com/ee/user/reserved_names.html
#
# 1. replace single '+' between word boundaries with '-'
# 2. replace any other '+' with literal 'plus'
# 3. replace any special chars other than '_', '-' and '.' with '-'
# 4. replace consecutive '_-' chars with a single '-'
# 5. replace 'tree' with 'unix-tree' due to GitLab reserved keyword
gitlab_project_name_to_path() {
local name=$1
printf "%s" "${name}" \
| sed -E 's/([a-zA-Z0-9]+)\+([a-zA-Z]+)/\1-\2/g' \
| sed -E 's/\+/plus/g' \
| sed -E 's/[^a-zA-Z0-9_\-\.]/-/g' \
| sed -E 's/[_\-]{2,}/-/g' \
| sed -E 's/^tree$/unix-tree/g'
}
gitlab_api_create_project() {
local pkgbase=$1
local outfile data path
local outfile data path project_path
[[ -z ${WORKDIR:-} ]] && setup_workdir
outfile=$(mktemp --tmpdir="${WORKDIR}" pkgctl-gitlab-api.XXXXXXXXXX)
project_path=$(gitlab_project_name_to_path "${pkgbase}")
# create GitLab project
data='{
"name": "'"${pkgbase}"'",
"path": "'"${project_path}"'",
"namespace_id": "'"${GIT_PACKAGING_NAMESPACE_ID}"'",
"request_access_enabled": "false"
}'

View File

@ -54,6 +54,9 @@ pkgctl_repo_clone() {
local CONFIGURE_OPTIONS=()
local pkgbases
# variables
local project_path
while (( $# )); do
case $1 in
-h|--help)
@ -126,7 +129,8 @@ pkgctl_repo_clone() {
for pkgbase in "${pkgbases[@]}"; do
if [[ ! -d ${pkgbase} ]]; then
msg "Cloning ${pkgbase} ..."
remote_url="${GIT_REPO_BASE_URL}/${pkgbase}.git"
project_path=$(gitlab_project_name_to_path "${pkgbase}")
remote_url="${GIT_REPO_BASE_URL}/${project_path}.git"
git clone --origin origin "${remote_url}" "${pkgbase}"
else
warning "Skip cloning ${pkgbase}: Directory exists"

View File

@ -96,7 +96,7 @@ pkgctl_repo_configure() {
local paths=()
# variables
local path realpath pkgbase remote_url
local path realpath pkgbase remote_url project_path
local PACKAGER GPGKEY packager_name packager_email
while (( $# )); do
@ -174,7 +174,8 @@ pkgctl_repo_configure() {
pushd "${path}" >/dev/null
remote_url="${GIT_REPO_BASE_URL}/${pkgbase}.git"
project_path=$(gitlab_project_name_to_path "${pkgbase}")
remote_url="${GIT_REPO_BASE_URL}/${project_path}.git"
if ! git remote add origin "${remote_url}" &>/dev/null; then
git remote set-url origin "${remote_url}"
fi