[PATCH] git-r3.eclass: Add support for sha256 objects

Michał Górny <[email protected]>
Newsgroups gmane.linux.gentoo.devel
Message-ID <[email protected]>
Add support for remote repositories using sha256 objects.  When fetching
a new repository, use ls-remote to check if the remote hashes look like
sha1 or sha256, and init the bare repository accordingly.  Similarly,
look at the checked out commit id to init the checkout repo.

This doesn't handle upstream migrating from sha1 to sha256 in place
gracefully.  Instead, whenever 'git fetch' fails, the eclass hints that
the local clone may need to be removed.

Note that sha256 support is experimental upstream and does not come with
any backwards compatibility support.  Upstream indicates that adding
said support may break compatibility with prior sha256 deployments.

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

diff --git a/eclass/git-r3.eclass b/eclass/git-r3.eclass
index 719e2eea4fb04..99f846b237b41 100644
--- a/eclass/git-r3.eclass
+++ b/eclass/git-r3.eclass
@@ -322,6 +322,27 @@ _git-r3_env_setup() {
 	fi
 }
 
+# @FUNCTION: _git-r3_get_object_format
+# @USAGE: <hash>
+# @INTERNAL
+# @DESCRIPTION:
+# Determine the object format from hash. Prints "sha1" or "sha256".
+_git-r3_get_object_format() {
+	local h=${1}
+
+	case "${#h}" in
+		40)
+			echo sha1
+			;;
+		64)
+			echo sha256
+			;;
+		*)
+			die "Unrecognized hash: ${h}"
+			;;
+	esac
+}
+
 # @FUNCTION: _git-r3_set_gitdir
 # @USAGE: <repo-uri>
 # @INTERNAL
@@ -334,7 +355,8 @@ _git-r3_env_setup() {
 _git-r3_set_gitdir() {
 	debug-print-function ${FUNCNAME} "$@"
 
-	local repo_name=${1#*://*/}
+	local repo_uri=${1}
+	local repo_name=${repo_uri#*://*/}
 
 	# strip the trailing slash
 	repo_name=${repo_name%/}
@@ -391,7 +413,13 @@ _git-r3_set_gitdir() {
 			umask "${EVCS_UMASK}" || die "Bad options to umask: ${EVCS_UMASK}"
 		fi
 		mkdir "${GIT_DIR}" || die
-		git init --bare -b __init__ || 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
@@ -850,7 +878,15 @@ git-r3_fetch() {
 	if [[ ${saved_umask} ]]; then
 		umask "${saved_umask}" || die
 	fi
-	[[ ${success} ]] || die "Unable to fetch from any of EGIT_REPO_URI"
+	if [[ ! ${success} ]]; then
+		eerror "Fetching git repository failed. Please inspect the log for errors."
+		eerror "If you see 'mismatched algorithm' errors, please remove the local clone"
+		eerror "and try again:"
+		eerror "  rm -r ${GIT_DIR}"
+		eerror
+
+		die "Unable to fetch from any of EGIT_REPO_URI"
+	fi
 
 	# submodules can reference commits in any branch
 	# always use the 'mirror' mode to accommodate that, bug #503332
@@ -958,7 +994,8 @@ git-r3_checkout() {
 		# use git init+fetch instead of clone since the latter doesn't like
 		# non-empty directories.
 
-		git init --quiet -b __init__ || die
+		local object_format=$(_git-r3_get_object_format "${new_commit_id}")
+		git init --object-format="${object_format}" --quiet -b __init__ || die
 		if [[ ${EGIT_LFS} ]]; then
 			# The "skip-repo" flag will just skip the installation of the pre-push hooks.
 			# We don't use these hook as we don't do any pushes
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.