summaryrefslogtreecommitdiffhomepage
path: root/subr.rtl/rtl_fetch_git.subr
blob: 13eb672d2f6b4e86189e40089e57bfe15d5a737e (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
#
# Copyright (c) 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 Lucía Andrea Illanes Albornoz <lucia@luciaillanes.de>
# set +o errexit -o noglob -o nounset is assumed.
#

rtlp_fetch_url_git() {
	local	_rpfug_cache_dname="${1}" _rpfug_git_args="${2}" _rpfug_git_branch="${3}"	\
		_rpfug_mirrors="${4}" _rpfug_pkg_name="${5}" _rpfug_subdir="${6}"		\
		_rpfug_tgtdir="${7}" _rpfug_url="${8}"						\
		_rpfug_cache_dname_full="" _rpfug_clonefl=0 _rpfug_dname=""			\
		_rpfug_git_pull_log_fname="" _rpfug_oldpwd="" _rpfug_url_base="";

	_rpfug_cache_dname_full="${_rpfug_cache_dname}/${_rpfug_subdir##*/}";
	(set -o errexit -o noglob -o nounset;
	rtl_flock_acquire 4 || exit "${?}";
	trap "rm -f \"${_rpfug_cache_dname_full%%[/]}.fetching\"" EXIT;
	if [ -e "${_rpfug_cache_dname_full}" ]; then
		(rtl_fileop cd "${_rpfug_cache_dname_full}" || exit 1;
		 _rpfug_git_pull_log_fname="$(mktemp)" || exit 1;
		 trap 'rm -f "${_rpfug_git_pull_log_fname}" 2>/dev/null' EXIT HUP INT TERM USR1 USR2;
		 if ! git pull ${_rpfug_git_args} origin "${_rpfug_git_branch:-main}" >"${_rpfug_git_pull_log_fname}" 2>&1; then
			if grep -q '^fatal: refusing to merge unrelated histories$' "${_rpfug_git_pull_log_fname}"; then
				cat "${_rpfug_git_pull_log_fname}"; printf "Detected forced push(es).\n";
			elif grep -q '^Automatic merge failed; fix conflicts and then commit the result.$' "${_rpfug_git_pull_log_fname}"; then
				cat "${_rpfug_git_pull_log_fname}"; printf "Detected forced push(es).\n"; git merge --abort;
			else
				cat "${_rpfug_git_pull_log_fname}"; exit 1;
			fi;
			while true; do
				printf "Attempting git-reset(1) --hard HEAD^ and git-pull(1)...\n";
				if ! git reset --hard "HEAD^"; then
					exit 1;
				elif git pull ${_rpfug_git_args} origin "${_rpfug_git_branch:-main}"; then
					exit 0;
				fi;
			done;
		 else
			cat "${_rpfug_git_pull_log_fname}"; exit 0;
		 fi;) || return 1;
		(rtl_fileop cd "${_rpfug_cache_dname_full}" &&\
			git submodule update) || return 1;
	else	if git clone ${_rpfug_git_args} -b "${_rpfug_git_branch:-main}" "${_rpfug_url}" "${_rpfug_cache_dname_full}"; then
			_rpfug_clonefl=1;
		elif [ "${_rpfug_mirrors}" = "skip" ]; then
			return 1;
		else	for _rpfug_url_base in ${_rpfug_mirrors}; do
				if git clone ${_rpfug_git_args} -b "${_rpfug_git_branch:-main}" "${_rpfug_url_base}/${_rpfug_pkg_name}/${_rpfug_subdir}" "${_rpfug_cache_dname_full}"; then
					_rpfug_clonefl=1; break;
				fi;
			done;
		fi;
		if [ "${_rpfug_clonefl}" -eq 0 ]; then
			return 1;
		else	if [ "${_rpfug_git_branch:+1}" = 1 ]; then
				(rtl_fileop cd "${_rpfug_cache_dname_full}" &&\
					git checkout "${_rpfug_git_branch}") || return 1;
			fi;
			(rtl_fileop cd "${_rpfug_cache_dname_full}" &&\
				git submodule update --init) || return 1;
		fi;
	fi;
	if [ "${_rpfug_cache_dname}" != "${_rpfug_tgtdir}" ]; then
		_rpfug_oldpwd="${PWD}"; rtl_fileop cd "${_rpfug_tgtdir}" || return 1;
		rtl_fileop rm "${_rpfug_tgtdir}/${_rpfug_subdir}" || return 1;
		_rpfug_dname="${_rpfug_tgtdir}/${_rpfug_subdir}"; rtl_dirname \$_rpfug_dname;
		if ! [ -e "${_rpfug_dname}" ]; then
			rtl_fileop mkdir "${_rpfug_dname}";
		fi;
		rtl_fileop cp "${_rpfug_cache_dname_full}" "${_rpfug_tgtdir}/${_rpfug_subdir}" || return 1;
		rtl_fileop cd "${_rpfug_oldpwd}" || return 1;
	fi) 4<>"${_rpfug_cache_dname_full%%[/]}.fetching";

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

rtl_fetch_mirror_urls_git() {
	local	_rfmug_git_args="${1}" _rfmug_tgtdir="${2}"				\
		_rfmug_dname="" _rfmug_rc=0 _rfmug_repo_dname="" _rfmug_subdir=""	\
		_rfmug_url="" _rfmug_url_spec=""; shift 2;

	for _rfmug_url_spec in "${@}"; do
		_rfmug_subdir="${_rfmug_url_spec%=*}"; _rfmug_subdir="${_rfmug_subdir##*/}"; _rfmug_url="${_rfmug_url_spec#*=}"; _rfmug_url="${_rfmug_url%@*}";
		_rfmug_repo_dname="${_rfmug_subdir}"; [ "${_rfmug_repo_dname%.git}" = "${_rfmug_repo_dname}" ] && _rfmug_repo_dname="${_rfmug_repo_dname}.git";

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

	return "${_rfmug_rc}";
};

rtl_fetch_urls_git() {
	local	_rfug_cache_dname="${1}" _rfug_git_args="${2}" _rfug_tgtdir="${3}"	\
		_rfug_pkg_name="${4}" _rfug_mirrors="${5}"				\
	       	_rfug_git_branch="" _rfug_subdir="" _rfug_url="" _rfug_url_spec=""; shift 5;

	for _rfug_url_spec in "${@}"; do
		_rfug_subdir="${_rfug_url_spec%=*}";
		_rfug_url="${_rfug_url_spec#*=}";
		_rfug_url="${_rfug_url%@*}";
		if [ "${_rfug_url_spec#*@}" != "${_rfug_url_spec}" ]; then
			_rfug_git_branch=${_rfug_url_spec#*@};
		fi;
		if ! rtlp_fetch_url_git	\
				"${_rfug_cache_dname}" "${_rfug_git_args}"	\
				"${_rfug_git_branch}" "${_rfug_mirrors}"	\
				"${_rfug_pkg_name}" "${_rfug_subdir}"		\
				"${_rfug_tgtdir}" "${_rfug_url}";
		then
			return 1;
		fi;
	done;

	return 0;
};

# vim:filetype=sh textwidth=0