#!/bin/bash # # To use this create a directory that you want to use for git repos, e.g. $HOME/git and copy/symlink this script into it. # Then you can use it like this: # # ./clone github.com/robertgzr/dotfiles # ./clone https://bitbucket.org/foo/bar # # If you don't have gitconfig set up like I have (using aliases for github/bitbucket ssh access) this won't really work set -e [ -n "$DEBUG" ] && set -x SHALLOW= RECURSE_SUBMODULES= TEMP="$(mktemp -d -p /tmp clone.XXXXXXXXXX)" URL= usage() { printf "usage: clone [-s][-r] URL\n" printf "\n" printf " URL example.com/user/repo\n" printf " http[s]://example.com/user/repo\n" printf "\n" printf " -s shallow clone\n" printf " -r recurse submodules\n" printf "\n" exit 0 } fail() { printf "error: %s\n" "${1:-error}" exit "${2:-1}" } confirm() { printf "%s, ok (y/n)? " "${1:-'do something'}" read -r yn if [[ "$yn" = "${yn#[Yy]}" ]]; then fail "ok, exiting" 0 fi } git_clone() { declare -a GIT_FLAGS if [[ -n "${SHALLOW}" ]]; then printf "* shallow clone\n" GIT_FLAGS+=("--depth=${SHALLOW}") fi if [[ -n "${RECURSE_SUBMODULES}" ]]; then printf "* recurse submodules\n" GIT_FLAGS+=("--recurse-submodules") fi git clone "${GIT_FLAGS[@]}" "${@}" } ssh_clone() { prefix=$1 in=$2 to=$3 IFS='/' read -r -a url <<< "${in}" ssh_url="${prefix}:${url[1]}/${url[2]}" printf "* via ssh: %s\n" "${ssh_url}" git_clone "${ssh_url}" "${to}" } http_clone() { to=$2 http_url="https://${URL}" printf "* via http: %s\n" "${ssh_url}" git_clone "${http_url}" "${to}" } clone() { in=$1 to=$2 IFS='/' read -r -a url <<< "${in}" case "${url[0]}" in github.com) ssh_clone git@github.com "${in}" "${to}";; gitlab.com) ssh_clone git@gitlab.com "${in}" "${to}";; bitbucket.org) ssh_clone git@bitbucket.org "${in}" "${to}";; git.sr.ht) ssh_clone git@git.sr.ht "${in}" "${to}";; * ) http_clone "${url/ /\/}" "${to}";; esac if [ -e "${to}/.gitmodules" ]; then git -C "${to}" submodule update --init --recursive fi } main() { while getopts ":hsr" opt; do case ${opt} in s) SHALLOW=1 ;; r) RECURSE_SUBMODULES=1 ;; h|\?) usage ;; esac done shift $((OPTIND -1)) URL=$1 if [[ -z "${URL}" ]]; then fail "no input" else URL="${URL//(http|https):\/\//}" fi clone "${URL}" "${TEMP}/${URL}" || fail target="${PWD}/$(dirname "${URL}")" install -d "${target}" || fail mv "${TEMP}/${URL}" "${target}" || fail } main "${@}"