[PATCH] git-r3.eclass: Respect overrides and fallbacks in ls-remote call

Michał Górny <[email protected]>
Newsgroups gmane.linux.gentoo.devel
Message-ID <[email protected]>
Refactor the eclass logic to defer the 'git ls-remote' call used to
determine the object format until overrides are in place.  Move it into
repository fetching loop so that mirrors and fallback URIs are respected
as well.  While at it, fix duplicate directory entries in
EVCS_STORE_DIRS, and avoid creating an empty directory if 'git
ls-remote' fails.

For historical reasons, git-r3_set_gitdir function was responsible both
for setting the value of GIT_DIR and creating it if necessary.
To ensure that GIT_DIR was stable, the canonical URI was always used.
No network traffic was involved at this stage.

While adding sha256 support in 0477949bcf64596be3e508b9664fedfc8158a364,
an additional 'git ls-remote' call was added to determine the remote
object format before creating GIT_DIR.  We've missed that this call
would be performed early on, with no respect for repository URI
overrides, mirrors and fallback URIs.  Most of the time this wasn't
a problem, at least as long as the canonical URI was reachable and had
the same object format.

It seems that the cleanest solution to this is to split setting GIT_DIR
from creating it.  The former still needs to be done early, using
the canonical URI.  The latter is best done in the fetching loop where
we are already iterating over the final list of URIs.  This also permits
us to easily support fallback when the initial URI fails, much like we
do in the 'git fetch' invocation.

Closes: https://bugs.gentoo.org/979189
Signed-off-by: Michał Górny <[email protected]>
---
 eclass/git-r3.eclass | 87 +++++++++++++++++++++++++-------------------
 1 file changed, 50 insertions(+), 37 deletions(-)

diff --git a/eclass/git-r3.eclass b/eclass/git-r3.eclass
index 99f846b237b41..cd017977c7ddb 100644
--- a/eclass/git-r3.eclass
+++ b/eclass/git-r3.eclass
@@ -343,6 +343,47 @@ _git-r3_get_object_format() {
 	esac
 }
 
+# @FUNCTION: _git-r3_create_gitdir
+# @USAGE: <repo-uri>
+# @RETURN: 0 if successful or GIT_DIR exists already, 1 if ls-remote failed
+# @INTERNAL
+# @DESCRIPTION:
+# Create GIT_DIR if necessary.
+_git-r3_create_gitdir() {
+	local repo_uri=${1}
+
+	[[ -d ${GIT_DIR} ]] && return 0
+
+	if [[ ! -d ${EGIT3_STORE_DIR} ]]; then
+		(
+			addwrite /
+			mkdir -p "${EGIT3_STORE_DIR}"
+		) || die "Unable to create ${EGIT3_STORE_DIR}"
+	fi
+
+	# determine the remote object format
+	local head_ref
+	head_ref=(
+		$(git ls-remote "${repo_uri}" "HEAD")
+	)
+	[[ ${?} -ne 0 ]] && return 1
+	local object_format=$(_git-r3_get_object_format "${head_ref[0]}")
+
+	addwrite "${EGIT3_STORE_DIR}"
+	local saved_umask
+	if [[ ${EVCS_UMASK} ]]; then
+		saved_umask=$(umask)
+		umask "${EVCS_UMASK}" || die "Bad options to umask: ${EVCS_UMASK}"
+	fi
+	mkdir "${GIT_DIR}" || die
+
+	git init --object-format="${object_format}" --bare -b __init__ || die
+	if [[ ${saved_umask} ]]; then
+		umask "${saved_umask}" || die
+	fi
+	return 0
+}
+
 # @FUNCTION: _git-r3_set_gitdir
 # @USAGE: <repo-uri>
 # @INTERNAL
@@ -387,43 +428,6 @@ _git-r3_set_gitdir() {
 	: "${EGIT3_STORE_DIR:=${distdir}/git3-src}"
 
 	GIT_DIR=${EGIT3_STORE_DIR}/${repo_name}
-
-	EVCS_STORE_DIRS+=( "${GIT_DIR}" )
-
-	if [[ ! -d ${EGIT3_STORE_DIR} && ! ${EVCS_OFFLINE} ]]; then
-		(
-			addwrite /
-			mkdir -p "${EGIT3_STORE_DIR}"
-		) || die "Unable to create ${EGIT3_STORE_DIR}"
-	fi
-
-	addwrite "${EGIT3_STORE_DIR}"
-	if [[ ! -d ${GIT_DIR} ]]; then
-		if [[ ${EVCS_OFFLINE} ]]; then
-			eerror "A clone of the following repository is required to proceed:"
-			eerror "  ${1}"
-			eerror "However, networking activity has been disabled using EVCS_OFFLINE and there"
-			eerror "is no local clone available."
-			die "No local clone of ${1}. Unable to proceed with EVCS_OFFLINE."
-		fi
-
-		local saved_umask
-		if [[ ${EVCS_UMASK} ]]; then
-			saved_umask=$(umask)
-			umask "${EVCS_UMASK}" || die "Bad options to umask: ${EVCS_UMASK}"
-		fi
-		mkdir "${GIT_DIR}" || die
-
-		# determine the remote object format
-		local head_ref=(
-			$(git ls-remote "${repo_uri}" "HEAD" || die)
-		)
-		local object_format=$(_git-r3_get_object_format "${head_ref[0]}")
-		git init --object-format="${object_format}" --bare -b __init__ || die
-		if [[ ${saved_umask} ]]; then
-			umask "${saved_umask}" || die
-		fi
-	fi
 }
 
 # @FUNCTION: _git-r3_set_submodules
@@ -619,6 +623,14 @@ git-r3_fetch() {
 
 	local -x GIT_DIR
 	_git-r3_set_gitdir "${repos[0]}"
+	if [[ ! -d ${GIT_DIR} && ${EVCS_OFFLINE} ]]; then
+		eerror "A clone of the following repository is required to proceed:"
+		eerror "  ${repos[0]}"
+		eerror "However, network activity has been disabled using EVCS_OFFLINE and there"
+		eerror "is no local clone available."
+		die "No local clone of ${repos[0]}. Unable to proceed with EVCS_OFFLINE."
+	fi
+	EVCS_STORE_DIRS+=( "${GIT_DIR}" )
 
 	einfo "Repository id: ${GIT_DIR##*/}"
 
@@ -692,6 +704,7 @@ git-r3_fetch() {
 	for r in "${repos[@]}"; do
 		if [[ ! ${EVCS_OFFLINE} ]]; then
 			einfo "Fetching ${r} ..."
+			_git-r3_create_gitdir "${r}" || continue
 
 			local fetch_command=( git fetch "${r}" )
 			local clone_type=${EGIT_CLONE_TYPE}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.