1 # Copyright 1999-2015 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
5 # @ECLASS: git-r3.eclass
7 # Michał Górny <mgorny@gentoo.org>
8 # @BLURB: Eclass for fetching and unpacking git repositories.
10 # Third generation eclass for easing maintenance of live ebuilds using
11 # git as remote repository.
17 die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
21 if [[ ! ${_GIT_R3} ]]; then
27 EXPORT_FUNCTIONS src_unpack
29 if [[ ! ${_GIT_R3} ]]; then
31 if [[ ! ${_INHERITED_BY_GIT_2} ]]; then
32 DEPEND=">=dev-vcs/git-1.8.2.1"
35 # @ECLASS-VARIABLE: EGIT_CLONE_TYPE
37 # Type of clone that should be used against the remote repository.
38 # This can be either of: 'mirror', 'single', 'shallow'.
40 # This is intended to be set by user in make.conf. Ebuilds are supposed
41 # to set EGIT_MIN_CLONE_TYPE if necessary instead.
43 # The 'mirror' type clones all remote branches and tags with complete
44 # history and all notes. EGIT_COMMIT can specify any commit hash.
45 # Upstream-removed branches and tags are purged from the local clone
46 # while fetching. This mode is suitable for cloning the local copy
47 # for development or hosting a local git mirror. However, clones
48 # of repositories with large diverged branches may quickly grow large.
50 # The 'single+tags' type clones the requested branch and all tags
51 # in the repository. All notes are fetched as well. EGIT_COMMIT
52 # can safely specify hashes throughout the current branch and all tags.
53 # No purging of old references is done (if you often switch branches,
54 # you may need to remove stale branches yourself). This mode is intended
55 # mostly for use with broken git servers such as Google Code that fail
56 # to fetch tags along with the branch in 'single' mode.
58 # The 'single' type clones only the requested branch or tag. Tags
59 # referencing commits throughout the branch history are fetched as well,
60 # and all notes. EGIT_COMMIT can safely specify only hashes
61 # in the current branch. No purging of old references is done (if you
62 # often switch branches, you may need to remove stale branches
63 # yourself). This mode is suitable for general use.
65 # The 'shallow' type clones only the newest commit on requested branch
66 # or tag. EGIT_COMMIT can only specify tags, and since the history is
67 # unavailable calls like 'git describe' will not reference prior tags.
68 # No purging of old references is done. This mode is intended mostly for
69 # embedded systems with limited disk space.
70 : ${EGIT_CLONE_TYPE:=single}
72 # @ECLASS-VARIABLE: EGIT_MIN_CLONE_TYPE
74 # 'Minimum' clone type supported by the ebuild. Takes same values
75 # as EGIT_CLONE_TYPE. When user sets a type that's 'lower' (that is,
76 # later on the list) than EGIT_MIN_CLONE_TYPE, the eclass uses
77 # EGIT_MIN_CLONE_TYPE instead.
79 # This variable is intended to be used by ebuilds only. Users are
80 # supposed to set EGIT_CLONE_TYPE instead.
82 # A common case is to use 'single' whenever the build system requires
83 # access to full branch history, or 'single+tags' when Google Code
84 # or a similar remote is used that does not support shallow clones
85 # and fetching tags along with commits. Please use sparingly, and to fix
86 # fatal errors rather than 'non-pretty versions'.
87 : ${EGIT_MIN_CLONE_TYPE:=shallow}
89 # @ECLASS-VARIABLE: EGIT3_STORE_DIR
91 # Storage directory for git sources.
93 # This is intended to be set by user in make.conf. Ebuilds must not set
96 # EGIT3_STORE_DIR=${DISTDIR}/git3-src
98 # @ECLASS-VARIABLE: EGIT_MIRROR_URI
101 # 'Top' URI to a local git mirror. If specified, the eclass will try
102 # to fetch from the local mirror instead of using the remote repository.
104 # The mirror needs to follow EGIT3_STORE_DIR structure. The directory
105 # created by eclass can be used for that purpose.
109 # EGIT_MIRROR_URI="git://mirror.lan/"
112 # @ECLASS-VARIABLE: EGIT_REPO_URI
115 # URIs to the repository, e.g. git://foo, https://foo. If multiple URIs
116 # are provided, the eclass will consider them as fallback URIs to try
117 # if the first URI does not work. For supported URI syntaxes, read up
118 # the manpage for git-clone(1).
120 # It can be overriden via env using ${PN}_LIVE_REPO variable.
122 # Can be a whitespace-separated list or an array.
126 # EGIT_REPO_URI="git://a/b.git https://c/d.git"
129 # @ECLASS-VARIABLE: EVCS_OFFLINE
132 # If non-empty, this variable prevents any online operations.
134 # @ECLASS-VARIABLE: EVCS_UMASK
137 # Set this variable to a custom umask. This is intended to be set by
138 # users. By setting this to something like 002, it can make life easier
139 # for people who do development as non-root (but are in the portage
140 # group), and then switch over to building with FEATURES=userpriv.
141 # Or vice-versa. Shouldn't be a security issue here as anyone who has
142 # portage group write access already can screw the system over in more
145 # @ECLASS-VARIABLE: EGIT_BRANCH
148 # The branch name to check out. If unset, the upstream default (HEAD)
151 # It can be overriden via env using ${PN}_LIVE_BRANCH variable.
153 # @ECLASS-VARIABLE: EGIT_COMMIT
156 # The tag name or commit identifier to check out. If unset, newest
157 # commit from the branch will be used. If set, EGIT_BRANCH will
160 # It can be overriden via env using ${PN}_LIVE_COMMIT variable.
162 # @ECLASS-VARIABLE: EGIT_CHECKOUT_DIR
164 # The directory to check the git sources out to.
166 # EGIT_CHECKOUT_DIR=${WORKDIR}/${P}
168 # @ECLASS-VARIABLE: EGIT_SUBMODULES
171 # An array of inclusive and exclusive wildcards on submodule names,
172 # stating which submodules are fetched and checked out. Exclusions
173 # start with '-', and exclude previously matched submodules.
175 # If unset, all submodules are enabled. Empty list disables all
176 # submodules. In order to use an exclude-only list, start the array
179 # Remember that wildcards need to be quoted in order to prevent filename
184 # # Disable all submodules
187 # # Include only foo and bar
188 # EGIT_SUBMODULES=( foo bar )
190 # # Use all submodules except for test-* but include test-lib
191 # EGIT_SUBMODULES=( '*' '-test-*' test-lib )
194 # @FUNCTION: _git-r3_env_setup
197 # Set the eclass variables as necessary for operation. This can involve
198 # setting EGIT_* to defaults or ${PN}_LIVE_* variables.
199 _git-r3_env_setup() {
200 debug-print-function ${FUNCNAME} "$@"
202 # check the clone type
203 case "${EGIT_CLONE_TYPE}" in
204 mirror|single+tags|single|shallow)
207 die "Invalid EGIT_CLONE_TYPE=${EGIT_CLONE_TYPE}"
209 case "${EGIT_MIN_CLONE_TYPE}" in
213 if [[ ${EGIT_CLONE_TYPE} == shallow ]]; then
214 einfo "git-r3: ebuild needs to be cloned in '\e[1msingle\e[22m' mode, adjusting"
215 EGIT_CLONE_TYPE=single
219 if [[ ${EGIT_CLONE_TYPE} == shallow || ${EGIT_CLONE_TYPE} == single ]]; then
220 einfo "git-r3: ebuild needs to be cloned in '\e[1msingle+tags\e[22m' mode, adjusting"
221 EGIT_CLONE_TYPE=single+tags
225 if [[ ${EGIT_CLONE_TYPE} != mirror ]]; then
226 einfo "git-r3: ebuild needs to be cloned in '\e[1mmirror\e[22m' mode, adjusting"
227 EGIT_CLONE_TYPE=mirror
231 die "Invalid EGIT_MIN_CLONE_TYPE=${EGIT_MIN_CLONE_TYPE}"
234 if [[ ${EGIT_SUBMODULES[@]+1} && $(declare -p EGIT_SUBMODULES) != "declare -a"* ]]
236 die 'EGIT_SUBMODULES must be an array.'
242 livevar=${esc_pn}_LIVE_REPO
243 EGIT_REPO_URI=${!livevar:-${EGIT_REPO_URI}}
245 && ewarn "Using ${livevar}, no support will be provided"
247 livevar=${esc_pn}_LIVE_BRANCH
248 EGIT_BRANCH=${!livevar:-${EGIT_BRANCH}}
250 && ewarn "Using ${livevar}, no support will be provided"
252 livevar=${esc_pn}_LIVE_COMMIT
253 EGIT_COMMIT=${!livevar:-${EGIT_COMMIT}}
255 && ewarn "Using ${livevar}, no support will be provided"
257 # Migration helpers. Remove them when git-2 is removed.
259 if [[ ${EGIT_SOURCEDIR} ]]; then
260 eerror "EGIT_SOURCEDIR has been replaced by EGIT_CHECKOUT_DIR. While updating"
261 eerror "your ebuild, please check whether the variable is necessary at all"
262 eerror "since the default has been changed from \${S} to \${WORKDIR}/\${P}."
263 eerror "Therefore, proper setting of S may be sufficient."
264 die "EGIT_SOURCEDIR has been replaced by EGIT_CHECKOUT_DIR."
267 if [[ ${EGIT_MASTER} ]]; then
268 eerror "EGIT_MASTER has been removed. Instead, the upstream default (HEAD)"
269 eerror "is used by the eclass. Please remove the assignment or use EGIT_BRANCH"
270 eerror "as necessary."
271 die "EGIT_MASTER has been removed."
274 if [[ ${EGIT_HAS_SUBMODULES} ]]; then
275 eerror "EGIT_HAS_SUBMODULES has been removed. The eclass no longer needs"
276 eerror "to switch the clone type in order to support submodules and therefore"
277 eerror "submodules are detected and fetched automatically. If you need to"
278 eerror "disable or filter submodules, see EGIT_SUBMODULES."
279 die "EGIT_HAS_SUBMODULES is no longer necessary."
282 if [[ ${EGIT_PROJECT} ]]; then
283 eerror "EGIT_PROJECT has been removed. Instead, the eclass determines"
284 eerror "the local clone path using path in canonical EGIT_REPO_URI."
285 eerror "If the current algorithm causes issues for you, please report a bug."
286 die "EGIT_PROJECT is no longer necessary."
289 if [[ ${EGIT_BOOTSTRAP} ]]; then
290 eerror "EGIT_BOOTSTRAP has been removed. Please create proper src_prepare()"
292 die "EGIT_BOOTSTRAP has been removed."
295 if [[ ${EGIT_NOUNPACK} ]]; then
296 eerror "EGIT_NOUNPACK has been removed. The eclass no longer calls default"
297 eerror "unpack function. If necessary, please declare proper src_unpack()."
298 die "EGIT_NOUNPACK has been removed."
302 # @FUNCTION: _git-r3_set_gitdir
306 # Obtain the local repository path and set it as GIT_DIR. Creates
307 # a new repository if necessary.
309 # <repo-uri> may be used to compose the path. It should therefore be
310 # a canonical URI to the repository.
311 _git-r3_set_gitdir() {
312 debug-print-function ${FUNCNAME} "$@"
314 local repo_name=${1#*://*/}
316 # strip the trailing slash
317 repo_name=${repo_name%/}
319 # strip common prefixes to make paths more likely to match
320 # e.g. git://X/Y.git vs https://X/git/Y.git
321 # (but just one of the prefixes)
322 case "${repo_name}" in
323 # gnome.org... who else?
324 browse/*) repo_name=${repo_name#browse/};;
325 # cgit can proxy requests to git
326 cgit/*) repo_name=${repo_name#cgit/};;
328 git/*) repo_name=${repo_name#git/};;
330 gitroot/*) repo_name=${repo_name#gitroot/};;
331 # google code, sourceforge
332 p/*) repo_name=${repo_name#p/};;
334 pub/scm/*) repo_name=${repo_name#pub/scm/};;
336 # ensure a .git suffix, same reason
337 repo_name=${repo_name%.git}.git
338 # now replace all the slashes
339 repo_name=${repo_name//\//_}
341 local distdir=${PORTAGE_ACTUAL_DISTDIR:-${DISTDIR}}
342 : ${EGIT3_STORE_DIR:=${distdir}/git3-src}
344 GIT_DIR=${EGIT3_STORE_DIR}/${repo_name}
346 if [[ ! -d ${EGIT3_STORE_DIR} ]]; then
349 mkdir -p "${EGIT3_STORE_DIR}"
350 ) || die "Unable to create ${EGIT3_STORE_DIR}"
353 addwrite "${EGIT3_STORE_DIR}"
354 if [[ ! -d ${GIT_DIR} ]]; then
356 if [[ ${EVCS_UMASK} ]]; then
358 umask "${EVCS_UMASK}" || die "Bad options to umask: ${EVCS_UMASK}"
360 mkdir "${GIT_DIR}" || die
361 git init --bare || die
362 if [[ ${saved_umask} ]]; then
363 umask "${saved_umask}" || die
368 # @FUNCTION: _git-r3_set_submodules
369 # @USAGE: <file-contents>
372 # Parse .gitmodules contents passed as <file-contents>
373 # as in "$(cat .gitmodules)"). Composes a 'submodules' array that
374 # contains in order (name, URL, path) for each submodule.
375 _git-r3_set_submodules() {
376 debug-print-function ${FUNCNAME} "$@"
380 # ( name url path ... )
385 # submodule.<path>.path=<path>
386 # submodule.<path>.url=<url>
387 [[ ${l} == submodule.*.url=* ]] || continue
390 local subname=${l%%.url=*}
392 # filter out on EGIT_SUBMODULES
393 if declare -p EGIT_SUBMODULES &>/dev/null; then
395 for p in "${EGIT_SUBMODULES[@]}"; do
396 if [[ ${p} == -* ]]; then
403 [[ ${subname} == ${p} ]] && res=${l_res}
406 if [[ ! ${res} ]]; then
407 einfo "Skipping submodule \e[1m${subname}\e[22m"
412 # skip modules that have 'update = none', bug #487262.
413 local upd=$(echo "${data}" | git config -f /dev/fd/0 \
414 submodule."${subname}".update)
415 [[ ${upd} == none ]] && continue
417 # https://github.com/git/git/blob/master/refs.c#L39
418 # for now, we just filter /. because of #572312
419 local enc_subname=${subname//\/.//_}
420 [[ ${enc_subname} == .* ]] && enc_subname=_${enc_subname#.}
424 "$(echo "${data}" | git config -f /dev/fd/0 \
425 submodule."${subname}".url || die)"
426 "$(echo "${data}" | git config -f /dev/fd/0 \
427 submodule."${subname}".path || die)"
429 done < <(echo "${data}" | git config -f /dev/fd/0 -l || die)
432 # @FUNCTION: _git-r3_set_subrepos
433 # @USAGE: <submodule-uri> <parent-repo-uri>...
436 # Create 'subrepos' array containing absolute (canonical) submodule URIs
437 # for the given <submodule-uri>. If the URI is relative, URIs will be
438 # constructed using all <parent-repo-uri>s. Otherwise, this single URI
439 # will be placed in the array.
440 _git-r3_set_subrepos() {
441 debug-print-function ${FUNCNAME} "$@"
444 subrepos=( "${@:2}" )
446 if [[ ${suburl} == ./* || ${suburl} == ../* ]]; then
447 # drop all possible trailing slashes for consistency
448 subrepos=( "${subrepos[@]%%/}" )
451 if [[ ${suburl} == ./* ]]; then
453 elif [[ ${suburl} == ../* ]]; then
456 # XXX: correctness checking
458 # drop the last path component
459 subrepos=( "${subrepos[@]%/*}" )
460 # and then the trailing slashes, again
461 subrepos=( "${subrepos[@]%%/}" )
467 # append the preprocessed path to the preprocessed URIs
468 subrepos=( "${subrepos[@]/%//${suburl}}")
470 subrepos=( "${suburl}" )
475 # @FUNCTION: _git-r3_is_local_repo
479 # Determine whether the given URI specifies a local (on-disk)
481 _git-r3_is_local_repo() {
482 debug-print-function ${FUNCNAME} "$@"
486 [[ ${uri} == file://* || ${uri} == /* ]]
489 # @FUNCTION: git-r3_fetch
490 # @USAGE: [<repo-uri> [<remote-ref> [<local-id>]]]
492 # Fetch new commits to the local clone of repository.
494 # <repo-uri> specifies the repository URIs to fetch from, as a space-
495 # -separated list. The first URI will be used as repository group
496 # identifier and therefore must be used consistently. When not
497 # specified, defaults to ${EGIT_REPO_URI}.
499 # <remote-ref> specifies the remote ref or commit id to fetch.
500 # It is preferred to use 'refs/heads/<branch-name>' for branches
501 # and 'refs/tags/<tag-name>' for tags. Other options are 'HEAD'
502 # for upstream default branch and hexadecimal commit SHA1. Defaults
503 # to the first of EGIT_COMMIT, EGIT_BRANCH or literal 'HEAD' that
504 # is set to a non-null value.
506 # <local-id> specifies the local branch identifier that will be used to
507 # locally store the fetch result. It should be unique to multiple
508 # fetches within the repository that can be performed at the same time
509 # (including parallel merges). It defaults to ${CATEGORY}/${PN}/${SLOT%/*}.
510 # This default should be fine unless you are fetching multiple trees
511 # from the same repository in the same ebuild.
513 # The fetch operation will affect the EGIT_STORE only. It will not touch
514 # the working copy, nor export any environment variables.
515 # If the repository contains submodules, they will be fetched
518 debug-print-function ${FUNCNAME} "$@"
520 [[ ${EVCS_OFFLINE} ]] && return
525 elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then
526 repos=( "${EGIT_REPO_URI[@]}" )
528 repos=( ${EGIT_REPO_URI} )
531 local branch=${EGIT_BRANCH:+refs/heads/${EGIT_BRANCH}}
532 local remote_ref=${2:-${EGIT_COMMIT:-${branch:-HEAD}}}
533 local local_id=${3:-${CATEGORY}/${PN}/${SLOT%/*}}
534 local local_ref=refs/git-r3/${local_id}/__main__
536 [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset"
539 _git-r3_set_gitdir "${repos[0]}"
541 # prepend the local mirror if applicable
542 if [[ ${EGIT_MIRROR_URI} ]]; then
544 "${EGIT_MIRROR_URI%/}/${GIT_DIR##*/}"
549 # try to fetch from the remote
550 local r success saved_umask
551 if [[ ${EVCS_UMASK} ]]; then
553 umask "${EVCS_UMASK}" || die "Bad options to umask: ${EVCS_UMASK}"
555 for r in "${repos[@]}"; do
556 einfo "Fetching \e[1m${r}\e[22m ..."
558 local fetch_command=( git fetch "${r}" )
559 local clone_type=${EGIT_CLONE_TYPE}
561 if [[ ${r} == https://* ]] && ! ROOT=/ has_version 'dev-vcs/git[curl]'; then
562 eerror "git-r3: fetching from https:// requested. In order to support https,"
563 eerror "dev-vcs/git needs to be built with USE=curl. Example solution:"
565 eerror " echo dev-vcs/git curl >> /etc/portage/package.use"
566 eerror " emerge -1v dev-vcs/git"
567 die "dev-vcs/git built with USE=curl required."
570 if [[ ${r} == https://code.google.com/* ]]; then
571 # Google Code has special magic on top of git that:
572 # 1) can't handle shallow clones at all,
573 # 2) fetches duplicately when tags are pulled in with branch
574 # so automatically switch to single+tags mode.
575 if [[ ${clone_type} == shallow ]]; then
576 einfo " Google Code does not support shallow clones"
577 einfo " using \e[1mEGIT_CLONE_TYPE=single+tags\e[22m"
578 clone_type=single+tags
579 elif [[ ${clone_type} == single ]]; then
580 einfo " git-r3: Google Code does not send tags properly in 'single' mode"
581 einfo " using \e[1mEGIT_CLONE_TYPE=single+tags\e[22m"
582 clone_type=single+tags
586 if [[ ${clone_type} == mirror ]]; then
589 # mirror the remote branches as local branches
590 "+refs/heads/*:refs/heads/*"
591 # pull tags explicitly in order to prune them properly
592 "+refs/tags/*:refs/tags/*"
593 # notes in case something needs them
594 "+refs/notes/*:refs/notes/*"
595 # and HEAD in case we need the default branch
596 # (we keep it in refs/git-r3 since otherwise --prune interferes)
597 "+HEAD:refs/git-r3/HEAD"
599 else # single or shallow
600 local fetch_l fetch_r
602 if [[ ${remote_ref} == HEAD ]]; then
605 elif [[ ${remote_ref} == refs/* ]]; then
606 # regular branch, tag or some other explicit ref
607 fetch_l=${remote_ref}
609 # tag or commit id...
610 # let ls-remote figure it out
611 local tagref=$(git ls-remote "${r}" "refs/tags/${remote_ref}")
613 # if it was a tag, ls-remote obtained a hash
614 if [[ ${tagref} ]]; then
616 fetch_l=refs/tags/${remote_ref}
619 # so we need to fetch the whole branch
620 if [[ ${branch} ]]; then
626 # fetching by commit in shallow mode? can't do.
627 if [[ ${clone_type} == shallow ]]; then
633 if [[ ${fetch_l} == HEAD ]]; then
634 fetch_r=refs/git-r3/HEAD
640 "+${fetch_l}:${fetch_r}"
643 if [[ ${clone_type} == single+tags ]]; then
645 # pull tags explicitly as requested
646 "+refs/tags/*:refs/tags/*"
651 if [[ ${clone_type} == shallow ]]; then
652 if _git-r3_is_local_repo; then
653 # '--depth 1' causes sandbox violations with local repos
656 elif [[ ! $(git rev-parse --quiet --verify "${fetch_r}") ]]
658 # use '--depth 1' when fetching a new branch
659 fetch_command+=( --depth 1 )
661 else # non-shallow mode
662 if [[ -f ${GIT_DIR}/shallow ]]; then
663 fetch_command+=( --unshallow )
667 set -- "${fetch_command[@]}"
670 if [[ ${clone_type} == mirror || ${fetch_l} == HEAD ]]; then
671 # update our HEAD to match our remote HEAD ref
672 git symbolic-ref HEAD refs/git-r3/HEAD \
673 || die "Unable to update HEAD"
676 # now let's see what the user wants from us
677 local full_remote_ref=$(
678 git rev-parse --verify --symbolic-full-name "${remote_ref}"
681 if [[ ${full_remote_ref} ]]; then
682 # when we are given a ref, create a symbolic ref
683 # so that we preserve the actual argument
684 set -- git symbolic-ref "${local_ref}" "${full_remote_ref}"
686 # otherwise, we were likely given a commit id
687 set -- git update-ref --no-deref "${local_ref}" "${remote_ref}"
692 die "Referencing ${remote_ref} failed (wrong ref?)."
699 if [[ ${saved_umask} ]]; then
700 umask "${saved_umask}" || die
702 [[ ${success} ]] || die "Unable to fetch from any of EGIT_REPO_URI"
704 # submodules can reference commits in any branch
705 # always use the 'mirror' mode to accomodate that, bug #503332
706 local EGIT_CLONE_TYPE=mirror
708 # recursively fetch submodules
709 if git cat-file -e "${local_ref}":.gitmodules &>/dev/null; then
711 _git-r3_set_submodules \
712 "$(git cat-file -p "${local_ref}":.gitmodules || die)"
714 while [[ ${submodules[@]} ]]; do
715 local subname=${submodules[0]}
716 local url=${submodules[1]}
717 local path=${submodules[2]}
719 # use only submodules for which path does exist
720 # (this is in par with 'git submodule'), bug #551100
721 # note: git cat-file does not work for submodules
722 if [[ $(git ls-tree -d "${local_ref}" "${path}") ]]
724 local commit=$(git rev-parse "${local_ref}:${path}" || die)
726 if [[ ! ${commit} ]]; then
727 die "Unable to get commit id for submodule ${subname}"
731 _git-r3_set_subrepos "${url}" "${repos[@]}"
733 git-r3_fetch "${subrepos[*]}" "${commit}" "${local_id}/${subname}"
736 submodules=( "${submodules[@]:3}" ) # shift
741 # @FUNCTION: git-r3_checkout
742 # @USAGE: [<repo-uri> [<checkout-path> [<local-id>]]]
744 # Check the previously fetched tree to the working copy.
746 # <repo-uri> specifies the repository URIs, as a space-separated list.
747 # The first URI will be used as repository group identifier
748 # and therefore must be used consistently with git-r3_fetch.
749 # The remaining URIs are not used and therefore may be omitted.
750 # When not specified, defaults to ${EGIT_REPO_URI}.
752 # <checkout-path> specifies the path to place the checkout. It defaults
753 # to ${EGIT_CHECKOUT_DIR} if set, otherwise to ${WORKDIR}/${P}.
755 # <local-id> needs to specify the local identifier that was used
756 # for respective git-r3_fetch.
758 # The checkout operation will write to the working copy, and export
759 # the repository state into the environment. If the repository contains
760 # submodules, they will be checked out recursively.
762 debug-print-function ${FUNCNAME} "$@"
767 elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then
768 repos=( "${EGIT_REPO_URI[@]}" )
770 repos=( ${EGIT_REPO_URI} )
773 local out_dir=${2:-${EGIT_CHECKOUT_DIR:-${WORKDIR}/${P}}}
774 local local_id=${3:-${CATEGORY}/${PN}/${SLOT%/*}}
777 _git-r3_set_gitdir "${repos[0]}"
779 einfo "Checking out \e[1m${repos[0]}\e[22m to \e[1m${out_dir}\e[22m ..."
781 if ! git cat-file -e refs/git-r3/"${local_id}"/__main__; then
782 if [[ ${EVCS_OFFLINE} ]]; then
783 die "No local clone of ${repos[0]}. Unable to work with EVCS_OFFLINE."
785 die "Logic error: no local clone of ${repos[0]}. git-r3_fetch not used?"
789 git symbolic-ref --quiet refs/git-r3/"${local_id}"/__main__
791 local new_commit_id=$(
792 git rev-parse --verify refs/git-r3/"${local_id}"/__main__
795 git-r3_sub_checkout() {
796 local orig_repo=${GIT_DIR}
797 local -x GIT_DIR=${out_dir}/.git
798 local -x GIT_WORK_TREE=${out_dir}
800 mkdir -p "${out_dir}" || die
802 # use git init+fetch instead of clone since the latter doesn't like
803 # non-empty directories.
805 git init --quiet || die
806 # setup 'alternates' to avoid copying objects
807 echo "${orig_repo}/objects" > "${GIT_DIR}"/objects/info/alternates || die
809 cp -R "${orig_repo}"/refs/* "${GIT_DIR}"/refs/ || die
811 # (no need to copy HEAD, we will set it via checkout)
813 if [[ -f ${orig_repo}/shallow ]]; then
814 cp "${orig_repo}"/shallow "${GIT_DIR}"/ || die
817 set -- git checkout --quiet
818 if [[ ${remote_ref} ]]; then
819 set -- "${@}" "${remote_ref#refs/heads/}"
821 set -- "${@}" "${new_commit_id}"
824 "${@}" || die "git checkout ${remote_ref:-${new_commit_id}} failed"
827 unset -f git-r3_sub_checkout
829 local old_commit_id=$(
830 git rev-parse --quiet --verify refs/git-r3/"${local_id}"/__old__
832 if [[ ! ${old_commit_id} ]]; then
833 echo "GIT NEW branch -->"
834 echo " repository: ${repos[0]}"
835 echo " at the commit: ${new_commit_id}"
837 # diff against previous revision
838 echo "GIT update -->"
839 echo " repository: ${repos[0]}"
840 # write out message based on the revisions
841 if [[ "${old_commit_id}" != "${new_commit_id}" ]]; then
842 echo " updating from commit: ${old_commit_id}"
843 echo " to commit: ${new_commit_id}"
845 git --no-pager diff --stat \
846 ${old_commit_id}..${new_commit_id}
848 echo " at the commit: ${new_commit_id}"
851 git update-ref --no-deref refs/git-r3/"${local_id}"/{__old__,__main__} || die
853 # recursively checkout submodules
854 if [[ -f ${out_dir}/.gitmodules ]]; then
856 _git-r3_set_submodules \
857 "$(<"${out_dir}"/.gitmodules)"
859 while [[ ${submodules[@]} ]]; do
860 local subname=${submodules[0]}
861 local url=${submodules[1]}
862 local path=${submodules[2]}
864 # use only submodules for which path does exist
865 # (this is in par with 'git submodule'), bug #551100
866 if [[ -d ${out_dir}/${path} ]]; then
868 _git-r3_set_subrepos "${url}" "${repos[@]}"
870 git-r3_checkout "${subrepos[*]}" "${out_dir}/${path}" \
871 "${local_id}/${subname}"
874 submodules=( "${submodules[@]:3}" ) # shift
878 # keep this *after* submodules
879 export EGIT_DIR=${GIT_DIR}
880 export EGIT_VERSION=${new_commit_id}
883 # @FUNCTION: git-r3_peek_remote_ref
884 # @USAGE: [<repo-uri> [<remote-ref>]]
886 # Peek the reference in the remote repository and print the matching
887 # (newest) commit SHA1.
889 # <repo-uri> specifies the repository URIs to fetch from, as a space-
890 # -separated list. When not specified, defaults to ${EGIT_REPO_URI}.
892 # <remote-ref> specifies the remote ref to peek. It is preferred to use
893 # 'refs/heads/<branch-name>' for branches and 'refs/tags/<tag-name>'
894 # for tags. Alternatively, 'HEAD' may be used for upstream default
895 # branch. Defaults to the first of EGIT_COMMIT, EGIT_BRANCH or literal
896 # 'HEAD' that is set to a non-null value.
898 # The operation will be done purely on the remote, without using local
899 # storage. If commit SHA1 is provided as <remote-ref>, the function will
900 # fail due to limitations of git protocol.
902 # On success, the function returns 0 and writes hexadecimal commit SHA1
903 # to stdout. On failure, the function returns 1.
904 git-r3_peek_remote_ref() {
905 debug-print-function ${FUNCNAME} "$@"
910 elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then
911 repos=( "${EGIT_REPO_URI[@]}" )
913 repos=( ${EGIT_REPO_URI} )
916 local branch=${EGIT_BRANCH:+refs/heads/${EGIT_BRANCH}}
917 local remote_ref=${2:-${EGIT_COMMIT:-${branch:-HEAD}}}
919 [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset"
922 for r in "${repos[@]}"; do
923 einfo "Peeking \e[1m${remote_ref}\e[22m on \e[1m${r}\e[22m ..." >&2
926 if [[ ${remote_ref} == refs/* || ${remote_ref} == HEAD ]]
928 lookup_ref=${remote_ref}
930 # ls-remote by commit is going to fail anyway,
931 # so we may as well pass refs/tags/ABCDEF...
932 lookup_ref=refs/tags/${remote_ref}
935 # split on whitespace
937 $(git ls-remote "${r}" "${lookup_ref}")
940 if [[ ${ref[0]} ]]; then
950 debug-print-function ${FUNCNAME} "$@"
952 if [[ ! ${EGIT3_STORE_DIR} && ${EGIT_STORE_DIR} ]]; then
953 ewarn "You have set EGIT_STORE_DIR but not EGIT3_STORE_DIR. Please consider"
954 ewarn "setting EGIT3_STORE_DIR for git-r3.eclass. It is recommended to use"
955 ewarn "a different directory than EGIT_STORE_DIR to ease removing old clones"
956 ewarn "when git-2 eclass becomes deprecated."
963 git-r3_src_unpack() {
964 debug-print-function ${FUNCNAME} "$@"
971 # https://bugs.gentoo.org/show_bug.cgi?id=482666
972 git-r3_pkg_needrebuild() {
973 debug-print-function ${FUNCNAME} "$@"
975 local new_commit_id=$(git-r3_peek_remote_ref)
976 [[ ${new_commit_id} && ${EGIT_VERSION} ]] || die "Lookup failed"
978 if [[ ${EGIT_VERSION} != ${new_commit_id} ]]; then
979 einfo "Update from \e[1m${EGIT_VERSION}\e[22m to \e[1m${new_commit_id}\e[22m"
981 einfo "Local and remote at \e[1m${EGIT_VERSION}\e[22m"
984 [[ ${EGIT_VERSION} != ${new_commit_id} ]]
987 # 'export' locally until this gets into EAPI
988 pkg_needrebuild() { git-r3_pkg_needrebuild; }