setup-apkrepos.in 4.71 KB
Newer Older
1 2 3 4
#!/bin/sh

PROGRAM=setup-apkrepos
PREFIX=
5
MIRRORS_URL=https://mirrors.alpinelinux.org/mirrors.txt
6 7 8

. $PREFIX/lib/libalpine.sh

9 10 11
if [ "$ROOT" != "/" ]; then
	apk_root_opt="--root $ROOT"
fi
Matt Smith's avatar
Matt Smith committed
12

13 14 15 16 17
get_hostname_from_url() {
	local n=${1#*://}
	echo ${n%%/*}
}

Matt Smith's avatar
Matt Smith committed
18
prompt_setup_method() {
19 20 21
	cat <<-__EOF__
		r) Add random from the above list
		f) Detect and add fastest mirror from above list
22
		e) Edit ${ROOT}etc/apk/repositories with text editor
23 24

	__EOF__
25
	echo -n "Enter mirror number (1-$mirror_count) or URL to add (or r/f/e/done) [$1]: "
Matt Smith's avatar
Matt Smith committed
26 27
}

28
add_random_mirror() {
Matt Smith's avatar
Matt Smith committed
29
	local i=0
30
	local random_mirror_index=$(( $RANDOM % $mirror_count ))
31

Matt Smith's avatar
Matt Smith committed
32 33 34 35 36
	echo -n "Picking random mirror... "
	for mirror in $MIRRORS; do
		if [ $i -eq $random_mirror_index ]; then
			break
		fi
37
		i=$(( $i + 1 ))
Matt Smith's avatar
Matt Smith committed
38
	done
39
	add_mirror $mirror
Matt Smith's avatar
Matt Smith committed
40 41
}

42 43
time_cmd() {
	local start=$(cut -d ' ' -f1 /proc/uptime)
44
	$@ >&2 || return
45 46 47
	awk -v start=$start -v end=$(cut -d ' ' -f1 /proc/uptime) \
		'BEGIN {print end - start; exit}'
}
Matt Smith's avatar
Matt Smith committed
48

49 50
find_fastest_mirror() {
	local url=
51
	local arch=$(apk --print-arch)
52
	for url in $MIRRORS; do
53 54
		# warm up the dns cache
		nslookup $(get_hostname_from_url $url) >/dev/null 2>&1
55
		local time=$(time_cmd wget --spider -q -T 5 \
56
			${url%/}/edge/main/$arch/APKINDEX.tar.gz)
57 58 59
		if [ -n "$time" ]; then
			echo "$time $url"
		fi
60
	done | tee /dev/stderr | sort -nk1,1 | head -n1 | cut -d' ' -f2
61 62 63 64 65
}

add_fastest_mirror() {
	echo "Finding fastest mirror... "
	local fastest=$(find_fastest_mirror)
66 67 68 69
	if [ -z "$fastest" ]; then
		echo "Warning! No mirror found"
		return 1
	fi
70
	add_mirror "$fastest"
Matt Smith's avatar
Matt Smith committed
71 72
}

73
# show mirrors and store how many in global mirror_count
74
show_mirror_list() {
75 76 77
	local mirror i=0
	mirror_count=0
	[ -z "$MIRRORS" ] && return
78
	echo ""
79
	echo "Available mirrors:"
80 81
	for mirror in $MIRRORS; do
		i=$(($i + 1))
82
		echo "$i) $(get_hostname_from_url $mirror)"
83
	done
84 85
	echo ""
	mirror_count=$i
86 87
}

88 89 90 91 92
add_from_list() {
	local mirror_index=$1
	if [ $mirror_index -lt 1 ] || [ $mirror_index -gt $mirror_count ]; then
		return 1
	fi
Matt Smith's avatar
Matt Smith committed
93
	set $MIRRORS
94
	eval "mirror=\$$mirror_index"
95
	add_mirror "$mirror"
Matt Smith's avatar
Matt Smith committed
96 97 98
}

get_alpine_release() {
99
	local version=$(cat "${ROOT}"etc/alpine-release 2>/dev/null)
100
	case "$version" in
101
		*_git*|*_alpha*) release="edge";;
102 103
		[0-9]*.[0-9]*.[0-9]*)
			# release in x.y.z format, cut last digit
104 105 106
			release=v${version%.[0-9]*};;
		*)	# fallback to edge
			release="edge";;
107
	esac
Matt Smith's avatar
Matt Smith committed
108
}
109

110 111
add_mirror() {
	local mirror="$1"
112
	mkdir -p "${APKREPOS_PATH%/*}"
113
	echo "${mirror%/}/${release}/main" >> $APKREPOS_PATH
114
	echo "#${mirror%/}/${release}/community" >> $APKREPOS_PATH
115 116
	case "$release" in
	v[0-9]*)
Ted Trask's avatar
Ted Trask committed
117
		echo "#${mirror%/}/edge/main" >> $APKREPOS_PATH;
118
		echo "#${mirror%/}/edge/community" >> $APKREPOS_PATH;;
119 120
	esac
	echo "#${mirror%/}/edge/testing" >> $APKREPOS_PATH
121 122 123
	echo "" >> $APKREPOS_PATH
	echo "Added mirror $(get_hostname_from_url $mirror)"
}
Matt Smith's avatar
Matt Smith committed
124

125
add_from_url() {
126
	mkdir -p "${APKREPOS_PATH%/*}"
127 128
	echo "$1" >> $APKREPOS_PATH
	echo "" >> $APKREPOS_PATH
Matt Smith's avatar
Matt Smith committed
129 130
}

131
edit_repositories() {
132 133
	local md5=$(md5sum $APKREPOS_PATH 2>/dev/null)
	mkdir -p "${APKREPOS_PATH%/*}"
134 135
	${EDITOR:-vi} "$APKREPOS_PATH"
	# return true if file changed
136
	test "$(md5sum $APKREPOS_PATH 2>/dev/null)" != "$md5"
137
}
Matt Smith's avatar
Matt Smith committed
138

139
usage() {
140 141
	cat <<-__EOF__
		usage: setup-apkrepos [-fhr] [REPO...]
142

143
		Setup apk repositories
144

145 146 147 148
		options:
		 -f  Detect and add fastest mirror
		 -h  Show this help
		 -r  Add a random mirror and do not prompt
149
		 -1  Add first mirror on the list (normally a CDN)
150
	__EOF__
151 152 153 154
	exit 1

}

155 156 157 158
add_fastest=false
add_first=false
add_random=false
while getopts "1fhr" opt; do
159
	case $opt in
160 161
		f) add_fastest=true;;
		1) add_first=true;;
162
		h) usage;;
163
		r) add_random=true;;
164
	esac
165
done
166
shift $(($OPTIND - 1))
167

168 169
if [ -z "$MIRRORS" ]; then
	MIRRORS=$(wget -qO- $MIRRORS_URL)
170 171
fi

172
APKREPOS_PATH="${ROOT}"etc/apk/repositories
173
if [ -r "$APKREPOS_PATH" ]; then
174
	APKREPOS=$(cat "$APKREPOS_PATH")
175 176
fi

177 178
get_alpine_release
default_answer=f
179 180 181 182 183 184
changed=false

if [ $# -gt 0 ]; then
	# replace the apk repos with the specified ones
	rm -f "$APKREPOS_PATH"
	for i; do
185
		echo "$i" >> "$APKREPOS_PATH" && changed=true
186 187 188
	done
fi

189 190 191 192 193 194
if $add_first; then
	set -- $MIRRORS
	add_mirror "$1" && changed=true
fi

if $add_random; then
195 196 197 198
	show_mirror_list > /dev/null
	add_random_mirror && changed=true
fi

199
if $add_fastest; then
200 201 202 203
	show_mirror_list > /dev/null
	add_fastest_mirror && changed=true
fi

204 205 206 207 208 209 210 211 212 213 214 215 216 217
while ! $changed; do
	show_mirror_list
	prompt_setup_method $default_answer

	default_read answer $default_answer
	case "$answer" in
		"done") break;;
		[0-9]*) add_from_list $answer && changed=true;;
		/*|http://*|ftp://*|https://*) add_from_url "$answer" \
			&& changed=true;;
		r) add_random_mirror && changed=true;;
		f) add_fastest_mirror && changed=true;;
		e) edit_repositories && changed=true;;
	esac
218
done
Matt Smith's avatar
Matt Smith committed
219

220
if $changed; then
221
	echo -n "Updating repository indexes... "
222
	apk update --quiet $apk_root_opt && echo "done."
223
fi
224