diff --git a/src/lib/api/gitlab.sh b/src/lib/api/gitlab.sh index 649e205..e5f4237 100644 --- a/src/lib/api/gitlab.sh +++ b/src/lib/api/gitlab.sh @@ -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" }' diff --git a/src/lib/repo/clone.sh b/src/lib/repo/clone.sh index 4b26fcf..dee4870 100644 --- a/src/lib/repo/clone.sh +++ b/src/lib/repo/clone.sh @@ -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" diff --git a/src/lib/repo/configure.sh b/src/lib/repo/configure.sh index d6262b7..942876a 100644 --- a/src/lib/repo/configure.sh +++ b/src/lib/repo/configure.sh @@ -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