And time for a small update. Dnia 2013-08-31, o godz. 01:37:44 Michał Górny <mgo...@gentoo.org> napisał(a):
> 3. sys-fs/bedup's btrfs-progs submodule says the given commit id is > 'not a valid branch point'. Need to investigate what this means. > > 4. 'git fetch --depth 1' seems to be refetching stuff even when nothing > changed. Need to investigate it. It may be enough to do an additional > 'did anything change?' check. Those are fixed now. The eclass has been adjusted to work properly with branches, tags and commit ids. It also avoids shallowing repo that was unshallowed already (since we expect that one of the packages needs it non-shallow), and properly unshallows shallow repos ;). Attaching the new version and a diff. -- Best regards, Michał Górny
# Copyright 1999-2013 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Header: $ # @ECLASS: git-r3.eclass # @MAINTAINER: # MichaŠGórny <mgo...@gentoo.org> # @BLURB: Eclass for fetching and unpacking git repositories. # @DESCRIPTION: # Third generation eclass for easing maitenance of live ebuilds using # git as remote repository. Eclass supports lightweight (shallow) # clones, local object deduplication and submodules. case "${EAPI:-0}" in 0|1|2|3|4|5) ;; *) die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}" ;; esac if [[ ! ${_GIT_R3} ]]; then inherit eutils fi EXPORT_FUNCTIONS src_unpack if [[ ! ${_GIT_R3} ]]; then # @ECLASS-VARIABLE: EGIT_STORE_DIR # @DESCRIPTION: # Storage directory for git sources. # # EGIT_STORE_DIR=${DISTDIR}/git3-src # @ECLASS-VARIABLE: EGIT_REPO_URI # @REQUIRED # @DESCRIPTION: # URIs to the repository, e.g. git://foo, https://foo. If multiple URIs # are provided, the eclass will consider them as fallback URIs to try # if the first URI does not work. # # It can be overriden via env using ${PN}_LIVE_REPO variable. # # Example: # @CODE # EGIT_REPO_URI="git://a/b.git https://c/d.git" # @CODE # @ECLASS-VARIABLE: EVCS_OFFLINE # @DEFAULT_UNSET # @DESCRIPTION: # If non-empty, this variable prevents any online operations. # @ECLASS-VARIABLE: EGIT_BRANCH # @DEFAULT_UNSET # @DESCRIPTION: # The branch name to check out. If unset, the upstream default (HEAD) # will be used. # # It can be overriden via env using ${PN}_LIVE_BRANCH variable. # @ECLASS-VARIABLE: EGIT_COMMIT # @DEFAULT_UNSET # @DESCRIPTION: # The tag name or commit identifier to check out. If unset, newest # commit from the branch will be used. If set, EGIT_BRANCH will # be ignored. # # It can be overriden via env using ${PN}_LIVE_COMMIT variable. # @ECLASS-VARIABLE: EGIT_NONSHALLOW # @DEFAULT_UNSET # @DESCRIPTION: # Disable performing shallow fetches/clones. Shallow clones have # a fair number of limitations. Therefore, if you'd like the eclass to # perform complete clones instead, set this to a non-null value. # # This variable is to be set in make.conf. Ebuilds are not allowed # to set it. # @FUNCTION: _git-r3_env_setup # @INTERNAL # @DESCRIPTION: # Set the eclass variables as necessary for operation. This can involve # setting EGIT_* to defaults or ${PN}_LIVE_* variables. _git-r3_env_setup() { debug-print-function ${FUNCNAME} "$@" local esc_pn livevar esc_pn=${PN//[-+]/_} livevar=${esc_pn}_LIVE_REPO EGIT_REPO_URI=${!livevar:-${EGIT_REPO_URI}} [[ ${EGIT_REPO_URI} ]] \ || die "EGIT_REPO_URI must be set to a non-empty value" [[ ${!livevar} ]] \ && ewarn "Using ${livevar}, no support will be provided" livevar=${esc_pn}_LIVE_BRANCH EGIT_BRANCH=${!livevar:-${EGIT_BRANCH}} [[ ${!livevar} ]] \ && ewarn "Using ${livevar}, no support will be provided" livevar=${esc_pn}_LIVE_COMMIT EGIT_COMMIT=${!livevar:-${EGIT_COMMIT}} [[ ${!livevar} ]] \ && ewarn "Using ${livevar}, no support will be provided" # git-2 unsupported cruft local v for v in EGIT_{SOURCEDIR,MASTER,HAS_SUBMODULES,PROJECT} \ EGIT_{NOUNPACK,BOOTSTRAP} do [[ ${!v} ]] && die "${v} is not supported." done } # @FUNCTION: _git-r3_set_gitdir # @USAGE: <repo-uri> # @INTERNAL # @DESCRIPTION: # Obtain the local repository path and set it as GIT_DIR. Creates # a new repository if necessary. # # <repo-uri> may be used to compose the path. It should therefore be # a canonical URI to the repository. _git-r3_set_gitdir() { debug-print-function ${FUNCNAME} "$@" local repo_name=${1#*://*/} # strip common prefixes to make paths more likely to match # e.g. git://X/Y.git vs https://X/git/Y.git # (but just one of the prefixes) case "${repo_name}" in # cgit can proxy requests to git cgit/*) repo_name=${repo_name#cgit/};; # pretty common git/*) repo_name=${repo_name#git/};; # gentoo.org gitroot/*) repo_name=${repo_name#gitroot/};; # google code, sourceforge p/*) repo_name=${repo_name#p/};; # kernel.org pub/scm/*) repo_name=${repo_name#pub/scm/};; esac # ensure a .git suffix, same reason repo_name=${repo_name%.git}.git # now replace all the slashes repo_name=${repo_name//\//_} local distdir=${PORTAGE_ACTUAL_DISTDIR:-${DISTDIR}} : ${EGIT_STORE_DIR:=${distdir}/git3-src} GIT_DIR=${EGIT_STORE_DIR}/${repo_name} if [[ ! -d ${EGIT_STORE_DIR} ]]; then ( addwrite / mkdir -m0755 -p "${EGIT_STORE_DIR}" ) || die "Unable to create ${EGIT_STORE_DIR}" fi addwrite "${EGIT_STORE_DIR}" if [[ ! -d ${GIT_DIR} ]]; then mkdir "${GIT_DIR}" || die git init --bare || die # avoid auto-unshallow :) touch "${GIT_DIR}"/shallow || die fi } # @FUNCTION: _git-r3_set_submodules # @USAGE: <file-contents> # @INTERNAL # @DESCRIPTION: # Parse .gitmodules contents passed as <file-contents> # as in "$(cat .gitmodules)"). Composes a 'submodules' array that # contains in order (name, URL, path) for each submodule. _git-r3_set_submodules() { debug-print-function ${FUNCNAME} "$@" local data=${1} # ( name url path ... ) submodules=() local l while read l; do # submodule.<path>.path=<path> # submodule.<path>.url=<url> [[ ${l} == submodule.*.url=* ]] || continue l=${l#submodule.} local subname=${l%%.url=*} submodules+=( "${subname}" "$(echo "${data}" | git config -f /dev/fd/0 \ submodule."${subname}".url)" "$(echo "${data}" | git config -f /dev/fd/0 \ submodule."${subname}".path)" ) done < <(echo "${data}" | git config -f /dev/fd/0 -l) } # @FUNCTION: git-r3_fetch # @USAGE: <repo-uri> <remote-ref> <local-id> # @DESCRIPTION: # Fetch new commits to the local clone of repository. <repo-uri> follows # the syntax of EGIT_REPO_URI and may list multiple (fallback) URIs. # <remote-ref> specifies the remote ref to fetch (branch, tag # or commit). <local-id> specifies an identifier that needs to uniquely # identify the fetch operation in case multiple parallel merges used # the git repo. <local-id> usually involves using CATEGORY, PN and SLOT. # # The fetch operation will only affect the local storage. It will not # touch the working copy. If the repository contains submodules, they # will be fetched recursively as well. git-r3_fetch() { debug-print-function ${FUNCNAME} "$@" local repos=( ${1} ) local remote_ref=${2} local local_id=${3} local local_ref=refs/heads/${local_id}/__main__ local -x GIT_DIR _git-r3_set_gitdir ${repos[0]} # try to fetch from the remote local r success for r in ${repos[@]}; do einfo "Fetching ${remote_ref} from ${r} ..." local is_branch lookup_ref if [[ ${remote_ref} == refs/heads/* || ${remote_ref} == HEAD ]] then is_branch=1 lookup_ref=${remote_ref} else # ls-remote by commit is going to fail anyway, # so we may as well pass refs/tags/ABCDEF... lookup_ref=refs/tags/${remote_ref} fi # first, try ls-remote to see if ${remote_ref} is a real ref # and not a commit id. if it succeeds, we can pass ${remote_ref} # to 'fetch'. otherwise, we will just fetch everything # split on whitespace local ref=( $(git ls-remote "${r}" "${lookup_ref}") ) # now, another important thing. we may only fetch a remote # branch directly to a local branch. Otherwise, we need to fetch # the commit and re-create the branch on top of it. local ref_param=() if [[ ! ${ref[0]} ]]; then local EGIT_NONSHALLOW=1 fi if [[ ! -f ${GIT_DIR}/shallow ]]; then # if it's a complete repo, fetch it as-is : elif [[ ${EGIT_NONSHALLOW} ]]; then # if it's a shallow clone but we need complete, # unshallow it ref_param+=( --unshallow ) else # otherwise, just fetch as shallow ref_param+=( --depth 1 ) fi if [[ ${ref[0]} ]]; then if [[ ${is_branch} ]]; then ref_param+=( -f "${remote_ref}:${local_id}/__main__" ) else ref_param+=( "${remote_ref}" ) fi fi # if ${remote_ref} is branch or tag, ${ref[@]} will contain # the respective commit id. otherwise, it will be an empty # array, so the following won't evaluate to a parameter. set -- git fetch --no-tags "${r}" "${ref_param[@]}" echo "${@}" >&2 if "${@}"; then if [[ ! ${is_branch} ]]; then set -- git branch -f "${local_id}/__main__" \ "${ref[0]:-${remote_ref}}" echo "${@}" >&2 if ! "${@}"; then die "Creating branch for ${remote_ref} failed (wrong ref?)." fi fi success=1 break fi done [[ ${success} ]] || die "Unable to fetch from any of EGIT_REPO_URI" # recursively fetch submodules if git cat-file -e "${local_ref}":.gitmodules &>/dev/null; then local submodules _git-r3_set_submodules \ "$(git cat-file -p "${local_ref}":.gitmodules || die)" while [[ ${submodules[@]} ]]; do local subname=${submodules[0]} local url=${submodules[1]} local path=${submodules[2]} local commit=$(git rev-parse "${local_ref}:${path}") if [[ ! ${commit} ]]; then die "Unable to get commit id for submodule ${subname}" fi git-r3_fetch "${url}" "${commit}" "${local_id}/${subname}" submodules=( "${submodules[@]:3}" ) # shift done fi } # @FUNCTION: git-r3_checkout # @USAGE: <repo-uri> <local-id> <path> # @DESCRIPTION: # Check the previously fetched commit out to <path> (usually # ${WORKDIR}/${P}). <repo-uri> follows the syntax of EGIT_REPO_URI # and will be used to re-construct the local storage path. <local-id> # is the unique identifier used for the fetch operation and will # be used to obtain the proper commit. # # If the repository contains submodules, they will be checked out # recursively as well. git-r3_checkout() { debug-print-function ${FUNCNAME} "$@" local repos=( ${1} ) local local_id=${2} local out_dir=${3} local -x GIT_DIR GIT_WORK_TREE _git-r3_set_gitdir ${repos[0]} GIT_WORK_TREE=${out_dir} einfo "Checking out ${repos[0]} to ${out_dir} ..." mkdir -p "${GIT_WORK_TREE}" set -- git checkout -f "${local_id}"/__main__ . echo "${@}" >&2 "${@}" || die "git checkout ${local_id}/__main__ failed" # diff against previous revision (if any) local new_commit_id=$(git rev-parse --verify "${local_id}"/__main__) local old_commit_id=$( git rev-parse --verify "${local_id}"/__old__ 2>/dev/null ) if [[ ! ${old_commit_id} ]]; then echo "GIT NEW branch -->" echo " repository: ${repos[0]}" echo " at the commit: ${new_commit_id}" else echo "GIT update -->" echo " repository: ${repos[0]}" # write out message based on the revisions if [[ "${old_commit_id}" != "${new_commit_id}" ]]; then echo " updating from commit: ${old_commit_id}" echo " to commit: ${new_commit_id}" git --no-pager diff --color --stat \ ${old_commit_id}..${new_commit_id} else echo " at the commit: ${new_commit_id}" fi fi git branch -f "${local_id}"/{__old__,__main__} || die # recursively checkout submodules if [[ -f ${GIT_WORK_TREE}/.gitmodules ]]; then local submodules _git-r3_set_submodules \ "$(cat "${GIT_WORK_TREE}"/.gitmodules)" while [[ ${submodules[@]} ]]; do local subname=${submodules[0]} local url=${submodules[1]} local path=${submodules[2]} git-r3_checkout "${url}" "${local_id}/${subname}" \ "${GIT_WORK_TREE}/${path}" submodules=( "${submodules[@]:3}" ) # shift done fi # keep this *after* submodules export EGIT_DIR=${GIT_DIR} export EGIT_VERSION=${new_commit_id} } git-r3_src_fetch() { debug-print-function ${FUNCNAME} "$@" [[ ${EVCS_OFFLINE} ]] && return _git-r3_env_setup local branch=${EGIT_BRANCH:+refs/heads/${EGIT_BRANCH}} git-r3_fetch "${EGIT_REPO_URI}" \ "${EGIT_COMMIT:-${branch:-HEAD}}" \ ${CATEGORY}/${PN}/${SLOT} } git-r3_src_unpack() { debug-print-function ${FUNCNAME} "$@" _git-r3_env_setup git-r3_src_fetch git-r3_checkout "${EGIT_REPO_URI}" \ ${CATEGORY}/${PN}/${SLOT} \ "${WORKDIR}/${P}" } _GIT_R3=1 fi
diff --git a/gx86/eclass/git-r3.eclass b/gx86/eclass/git-r3.eclass index 36673a8..d56c818 100644 --- a/gx86/eclass/git-r3.eclass +++ b/gx86/eclass/git-r3.eclass @@ -168,6 +168,9 @@ _git-r3_set_gitdir() { if [[ ! -d ${GIT_DIR} ]]; then mkdir "${GIT_DIR}" || die git init --bare || die + + # avoid auto-unshallow :) + touch "${GIT_DIR}"/shallow || die fi } @@ -234,29 +237,70 @@ git-r3_fetch() { for r in ${repos[@]}; do einfo "Fetching ${remote_ref} from ${r} ..." + local is_branch lookup_ref + if [[ ${remote_ref} == refs/heads/* || ${remote_ref} == HEAD ]] + then + is_branch=1 + lookup_ref=${remote_ref} + else + # ls-remote by commit is going to fail anyway, + # so we may as well pass refs/tags/ABCDEF... + lookup_ref=refs/tags/${remote_ref} + fi + # first, try ls-remote to see if ${remote_ref} is a real ref # and not a commit id. if it succeeds, we can pass ${remote_ref} # to 'fetch'. otherwise, we will just fetch everything # split on whitespace local ref=( - $(git ls-remote "${r}" "${remote_ref}") + $(git ls-remote "${r}" "${lookup_ref}") ) + # now, another important thing. we may only fetch a remote + # branch directly to a local branch. Otherwise, we need to fetch + # the commit and re-create the branch on top of it. + local ref_param=() + if [[ ! ${ref[0]} ]]; then + local EGIT_NONSHALLOW=1 + fi + + if [[ ! -f ${GIT_DIR}/shallow ]]; then + # if it's a complete repo, fetch it as-is + : + elif [[ ${EGIT_NONSHALLOW} ]]; then + # if it's a shallow clone but we need complete, + # unshallow it + ref_param+=( --unshallow ) + else + # otherwise, just fetch as shallow + ref_param+=( --depth 1 ) + fi + if [[ ${ref[0]} ]]; then - [[ ${EGIT_NONSHALLOW} ]] || ref_param+=( --depth 1 ) - ref_param+=( "${remote_ref}" ) + if [[ ${is_branch} ]]; then + ref_param+=( -f "${remote_ref}:${local_id}/__main__" ) + else + ref_param+=( "${remote_ref}" ) + fi fi # if ${remote_ref} is branch or tag, ${ref[@]} will contain # the respective commit id. otherwise, it will be an empty # array, so the following won't evaluate to a parameter. - if git fetch --no-tags "${r}" "${ref_param[@]}"; then - if ! git branch -f "${local_id}/__main__" "${ref[0]:-${remote_ref}}" - then - die "Creating tag failed (${remote_ref} invalid?)" + set -- git fetch --no-tags "${r}" "${ref_param[@]}" + echo "${@}" >&2 + if "${@}"; then + if [[ ! ${is_branch} ]]; then + set -- git branch -f "${local_id}/__main__" \ + "${ref[0]:-${remote_ref}}" + echo "${@}" >&2 + if ! "${@}"; then + die "Creating branch for ${remote_ref} failed (wrong ref?)." + fi fi + success=1 break fi @@ -311,7 +355,9 @@ git-r3_checkout() { einfo "Checking out ${repos[0]} to ${out_dir} ..." mkdir -p "${GIT_WORK_TREE}" - git checkout -f "${local_id}"/__main__ || die + set -- git checkout -f "${local_id}"/__main__ . + echo "${@}" >&2 + "${@}" || die "git checkout ${local_id}/__main__ failed" # diff against previous revision (if any) local new_commit_id=$(git rev-parse --verify "${local_id}"/__main__) @@ -330,6 +376,9 @@ git-r3_checkout() { if [[ "${old_commit_id}" != "${new_commit_id}" ]]; then echo " updating from commit: ${old_commit_id}" echo " to commit: ${new_commit_id}" + + git --no-pager diff --color --stat \ + ${old_commit_id}..${new_commit_id} else echo " at the commit: ${new_commit_id}" fi
signature.asc
Description: PGP signature