Last active
April 4, 2019 18:27
-
-
Save augustohp/b314e031fec59dbc95b260ba4d612677 to your computer and use it in GitHub Desktop.
Command line script to clone all repositories from a group in GitLab.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env sh | |
# | |
# This script will help you clone all repositories | |
# from an organization in GitLab. | |
APP_NAME=$(basename $0) | |
APP_VERSION="1.0.0" | |
APP_AUTHOR="[email protected]" | |
OPTION_ORG_NAME="" | |
OPTION_REPOSITORIES_PATH="${HOME}/src" | |
OPTION_GITLAB_API_PRIVATE_TOKEN="${GITLAB_API_TOKEN:-}" | |
OPTION_GITLAB_API_ENDPOINT="https://gitlab.com/api/v4" | |
OPTION_DRY_RUN="" | |
set -e | |
if [ ! -z "$DEBUG" ] | |
then | |
set -x | |
fi | |
# Check environment for requirements ------------------------------------------ | |
DOCKER=$(command -v docker) | |
JQ=$(command -v jq) | |
SED=$(command -v sed) | |
GIT=$(command -v git) | |
if [ -z "$JQ" ] | |
then | |
echo "Jq is not installed. (https://stedolan.github.io/jq/)" >&2 | |
exit 2 | |
fi | |
if [ -z "$DOCKER" ] | |
then | |
echo "Docker is not installed. (https://docker.io)" >&2 | |
exit 2 | |
fi | |
if [ -z "$SED" ] | |
then | |
echo "sed is not installed." >&2 | |
exit 2 | |
fi | |
if [ -z "$GIT" ] | |
then | |
echo "Git is not installed. (https://git-scm.com/)" >&2 | |
exit 2 | |
fi | |
# Utilitary functions --------------------------------------------------------- | |
# Usage: echo " a " | trim | |
trim() | |
{ | |
$SED 's/[ \"]//g' | |
} | |
# https://github.com/narkoz/gitlab | |
# Usage: gitlab [options|commands] | |
gitlab() | |
{ | |
if [ -z "${OPTION_GITLAB_API_PRIVATE_TOKEN}" ] | |
then | |
echo "GitLab token not provided. ($APP_NAME --help)" >&2 | |
exit 2 | |
fi | |
$DOCKER run -it \ | |
-e "GITLAB_API_PRIVATE_TOKEN=${OPTION_GITLAB_API_PRIVATE_TOKEN:-}" \ | |
-e "GITLAB_API_ENDPOINT=${OPTION_GITLAB_API_ENDPOINT:-}" \ | |
"augustohp/ore-gitlab-cli:latest" \ | |
"$@" | |
} | |
# Usage: display_help | |
display_help() | |
{ | |
cat <<-EOT | |
Usage: $APP_NAME <options> | |
$APP_NAME --to ~/src/gadle.it --token A678ndt47i --group gadleit | |
$APP_NAME --dry-run --token A678ndt47i --group gadleit | |
Will clone all repositories from a GitLab group to a given path, or just | |
print all repositories to stdout. | |
Options: | |
-g | --group <name> Name of the GitLab group? (Default: $OPTION_ORG_NAME) | |
-d | --destination <path> Where to clone repositories to? (Default: $PWD) | |
-t | --token <token> What access token to use? (Default: $OPTION_GITLAB_API_PRIVATE_TOKEN) | |
-a | --api <domain> What API to use? (Default: $OPTION_GITLAB_API_ENDPOINT) | |
-x | --dry-run Don't clone, just print repository names. | |
-h | --help This help message. | |
-v | --version Prints version information. | |
You can generate an Access Token at https://gitlab.com/profile/personal_access_tokens. | |
Contact $APP_AUTHOR for help, suggestions or bugs. | |
EOT | |
} | |
# TODO: Put limit of repository listing as option | |
# Usage: list_repositories <group name> | |
list_repositories() | |
{ | |
group_name="$1" | |
if [ -z "$group_name" ] | |
then | |
echo "Group name not provided. ($APP_NAME --help)" >&2 | |
exit 2 | |
fi | |
result=$(gitlab group_projects --json "${group_name}" "{per_page: '250'}") | |
if [ -z "$result" ] | |
then | |
echo "Error fetching repositories from GitLab, maybe the group '$group_name' does not exist !?" >&2 | |
exit 2 | |
fi | |
echo $result \ | |
| $JQ '.result[] | .path_with_namespace' \ | |
| trim | |
} | |
# Usage: clone_repository <repository name with namespace> [directory to clone into] | |
clone_repository() | |
{ | |
repo_with_namespace="$1" | |
clone_into_directory="${2%%/:-$PWD}" | |
if [ ! -d "${clone_into_directory}" ] | |
then | |
echo "Directory to clone repositories does not exist: '${clone_into_directory}'." >&2 | |
exit 2 | |
fi | |
namespace=$(echo "$repo_with_namespace" | cut -d"/" -f1) | |
repository_without_namespace=${repo_with_namespace##$namespace/} | |
destination_dir="${clone_into_directory}/${repository_without_namespace}" | |
repository_url="[email protected]:${repo_with_namespace}.git" | |
if [ -d "${destination_dir}" ] | |
then | |
echo "Repository '${repo_with_namespace}' was already cloned." >&2 | |
return 0 | |
fi | |
echo "${repo_with_namespace}" | |
if [ -z "${OPTION_DRY_RUN}" ] | |
then | |
$GIT clone "${repository_url}" "${destination_dir}" 2>&1 \ | |
| $SED 's/^/ /' | |
fi | |
} | |
main() | |
{ | |
for repository_with_namespace in $(list_repositories "${OPTION_ORG_NAME}") | |
do | |
clone_repository "${repository_with_namespace}" "${OPTION_REPOSITORIES_PATH}" | |
done | |
} | |
# Program --------------------------------------------------------------------- | |
while :; | |
do | |
if [ $# = 0 ] | |
then | |
break | |
fi | |
case "$1" in | |
-h|--help|help) | |
display_help | |
exit 0 | |
;; | |
-v|--version|version) | |
echo "$APP_NAME $APP_VERSION" | |
exit 0 | |
;; | |
-x|--dry-run|--dryrun) | |
OPTION_DRY_RUN="yes" | |
;; | |
-d|--destination) | |
OPTION_REPOSITORIES_PATH="${2}" | |
shift | |
;; | |
-t|--access-token|--token) | |
OPTION_GITLAB_API_PRIVATE_TOKEN="${2}" | |
shift | |
;; | |
-g|--group|--organization|--org) | |
OPTION_ORG_NAME="${2}" | |
shift | |
;; | |
-a|--api) | |
OPTION_GITLAB_API_ENDPOINT="$2" | |
shift | |
;; | |
*) | |
echo "Invalid option '$1', please use '$APP_NAME --help'." >&2 | |
exit 2 | |
;; | |
esac | |
shift | |
done | |
main | |
# vim: noet ts=4 sw=4 ft=sh: |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment