summaryrefslogtreecommitdiffhomepage
path: root/subr.rtl/rtl_fetch.subr
blob: f5410e30b3269234f826fdebcc3a4c19d8dd2fda (plain)
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#
# set +o errexit -o noglob -o nounset is assumed.
#

rtl_fetch_mirror_urls_git() {
	local _git_args="${1}" _tgtdir="${2}" _rc=0 _repo_dname="" _subdir="" _url="" _url_spec=""; shift 2;

	for _url_spec in "${@}"; do
		_subdir="${_url_spec%=*}"; _subdir="${_subdir##*/}"; _url="${_url_spec#*=}"; _url="${_url%@*}";
		_repo_dname="${_url##*/}"; [ "${_repo_dname%.git}" = "${_repo_dname}" ] && _repo_dname="${_repo_dname}.git";

		if [ ! -e "$(rtl_dirname "${_tgtdir}")" ]; then
			rtl_fileop mkdir "$(rtl_dirname "${_tgtdir}")";
		fi;
		(set -o errexit -o noglob -o nounset;
		rtl_flock_acquire 4 || exit "${?}";
		trap "rm -f \"${_tgtdir}/.fetching\"" EXIT;
		if [ -e "${_tgtdir}/${_repo_dname}" ]; then
			(rtl_fileop cd "${_tgtdir}/${_repo_dname}" && git fetch ${_git_args} --all) || return 1;
		else	(rtl_fileop cd "${_tgtdir}" && git clone ${_git_args} --mirror "${_url}") || return 1;
		fi) 4<>"${_tgtdir}/.fetching";
		if [ "${?}" -ne 0 ]; then
			_rc=1;
		fi;
	done; return "${_rc}";
};

rtlp_fetch_url_git() {
	local	_cache_dname="${1}" _git_args="${2}" _git_branch="${3}" _mirrors="${4}" _pkg_name="${5}"\
		_subdir="${6}" _tgtdir="${7}" _url="${8}" _cache_dname_full="" _clonefl=0 _oldpwd="" _url_base="";

	_cache_dname_full="${_cache_dname}/${_subdir##*/}";
	(set -o errexit -o noglob -o nounset;
	rtl_flock_acquire 4 || exit "${?}";
	trap "rm -f \"${_cache_dname_full%%[/]}.fetching\"" EXIT;
	if [ -e "${_cache_dname_full}" ]; then
		(rtl_fileop cd "${_cache_dname_full}" &&\
			git pull ${_git_args} origin "${_git_branch:-main}") || return 1;
		(rtl_fileop cd "${_cache_dname_full}" &&\
			git submodule update) || return 1;
	else	if git clone ${_git_args} -b "${_git_branch:-main}" "${_url}" "${_cache_dname_full}"; then
			_clonefl=1;
		elif [ "${_mirrors}" = "skip" ]; then
			return 1;
		else	for _url_base in ${_mirrors}; do
				if git clone ${_git_args} -b "${_git_branch:-main}" "${_url_base}/${_pkg_name}/${_url##*/}" "${_cache_dname_full}"; then
					_clonefl=1; break;
				fi;
			done;
		fi;
		if [ "${_clonefl}" -eq 0 ]; then
			return 1;
		else	if [ -n "${_git_branch}" ]; then
				(rtl_fileop cd "${_cache_dname_full}" &&\
					git checkout "${_git_branch}") || return 1;
			fi;
			(rtl_fileop cd "${_cache_dname_full}" &&\
				git submodule update --init) || return 1;
		fi;
	fi;
	if [ "${_cache_dname}" != "${_tgtdir}" ]; then
		_oldpwd="${PWD}"; rtl_fileop cd "${_tgtdir}" || return 1;
		rtl_fileop rm "${_tgtdir}/${_subdir}" || return 1;
		if [ ! -e "$(rtl_dirname "${_tgtdir}/${_subdir}")" ]; then
			rtl_fileop mkdir "$(rtl_dirname "${_tgtdir}/${_subdir}")";
		fi;
		rtl_fileop cp "${_cache_dname_full}" "${_tgtdir}/${_subdir}" || return 1;
		rtl_fileop cd "${_oldpwd}" || return 1;
	fi) 4<>"${_cache_dname_full%%[/]}.fetching";

	if [ "${?}" -eq 0 ]; then
		cd "$(pwd)";
	else
		return 1;
	fi;
};

