Skip to content

Instantly share code, notes, and snippets.

@augustohp
Last active April 4, 2019 18:27
Show Gist options
  • Save augustohp/b314e031fec59dbc95b260ba4d612677 to your computer and use it in GitHub Desktop.
Save augustohp/b314e031fec59dbc95b260ba4d612677 to your computer and use it in GitHub Desktop.
Command line script to clone all repositories from a group in GitLab.
#!/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