git-r3.eclass: Add support for sha256 objects

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 <mgorny@gentoo.org>
Part-of: https://codeberg.org/gentoo/gentoo/pulls/751
Merges: https://codeberg.org/gentoo/gentoo/pulls/751
This commit is contained in:
Michał Górny
2026-04-26 18:35:29 +02:00
parent 903e4913c3
commit 0477949bcf

View File

@@ -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