rtl_fetch_urls_git() {
	local	_cache_dname="${1}" _git_args="${2}" _tgtdir="${3}" _pkg_name="${4}" _mirrors="${5}"\
		_git_branch="" _subdir="" _url="" _url_spec=""; shift 5;

	for _url_spec in "${@}"; do
		_subdir="${_url_spec%=*}"; _url="${_url_spec#*=}"; _url="${_url%@*}";
		if [ "${_url_spec#*@}" != "${_url_spec}" ]; then
			_git_branch=${_url_spec#*@};
		fi;
		if ! rtlp_fetch_url_git	\
				"${_cache_dname}" "${_git_args}" "${_git_branch}" "${_mirrors}"\
				"${_pkg_name}" "${_subdir}" "${_tgtdir}" "${_url}"; then
			return 1;
		fi;
	done;
};

# N.B.	URLs ($1) may contain `?' or '&' characters.
rtl_fetch_url_wget() {
	local _urls="${1}" _sha256sum_src="${2}" _target_dname="${3}" _target_fname="${4}" _target_name="${5}" _mirrors="${6:-}"\
		_rc=0 _sha256sum_target="" _target_fname_full="" _url="" _url_base="" _urls_count=0 _urls_full="";

	_urls_full="${_urls}";
	for _url_base in ${_mirrors}; do
		_urls_full="$(rtl_lconcat "${_urls_full}" "${_url_base%/}/${_target_name}/${_target_fname}")";
	done;
	_urls_count="$(rtl_llength "${_urls_full}")";
	for _url in ${_urls_full}; do
		if [ -z "${_target_fname}" ]; then
			_target_fname="$(rtl_basename "${_url}")";
		fi;
		_target_fname_full="${_target_dname}/${_target_fname}";
		(set +o errexit -o noglob -o nounset;
		rtl_flock_acquire 4 || exit 1;
		trap "_rc=\"\${?}\"; rm -f \"${_target_fname_full}.fetching\"; exit \"\${_rc}\";" EXIT;
		if [ -z "${_sha256sum_src}" ]\
		|| ! rtl_check_digest_file "${_target_fname_full}" "${_sha256sum_src}" "${_target_fname_full}.fetched"; then
			wget ${DEFAULT_WGET_ARGS} -O "${_target_fname_full}" "${_url}"; _rc="${?}";
			if [ "${_rc}" -ne 0 ]; then
				exit $((${_rc}+2));
			elif [ -n "${_sha256sum_src}" ]\
			&& ! rtl_check_digest "${_target_fname_full}" "${_sha256sum_src}"; then
				exit 2;
			else
				printf "%s" "${RTL_CHECK_DIGEST_DIGEST}" > "${_target_fname_full}.fetched"; exit 0;
			fi;
		else
			exit 0;
		fi;) 4<>"${_target_fname_full}.fetching"; _rc="${?}"; : $((_urls_count-=1));
		case "${_rc}" in
		0)	break; ;;
		1)	if [ "${_urls_count}" -ge 1 ]; then
				rtl_log_msg warning "Warning: failed to acquire fetching lock for URL \`%s', retrying with alternative URL..." "${_url}";
			else
				rtl_log_msg fatal "Error: failed to acquire fetching lock for URL \`%s'." "${_url}";
				rtl_fileop rm "${_target_fname_full}"; break;
			fi; ;;
		2)	if [ "${_urls_count}" -ge 1 ]; then
				rtl_log_msg warning "Warning: hash mismatch for URL \`%s', retrying with alternative URL... (from build variables: %s.)"\
						"${_url}" "${_sha256sum_src}";
			else
				if _sha256sum_target="$(sha256sum "${_target_fname_full}" |\
							awk '{print $1}' 2>/dev/null)"; then
					rtl_log_msg fatal "Error: hash mismatch for URL \`%s' (should be: %s vs.: %s.)"\
							"${_url}" "${_sha256sum_src}" "${_sha256sum_target}";
				else
					rtl_log_msg fatal "Error: hash mismatch for URL \`%s' (should be: %s.)"\
							"${_url}" "${_sha256sum_src}";
				fi;
				rtl_fileop rm "${_target_fname_full}"; break;
			fi; ;;
		*)	if [ "${_urls_count}" -ge 1 ]; then
				rtl_log_msg warning "Warning: failed to fetch URL \`%s', retrying with alternative URL... (wget(1) exit status: %s)"\
						"${_url}" "$((${_rc}-2))";
			else
				rtl_log_msg fatal "Error: failed to fetch URL \`%s' (wget(1) exit status: %s)"\
						"${_url}" "$((${_rc}-2))";
				rtl_fileop rm "${_target_fname_full}"; break;
			fi; ;;
		esac;
	done;
	return "${_rc}";
};

# vim:filetype=sh