Skip to content

Instantly share code, notes, and snippets.

@konsolebox
Last active May 31, 2026 02:04
Show Gist options
  • Select an option

  • Save konsolebox/a91f8d9cfea69fa19ef26ceedd64113c to your computer and use it in GitHub Desktop.

Select an option

Save konsolebox/a91f8d9cfea69fa19ef26ceedd64113c to your computer and use it in GitHub Desktop.
#!/bin/bash
# Based on parona's generate-cache.sh <https://gitlab.com/Parona/parona-scripts/-/blob/master/portage-hooks/repo.postsync.d/generate-cache.sh>
set +o posix || exit
GENFUN_MODULES="rc portage"
source /lib/gentoo/functions.sh -- || exit
hash git sudo >/dev/null || exit
function git.is_git_repo {
local repo_location=$1
[[ -e ${repo_location}/.git ]]
}
function git.is_file_tracked {
local repo_location=$1 file=$2
git -C "${repo_location}" ls-files --error-unmatch -- "${file}" &>/dev/null
}
function git.get_current_branch {
local repo_location=$1
__=$(git -C "${repo_location}" branch --show-current) && [[ $__ ]]
}
function git.get_current_branch_remote_repo {
local repo_location=$1
git.get_current_branch "${repo_location}" || die "Failed to get current branch of ${repo_location}"
__=$(git -C "${repo_location}" config --get branch."$__".remote) && [[ $__ ]]
}
function git.get_current_branch_remote_uri {
local repo_location=$1
git.get_current_branch_remote_repo "${repo_location}" || die "Failed to get remote repo of ${repo_location}"
__=$(git -C "${repo_location}" remote get-url "$__") && [[ $__ ]]
}
function is_gentoo_mirror_repo {
local repo_location=$1 __
git.get_current_branch_remote_uri "${repo_location}" || die "Failed to get remote URI of ${repo_location}"
[[ $__ == https://github.com/gentoo-mirror/* ]]
}
function main {
local repository_name=$1 sync_uri=$2 repository_path=$3 nproc pk_opts pmaint_opts egencache_opts
[[ ${repository_name} ]] || die "Repository name not provided."
[[ ${repository_path} ]] || die "Repository path not provided."
# Update every metadata/md5-cache even those included in the git repo since changes in ::gentoo
# especially those in eclasses can invalidate the dependent repo's cache.
#
# But exclude those in gentoo-mirror since officially generated caches are likely more reliable
# and invalidations that might occur when ::gentoo (raw) gets updated first even just by theory
# is negligible.
#
# On non-gentoo-mirror repos however, make sure their metadata/md5-cache directory is reset to
# their original state first, just in case update conflicts happened earlier during sync.
if git.is_git_repo "${repository_path}"; then
if is_gentoo_mirror_repo "${repository_path}"; then
einfo "Skipping cache update of ${repository_name} (${repository_path}): Repo is from https://github.com/gentoo-mirror"
return 0
elif git.is_file_tracked "${repository_path}" metadata/md5-cache; then
einfo "Restoring ${repository_name} (${repository_path})'s metadata to its original state."
git -C "${repository_path}" restore --source=HEAD metadata
fi
fi
einfo "Updating cache of ${repository_name} (${repository_path})."
nproc=$(nproc) && [[ ${nproc} ]] || die "Unable to get nproc output."
pk_opts=("${repository_path}" --jobs "${nproc}")
pmaint_opts=("${repository_name}" -t "${nproc}" --pkg-desc-index)
egencache_opts=(--repo "${repository_name}" --jobs "${nproc}" --update-pkg-desc-index)
if [[ ! -f ${repository_path}/profiles/use.local.desc ]] || { git.is_git_repo \
"${repository_path}" && ! git.is_file_tracked "${repository_path}" \
profiles/use.local.desc; }; then
pk_opts+=(--use-local)
pmaint_opts+=(--use-local-desc)
egencache_opts+=(--update-use-local-desc)
fi
# Prefer pkgcraft-tools over pkgcore and pkgcore over egencache if available.
#
# Also check that profiles/eapi exists as that is a common requirement difference that
# many repos miss.
#
# Also pk seems broken with non-gentoo repos as it does nothing. No error messages even.
if hash pk &>/dev/null && [[ -e ${repository_path}/profiles/eapi && \
${repository_name} == gentoo ]]; then
edo sudo -Hu portage pk repo metadata regen "${pk_opts[@]}" || return 1
elif hash pmaint &>/dev/null; then
edo sudo -Hu portage pmaint regen "${pmaint_opts[@]}" || return 1
elif hash egencache &>/dev/null; then
edo sudo -Hu portage egencache "${egencache_opts[@]}" || return 1
else
eerror "pk, pmaint or egencache not found or unusable with repo."
fi
}
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment