summary refs log tree commit diff
path: root/bin/clone
blob: 9ee160b24fffc269ea03635ef9895546ec498834 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#!/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
#
# TODO: does it still?
# This requires url aliases to be setup for the git-clone to work properly:
#
# [url "git@github.com:"]
#     insteadOf = "gh:"
#     insteadOf = "https://github.com/"
#     pushInsteadOf = "github:"
#     pushInsteadOf = "git://github.com/"
#
set -e
[ -n "$DEBUG" ] && set -x

SHALLOW=
RECURSE_SUBMODULES=
TEMP="$(mktemp -d -p /tmp clone.XXXXXXXXXX)"
URL=

while getopts ":hsr" opt; do
	case ${opt} in
	s) SHALLOW=1 ;;
	r) RECURSE_SUBMODULES=1 ;;
	h | \?)
		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   don't cd after cloning\n"
		printf "\n"
		exit 0
		;;
	esac
done
shift $((OPTIND - 1))

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

	mkdir -p "${to}"

	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
}

URL=$1
if [[ -z "${URL}" ]]; then
	fail "no input"
else
	URL="${URL//http*:\/\//}"
	URL="${URL//#*/}"
fi

target="${PWD}/$(dirname "${URL}")"
name="$(basename "${URL}")"

if [ ! -d "${target}/${name}" ]; then
	clone "${URL}" "${TEMP}/${URL}" || fail

	install -d "${target}" || fail
	mv "${TEMP}/${URL}" "${target}" || fail
fi